From 7688865b9642290ba71c1ecf06b99127c5eb56ae Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sat, 4 Aug 2001 01:54:34 +0000 Subject: [PATCH] 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 --- docs/presents/notes.txt | 2 + .../presents/server/ClientManager.java | 4 +- .../presents/server/PresentsClient.java | 142 ++++++++++++++---- 3 files changed, 114 insertions(+), 34 deletions(-) diff --git a/docs/presents/notes.txt b/docs/presents/notes.txt index 8eceac251..00a225bf4 100644 --- a/docs/presents/notes.txt +++ b/docs/presents/notes.txt @@ -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 diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index 63839fa46..4c8fdc671 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -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 " + diff --git a/src/java/com/threerings/presents/server/PresentsClient.java b/src/java/com/threerings/presents/server/PresentsClient.java index 440418ab4..1fe113b90 100644 --- a/src/java/com/threerings/presents/server/PresentsClient.java +++ b/src/java/com/threerings/presents/server/PresentsClient.java @@ -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 - * super.sessionWillStart(). + * this method should be sure to call + * super.sessionWillStart. + * + *

Note: 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 - * super.sessionWillResume(). + * method should be sure to call super.sessionWillResume. + * + *

Note: 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 + * super.sessionDidTerminate. + * + *

Note: 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 super.populateBootstrapData() before doing their + * call super.populateBootstrapData before doing their * own populating, however. + * + *

Note: 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;