diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index 275b8f255..13d15aaac 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -45,8 +45,6 @@ import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.Credentials; import com.threerings.presents.server.net.AuthingConnection; import com.threerings.presents.server.net.Connection; -import com.threerings.presents.server.net.ConnectionManager; -import com.threerings.presents.server.net.ConnectionObserver; import static com.threerings.presents.Log.log; @@ -61,8 +59,7 @@ import static com.threerings.presents.Log.log; */ @Singleton public class ClientManager - implements ConnectionObserver, ClientResolutionListener, - ReportManager.Reporter, ShutdownManager.Shutdowner + implements ClientResolutionListener, ReportManager.Reporter, ShutdownManager.Shutdowner { /** * Used by {@link ClientManager#applyToClient}. @@ -100,11 +97,8 @@ public class ClientManager /** * Constructs a client manager that will interact with the supplied connection manager. */ - @Inject public ClientManager (ConnectionManager conmgr, ReportManager repmgr, - ShutdownManager shutmgr) + @Inject public ClientManager (ReportManager repmgr, ShutdownManager shutmgr) { - // register as a connection observer, a "state of server" reporter and a shutdowner - conmgr.addConnectionObserver(this); repmgr.registerReporter(this); shutmgr.registerShutdowner(this); @@ -367,7 +361,9 @@ public class ClientManager _penders.remove(username); } - // from interface ConnectionObserver + /** + * Called by the connection manager to let us know when a new connection has been established. + */ public synchronized void connectionEstablished ( Connection conn, AuthRequest req, AuthResponse rsp) { @@ -397,7 +393,9 @@ public class ClientManager _conmap.put(conn, client); } - // from interface ConnectionObserver + /** + * Called by the connection manager to let us know when a connection has failed. + */ public synchronized void connectionFailed (Connection conn, IOException fault) { // remove the client from the connection map @@ -415,7 +413,9 @@ public class ClientManager } } - // from interface ConnectionObserver + /** + * Called by the connection manager to let us know when a connection has been closed. + */ public synchronized void connectionClosed (Connection conn) { // remove the client from the connection map diff --git a/src/java/com/threerings/presents/server/PresentsSession.java b/src/java/com/threerings/presents/server/PresentsSession.java index 4b5440fd4..1543d6190 100644 --- a/src/java/com/threerings/presents/server/PresentsSession.java +++ b/src/java/com/threerings/presents/server/PresentsSession.java @@ -734,15 +734,19 @@ public class PresentsSession // clear out our connection reference setConnection(null); - // clear out our subscriptions. we need to do this on the dobjmgr thread. 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) - _omgr.postRunnable(new Runnable() { - public void run () { - sessionConnectionClosed(); - } - }); + // if we are being closed after the omgr has shutdown, then just stop here; the whole world + // is about to come to a screeching halt anyway + if (_omgr.isRunning()) { + // clear out our subscriptions: we need to do this on the dobjmgr thread. 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) + _omgr.postRunnable(new Runnable() { + public void run () { + sessionConnectionClosed(); + } + }); + } } /** diff --git a/src/java/com/threerings/presents/server/net/ConnectionManager.java b/src/java/com/threerings/presents/server/net/ConnectionManager.java index c65944c9c..512bf2208 100644 --- a/src/java/com/threerings/presents/server/net/ConnectionManager.java +++ b/src/java/com/threerings/presents/server/net/ConnectionManager.java @@ -25,7 +25,6 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; @@ -41,7 +40,6 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -68,6 +66,7 @@ import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.Message; import com.threerings.presents.server.Authenticator; import com.threerings.presents.server.ChainedAuthenticator; +import com.threerings.presents.server.ClientManager; import com.threerings.presents.server.DummyAuthenticator; import com.threerings.presents.server.PresentsDObjectMgr; import com.threerings.presents.server.ReportManager; @@ -162,29 +161,6 @@ public class ConnectionManager extends LoopingThread return (ConMgrStats)_stats.clone(); } - /** - * Adds the specified connection observer to the observers list. Connection observers will be - * notified of connection-related events. An observer will not be added to the list twice. - * - * @see ConnectionObserver - */ - public void addConnectionObserver (ConnectionObserver observer) - { - synchronized (_observers) { - _observers.add(observer); - } - } - - /** - * Removes the specified connection observer from the observers list. - */ - public void removeConnectionObserver (ConnectionObserver observer) - { - synchronized (_observers) { - _observers.remove(observer); - } - } - /** * Opens an outgoing connection to the supplied address. The connection will be opened in a * non-blocking manner and added to the connection manager's select set. Messages posted to the @@ -350,31 +326,6 @@ public class ConnectionManager extends LoopingThread } } - /** - * Notifies the connection observers of a connection event. Used internally. - */ - protected void notifyObservers ( - int code, Connection conn, Object arg1, Object arg2) - { - synchronized (_observers) { - for (ConnectionObserver obs : _observers) { - switch (code) { - case CONNECTION_ESTABLISHED: - obs.connectionEstablished(conn, (AuthRequest)arg1, (AuthResponse)arg2); - break; - case CONNECTION_FAILED: - obs.connectionFailed(conn, (IOException)arg1); - break; - case CONNECTION_CLOSED: - obs.connectionClosed(conn); - break; - default: - throw new RuntimeException("Invalid code supplied to notifyObservers: " + code); - } - } - } - } - @Override protected void willStart () { @@ -497,9 +448,9 @@ public class ConnectionManager extends LoopingThread @Override protected void iterate () { - long iterStamp = System.currentTimeMillis(); + final long iterStamp = System.currentTimeMillis(); - // note whether or not we're generating + // note whether or not we're generating a debug report boolean generateDebugReport = (iterStamp - _lastDebugStamp > DEBUG_REPORT_INTERVAL); if (DEBUG_REPORT && generateDebugReport) { _lastDebugStamp = iterStamp; @@ -515,12 +466,6 @@ public class ConnectionManager extends LoopingThread } } - // start up any outgoing connections that need to be connected - Tuple pconn; - while ((pconn = _connectq.getNonBlocking()) != null) { - startOutgoingConnection(pconn.left, pconn.right); - } - // close connections that have had no network traffic for too long for (NetEventHandler handler : _handlers.values()) { if (handler.checkIdle(iterStamp)) { @@ -532,11 +477,17 @@ public class ConnectionManager extends LoopingThread // send any messages that are waiting on the outgoing overflow and message queues sendOutgoingMessages(iterStamp); - // if we have been shutdown, but we're still around because the DObjectManager is still - // running (and we want to deliver any outgoing events queued up during shutdown), then we - // don't process authenticated connections or read incoming network events; the only thing - // we want to do during the shutdown phase is send outgoing messages to existing clients + // we may be in the middle of shutting down (in which case super.isRunning() is false but + // isRunning() is true); this is because we stick around until the dobject manager is + // totally done so that we can send shutdown-related events out to our clients; during + // those last moments we don't want to accept new connections or read any incoming messages if (super.isRunning()) { + // start up any outgoing connections that need to be connected + Tuple pconn; + while ((pconn = _connectq.getNonBlocking()) != null) { + startOutgoingConnection(pconn.left, pconn.right); + } + // check for connections that have completed authentication processAuthedConnections(iterStamp); @@ -551,7 +502,7 @@ public class ConnectionManager extends LoopingThread /** * Converts connections that have completed the authentication process into full running - * connections and notifies observers that a new connection has been established. + * connections and notifies the client manager that new connections have been established. */ protected void processAuthedConnections (long iterStamp) { @@ -581,9 +532,8 @@ public class ConnectionManager extends LoopingThread _oflowqs.put(rconn, oflowHandler); } - // and let our observers know about our new connection - notifyObservers(CONNECTION_ESTABLISHED, rconn, - conn.getAuthRequest(), conn.getAuthResponse()); + // and let the client manager know about our new connection + _clmgr.connectionEstablished(rconn, conn.getAuthRequest(), conn.getAuthResponse()); } catch (IOException ioe) { log.warning("Failure upgrading authing connection to running.", ioe); @@ -1028,8 +978,8 @@ public class ConnectionManager extends LoopingThread _stats.disconnects++; } - // let our observers know what's up - notifyObservers(CONNECTION_FAILED, conn, ioe, null); + // let the client manager know what's up + _clmgr.connectionFailed(conn, ioe); } /** @@ -1046,8 +996,8 @@ public class ConnectionManager extends LoopingThread _stats.closes++; } - // let our observers know what's up - notifyObservers(CONNECTION_CLOSED, conn, null, null); + // let the client manager know what's up + _clmgr.connectionClosed(conn); } @Override @@ -1236,7 +1186,6 @@ public class ConnectionManager extends LoopingThread protected ByteBuffer _databuf = ByteBuffer.allocateDirect(Client.MAX_DATAGRAM_SIZE); protected Map _oflowqs = Maps.newHashMap(); - protected List _observers = Lists.newArrayList(); /** Our current runtime stats. */ protected ConMgrStats _stats; @@ -1253,6 +1202,7 @@ public class ConnectionManager extends LoopingThread // some dependencies @Inject @AuthInvoker protected Invoker _authInvoker; @Inject protected PresentsDObjectMgr _omgr; + @Inject protected ClientManager _clmgr; @Inject protected ShutdownManager _shutmgr; /** How long we wait for network events before checking our running flag to see if we should @@ -1261,11 +1211,6 @@ public class ConnectionManager extends LoopingThread * the queue. */ protected static final int SELECT_LOOP_TIME = 100; - // codes for notifyObservers() - protected static final int CONNECTION_ESTABLISHED = 0; - protected static final int CONNECTION_FAILED = 1; - protected static final int CONNECTION_CLOSED = 2; - /** Used to denote asynchronous close requests. */ protected static final byte[] ASYNC_CLOSE_REQUEST = new byte[0]; diff --git a/src/java/com/threerings/presents/server/net/ConnectionObserver.java b/src/java/com/threerings/presents/server/net/ConnectionObserver.java deleted file mode 100644 index 9661fb20e..000000000 --- a/src/java/com/threerings/presents/server/net/ConnectionObserver.java +++ /dev/null @@ -1,69 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.presents.server.net; - -import java.io.IOException; - -import com.threerings.presents.net.AuthRequest; -import com.threerings.presents.net.AuthResponse; - -/** - * A connection observer can be registered with the connection manager to - * hear about new connections and to be notified when connections fail or - * are closed. Only fully authenticated connections will be passed on to - * the connection observer. Connections that fail to authenticate will be - * handled entirely within the confines of the connection manager. - * - * @see ConnectionManager - * @see Connection - */ -public interface ConnectionObserver -{ - /** - * Called when a new connection is established with the connection - * manager. Only fully authenticated connections will be passed on to - * the connection observer. - * - * @param conn The newly established connection. - * @param req The auth request provided by the client. - * @param rsp The auth response provided to the client. - */ - void connectionEstablished (Connection conn, AuthRequest req, AuthResponse rsp); - - /** - * Called if a connection fails for any reason. If a connection fails, - * connectionClosed will not be called. This call to - * connectionFailed is the last the observers will hear - * about it. - * - * @param conn The connection in that failed. - * @param fault The exception associated with the failure. - */ - void connectionFailed (Connection conn, IOException fault); - - /** - * Called when a connection has been closed in an orderly manner. - * - * @param conn The recently closed connection. - */ - void connectionClosed (Connection conn); -}