diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java
index f21c0d1ba..a4e552a7d 100644
--- a/src/java/com/threerings/crowd/server/PlaceManager.java
+++ b/src/java/com/threerings/crowd/server/PlaceManager.java
@@ -683,12 +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 = _omgr.newInterval(new Runnable() {
+ (_shutdownInterval = _omgr.newInterval(new Runnable() {
public void run () {
log.debug("Unloading idle place '" + where() + "'.");
shutdown();
}
- }).schedule(idlePeriod);
+ })).schedule(idlePeriod);
}
}
diff --git a/src/java/com/threerings/presents/peer/server/CronLogic.java b/src/java/com/threerings/presents/peer/server/CronLogic.java
deleted file mode 100644
index 9fc50155a..000000000
--- a/src/java/com/threerings/presents/peer/server/CronLogic.java
+++ /dev/null
@@ -1,242 +0,0 @@
-//
-// $Id$
-
-package com.threerings.presents.peer.server;
-
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-import com.samskivert.util.Interval;
-import com.samskivert.util.Lifecycle;
-import com.samskivert.util.RandomUtil;
-import com.samskivert.util.ResultListener;
-
-import com.threerings.presents.peer.data.NodeObject;
-import com.threerings.presents.server.PresentsDObjectMgr;
-
-import static com.threerings.presents.Log.log;
-
-/**
- * Provides peer-aware cron services. Jobs are scheduled at fixed wall times and the peers
- * coordinate to ensure that only one peer runs a job at its scheduled wall time.
- *
- *
Note: these jobs do not run on the dobj thread, they run on individual separate
- * worker threads. If such coordination is needed with the dobj world, it must be handled manually
- * by the job.
- */
-@Singleton
-public class CronLogic
-{
- @Inject public CronLogic (Lifecycle cycle, PresentsDObjectMgr omgr)
- {
- _ticker = new JobTicker(omgr);
- cycle.addComponent(new Lifecycle.Component() {
- public void init () {
- // scheule our ticker to start running at 0 milliseconds after the minute; we'll
- // randomize from there, but this reduces any initial bias
- Calendar cal = Calendar.getInstance();
- long curmils = cal.get(Calendar.SECOND) * 1000L + cal.get(Calendar.MILLISECOND);
- _ticker.schedule(60 * 1000L - curmils);
- }
- public void shutdown () {
- _ticker.cancel();
- }
- });
- }
-
- /**
- * Schedules a job every N hours. We schedule the job at midnight and then again every N hours
- * for the rest of the day. This means that if N does not evenly divide 24, there may be a gap
- * smaller than N between the last job of the day and 00:00 of the next day.
- *
- *
Note that the job will be scheduled to run at some arbitrary minute after the our based
- * on the hashcode of the name of the job class.
- *
- *
Your job will be run on a separate thread and a lock will be held for the duration of
- * the execution of your job. Do not send your job off to a different thread as the holding of
- * the lock for some meaningful amount of time is necessary to prevent other nodes from
- * executing your job at the same time. This will probably change in the future to be less
- * fragile, but you still don't need to use a separate thread.
- *
- * @param job a runnable that will be executed periodically on a separate thread.
- * @param hourlyPeriod the number of hours between executions of this job.
- */
- public void scheduleEvery (int hourlyPeriod, Runnable job)
- {
- int minOfHour = Math.abs(job.getClass().toString().hashCode()) % 60;
- int minOfDay = 0;
- synchronized (_jobs) {
- while (minOfDay < 24*60) {
- _jobs.put(minOfDay + minOfHour, job);
- minOfDay += hourlyPeriod * 60;
- }
- }
- }
-
- /**
- * Schedules a job to run once per day at the specified hour.
- *
- * Note that the job will be scheduled to run at some arbitrary minute after the our based
- * on the hashcode of the name of the job class.
- *
- *
Your job will be run on a separate thread and a lock will be held for the duration of
- * the execution of your job. Do not send your job off to a different thread as the holding of
- * the lock for some meaningful amount of time is necessary to prevent other nodes from
- * executing your job at the same time. This will probably change in the future to be less
- * fragile, but you still don't need to use a separate thread.
- *
- * @param job a runnable that will be executed periodically on a separate thread.
- * @param hour the hour of the day at which to execute this job.
- */
- public void scheduleAt (int hour, Runnable job)
- {
- int minOfHour = Math.abs(job.getClass().toString().hashCode()) % 60;
- synchronized (_jobs) {
- _jobs.put(hour * 60 + minOfHour, job);
- }
- }
-
- /**
- * Removes the specified job from the schedule.
- */
- public void unschedule (Runnable job)
- {
- synchronized (_jobs) {
- // we have to iterate over our entire jobs table to remove all occurrances of this job,
- // but the table's not huge and we don't do this very often so it's no big deal
- for (Iterator> iter = _jobs.entries().iterator();
- iter.hasNext(); ) {
- Map.Entry entry = iter.next();
- if (entry.getValue() == job) {
- iter.remove();
- }
- }
- }
- }
-
- protected void executeJobs (int minuteOfDay)
- {
- List jobs = Lists.newArrayList();
- synchronized (_jobs) {
- List sched = _jobs.get(minuteOfDay);
- if (sched != null) {
- jobs.addAll(sched);
- }
- }
- for (Runnable job : jobs) {
- executeJob(job);
- }
- }
-
- protected void executeJob (final Runnable job)
- {
- final NodeObject.Lock lock = new NodeObject.Lock(CRON_LOCK, job.getClass().getName());
- _peerMan.acquireLock(lock, new ResultListener() {
- public void requestCompleted (String result) {
- if (!result.equals(_peerMan.getNodeObject().nodeName)) {
- return;
- }
- startJob(job, lock);
- }
- public void requestFailed (Exception cause) {
- log.warning("Failed to acquire lock for job", "job", job, cause);
- }
- });
- }
-
- protected void startJob (final Runnable job, final NodeObject.Lock lock)
- {
- if (_running.putIfAbsent(job.getClass(), lock) != null) {
- log.info("Dropping job as it is still executing", "job", job);
- return;
- }
- new Thread() {
- @Override public void run () {
- try {
- job.run();
- } catch (Throwable t) {
- log.warning("Job failed", "job", job, t);
- } finally {
- jobCompleted(job);
- }
- }
- }.start();
- }
-
- protected void jobCompleted (Runnable job)
- {
- final NodeObject.Lock lock = _running.remove(job.getClass());
- if (lock != null) {
- _omgr.postRunnable(new Runnable() {
- public void run () {
- _peerMan.releaseLock(lock, new ResultListener.NOOP());
- }
- });
- }
- }
-
- protected class JobTicker extends Interval
- {
- public JobTicker (PresentsDObjectMgr omgr) {
- super(omgr);
- }
-
- @Override public void expired () {
- // if the current minute is less than our previous, we wrapped around midnight
- int curMinute = getMinuteOfDay();
- if (curMinute < _prevMinute) {
- processMinutes(_prevMinute+1, 24*60-1);
- processMinutes(0, curMinute);
- } else {
- processMinutes(_prevMinute+1, curMinute);
- }
-
- // note our previously executed minute
- _prevMinute = curMinute;
-
- // schedule ourselves for 60000 +/- rand(1000) millis in the future to randomize which
- // node is likely to win the job lottery every minute
- schedule(61*1000L - RandomUtil.getInt(2000));
- }
-
- protected int getMinuteOfDay () {
- _cal.setTimeInMillis(System.currentTimeMillis());
- return _cal.get(Calendar.HOUR_OF_DAY) * 60 + _cal.get(Calendar.MINUTE);
- }
-
- protected void processMinutes (int fromMinute, int toMinute) {
- for (int mm = fromMinute; mm <= toMinute; mm++) {
- executeJobs(mm);
- }
- }
-
- protected Calendar _cal = Calendar.getInstance();
- protected int _prevMinute = getMinuteOfDay();
- }
-
- /** The ticker that handles our periodic jobs. */
- protected JobTicker _ticker;
-
- /** A map of all jobs scheduled for a single day. */
- protected ListMultimap _jobs = ArrayListMultimap.create();
-
- /** A map of jobs currently running on this node. */
- protected ConcurrentHashMap, NodeObject.Lock> _running =
- new ConcurrentHashMap, NodeObject.Lock>();
-
- // los dependidos
- @Inject protected PeerManager _peerMan;
- @Inject protected PresentsDObjectMgr _omgr;
-
- /** The name of the locks we use to coordinate cron jobs between peers. */
- protected static final String CRON_LOCK = "peer_cron_job";
-}
diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java
index 178fa9a3c..0ca8bf7ce 100644
--- a/src/java/com/threerings/presents/peer/server/PeerManager.java
+++ b/src/java/com/threerings/presents/peer/server/PeerManager.java
@@ -1188,14 +1188,14 @@ public abstract class PeerManager
_remoids = (ArrayIntSet)_suboids.clone();
// schedule a timeout to act if something goes wrong
- _timeout = _omgr.newInterval(new Runnable () {
+ (_timeout = _omgr.newInterval(new Runnable () {
public void run () {
log.warning("Lock handler timed out, acting anyway", "lock", _lock,
"acquire", _acquire);
_stats.lockTimeouts++;
activate();
}
- }).schedule(LOCK_TIMEOUT);
+ })).schedule(LOCK_TIMEOUT);
}
/**
diff --git a/src/java/com/threerings/presents/server/RebootManager.java b/src/java/com/threerings/presents/server/RebootManager.java
index bd2208c28..41c9751d6 100644
--- a/src/java/com/threerings/presents/server/RebootManager.java
+++ b/src/java/com/threerings/presents/server/RebootManager.java
@@ -151,11 +151,11 @@ public abstract class RebootManager
// should issue the first pre-reboot warning
_rebootSoon = false;
long firstWarnTime = (_nextReboot - (WARNINGS[0] * 60 * 1000)) - now;
- _interval = _omgr.newInterval(new Runnable() {
+ (_interval = _omgr.newInterval(new Runnable() {
public void run () {
doWarning(0);
}
- }).schedule(firstWarnTime);
+ })).schedule(firstWarnTime);
}
/**
@@ -267,11 +267,11 @@ public abstract class RebootManager
}
// schedule the next warning
- _interval = _omgr.newInterval(new Runnable() {
+ (_interval = _omgr.newInterval(new Runnable() {
public void run () {
doWarning(level + 1);
}
- }).schedule(minutes * 60 * 1000);
+ })).schedule(minutes * 60 * 1000);
notifyObservers(level);
}
@@ -287,11 +287,11 @@ public abstract class RebootManager
log.info("Reboot delayed due to outstanding locks", "locks", _rebootLocks.elements());
broadcast("m.reboot_delayed");
- _interval = _omgr.newInterval(new Runnable() {
+ (_interval = _omgr.newInterval(new Runnable() {
public void run () {
doWarning(WARNINGS.length);
}
- }).schedule(60 * 1000);
+ })).schedule(60 * 1000);
return true;
}