From c0c68f98d3d44d363bd81dcea2ccdcf8103e750a Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 20 Jul 2009 22:43:00 +0000 Subject: [PATCH] Added RootDObjectManager.newInterval() for creating intervals that are automatically canceled when the omgr is shutdown (they actually cancel themselves if they fire after the omgr has been shutdown, which stock intervals also do, but these guys do so quietly because we know they mean to work that way). Made use of that new method and the fluent schedule methods in various places. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5880 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/chat/server/ChatChannelManager.java | 28 ++++--------------- .../threerings/crowd/server/PlaceManager.java | 8 ++---- .../presents/dobj/RootDObjectManager.java | 13 +++++++++ .../presents/peer/server/PeerManager.java | 23 ++++++--------- .../presents/server/ClientManager.java | 16 ++++------- .../presents/server/PresentsDObjectMgr.java | 14 ++++++++++ .../presents/server/RebootManager.java | 21 ++++++-------- .../presents/server/ReportManager.java | 20 +++++-------- 8 files changed, 65 insertions(+), 78 deletions(-) diff --git a/src/java/com/threerings/crowd/chat/server/ChatChannelManager.java b/src/java/com/threerings/crowd/chat/server/ChatChannelManager.java index 111b297db..ae2a3af24 100644 --- a/src/java/com/threerings/crowd/chat/server/ChatChannelManager.java +++ b/src/java/com/threerings/crowd/chat/server/ChatChannelManager.java @@ -31,8 +31,6 @@ import com.google.inject.Inject; import com.samskivert.util.ArrayIntSet; import com.samskivert.util.IntSet; -import com.samskivert.util.Interval; -import com.samskivert.util.Lifecycle; import com.threerings.util.Name; @@ -59,7 +57,7 @@ import static com.threerings.crowd.Log.log; * Handles chat channel services. */ public abstract class ChatChannelManager - implements ChannelSpeakProvider, Lifecycle.ShutdownComponent + implements ChannelSpeakProvider { /** * When a body becomes a member of a channel, this method should be called so that any server @@ -111,30 +109,19 @@ public abstract class ChatChannelManager }); } - // from interface Lifecycle.Shutdowner - public void shutdown () - { - // stop our channel closer; always be closing... except now - _closer.cancel(); - _closer = null; - } - /** * Creates our singleton manager and registers our invocation service. */ - @Inject protected ChatChannelManager (PresentsDObjectMgr omgr, InvocationManager invmgr, - Lifecycle cycle) + @Inject protected ChatChannelManager (PresentsDObjectMgr omgr, InvocationManager invmgr) { invmgr.registerDispatcher(new ChannelSpeakDispatcher(this), CrowdCodes.CROWD_GROUP); - cycle.addComponent(this); - // create and start our idle channel closer (always be closing) - _closer = new Interval(omgr) { - @Override public void expired () { + // create and start our idle channel closer; this will run as long as omgr is alive + omgr.newInterval(new Runnable() { + public void run () { closeIdleChannels(); } - }; - _closer.schedule(IDLE_CHANNEL_CHECK_PERIOD, true); + }).schedule(IDLE_CHANNEL_CHECK_PERIOD, true); } /** @@ -391,9 +378,6 @@ public abstract class ChatChannelManager public long lastMessage; } - /** Used to close channels that have not had any activity in a few minutes. */ - protected Interval _closer; - /** Contains pending messages for all channels currently being resolved. */ protected Map> _resolving = Maps.newHashMap(); diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index 08148ca85..f21c0d1ba 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -683,14 +683,12 @@ public class PlaceManager // queue up a shutdown interval, unless we've already got one. long idlePeriod = idleUnloadPeriod(); if (idlePeriod > 0L && _shutdownInterval == null) { - _shutdownInterval = new Interval(_omgr) { - @Override - public void expired () { + _shutdownInterval = _omgr.newInterval(new Runnable() { + public void run () { log.debug("Unloading idle place '" + where() + "'."); shutdown(); } - }; - _shutdownInterval.schedule(idlePeriod); + }).schedule(idlePeriod); } } diff --git a/src/java/com/threerings/presents/dobj/RootDObjectManager.java b/src/java/com/threerings/presents/dobj/RootDObjectManager.java index 10c9dce69..187cf5c2c 100644 --- a/src/java/com/threerings/presents/dobj/RootDObjectManager.java +++ b/src/java/com/threerings/presents/dobj/RootDObjectManager.java @@ -21,6 +21,7 @@ package com.threerings.presents.dobj; +import com.samskivert.util.Interval; import com.samskivert.util.RunQueue; /** @@ -53,4 +54,16 @@ public interface RootDObjectManager extends DObjectManager, RunQueue * @param oid The object id of the distributed object to be destroyed. */ void destroyObject (int oid); + + /** + * Creates an {@link Interval} that runs the supplied runnable. If the root omgr is shutdown + * before the interval expires (or if the interval is scheduled to repeat), it will be + * automatically cancelled. This makes it easy to schedule fire-and-forget intervals: + * + *
+     * _omgr.newInterval(someRunnable).schedule(500); // one shot
+     * Interval ival = _omgr.newInterval(someRunnable).schedule(500, true); // repeater
+     * 
+ */ + Interval newInterval (Runnable action); } diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java index c5f8fc057..178fa9a3c 100644 --- a/src/java/com/threerings/presents/peer/server/PeerManager.java +++ b/src/java/com/threerings/presents/peer/server/PeerManager.java @@ -281,8 +281,12 @@ public abstract class PeerManager // register ourselves as a client observer _clmgr.addClientObserver(this); - // and start our peer refresh interval - _peerRefresher.schedule(5000L, 60*1000L); + // and start our peer refresh interval (this lives for the lifetime of the server) + _omgr.newInterval(new Runnable() { + public void run () { + refreshPeers(); + } + }).schedule(5000L, 60*1000L); // give derived classes an easy way to get in on the init action didInit(); @@ -773,9 +777,6 @@ public abstract class PeerManager _invmgr.clearDispatcher(_nodeobj.peerService); } - // stop our peer refresher interval - _peerRefresher.cancel(); - // clear out our client observer registration _clmgr.removeClientObserver(this); @@ -1187,9 +1188,8 @@ public abstract class PeerManager _remoids = (ArrayIntSet)_suboids.clone(); // schedule a timeout to act if something goes wrong - (_timeout = new Interval(_omgr) { - @Override - public void expired () { + _timeout = _omgr.newInterval(new Runnable () { + public void run () { log.warning("Lock handler timed out, acting anyway", "lock", _lock, "acquire", _acquire); _stats.lockTimeouts++; @@ -1372,13 +1372,6 @@ public abstract class PeerManager } }; - // (this need not use a runqueue as all it will do is post an invoker unit) - protected Interval _peerRefresher = new Interval() { - @Override public void expired () { - refreshPeers(); - } - }; - protected String _nodeName, _sharedSecret; protected NodeRecord _self; protected NodeObject _nodeobj; diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index 62c2d8e81..38aab6366 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -35,7 +35,6 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; -import com.samskivert.util.Interval; import com.samskivert.util.Lifecycle; import com.samskivert.util.ObserverList; import com.samskivert.util.StringUtil; @@ -337,13 +336,13 @@ public class ClientManager // from interface Lifecycle.Component public void init () { - // start up an interval that will check for and flush expired sessions - _flushSessions = new Interval(_omgr) { - @Override public void expired () { + // start up an interval that will check for and flush expired sessions (this will be + // canceled when the omgr shuts down) + _omgr.newInterval(new Runnable() { + public void run () { flushSessions(); } - }; - _flushSessions.schedule(SESSION_FLUSH_INTERVAL, true); + }).schedule(SESSION_FLUSH_INTERVAL, true); } // from interface Lifecycle.Component @@ -351,8 +350,6 @@ public class ClientManager { log.info("Client manager shutting down", "ccount", _usermap.size()); - _flushSessions.cancel(); - // inform all of our clients that they are being shut down synchronized (_usermap) { for (PresentsSession pc : _usermap.values()) { @@ -625,9 +622,6 @@ public class ClientManager /** Tracks registered {@link ClientObserver}s. */ protected ObserverList _clobservers = ObserverList.newSafeInOrder(); - /** Interval to flush expired sessions. */ - protected Interval _flushSessions; - // our injected dependencies @Inject protected PresentsDObjectMgr _omgr; diff --git a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java index 8c657a1fc..08301bf4a 100644 --- a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java +++ b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java @@ -276,6 +276,20 @@ public class PresentsDObjectMgr postEvent(new ObjectDestroyedEvent(oid)); } + // from interface RootDObjectManager + public Interval newInterval (final Runnable action) + { + return new Interval(this) { + public void expired () { + if (isRunning()) { + action.run(); + } else { + cancel(); + } + } + }; + } + /** * Returns the object in the object table with the specified oid or null if no object has that * oid. Be sure only to call this function from the dobjmgr thread and not to do anything funny diff --git a/src/java/com/threerings/presents/server/RebootManager.java b/src/java/com/threerings/presents/server/RebootManager.java index 9af15e0a8..70e5f3ec8 100644 --- a/src/java/com/threerings/presents/server/RebootManager.java +++ b/src/java/com/threerings/presents/server/RebootManager.java @@ -154,12 +154,11 @@ public abstract class RebootManager // should issue the first pre-reboot warning _rebootSoon = false; long firstWarnTime = (_nextReboot - (WARNINGS[0] * 60 * 1000)) - now; - _interval = new Interval(_omgr) { - @Override public void expired () { + _interval = _omgr.newInterval(new Runnable() { + public void run () { doWarning(0); } - }; - _interval.schedule(firstWarnTime); + }).schedule(firstWarnTime); } /** @@ -271,12 +270,11 @@ public abstract class RebootManager } // schedule the next warning - _interval = new Interval(_omgr) { - @Override public void expired () { + _interval = _omgr.newInterval(new Runnable() { + public void run () { doWarning(level + 1); } - }; - _interval.schedule(minutes * 60 * 1000); + }).schedule(minutes * 60 * 1000); notifyObservers(level); } @@ -292,12 +290,11 @@ 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 () { + _interval = _omgr.newInterval(new Runnable() { + public void run () { doWarning(WARNINGS.length); } - }; - _interval.schedule(60 * 1000); + }).schedule(60 * 1000); return true; } diff --git a/src/java/com/threerings/presents/server/ReportManager.java b/src/java/com/threerings/presents/server/ReportManager.java index 47e0c207e..cd5700f40 100644 --- a/src/java/com/threerings/presents/server/ReportManager.java +++ b/src/java/com/threerings/presents/server/ReportManager.java @@ -26,11 +26,10 @@ import com.google.common.collect.Multimap; import com.google.inject.Inject; import com.google.inject.Singleton; -import com.samskivert.util.Interval; import com.samskivert.util.RunQueue; import com.samskivert.util.StringUtil; -import com.threerings.presents.annotation.EventQueue; +import com.threerings.presents.dobj.RootDObjectManager; import static com.threerings.presents.Log.log; @@ -69,15 +68,13 @@ public class ReportManager */ public void activatePeriodicReport () { - // queue up an interval which will generate reports - _reportInterval = new Interval(_dobjq) { - @Override - public void expired () { + // queue up an interval which will generate reports as long as the omgr is alive + _omgr.newInterval(new Runnable() { + public void run () { logReport(LOG_REPORT_HEADER + generateReport(DEFAULT_TYPE, System.currentTimeMillis(), true)); } - }; - _reportInterval.schedule(REPORT_INTERVAL, true); + }).schedule(REPORT_INTERVAL, true); } /** @@ -178,9 +175,6 @@ public class ReportManager log.info(report); } - /** Our interval that generates "state of server" reports. */ - protected Interval _reportInterval; - /** The time at which the server was started. */ protected long _serverStartTime = System.currentTimeMillis(); @@ -190,8 +184,8 @@ public class ReportManager /** Used to generate "state of server" reports. */ protected Multimap _reporters = ArrayListMultimap.create(); - /** We need to queue up our reporting interval on this feller. */ - @Inject protected @EventQueue RunQueue _dobjq; + /** We use the root omgr to queue up our reporting interval. */ + @Inject protected RootDObjectManager _omgr; /** The frequency with which we generate "state of server" reports. */ protected static final long REPORT_INTERVAL = 15 * 60 * 1000L;