Modified client internals to ensure that sessionWillStart(),

sessionWillResume() and sendBootstrapData() are all consistently called on
the dobjmgr thread because that is the most useful. Added
sessionDidTerminate() but session termination is not implemented yet.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@177 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-08-04 01:54:34 +00:00
parent 42967815e1
commit 7688865b96
3 changed files with 114 additions and 34 deletions
+2
View File
@@ -12,6 +12,8 @@ clientWillLogff becomes clientMayLogoff?
Look into nbio waking up all sockets when any data comes in.
Wire up Client.sessionDidTerminate; do session termination in general.
* Server-side event concentrator
The client objects will not subscribe directly, but will subscribe through
the concentrator so that, at least, it can create a single
@@ -1,5 +1,5 @@
//
// $Id: ClientManager.java,v 1.8 2001/08/03 02:25:49 mdb Exp $
// $Id: ClientManager.java,v 1.9 2001/08/04 01:54:34 mdb Exp $
package com.threerings.cocktail.cher.server;
@@ -109,7 +109,7 @@ public class ClientManager implements ConnectionObserver
// create a new client and stick'em in the table
try {
client = (CherClient)_clientClass.newInstance();
client.init(this, username, conn);
client.startSession(this, username, conn);
_usermap.put(username, client);
} catch (Exception e) {
Log.warning("Failed to instantiate client instance to " +
@@ -1,5 +1,5 @@
//
// $Id: PresentsClient.java,v 1.13 2001/08/03 02:25:49 mdb Exp $
// $Id: PresentsClient.java,v 1.14 2001/08/04 01:54:34 mdb Exp $
package com.threerings.cocktail.cher.server;
@@ -29,10 +29,27 @@ import com.threerings.cocktail.cher.server.net.*;
public class CherClient implements Subscriber, MessageHandler
{
/**
* Initializes this client instance with the specified username and
* connection instance.
* Returns the username with which this client instance is associated.
*/
public void init (ClientManager cmgr, String username, Connection conn)
public String getUsername ()
{
return _username;
}
/**
* Returns the client object that is associated with this client.
*/
public ClientObject getClientObject ()
{
return _clobj;
}
/**
* Initializes this client instance with the specified username and
* connection instance and begins a client session.
*/
protected void startSession (
ClientManager cmgr, String username, Connection conn)
{
_cmgr = cmgr;
_username = username;
@@ -44,7 +61,7 @@ public class CherClient implements Subscriber, MessageHandler
{
public void objectAvailable (DObject object)
{
_clobj = (ClientObject)object;
setClientObject((ClientObject)object);
sessionWillStart();
sendBootstrap();
}
@@ -66,19 +83,13 @@ public class CherClient implements Subscriber, MessageHandler
}
/**
* Returns the username with which this client instance is associated.
* Called when we receive our client object from the dobjmgr. We go
* through this synchronized method to ensure that the client object
* is visible to the conmgr.
*/
public String getUsername ()
protected synchronized void setClientObject (ClientObject clobj)
{
return _username;
}
/**
* Returns the client object that is associated with this client.
*/
public ClientObject getClientObject ()
{
return _clobj;
_clobj = clobj;
}
/**
@@ -86,7 +97,7 @@ public class CherClient implements Subscriber, MessageHandler
* authenticates as this already established client. This must only be
* called from the congmr thread.
*/
public void resumeSession (Connection conn)
protected void resumeSession (Connection conn)
{
Connection oldconn = getConnection();
@@ -103,6 +114,18 @@ public class CherClient implements Subscriber, MessageHandler
// start using the new connection
setConnection(conn);
// we need to queue up an event so that we can finalize the
// resumption of the session on the dobjmgr thread
CherServer.omgr.postEvent(new ResumeSessionEvent(_clobj.getOid()));
}
/**
* This is called from the dobjmgr thread to complete the session
* resumption. We call some call backs and send the bootstrap info to
* the client.
*/
protected void finishResumeSession ()
{
// let derived classes do any session resuming
sessionWillResume();
@@ -118,8 +141,12 @@ public class CherClient implements Subscriber, MessageHandler
* has been created at this point and after this method is executed,
* the bootstrap information will be sent to the client which will
* trigger the start of the session. Derived classes that override
* this function should be sure to call
* <code>super.sessionWillStart()</code>.
* this method should be sure to call
* <code>super.sessionWillStart</code>.
*
* <p><em>Note:</em> This function will be called on the dobjmgr
* thread which means that object manipulations are OK, but client
* instance manipulations must done carefully.
*/
protected void sessionWillStart ()
{
@@ -130,13 +157,30 @@ public class CherClient implements Subscriber, MessageHandler
* and reconnected). After this method is executed, the bootstrap
* information will be sent to the client which will trigger the
* resumption of the session. Derived classes that override this
* function should be sure to call
* <code>super.sessionWillResume()</code>.
* method should be sure to call <code>super.sessionWillResume</code>.
*
* <p><em>Note:</em> This function will be called on the dobjmgr
* thread which means that object manipulations are OK, but client
* instance manipulations must done carefully.
*/
protected void sessionWillResume ()
{
}
/**
* Called when the client session ends (either because the client
* logged off or because the server forcibly terminated the session).
* Derived classes that override this method should be sure to call
* <code>super.sessionDidTerminate</code>.
*
* <p><em>Note:</em> This function will be called on the dobjmgr
* thread which means that object manipulations are OK, but client
* instance manipulations must done carefully.
*/
protected void sessionDidTerminate ()
{
}
/**
* This is called once we have a handle on the client distributed
* object. It sends a bootstrap notification to the client with all
@@ -167,8 +211,12 @@ public class CherClient implements Subscriber, MessageHandler
/**
* Derived client classes can override this member to populate the
* bootstrap data with additional information. They should be sure to
* call <code>super.populateBootstrapData()</code> before doing their
* call <code>super.populateBootstrapData</code> before doing their
* own populating, however.
*
* <p><em>Note:</em> This function will be called on the dobjmgr
* thread which means that object manipulations are OK, but client
* instance manipulations must done carefully.
*/
protected void populateBootstrapData (BootstrapData data)
{
@@ -184,12 +232,17 @@ public class CherClient implements Subscriber, MessageHandler
* fails. This is invoked on the conmgr thread, and should behave
* accordingly.
*/
public void connectionFailed (IOException fault)
protected void connectionFailed (IOException fault)
{
// clear out our connection reference
setConnection(null);
}
/**
* Sets our connection reference in a thread safe way. Also
* establishes the back reference to us as the connection's message
* handler.
*/
protected synchronized void setConnection (Connection conn)
{
// keep a handle to the new connection
@@ -260,17 +313,24 @@ public class CherClient implements Subscriber, MessageHandler
// documentation inherited from interface
public boolean handleEvent (DEvent event, DObject target)
{
// forward the event to the client
Connection conn = getConnection();
if (conn != null) {
// only typed events will be forwarded to the client, so we
// need not worry that a non-typed event would make it here
TypedEvent tevent = (TypedEvent)event;
conn.postMessage(new EventNotification(tevent));
if (event instanceof ResumeSessionEvent) {
finishResumeSession();
} else {
Log.info("Dropped event forward notification " +
"[client=" + this + ", event=" + event + "].");
// forward the event to the client
Connection conn = getConnection();
if (conn != null) {
// only typed events will be forwarded to the client, so
// we need not worry that a non-typed event would make it
// here
TypedEvent tevent = (TypedEvent)event;
conn.postMessage(new EventNotification(tevent));
} else {
Log.info("Dropped event forward notification " +
"[client=" + this + ", event=" + event + "].");
}
}
return true;
}
@@ -386,6 +446,24 @@ public class CherClient implements Subscriber, MessageHandler
}
}
/**
* Used to inject ourselves onto the dobjmgr thread.
*/
protected static class ResumeSessionEvent extends DEvent
{
public ResumeSessionEvent (int oid)
{
super(oid);
}
public boolean applyToObject (DObject target)
throws ObjectAccessException
{
// nothing to do here and don't tell our subscribers
return false;
}
}
protected ClientManager _cmgr;
protected String _username;
protected Connection _conn;