Automatically register the peer manager as a shutdowner rather than require

that it be shut down manually.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4794 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2007-07-31 20:01:52 +00:00
parent 47bace1003
commit ea501d7083
@@ -71,7 +71,7 @@ import static com.threerings.presents.Log.log;
* servers and uses those objects to communicate cross-node information.
*/
public class PeerManager
implements PeerProvider, ClientManager.ClientObserver
implements PeerProvider, ClientManager.ClientObserver, PresentsServer.Shutdowner
{
/**
* Used by entities that wish to know when cached data has become stale due to a change on
@@ -117,7 +117,7 @@ public class PeerManager
{
/**
* Called when the resource lock was acquired successfully. The lock will be released
* immediately after this function call finishes.
* immediately after this function call finishes.
*/
public void run ();
@@ -127,7 +127,7 @@ public class PeerManager
*/
public void fail (String peerName);
}
/**
* Creates a peer manager which will create a {@link NodeRepository} which will be used to
* publish our existence and discover the other nodes.
@@ -136,6 +136,7 @@ public class PeerManager
{
_invoker = invoker;
_noderepo = new NodeRepository(ctx);
PresentsServer.registerShutdowner(this);
}
/**
@@ -213,39 +214,6 @@ public class PeerManager
didInit();
}
/**
* Call this when the server is shutting down to give this node a chance to cleanly logoff from
* its peers and remove its record from the nodes table.
*/
public void shutdown ()
{
// clear out our invocation service
if (_nodeobj != null) {
PresentsServer.invmgr.clearDispatcher(_nodeobj.peerService);
}
// clear out our client observer registration
PresentsServer.clmgr.removeClientObserver(this);
// clear our record from the node table
_invoker.postUnit(new Invoker.Unit("deleteNode") {
public boolean invoke () {
try {
_noderepo.deleteNode(_nodeName);
} catch (PersistenceException pe) {
log.warning("Failed to delete node record [nodeName=" + _nodeName +
", error=" + pe + "].");
}
return false;
}
});
// shut down the peers
for (PeerNode peer : _peers.values()) {
peer.shutdown();
}
}
/**
* Locates the client with the specified name. Returns null if the client is not logged onto
* any peer.
@@ -529,7 +497,7 @@ public class PeerManager
/**
* Tries to acquire the resource lock and, if successful, performs the operation and releases
* the lock; if unsuccessful, calls the operation's failure handler. Please note: the lock will
* be released immediately after the operation.
* be released immediately after the operation.
*/
public void performWithLock (final NodeObject.Lock lock, final LockedOperation operation)
{
@@ -570,62 +538,6 @@ public class PeerManager
_dropobs.remove(observer);
}
// documentation inherited from interface PeerProvider
public void ratifyLockAction (ClientObject caller, NodeObject.Lock lock, boolean acquire)
{
LockHandler handler = _locks.get(lock);
if (handler != null && handler.getNodeName().equals(_nodeName)) {
handler.ratify(caller, acquire);
} else {
// this is not an error condition, as we may have cancelled the handler or
// allowed another to take priority
}
}
// documentation inherited from interface ClientManager.ClientObserver
public void clientSessionDidStart (PresentsClient client)
{
// if this is another peer, don't publish their info
if (client instanceof PeerClient) {
return;
}
// create and publish a ClientInfo record for this client
ClientInfo clinfo = createClientInfo();
initClientInfo(client, clinfo);
// sanity check
if (_nodeobj.clients.contains(clinfo)) {
log.warning("Received clientSessionDidStart() for already registered client!? " +
"[old=" + _nodeobj.clients.get(clinfo.getKey()) + ", new=" + clinfo + "].");
// go ahead and update the record
_nodeobj.updateClients(clinfo);
} else {
_nodeobj.addToClients(clinfo);
}
}
// documentation inherited from interface ClientManager.ClientObserver
public void clientSessionDidEnd (PresentsClient client)
{
// if this is another peer, don't worry about it
if (client instanceof PeerClient) {
return;
}
// we scan through the list instead of relying on ClientInfo.getKey() because we want
// derived classes to be able to override that for lookups that happen way more frequently
// than logging off
Name username = client.getCredentials().getUsername();
for (ClientInfo clinfo : _nodeobj.clients) {
if (clinfo.username.equals(username)) {
clearClientInfo(client, clinfo);
return;
}
}
log.warning("Session ended for unregistered client [who=" + username + "].");
}
/**
* Called by {@link PeerClient}s when clients subscribe to the {@link NodeObject}.
*/
@@ -683,6 +595,92 @@ public class PeerManager
_nodeobj.setCacheData(new NodeObject.CacheData(cache, data));
}
// from interface PresentsServer.Shutdowner
public void shutdown ()
{
// clear out our invocation service
if (_nodeobj != null) {
PresentsServer.invmgr.clearDispatcher(_nodeobj.peerService);
}
// clear out our client observer registration
PresentsServer.clmgr.removeClientObserver(this);
// clear our record from the node table
_invoker.postUnit(new Invoker.Unit("deleteNode") {
public boolean invoke () {
try {
_noderepo.deleteNode(_nodeName);
} catch (PersistenceException pe) {
log.warning("Failed to delete node record [nodeName=" + _nodeName +
", error=" + pe + "].");
}
return false;
}
});
// shut down the peers
for (PeerNode peer : _peers.values()) {
peer.shutdown();
}
}
// from interface PeerProvider
public void ratifyLockAction (ClientObject caller, NodeObject.Lock lock, boolean acquire)
{
LockHandler handler = _locks.get(lock);
if (handler != null && handler.getNodeName().equals(_nodeName)) {
handler.ratify(caller, acquire);
} else {
// this is not an error condition, as we may have cancelled the handler or
// allowed another to take priority
}
}
// from interface ClientManager.ClientObserver
public void clientSessionDidStart (PresentsClient client)
{
// if this is another peer, don't publish their info
if (client instanceof PeerClient) {
return;
}
// create and publish a ClientInfo record for this client
ClientInfo clinfo = createClientInfo();
initClientInfo(client, clinfo);
// sanity check
if (_nodeobj.clients.contains(clinfo)) {
log.warning("Received clientSessionDidStart() for already registered client!? " +
"[old=" + _nodeobj.clients.get(clinfo.getKey()) + ", new=" + clinfo + "].");
// go ahead and update the record
_nodeobj.updateClients(clinfo);
} else {
_nodeobj.addToClients(clinfo);
}
}
// from interface ClientManager.ClientObserver
public void clientSessionDidEnd (PresentsClient client)
{
// if this is another peer, don't worry about it
if (client instanceof PeerClient) {
return;
}
// we scan through the list instead of relying on ClientInfo.getKey() because we want
// derived classes to be able to override that for lookups that happen way more frequently
// than logging off
Name username = client.getCredentials().getUsername();
for (ClientInfo clinfo : _nodeobj.clients) {
if (clinfo.username.equals(username)) {
clearClientInfo(client, clinfo);
return;
}
}
log.warning("Session ended for unregistered client [who=" + username + "].");
}
/**
* Called after we have finished our initialization.
*/