package geniusweb.partiesserver; import java.util.logging.Level; import geniusweb.partiesserver.repository.RunningPartiesRepo; import geniusweb.partiesserver.repository.RunningParty; import geniusweb.party.Party; import tudelft.utilities.logging.ReportToLogger; import tudelft.utilities.logging.Reporter; /** * * This object keeps the {@link RunningPartiesRepo} up to date. Main job is to * remove parties that have been timed out. When a party times out, * it calls {@link Party#terminate()} but that might fail to stop a party. * In the end, the protocol should close the connection after the deadline. Start and run only once. */ public class RunningPartiesUpdater implements Runnable { private final long period; private final Reporter log = new ReportToLogger("partiesserver"); private final RunningPartiesRepo running; /** * when a negotiation runs out of time, the protocol may want to inform all * parties about the failed session. If the parties are all killed at that * moment, this is impossible. Therefore we wait KILL_DELAY extra time before * really killing the parties. */ private static final long KILL_DELAY = 2000; /** * @param repo the {@link RunningPartiesRepo} that must be updated * automatically * @param period the period with which to check time-out (ms). Recommended 1000. * After constructing you can run this in separate thread or just * call {@link #run()} * */ public RunningPartiesUpdater(RunningPartiesRepo repo, final long period) { this.running = repo; this.period = period; } /** * * run the updater. Please run only one of this to avoid neeedless CPU load. */ @Override public void run() { try { while (true) { Thread.sleep(period); update(); } } catch (InterruptedException e) { System.err.println("ERROR: RunningPartiesUpdater was interrupted!"); } } /** * Called when some file that may be relevant has changed. Synchronized to avoid * weird states if filesystem changes rapidly. We ignore everything but jar * files. */ void update() { for (RunningParty party : running.list()) { long now = System.currentTimeMillis(); if (now >= party.getEndDate().getTime() + KILL_DELAY) { running.remove(party.getID()); log.log(Level.WARNING, "party " + party.getID() + " still running 2s after deadline. Removed now."); } } } }