Finished up the basic peer system and wired up the tell forwarding. In theory
it all works, now to test it. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4249 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -35,8 +35,11 @@ import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientObserver;
|
||||
import com.threerings.presents.dobj.ObjectAccessException;
|
||||
import com.threerings.presents.dobj.Subscriber;
|
||||
import com.threerings.presents.server.ClientManager;
|
||||
import com.threerings.presents.server.PresentsClient;
|
||||
import com.threerings.presents.server.PresentsServer;
|
||||
|
||||
import com.threerings.presents.peer.data.ClientInfo;
|
||||
import com.threerings.presents.peer.data.NodeObject;
|
||||
import com.threerings.presents.peer.net.PeerBootstrapData;
|
||||
import com.threerings.presents.peer.net.PeerCreds;
|
||||
@@ -52,6 +55,7 @@ import static com.threerings.presents.Log.log;
|
||||
* communicate cross-node information.
|
||||
*/
|
||||
public class PeerManager
|
||||
implements ClientManager.ClientObserver
|
||||
{
|
||||
/**
|
||||
* Creates a peer manager which will create a {@link NodeRepository} which
|
||||
@@ -124,6 +128,9 @@ public class PeerManager
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
// clear out our client observer registration
|
||||
PresentsServer.clmgr.removeClientObserver(this);
|
||||
|
||||
// TODO: clear our record from the node table
|
||||
for (PeerNode peer : _peers.values()) {
|
||||
peer.shutdown();
|
||||
@@ -139,6 +146,43 @@ public class PeerManager
|
||||
creds.getNodeName(), _sharedSecret).equals(creds.getPassword());
|
||||
}
|
||||
|
||||
// documentation inherited from interface ClientManager.ClientObserver
|
||||
public void clientSessionDidStart (PresentsClient client)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// we create a new client info for this client so that we can support
|
||||
// derived classes overriding the value we use for the DSet key
|
||||
ClientInfo clinfo = createClientInfo();
|
||||
initClientInfo(client, clinfo);
|
||||
|
||||
// sanity check
|
||||
if (!_nodeobj.clients.containsKey(clinfo.getKey())) {
|
||||
log.warning("Session ended for unregistered client " +
|
||||
"[info=" + clinfo + "].");
|
||||
} else {
|
||||
_nodeobj.removeFromClients(clinfo.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once our node object is available.
|
||||
*/
|
||||
@@ -161,6 +205,9 @@ public class PeerManager
|
||||
}
|
||||
});
|
||||
|
||||
// register ourselves as a client observer
|
||||
PresentsServer.clmgr.addClientObserver(this);
|
||||
|
||||
// and start our peer refresh interval (this need not use a runqueue as
|
||||
// all it will do is post an invoker unit)
|
||||
new Interval() {
|
||||
@@ -226,6 +273,23 @@ public class PeerManager
|
||||
return NodeObject.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientInfo} record which will subsequently be
|
||||
* initialized by a call to {@link #initClientInfo}.
|
||||
*/
|
||||
protected ClientInfo createClientInfo ()
|
||||
{
|
||||
return new ClientInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the supplied client info for the supplied client.
|
||||
*/
|
||||
protected void initClientInfo (PresentsClient client, ClientInfo info)
|
||||
{
|
||||
info.username = client.getCredentials().getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all runtime information for one of our peer nodes.
|
||||
*/
|
||||
@@ -242,6 +306,11 @@ public class PeerManager
|
||||
_client.addClientObserver(this);
|
||||
}
|
||||
|
||||
public Client getClient ()
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
|
||||
public void refresh (NodeRecord record)
|
||||
{
|
||||
// if the hostname of this node changed, kill our existing client
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.Interval;
|
||||
import com.samskivert.util.ObserverList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
@@ -70,6 +71,25 @@ public class ClientManager
|
||||
public void resolutionFailed (Exception e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by entites that wish to track when clients initiate and end
|
||||
* sessions on this server.
|
||||
*/
|
||||
public static interface ClientObserver
|
||||
{
|
||||
/**
|
||||
* Called when a client has authenticated and been resolved and has
|
||||
* started their session.
|
||||
*/
|
||||
public void clientSessionDidStart (PresentsClient client);
|
||||
|
||||
/**
|
||||
* Called when a client has logged off or been forcibly logged off due
|
||||
* to inactivity and has thus ended their session.
|
||||
*/
|
||||
public void clientSessionDidEnd (PresentsClient client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a client manager that will interact with the supplied
|
||||
* connection manager.
|
||||
@@ -161,6 +181,24 @@ public class ClientManager
|
||||
return _objmap.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an observer that will be notified when clients start and end
|
||||
* their sessions.
|
||||
*/
|
||||
public void addClientObserver (ClientObserver observer)
|
||||
{
|
||||
_clobservers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an observer previously registered with {@link
|
||||
* #addClientObserver}.
|
||||
*/
|
||||
public void removeClientObserver (ClientObserver observer)
|
||||
{
|
||||
_clobservers.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client instance that manages the client session for the
|
||||
* specified authentication username or null if that client is not
|
||||
@@ -372,15 +410,31 @@ public class ClientManager
|
||||
report.append("- Mapped users: ").append(_objmap.size()).append("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client instance when it has started its session. This is
|
||||
* called from the dobjmgr thread.
|
||||
*/
|
||||
protected void clientSessionDidStart (final PresentsClient client)
|
||||
{
|
||||
// let the observers know
|
||||
_clobservers.apply(new ObserverList.ObserverOp<ClientObserver>() {
|
||||
public boolean apply (ClientObserver observer) {
|
||||
observer.clientSessionDidStart(client);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client instance when the client requests a logoff.
|
||||
* This is called from the conmgr thread.
|
||||
*/
|
||||
synchronized void clientDidEndSession (PresentsClient client)
|
||||
protected synchronized void clientSessionDidEnd (
|
||||
final PresentsClient client)
|
||||
{
|
||||
// remove the client from the username map
|
||||
Credentials creds = client.getCredentials();
|
||||
PresentsClient rc = _usermap.remove(creds.getUsername());
|
||||
PresentsClient rc = _usermap.remove(
|
||||
client.getCredentials().getUsername());
|
||||
|
||||
// sanity check just because we can
|
||||
if (rc == null) {
|
||||
@@ -392,6 +446,20 @@ public class ClientManager
|
||||
} else {
|
||||
Log.info("Ending session " + client + ".");
|
||||
}
|
||||
|
||||
// queue up a unit on the dobjmgr thread to notify the client observers
|
||||
// that the session is ended
|
||||
PresentsServer.omgr.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
_clobservers.apply(
|
||||
new ObserverList.ObserverOp<ClientObserver>() {
|
||||
public boolean apply (ClientObserver observer) {
|
||||
observer.clientSessionDidEnd(client);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -484,6 +552,10 @@ public class ClientManager
|
||||
/** The client class in use. */
|
||||
protected ClientFactory _factory = ClientFactory.DEFAULT;
|
||||
|
||||
/** Tracks registered {@link ClientObserver}s. */
|
||||
protected ObserverList<ClientObserver> _clobservers =
|
||||
new ObserverList<ClientObserver>(ObserverList.SAFE_IN_ORDER_NOTIFY);
|
||||
|
||||
/** The frequency with which we check for expired clients. */
|
||||
protected static final long CLIENT_FLUSH_INTERVAL = 60 * 1000L;
|
||||
}
|
||||
|
||||
@@ -340,6 +340,9 @@ public class PresentsClient
|
||||
// finish up our regular business
|
||||
sessionWillStart();
|
||||
sendBootstrap();
|
||||
|
||||
// let the client manager know that we're operational
|
||||
_cmgr.clientSessionDidStart(this);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
@@ -449,7 +452,7 @@ public class PresentsClient
|
||||
}
|
||||
|
||||
// let the client manager know that we're audi 5000
|
||||
_cmgr.clientDidEndSession(this);
|
||||
_cmgr.clientSessionDidEnd(this);
|
||||
|
||||
// clear out the client object so that we know the session is over
|
||||
_clobj = null;
|
||||
|
||||
Reference in New Issue
Block a user