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
This commit is contained in:
Michael Bayne
2009-07-20 22:43:00 +00:00
parent 57b630727e
commit c0c68f98d3
8 changed files with 65 additions and 78 deletions
@@ -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<ChatChannel,List<UserMessage>> _resolving = Maps.newHashMap();
@@ -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);
}
}
@@ -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:
*
* <pre>
* _omgr.newInterval(someRunnable).schedule(500); // one shot
* Interval ival = _omgr.newInterval(someRunnable).schedule(500, true); // repeater
* </pre>
*/
Interval newInterval (Runnable action);
}
@@ -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;
@@ -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<ClientObserver> _clobservers = ObserverList.newSafeInOrder();
/** Interval to flush expired sessions. */
protected Interval _flushSessions;
// our injected dependencies
@Inject protected PresentsDObjectMgr _omgr;
@@ -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
@@ -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;
}
@@ -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<String, Reporter> _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;