Finished up session termination processing; added code to track
subscriptions and clear them out when the client disconnects. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@189 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -3,7 +3,7 @@ Cher Notes -*- outline -*-
|
|||||||
* TODO
|
* TODO
|
||||||
Pass cause back to client somehow via FailureResponse in Client.requestFailed
|
Pass cause back to client somehow via FailureResponse in Client.requestFailed
|
||||||
|
|
||||||
Implement object destroyed; finish wiring up oid list tracking.
|
Finish wiring up oid list tracking.
|
||||||
|
|
||||||
Ensure at time of OBJECT_ADDED that the object being added exists and has
|
Ensure at time of OBJECT_ADDED that the object being added exists and has
|
||||||
not been destroyed.
|
not been destroyed.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ClientManager.java,v 1.9 2001/08/04 01:54:34 mdb Exp $
|
// $Id: ClientManager.java,v 1.10 2001/08/07 21:20:48 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server;
|
package com.threerings.cocktail.cher.server;
|
||||||
|
|
||||||
@@ -140,7 +140,9 @@ public class ClientManager implements ConnectionObserver
|
|||||||
if (client != null) {
|
if (client != null) {
|
||||||
Log.info("Unmapped failed client [client=" + client +
|
Log.info("Unmapped failed client [client=" + client +
|
||||||
", conn=" + conn + ", fault=" + fault + "].");
|
", conn=" + conn + ", fault=" + fault + "].");
|
||||||
// let the client know things went haywire
|
// let the client know the connection went away
|
||||||
|
client.wasUnmapped();
|
||||||
|
// and let the client know things went haywire
|
||||||
client.connectionFailed(fault);
|
client.connectionFailed(fault);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -161,6 +163,9 @@ public class ClientManager implements ConnectionObserver
|
|||||||
if (client != null) {
|
if (client != null) {
|
||||||
Log.info("Unmapped client [client=" + client +
|
Log.info("Unmapped client [client=" + client +
|
||||||
", conn=" + conn + "].");
|
", conn=" + conn + "].");
|
||||||
|
// let the client know the connection went away
|
||||||
|
client.wasUnmapped();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.info("Closed unmapped connection? [conn=" + conn + "].");
|
Log.info("Closed unmapped connection? [conn=" + conn + "].");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
//
|
//
|
||||||
// $Id: PresentsClient.java,v 1.15 2001/08/04 03:26:00 mdb Exp $
|
// $Id: PresentsClient.java,v 1.16 2001/08/07 21:20:48 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server;
|
package com.threerings.cocktail.cher.server;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
import com.threerings.cocktail.cher.Log;
|
import com.threerings.cocktail.cher.Log;
|
||||||
import com.threerings.cocktail.cher.data.ClientObject;
|
import com.threerings.cocktail.cher.data.ClientObject;
|
||||||
import com.threerings.cocktail.cher.dobj.*;
|
import com.threerings.cocktail.cher.dobj.*;
|
||||||
import com.threerings.cocktail.cher.net.*;
|
import com.threerings.cocktail.cher.net.*;
|
||||||
import com.threerings.cocktail.cher.server.net.*;
|
import com.threerings.cocktail.cher.server.net.*;
|
||||||
|
import com.threerings.cocktail.cher.util.IntMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client object represents a client session in the server. It is
|
* A client object represents a client session in the server. It is
|
||||||
@@ -116,36 +119,18 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
|
|
||||||
// we need to get onto the distributed object thread so that we
|
// we need to get onto the distributed object thread so that we
|
||||||
// can finalize the resumption of the session. we do so by
|
// can finalize the resumption of the session. we do so by
|
||||||
// subscribing to the client object (to which we are normally not
|
// posting a special event
|
||||||
// subscribed in between active connections)
|
DEvent event = new DEvent(0)
|
||||||
Subscriber sub = new Subscriber() {
|
{
|
||||||
public void objectAvailable (DObject dobj)
|
public boolean applyToObject (DObject target)
|
||||||
{
|
{
|
||||||
// we don't want to continue to be subscribed to the
|
|
||||||
// client object so we remove our subscription
|
|
||||||
dobj.removeSubscriber(this);
|
|
||||||
// now that we're on the dobjmgr thread we can resume our
|
// now that we're on the dobjmgr thread we can resume our
|
||||||
// session resumption
|
// session resumption
|
||||||
finishResumeSession();
|
finishResumeSession();
|
||||||
}
|
|
||||||
|
|
||||||
public void requestFailed (int oid, ObjectAccessException cause)
|
|
||||||
{
|
|
||||||
Log.warning("Not able to subscribe to client object and " +
|
|
||||||
"resume session!? [client=" + CherClient.this +
|
|
||||||
", cause=" + cause + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleEvent (DEvent event, DObject target)
|
|
||||||
{
|
|
||||||
Log.warning("Resuming subscriber received an event!? " +
|
|
||||||
"[client=" + CherClient.this +
|
|
||||||
", event=" + event + "].");
|
|
||||||
// we shouldn't have been subscribed in the first place
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CherServer.omgr.subscribeToObject(_clobj.getOid(), sub);
|
CherServer.omgr.postEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,6 +150,78 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
Log.info("Session resumed [client=" + this + "].");
|
Log.info("Session resumed [client=" + this + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the client session be terminated. This is normally
|
||||||
|
* invoked as a result of a logoff request by the client. It should
|
||||||
|
* only be invoked from the conmgr thread.
|
||||||
|
*/
|
||||||
|
public void endSession ()
|
||||||
|
{
|
||||||
|
// close our connection (which results in everything being
|
||||||
|
// properly unregistered)
|
||||||
|
Connection conn = getConnection();
|
||||||
|
if (conn != null) {
|
||||||
|
conn.close();
|
||||||
|
} else {
|
||||||
|
Log.info("Unable to close connection for logoff request " +
|
||||||
|
"[client=" + this + "].");
|
||||||
|
}
|
||||||
|
// then let the client manager know what's up
|
||||||
|
_cmgr.clientDidEndSession(this);
|
||||||
|
|
||||||
|
// we need to get onto the distributed object thread so that we
|
||||||
|
// can finalize the ending of the session. we do so by posting a
|
||||||
|
// special event
|
||||||
|
DEvent event = new DEvent(0)
|
||||||
|
{
|
||||||
|
public boolean applyToObject (DObject target)
|
||||||
|
{
|
||||||
|
// now that we're on the dobjmgr thread we can call into
|
||||||
|
// our derived classes to finish the session termination
|
||||||
|
sessionDidTerminate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CherServer.omgr.postEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a note that this client is subscribed to this object so that
|
||||||
|
* we can clean up after ourselves if and when the client goes
|
||||||
|
* away. This is called by the client internals and needn't be called
|
||||||
|
* by code outside the client.
|
||||||
|
*/
|
||||||
|
public synchronized void mapSubscrip (DObject object)
|
||||||
|
{
|
||||||
|
_subscrips.put(object.getOid(), object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a note that this client is no longer subscribed to this
|
||||||
|
* object. The subscription map is used to clean up after the client
|
||||||
|
* when it goes away. This is called by the client internals and
|
||||||
|
* needn't be called by code outside the client.
|
||||||
|
*/
|
||||||
|
public synchronized void unmapSubscrip (int oid)
|
||||||
|
{
|
||||||
|
_subscrips.remove(oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears out the tracked client subscriptions. Called when the client
|
||||||
|
* goes away and shouldn't be called otherwise.
|
||||||
|
*/
|
||||||
|
protected synchronized void clearSubscrips ()
|
||||||
|
{
|
||||||
|
Enumeration enum = _subscrips.elements();
|
||||||
|
while (enum.hasMoreElements()) {
|
||||||
|
DObject object = (DObject)enum.nextElement();
|
||||||
|
// Log.info("Clearing subscription [client=" + this +
|
||||||
|
// ", obj=" + object + "].");
|
||||||
|
object.removeSubscriber(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the client session is first started. The client object
|
* Called when the client session is first started. The client object
|
||||||
* has been created at this point and after this method is executed,
|
* has been created at this point and after this method is executed,
|
||||||
@@ -208,6 +265,8 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
*/
|
*/
|
||||||
protected void sessionDidTerminate ()
|
protected void sessionDidTerminate ()
|
||||||
{
|
{
|
||||||
|
// destroy the client object
|
||||||
|
CherServer.omgr.destroyObject(_clobj.getOid());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,15 +315,46 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
data.invOid = CherServer.invmgr.getOid();
|
data.invOid = CherServer.invmgr.getOid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the connection manager when this client's connection is
|
||||||
|
* unmapped. That may be because of a connection failure (in which
|
||||||
|
* case this call will be followed up by a call to
|
||||||
|
* <code>connectionFailed</code>) or it may be because of an orderly
|
||||||
|
* closing of the connection. In either case, the client can deal with
|
||||||
|
* its lack of a connection in this method. This is invoked by the
|
||||||
|
* conmgr thread and should behave accordingly.
|
||||||
|
*/
|
||||||
|
protected void wasUnmapped ()
|
||||||
|
{
|
||||||
|
// clear out our connection reference
|
||||||
|
setConnection(null);
|
||||||
|
|
||||||
|
// clear out our subscriptions. we need to do this on the dobjmgr
|
||||||
|
// thread. so we do so by posting a special event. it is important
|
||||||
|
// that we do this *after* we clear out our connection reference.
|
||||||
|
// once the connection ref is null, no more subscriptions will be
|
||||||
|
// processed (even those that were queued up before the connection
|
||||||
|
// went away)
|
||||||
|
DEvent event = new DEvent(0)
|
||||||
|
{
|
||||||
|
public boolean applyToObject (DObject target)
|
||||||
|
{
|
||||||
|
clearSubscrips();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CherServer.omgr.postEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the connection manager when this client's connection
|
* Called by the connection manager when this client's connection
|
||||||
* fails. This is invoked on the conmgr thread, and should behave
|
* fails. This is invoked on the conmgr thread and should behave
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*/
|
*/
|
||||||
protected void connectionFailed (IOException fault)
|
protected void connectionFailed (IOException fault)
|
||||||
{
|
{
|
||||||
// clear out our connection reference
|
// nothing to do here presently. the client manager already
|
||||||
setConnection(null);
|
// complained about the failed connection
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -319,7 +409,11 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
// queue up an object response
|
// queue up an object response
|
||||||
Connection conn = getConnection();
|
Connection conn = getConnection();
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
|
// pass the successful subscrip on to the client
|
||||||
conn.postMessage(new ObjectResponse(object));
|
conn.postMessage(new ObjectResponse(object));
|
||||||
|
// make a note of this new subscription
|
||||||
|
mapSubscrip(object);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.info("Dropped object available notification " +
|
Log.info("Dropped object available notification " +
|
||||||
"[client=" + this + ", oid=" + object.getOid() + "].");
|
"[client=" + this + ", oid=" + object.getOid() + "].");
|
||||||
@@ -404,6 +498,8 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
", oid=" + req.getOid() + "].");
|
", oid=" + req.getOid() + "].");
|
||||||
// forward the unsubscribe request to the omgr for processing
|
// forward the unsubscribe request to the omgr for processing
|
||||||
CherServer.omgr.unsubscribeFromObject(req.getOid(), client);
|
CherServer.omgr.unsubscribeFromObject(req.getOid(), client);
|
||||||
|
// update our subscription tracking table
|
||||||
|
client.unmapSubscrip(req.getOid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,17 +551,8 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
{
|
{
|
||||||
Log.info("Client requested logoff " +
|
Log.info("Client requested logoff " +
|
||||||
"[client=" + client + "].");
|
"[client=" + client + "].");
|
||||||
// close our connection (which results in everything being
|
// request that the client end the session
|
||||||
// properly unregistered)
|
client.endSession();
|
||||||
Connection conn = client.getConnection();
|
|
||||||
if (conn != null) {
|
|
||||||
conn.close();
|
|
||||||
} else {
|
|
||||||
Log.info("Unable to close connection for logoff request " +
|
|
||||||
"[client=" + client + "].");
|
|
||||||
}
|
|
||||||
// then let the client manager know what's up
|
|
||||||
client._cmgr.clientDidEndSession(client);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,6 +560,7 @@ public class CherClient implements Subscriber, MessageHandler
|
|||||||
protected String _username;
|
protected String _username;
|
||||||
protected Connection _conn;
|
protected Connection _conn;
|
||||||
protected ClientObject _clobj;
|
protected ClientObject _clobj;
|
||||||
|
protected IntMap _subscrips = new IntMap();
|
||||||
|
|
||||||
protected static HashMap _disps = new HashMap();
|
protected static HashMap _disps = new HashMap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user