Out with ShutdownManager, in with LifecycleManager which handles both
initialization and shutdown. This will obviate the need for a lot of manual wiring up. ShutdownManager still works and passes through to LifecycleManager, but switching to the new deal is encouraged. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5802 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -43,8 +43,8 @@ import com.threerings.presents.peer.data.ClientInfo;
|
||||
import com.threerings.presents.peer.data.NodeObject;
|
||||
import com.threerings.presents.peer.server.PeerManager;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.LifecycleManager;
|
||||
import com.threerings.presents.server.PresentsDObjectMgr;
|
||||
import com.threerings.presents.server.ShutdownManager;
|
||||
|
||||
import com.threerings.crowd.chat.data.ChatChannel;
|
||||
import com.threerings.crowd.chat.data.ChatCodes;
|
||||
@@ -62,7 +62,7 @@ import static com.threerings.crowd.Log.log;
|
||||
*/
|
||||
@Singleton
|
||||
public abstract class ChatChannelManager
|
||||
implements ChannelSpeakProvider, ShutdownManager.Shutdowner
|
||||
implements ChannelSpeakProvider, LifecycleManager.ShutdownComponent
|
||||
{
|
||||
/**
|
||||
* When a body becomes a member of a channel, this method should be called so that any server
|
||||
@@ -114,7 +114,7 @@ public abstract class ChatChannelManager
|
||||
});
|
||||
}
|
||||
|
||||
// from interface ShutdownManager.Shutdowner
|
||||
// from interface LifecycleManager.Shutdowner
|
||||
public void shutdown ()
|
||||
{
|
||||
// stop our channel closer; always be closing... except now
|
||||
@@ -126,15 +126,14 @@ public abstract class ChatChannelManager
|
||||
* Creates our singleton manager and registers our invocation service.
|
||||
*/
|
||||
@Inject protected ChatChannelManager (PresentsDObjectMgr omgr, InvocationManager invmgr,
|
||||
ShutdownManager shutmgr)
|
||||
LifecycleManager lifemgr)
|
||||
{
|
||||
invmgr.registerDispatcher(new ChannelSpeakDispatcher(this), CrowdCodes.CROWD_GROUP);
|
||||
shutmgr.registerShutdowner(this);
|
||||
lifemgr.addComponent(this);
|
||||
|
||||
// create and start our idle channel closer (always be closing)
|
||||
_closer = new Interval(omgr) {
|
||||
@Override
|
||||
public void expired () {
|
||||
@Override public void expired () {
|
||||
closeIdleChannels();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,8 +32,8 @@ import com.threerings.presents.peer.server.PeerManager;
|
||||
import com.threerings.presents.peer.server.PeerNode;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.LifecycleManager;
|
||||
import com.threerings.presents.server.PresentsSession;
|
||||
import com.threerings.presents.server.ShutdownManager;
|
||||
|
||||
import com.threerings.crowd.chat.client.ChatService;
|
||||
import com.threerings.crowd.chat.data.UserMessage;
|
||||
@@ -51,9 +51,9 @@ public abstract class CrowdPeerManager extends PeerManager
|
||||
/**
|
||||
* Creates an uninitialized peer manager.
|
||||
*/
|
||||
@Inject public CrowdPeerManager (ShutdownManager shutmgr)
|
||||
@Inject public CrowdPeerManager (LifecycleManager lifeMgr)
|
||||
{
|
||||
super(shutmgr);
|
||||
super(lifeMgr);
|
||||
}
|
||||
|
||||
// from interface CrowdPeerProvider
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.samskivert.util.IntMaps;
|
||||
import com.threerings.presents.dobj.RootDObjectManager;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.ShutdownManager;
|
||||
import com.threerings.presents.server.LifecycleManager;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
@@ -48,7 +48,7 @@ import static com.threerings.crowd.Log.log;
|
||||
*/
|
||||
@Singleton
|
||||
public class PlaceRegistry
|
||||
implements ShutdownManager.Shutdowner
|
||||
implements LifecycleManager.ShutdownComponent
|
||||
{
|
||||
/** Used in conjunction with {@link PlaceRegistry#createPlace(PlaceConfig,PreStartupHook)}. */
|
||||
public static interface PreStartupHook
|
||||
@@ -60,9 +60,9 @@ public class PlaceRegistry
|
||||
* Creates and initializes the place registry. This is called by the server during its
|
||||
* initialization phase.
|
||||
*/
|
||||
@Inject public PlaceRegistry (ShutdownManager shutmgr)
|
||||
@Inject public PlaceRegistry (LifecycleManager lifemgr)
|
||||
{
|
||||
shutmgr.registerShutdowner(this);
|
||||
lifemgr.addComponent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +155,7 @@ public class PlaceRegistry
|
||||
return _pmgrs.values().iterator();
|
||||
}
|
||||
|
||||
// from interface ShutdownManager.Shutdowner
|
||||
// from interface LifecycleManager.ShutdownComponent
|
||||
public void shutdown ()
|
||||
{
|
||||
// shut down all active places
|
||||
|
||||
@@ -65,10 +65,10 @@ import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.ClientManager;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.PresentsSession;
|
||||
import com.threerings.presents.server.LifecycleManager;
|
||||
import com.threerings.presents.server.PresentsDObjectMgr;
|
||||
import com.threerings.presents.server.PresentsSession;
|
||||
import com.threerings.presents.server.ReportManager;
|
||||
import com.threerings.presents.server.ShutdownManager;
|
||||
import com.threerings.presents.server.net.ConnectionManager;
|
||||
|
||||
import com.threerings.presents.peer.client.PeerService;
|
||||
@@ -86,7 +86,7 @@ import static com.threerings.presents.Log.log;
|
||||
* servers and uses those objects to communicate cross-node information.
|
||||
*/
|
||||
public abstract class PeerManager
|
||||
implements PeerProvider, ClientManager.ClientObserver, ShutdownManager.Shutdowner
|
||||
implements PeerProvider, ClientManager.ClientObserver, LifecycleManager.ShutdownComponent
|
||||
{
|
||||
/**
|
||||
* Used by entities that wish to know when cached data has become stale due to a change on
|
||||
@@ -198,9 +198,9 @@ public abstract class PeerManager
|
||||
/**
|
||||
* Creates an uninitialized peer manager.
|
||||
*/
|
||||
@Inject public PeerManager (ShutdownManager shutmgr)
|
||||
@Inject public PeerManager (LifecycleManager lifeMgr)
|
||||
{
|
||||
shutmgr.registerShutdowner(this);
|
||||
lifeMgr.addComponent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -753,7 +753,7 @@ public abstract class PeerManager
|
||||
return _stats.clone();
|
||||
}
|
||||
|
||||
// from interface ShutdownManager.Shutdowner
|
||||
// from interface LifecycleManager.ShutdownComponent
|
||||
public void shutdown ()
|
||||
{
|
||||
if (_nodeName == null) { // sanity check
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class AbstractSignalHandler
|
||||
protected void termReceived ()
|
||||
{
|
||||
log.info("Shutdown initiated by TERM signal.");
|
||||
_shutmgr.queueShutdown();
|
||||
_lifemgr.queueShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ public abstract class AbstractSignalHandler
|
||||
protected void intReceived ()
|
||||
{
|
||||
log.info("Shutdown initiated by INT signal.");
|
||||
_shutmgr.queueShutdown();
|
||||
_lifemgr.queueShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +72,6 @@ public abstract class AbstractSignalHandler
|
||||
log.info(_repmgr.generateReport(ReportManager.DEFAULT_TYPE));
|
||||
}
|
||||
|
||||
@Inject protected ShutdownManager _shutmgr;
|
||||
@Inject protected LifecycleManager _lifemgr;
|
||||
@Inject protected ReportManager _repmgr;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ import static com.threerings.presents.Log.log;
|
||||
*/
|
||||
@Singleton
|
||||
public class ClientManager
|
||||
implements ClientResolutionListener, ReportManager.Reporter, ShutdownManager.Shutdowner
|
||||
implements ClientResolutionListener, ReportManager.Reporter, LifecycleManager.Component
|
||||
{
|
||||
/**
|
||||
* Used by {@link ClientManager#applyToClient}.
|
||||
@@ -100,21 +100,10 @@ public class ClientManager
|
||||
/**
|
||||
* Constructs a client manager that will interact with the supplied connection manager.
|
||||
*/
|
||||
@Inject public ClientManager (
|
||||
ReportManager repmgr, ShutdownManager shutmgr, PresentsDObjectMgr omgr)
|
||||
@Inject public ClientManager (ReportManager repmgr, LifecycleManager lifemgr)
|
||||
{
|
||||
repmgr.registerReporter(this);
|
||||
shutmgr.registerShutdowner(this);
|
||||
|
||||
// start up an interval that will check for expired clients and flush them from the bowels
|
||||
// of the server
|
||||
_flushClients = new Interval(omgr) {
|
||||
@Override
|
||||
public void expired () {
|
||||
flushClients();
|
||||
}
|
||||
};
|
||||
_flushClients.schedule(CLIENT_FLUSH_INTERVAL, true);
|
||||
lifemgr.addComponent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,26 +115,6 @@ public class ClientManager
|
||||
_injector = injector;
|
||||
}
|
||||
|
||||
// from interface ShutdownManager.Shutdowner
|
||||
public void shutdown ()
|
||||
{
|
||||
log.info("Client manager shutting down", "ccount", _usermap.size());
|
||||
|
||||
_flushClients.cancel();
|
||||
|
||||
// inform all of our clients that they are being shut down
|
||||
synchronized (_usermap) {
|
||||
for (PresentsSession pc : _usermap.values()) {
|
||||
try {
|
||||
pc.shutdown();
|
||||
} catch (Exception e) {
|
||||
log.warning("Client choked in shutdown()",
|
||||
"client", StringUtil.safeToString(pc), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the client manager with a factory for creating {@link PresentsSession} and {@link
|
||||
* ClientResolver} classes for authenticated client connections.
|
||||
@@ -354,6 +323,38 @@ public class ClientManager
|
||||
_omgr.destroyObject(clobj.getOid());
|
||||
}
|
||||
|
||||
// from interface LifecycleManager.Component
|
||||
public void init ()
|
||||
{
|
||||
// start up an interval that will check for and flush expired clients
|
||||
_flushClients = new Interval(_omgr) {
|
||||
@Override public void expired () {
|
||||
flushClients();
|
||||
}
|
||||
};
|
||||
_flushClients.schedule(CLIENT_FLUSH_INTERVAL, true);
|
||||
}
|
||||
|
||||
// from interface LifecycleManager.Component
|
||||
public void shutdown ()
|
||||
{
|
||||
log.info("Client manager shutting down", "ccount", _usermap.size());
|
||||
|
||||
_flushClients.cancel();
|
||||
|
||||
// inform all of our clients that they are being shut down
|
||||
synchronized (_usermap) {
|
||||
for (PresentsSession pc : _usermap.values()) {
|
||||
try {
|
||||
pc.shutdown();
|
||||
} catch (Exception e) {
|
||||
log.warning("Client choked in shutdown()",
|
||||
"client", StringUtil.safeToString(pc), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a currently connected client from <code>oldname</code> to <code>newname</code>.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2008 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;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import com.samskivert.util.ObserverList;
|
||||
import com.samskivert.util.RunQueue;
|
||||
import com.threerings.util.DependencyGraph;
|
||||
|
||||
import com.threerings.presents.annotation.EventQueue;
|
||||
|
||||
import static com.threerings.presents.Log.log;
|
||||
|
||||
/**
|
||||
* Manages the lifecycle (initialization and shutdown) of our various server managers and other
|
||||
* entities.
|
||||
*/
|
||||
public class LifecycleManager
|
||||
{
|
||||
/** An interface implemented by components which wish to participate in the lifecycle. */
|
||||
public interface BaseComponent
|
||||
{
|
||||
}
|
||||
|
||||
/** An interface implemented by components which wish to participate in the lifecycle. */
|
||||
public interface InitComponent extends BaseComponent
|
||||
{
|
||||
/** Called after dependencies have been fully resolved to initialize this component. */
|
||||
public void init ();
|
||||
|
||||
/** Called when the server is shutting down. */
|
||||
public void shutdown ();
|
||||
}
|
||||
|
||||
/** An interface implemented by components which wish to participate in the lifecycle. */
|
||||
public interface ShutdownComponent extends BaseComponent
|
||||
{
|
||||
/** Called when the server is shutting down. */
|
||||
public void shutdown ();
|
||||
}
|
||||
|
||||
/** An interface implemented by components which wish to participate in the lifecycle. */
|
||||
public interface Component extends InitComponent, ShutdownComponent
|
||||
{
|
||||
}
|
||||
|
||||
/** Constraints for use with {@link #addConstraint}. */
|
||||
public static enum Constraint { RUNS_BEFORE, RUNS_AFTER };
|
||||
|
||||
/**
|
||||
* Registers a component with the manager. This should be done during the dependency resolution
|
||||
* phase by injecting the LifecycleManager into your constructor and calling this method there.
|
||||
*/
|
||||
public void addComponent (BaseComponent comp)
|
||||
{
|
||||
if (_initers == null || _downers == null) {
|
||||
throw new IllegalStateException("Too late to register component.");
|
||||
}
|
||||
if (comp instanceof InitComponent) {
|
||||
_initers.add((InitComponent)comp);
|
||||
}
|
||||
if (comp instanceof ShutdownComponent) {
|
||||
_downers.add((ShutdownComponent)comp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a component from the manager. This is generally not used.
|
||||
*/
|
||||
public void removeComponent (BaseComponent comp)
|
||||
{
|
||||
if (_initers != null && comp instanceof InitComponent) {
|
||||
_initers.remove((InitComponent)comp);
|
||||
}
|
||||
if (_downers != null && comp instanceof ShutdownComponent) {
|
||||
_downers.remove((ShutdownComponent)comp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a constraint that a certain component must be initialized before another.
|
||||
*/
|
||||
public void addInitConstraint (InitComponent lhs, Constraint constraint, InitComponent rhs)
|
||||
{
|
||||
if (lhs == null || rhs == null) {
|
||||
throw new IllegalArgumentException("Cannot add constraint about null component.");
|
||||
}
|
||||
InitComponent before = (constraint == Constraint.RUNS_BEFORE) ? lhs : rhs;
|
||||
InitComponent after = (constraint == Constraint.RUNS_BEFORE) ? rhs : lhs;
|
||||
_initers.addDependency(after, before);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a constraint that a certain component must be shutdown before another.
|
||||
*/
|
||||
public void addShutdownConstraint (ShutdownComponent lhs, Constraint constraint,
|
||||
ShutdownComponent rhs)
|
||||
{
|
||||
if (lhs == null || rhs == null) {
|
||||
throw new IllegalArgumentException("Cannot add constraint about null component.");
|
||||
}
|
||||
ShutdownComponent before = (constraint == Constraint.RUNS_BEFORE) ? lhs : rhs;
|
||||
ShutdownComponent after = (constraint == Constraint.RUNS_BEFORE) ? rhs : lhs;
|
||||
_downers.addDependency(after, before);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up a request to shutdown on the event thread. This method may be safely called from
|
||||
* any thread.
|
||||
*/
|
||||
public void queueShutdown ()
|
||||
{
|
||||
_eventQueue.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we're in the process of shutting down.
|
||||
*/
|
||||
public boolean isShuttingDown ()
|
||||
{
|
||||
return (_downers == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all components immediately on the caller's thread.
|
||||
*/
|
||||
public void init ()
|
||||
{
|
||||
if (_initers == null) {
|
||||
log.warning("Refusing repeat init() request.");
|
||||
return;
|
||||
}
|
||||
|
||||
ObserverList<InitComponent> list = _initers.toObserverList();
|
||||
_initers = null;
|
||||
list.apply(new ObserverList.ObserverOp<InitComponent>() {
|
||||
public boolean apply (InitComponent comp) {
|
||||
log.debug("Initializing component", "comp", comp);
|
||||
comp.init();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down all components immediately on the caller's thread.
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
if (_downers == null) {
|
||||
log.warning("Refusing repeat shutdown() request.");
|
||||
return;
|
||||
}
|
||||
|
||||
ObserverList<ShutdownComponent> list = _downers.toObserverList();
|
||||
_downers = null;
|
||||
list.apply(new ObserverList.ObserverOp<ShutdownComponent>() {
|
||||
public boolean apply (ShutdownComponent comp) {
|
||||
log.debug("Shutting down component", "comp", comp);
|
||||
comp.shutdown();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** The queue we'll use to get onto the event thread before shutting down. */
|
||||
@Inject @EventQueue protected RunQueue _eventQueue;
|
||||
|
||||
/** A dependency graph of our components arranged by initialization dependencies. */
|
||||
protected DependencyGraph<InitComponent> _initers = new DependencyGraph<InitComponent>();
|
||||
|
||||
/** A dependency graph of our components arranged by shutdown dependencies. */
|
||||
protected DependencyGraph<ShutdownComponent> _downers =
|
||||
new DependencyGraph<ShutdownComponent>();
|
||||
}
|
||||
@@ -33,17 +33,17 @@ import static com.threerings.presents.Log.log;
|
||||
*/
|
||||
@Singleton
|
||||
public class PresentsInvoker extends ReportingInvoker
|
||||
implements ShutdownManager.Shutdowner
|
||||
implements LifecycleManager.ShutdownComponent
|
||||
{
|
||||
@Inject public PresentsInvoker (
|
||||
PresentsDObjectMgr omgr, ShutdownManager shutmgr, ReportManager repmgr)
|
||||
@Inject public PresentsInvoker (PresentsDObjectMgr omgr, LifecycleManager lifemgr,
|
||||
ReportManager repmgr)
|
||||
{
|
||||
super("presents.Invoker", omgr, repmgr);
|
||||
_omgr = omgr;
|
||||
shutmgr.registerShutdowner(this);
|
||||
lifemgr.addComponent(this);
|
||||
}
|
||||
|
||||
@Override // from Invoker
|
||||
@Override // from Invoker, LifecycleManager.ShutdownComponent
|
||||
public void shutdown ()
|
||||
{
|
||||
// this will do a sophisticated shutdown of both ourself and the dobjmgr; note: we
|
||||
|
||||
@@ -159,10 +159,13 @@ public class PresentsServer
|
||||
// initialize the time base services
|
||||
TimeBaseProvider.init(_invmgr, _omgr);
|
||||
|
||||
// Make the client manager shut down before the invoker and dobj threads. This will help
|
||||
// application code to avoid long chains of shutdown constraints (e.g. msoy bureau manager).
|
||||
_shutmgr.addConstraint(
|
||||
_clmgr, ShutdownManager.Constraint.RUNS_BEFORE, (PresentsInvoker)_invoker);
|
||||
// make the client manager shut down before the invoker and dobj threads; this helps
|
||||
// application code to avoid long chains of shutdown constraints
|
||||
_lifemgr.addShutdownConstraint(
|
||||
_clmgr, LifecycleManager.Constraint.RUNS_BEFORE, (PresentsInvoker)_invoker);
|
||||
|
||||
// initialize all of our registered components
|
||||
_lifemgr.init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,8 +241,8 @@ public class PresentsServer
|
||||
/** The manager of invocation services. */
|
||||
@Inject protected InvocationManager _invmgr;
|
||||
|
||||
/** Handles orderly shutdown of our managers, etc. */
|
||||
@Inject protected ShutdownManager _shutmgr;
|
||||
/** Handles orderly initialization and shutdown of our managers, etc. */
|
||||
@Inject protected LifecycleManager _lifemgr;
|
||||
|
||||
/** Handles generation of state of the server reports. */
|
||||
@Inject protected ReportManager _repmgr;
|
||||
|
||||
@@ -155,8 +155,7 @@ public abstract class RebootManager
|
||||
_rebootSoon = false;
|
||||
long firstWarnTime = (_nextReboot - (WARNINGS[0] * 60 * 1000)) - now;
|
||||
_interval = new Interval(_omgr) {
|
||||
@Override
|
||||
public void expired () {
|
||||
@Override public void expired () {
|
||||
doWarning(0);
|
||||
}
|
||||
};
|
||||
@@ -189,9 +188,9 @@ public abstract class RebootManager
|
||||
/**
|
||||
* Provides us with our dependencies.
|
||||
*/
|
||||
protected RebootManager (ShutdownManager shutmgr, RootDObjectManager omgr)
|
||||
protected RebootManager (LifecycleManager lmgr, RootDObjectManager omgr)
|
||||
{
|
||||
_shutmgr = shutmgr;
|
||||
_lmgr = lmgr;
|
||||
_omgr = omgr;
|
||||
}
|
||||
|
||||
@@ -257,12 +256,11 @@ public abstract class RebootManager
|
||||
|
||||
// wait 1 second, then do it
|
||||
new Interval() { // Note: This interval does not run on the dobj thread
|
||||
@Override
|
||||
public void expired () {
|
||||
@Override public void expired () {
|
||||
// ...but we then post a LongRunnable...
|
||||
_omgr.postRunnable(new PresentsDObjectMgr.LongRunnable() {
|
||||
public void run () {
|
||||
_shutmgr.shutdown();
|
||||
_lmgr.shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -279,8 +277,7 @@ public abstract class RebootManager
|
||||
|
||||
// schedule the next warning
|
||||
_interval = new Interval(_omgr) {
|
||||
@Override
|
||||
public void expired () {
|
||||
@Override public void expired () {
|
||||
doWarning(level + 1);
|
||||
}
|
||||
};
|
||||
@@ -301,8 +298,7 @@ public abstract class RebootManager
|
||||
log.info("Reboot delayed due to outstanding locks", "locks", _rebootLocks.elements());
|
||||
broadcast("m.reboot_delayed");
|
||||
_interval = new Interval(_omgr) {
|
||||
@Override
|
||||
public void expired () {
|
||||
@Override public void expired () {
|
||||
doWarning(WARNINGS.length);
|
||||
}
|
||||
};
|
||||
@@ -325,8 +321,8 @@ public abstract class RebootManager
|
||||
});
|
||||
}
|
||||
|
||||
/** Our shutdown manager, which is how we will reboot. */
|
||||
protected ShutdownManager _shutmgr;
|
||||
/** Our lifecycle manager, which is how we will reboot. */
|
||||
protected LifecycleManager _lmgr;
|
||||
|
||||
/** Our distributed object manager. */
|
||||
protected RootDObjectManager _omgr;
|
||||
|
||||
@@ -24,44 +24,28 @@ package com.threerings.presents.server;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import com.samskivert.util.ObserverList;
|
||||
import com.samskivert.util.RunQueue;
|
||||
|
||||
import com.threerings.util.DependencyGraph;
|
||||
|
||||
import com.threerings.presents.annotation.EventQueue;
|
||||
|
||||
import static com.threerings.presents.Log.log;
|
||||
|
||||
/**
|
||||
* Handles the orderly shutdown of all server services.
|
||||
*
|
||||
* @Deprecated use LifecycleManager
|
||||
*/
|
||||
@Singleton
|
||||
public class ShutdownManager
|
||||
{
|
||||
/** Implementers of this interface will be notified when the server is shutting down. */
|
||||
public static interface Shutdowner
|
||||
public static interface Shutdowner extends LifecycleManager.ShutdownComponent
|
||||
{
|
||||
/**
|
||||
* Called when the server is shutting down.
|
||||
*/
|
||||
void shutdown ();
|
||||
}
|
||||
|
||||
/** Constraints for use with {@link ShutdownManager#addConstraint}. */
|
||||
public static enum Constraint { RUNS_BEFORE, RUNS_AFTER };
|
||||
|
||||
@Inject ShutdownManager (@EventQueue RunQueue dobjq)
|
||||
{
|
||||
_dobjq = dobjq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an entity that will be notified when the server is shutting down.
|
||||
*/
|
||||
public void registerShutdowner (Shutdowner downer)
|
||||
{
|
||||
_downers.add(downer);
|
||||
_lifeMgr.addComponent(downer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +53,7 @@ public class ShutdownManager
|
||||
*/
|
||||
public void unregisterShutdowner (Shutdowner downer)
|
||||
{
|
||||
_downers.remove(downer);
|
||||
_lifeMgr.removeComponent(downer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,12 +61,14 @@ public class ShutdownManager
|
||||
*/
|
||||
public void addConstraint (Shutdowner lhs, Constraint constraint, Shutdowner rhs)
|
||||
{
|
||||
if (lhs == null || rhs == null) {
|
||||
throw new IllegalArgumentException("Cannot add constraint about null shutdowner.");
|
||||
switch (constraint) {
|
||||
case RUNS_BEFORE:
|
||||
_lifeMgr.addShutdownConstraint(lhs, LifecycleManager.Constraint.RUNS_BEFORE, rhs);
|
||||
break;
|
||||
case RUNS_AFTER:
|
||||
_lifeMgr.addShutdownConstraint(lhs, LifecycleManager.Constraint.RUNS_AFTER, rhs);
|
||||
break;
|
||||
}
|
||||
Shutdowner before = (constraint == Constraint.RUNS_BEFORE) ? lhs : rhs;
|
||||
Shutdowner after = (constraint == Constraint.RUNS_BEFORE) ? rhs : lhs;
|
||||
_downers.addDependency(after, before);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,11 +77,7 @@ public class ShutdownManager
|
||||
*/
|
||||
public void queueShutdown ()
|
||||
{
|
||||
_dobjq.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
_lifeMgr.queueShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,41 +85,8 @@ public class ShutdownManager
|
||||
*/
|
||||
public boolean isShuttingDown ()
|
||||
{
|
||||
return _downers == null;
|
||||
return _lifeMgr.isShuttingDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down all shutdowners immediately on the caller's thread.
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
if (_downers == null) {
|
||||
log.warning("Refusing repeat shutdown request.");
|
||||
return;
|
||||
}
|
||||
|
||||
ObserverList<Shutdowner> downers = ObserverList.newSafeInOrder();
|
||||
|
||||
while (!_downers.isEmpty()) {
|
||||
downers.add(_downers.removeAvailableElement());
|
||||
}
|
||||
|
||||
_downers = null;
|
||||
|
||||
// shut down all shutdown participants
|
||||
downers.apply(new ObserverList.ObserverOp<Shutdowner>() {
|
||||
public boolean apply (Shutdowner downer) {
|
||||
log.debug("Calling shutdown registrant", "downer", downer);
|
||||
downer.shutdown();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** All of the registered shutdowners along with related constraints. */
|
||||
protected DependencyGraph<Shutdowner> _downers = new DependencyGraph<Shutdowner>();
|
||||
|
||||
/** The queue we'll use to get onto the dobjmgr thread before shutting down. */
|
||||
protected RunQueue _dobjq;
|
||||
|
||||
@Inject protected LifecycleManager _lifeMgr;
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ 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.LifecycleManager;
|
||||
import com.threerings.presents.server.PresentsDObjectMgr;
|
||||
import com.threerings.presents.server.ReportManager;
|
||||
import com.threerings.presents.server.ShutdownManager;
|
||||
import com.threerings.presents.util.DatagramSequencer;
|
||||
|
||||
import static com.threerings.presents.Log.log;
|
||||
@@ -82,15 +82,15 @@ import static com.threerings.presents.Log.log;
|
||||
*/
|
||||
@Singleton
|
||||
public class ConnectionManager extends LoopingThread
|
||||
implements ShutdownManager.Shutdowner, ReportManager.Reporter
|
||||
implements LifecycleManager.ShutdownComponent, ReportManager.Reporter
|
||||
{
|
||||
/**
|
||||
* Creates a connection manager instance. Don't call this, Guice will do it for you.
|
||||
*/
|
||||
@Inject public ConnectionManager (ShutdownManager shutmgr, ReportManager repmgr)
|
||||
@Inject public ConnectionManager (LifecycleManager lifemgr, ReportManager repmgr)
|
||||
{
|
||||
super("ConnectionManager");
|
||||
shutmgr.registerShutdowner(this);
|
||||
lifemgr.addComponent(this);
|
||||
repmgr.registerReporter(this);
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ public class ConnectionManager extends LoopingThread
|
||||
// if we failed to listen on at least one port, give up the ghost
|
||||
if (successes == 0) {
|
||||
log.warning("ConnectionManager failed to bind to any ports. Shutting down.");
|
||||
_shutmgr.queueShutdown();
|
||||
_lifemgr.queueShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1232,7 +1232,7 @@ public class ConnectionManager extends LoopingThread
|
||||
@Inject @AuthInvoker protected Invoker _authInvoker;
|
||||
@Inject protected PresentsDObjectMgr _omgr;
|
||||
@Inject protected ClientManager _clmgr;
|
||||
@Inject protected ShutdownManager _shutmgr;
|
||||
@Inject protected LifecycleManager _lifemgr;
|
||||
|
||||
/** How long we wait for network events before checking our running flag to see if we should
|
||||
* still be running. We don't want to loop too tightly, but we need to make sure we don't sit
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
package com.threerings.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -6,12 +9,15 @@ import java.util.HashMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.samskivert.util.ObserverList;
|
||||
|
||||
/**
|
||||
* Maintains a bidirectional graph to manage the order that the items are removed. Children
|
||||
* must wait until their parents are accessed - thus removing an available element means that
|
||||
* a node without parents (an orphan) is removed and returned and the rest of the graph is
|
||||
* updated to reflect that removal.
|
||||
* @param <T>
|
||||
* Maintains a bidirectional graph to manage the order that the items are removed. Children must
|
||||
* wait until their parents are accessed - thus removing an available element means that a node
|
||||
* without parents (an orphan) is removed and returned and the rest of the graph is updated to
|
||||
* reflect that removal.
|
||||
*
|
||||
* @param <T> the type of object maintained in the graph.
|
||||
*/
|
||||
public class DependencyGraph<T>
|
||||
{
|
||||
@@ -49,7 +55,7 @@ public class DependencyGraph<T>
|
||||
|
||||
/**
|
||||
* Removes and returns an element which is available, meaning not dependent upon any other
|
||||
* still in the graph.
|
||||
* still in the graph.
|
||||
*/
|
||||
public T removeAvailableElement ()
|
||||
{
|
||||
@@ -126,6 +132,19 @@ public class DependencyGraph<T>
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens this graph into an observer list in dependencys order. Empties the graph in the
|
||||
* process.
|
||||
*/
|
||||
public ObserverList<T> toObserverList ()
|
||||
{
|
||||
ObserverList<T> list = ObserverList.newSafeInOrder();
|
||||
while (!isEmpty()) {
|
||||
list.add(removeAvailableElement());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/** All the nodes included in the graph. */
|
||||
protected HashMap<T, DependencyNode<T>> _nodes = Maps.newHashMap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user