From c0b9fe034021344e0f787a90a50aabdf87d685c6 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 29 Nov 2011 15:25:40 +0000 Subject: [PATCH] * Router: Refactor periodic tasks to their own files --- apps/routerconsole/java/bundle-messages.sh | 2 +- router/java/src/net/i2p/router/Router.java | 248 +----------------- .../i2p/router/tasks/CoalesceStatsEvent.java | 107 ++++++++ .../net/i2p/router/tasks/MarkLiveliness.java | 55 ++++ .../router/tasks/PersistRouterInfoJob.java | 59 +++++ .../src/net/i2p/router/tasks/Republish.java | 38 +++ .../router/{ => tasks}/RouterWatchdog.java | 7 +- .../net/i2p/router/tasks/ShutdownHook.java | 37 +++ .../src/net/i2p/router/tasks/Spinner.java | 24 ++ .../tasks/UpdateRoutingKeyModifierJob.java | 61 +++++ .../src/net/i2p/router/tasks/package.html | 9 + 11 files changed, 403 insertions(+), 244 deletions(-) create mode 100644 router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java create mode 100644 router/java/src/net/i2p/router/tasks/MarkLiveliness.java create mode 100644 router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java create mode 100644 router/java/src/net/i2p/router/tasks/Republish.java rename router/java/src/net/i2p/router/{ => tasks}/RouterWatchdog.java (97%) create mode 100644 router/java/src/net/i2p/router/tasks/ShutdownHook.java create mode 100644 router/java/src/net/i2p/router/tasks/Spinner.java create mode 100644 router/java/src/net/i2p/router/tasks/UpdateRoutingKeyModifierJob.java create mode 100644 router/java/src/net/i2p/router/tasks/package.html diff --git a/apps/routerconsole/java/bundle-messages.sh b/apps/routerconsole/java/bundle-messages.sh index e75e0d8976..dd3ea83224 100755 --- a/apps/routerconsole/java/bundle-messages.sh +++ b/apps/routerconsole/java/bundle-messages.sh @@ -44,7 +44,7 @@ fi # list specific files in core/ and router/ here, so we don't scan the whole tree ROUTERFILES="\ ../../../core/java/src/net/i2p/data/DataHelper.java \ - ../../../router/java/src/net/i2p/router/Router.java \ + ../../../router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java \ ../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \ ../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \ ../../../router/java/src/net/i2p/router/transport/TransportManager.java \ diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 77994bdb3a..b2ca9c5e9b 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -15,11 +15,8 @@ import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.Writer; -import java.text.DecimalFormat; -import java.util.Calendar; import java.util.Collections; import java.util.Date; -import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -43,9 +40,9 @@ import net.i2p.router.message.GarlicMessageHandler; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.startup.StartupJob; import net.i2p.router.startup.WorkingDir; +import net.i2p.router.tasks.*; import net.i2p.router.transport.FIFOBandwidthLimiter; import net.i2p.router.transport.udp.UDPTransport; -import net.i2p.stat.Rate; import net.i2p.stat.RateStat; import net.i2p.stat.StatManager; import net.i2p.util.ByteCache; @@ -57,7 +54,6 @@ import net.i2p.util.Log; import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SimpleByteCache; import net.i2p.util.SimpleScheduler; -import net.i2p.util.SimpleTimer; /** * Main driver for the router. @@ -94,7 +90,7 @@ public class Router implements RouterClock.ClockShiftListener { public static final int NETWORK_ID = 2; /** coalesce stats this often - should be a little less than one minute, so the graphs get updated */ - private static final int COALESCE_TIME = 50*1000; + public static final int COALESCE_TIME = 50*1000; /** this puts an 'H' in your routerInfo **/ public final static String PROP_HIDDEN = "router.hiddenMode"; @@ -310,7 +306,7 @@ public class Router implements RouterClock.ClockShiftListener { } /** @since 0.8.8 */ - private static final void clearCaches() { + public static final void clearCaches() { ByteCache.clearAll(); SimpleByteCache.clearAll(); } @@ -510,7 +506,7 @@ public class Router implements RouterClock.ClockShiftListener { setRouterInfo(ri); if (!ri.isValid()) throw new DataFormatException("Our RouterInfo has a bad signature"); - Republish r = new Republish(); + Republish r = new Republish(_context); if (blockingRebuild) r.timeReached(); else @@ -519,18 +515,7 @@ public class Router implements RouterClock.ClockShiftListener { _log.log(Log.CRIT, "Internal error - unable to sign our own address?!", dfe); } } - - private class Republish implements SimpleTimer.TimedEvent { - public void timeReached() { - try { - _context.netDb().publish(getRouterInfo()); - } catch (IllegalArgumentException iae) { - _log.log(Log.CRIT, "Local router info is invalid? rebuilding a new identity", iae); - rebuildNewIdentity(); - } - } - } - + // publicize our ballpark capacity public static final char CAPABILITY_BW12 = 'K'; public static final char CAPABILITY_BW32 = 'L'; @@ -1032,8 +1017,9 @@ public class Router implements RouterClock.ClockShiftListener { /** * Cancel the JVM runtime hook before calling this. + * NOT to be called by others, use shutdown(). */ - private void shutdown2(int exitCode) { + public void shutdown2(int exitCode) { // So we can get all the way to the end // No, you can't do Thread.currentThread.setDaemon(false) if (_killVMOnEnd) { @@ -1739,224 +1725,4 @@ public class Router implements RouterClock.ClockShiftListener { recv = (int)rs.getRate(5*60*1000).getAverageValue(); return Math.max(send, recv); } - - /** - * Mark a string for extraction by xgettext and translation. - * Use this only in static initializers. - * It does not translate! - * @return s - * @since 0.8.7 - */ - private static final String _x(String s) { - return s; - } - -/* following classes are now private static inner classes, didn't bother to reindent */ - -private static final long LOW_MEMORY_THRESHOLD = 5 * 1024 * 1024; - -/** - * coalesce the stats framework every minute - * - */ -private static class CoalesceStatsEvent implements SimpleTimer.TimedEvent { - private RouterContext _ctx; - private long _maxMemory; - - public CoalesceStatsEvent(RouterContext ctx) { - _ctx = ctx; - // NOTE TO TRANSLATORS - each of these phrases is a description for a statistic - // to be displayed on /stats.jsp and in the graphs on /graphs.jsp. - // Please keep relatively short so it will fit on the graphs. - ctx.statManager().createRequiredRateStat("bw.receiveBps", _x("Message receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); - ctx.statManager().createRequiredRateStat("bw.sendBps", _x("Message send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); - ctx.statManager().createRequiredRateStat("bw.sendRate", _x("Low-level send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); - ctx.statManager().createRequiredRateStat("bw.recvRate", _x("Low-level receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); - ctx.statManager().createRequiredRateStat("router.activePeers", _x("How many peers we are actively talking with"), "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); - ctx.statManager().createRateStat("router.activeSendPeers", "How many peers we've sent to this minute", "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); - ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 }); - ctx.statManager().createRequiredRateStat("router.fastPeers", _x("Known fast peers"), "Throttle", new long[] { 5*60*1000, 60*60*1000 }); - _maxMemory = Runtime.getRuntime().maxMemory(); - String legend = "(Bytes)"; - if (_maxMemory < Long.MAX_VALUE) - legend += " Max is " + DataHelper.formatSize(_maxMemory) + 'B'; - // router.memoryUsed currently has the max size in the description so it can't be tagged - ctx.statManager().createRequiredRateStat("router.memoryUsed", legend, "Router", new long[] { 60*1000 }); - } - private RouterContext getContext() { return _ctx; } - public void timeReached() { - int active = getContext().commSystem().countActivePeers(); - getContext().statManager().addRateData("router.activePeers", active, 60*1000); - - int activeSend = getContext().commSystem().countActiveSendPeers(); - getContext().statManager().addRateData("router.activeSendPeers", activeSend, 60*1000); - - int fast = getContext().profileOrganizer().countFastPeers(); - getContext().statManager().addRateData("router.fastPeers", fast, 60*1000); - - int highCap = getContext().profileOrganizer().countHighCapacityPeers(); - getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000); - - getContext().statManager().addRateData("bw.sendRate", (long)getContext().bandwidthLimiter().getSendBps(), 0); - getContext().statManager().addRateData("bw.recvRate", (long)getContext().bandwidthLimiter().getReceiveBps(), 0); - - long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - getContext().statManager().addRateData("router.memoryUsed", used, 0); - if (_maxMemory - used < LOW_MEMORY_THRESHOLD) - clearCaches(); - - getContext().tunnelDispatcher().updateParticipatingStats(COALESCE_TIME); - - getContext().statManager().coalesceStats(); - - RateStat receiveRate = getContext().statManager().getRate("transport.receiveMessageSize"); - if (receiveRate != null) { - Rate rate = receiveRate.getRate(60*1000); - if (rate != null) { - double bytes = rate.getLastTotalValue(); - double bps = (bytes*1000.0d)/rate.getPeriod(); - getContext().statManager().addRateData("bw.receiveBps", (long)bps, 60*1000); - } - } - - RateStat sendRate = getContext().statManager().getRate("transport.sendMessageSize"); - if (sendRate != null) { - Rate rate = sendRate.getRate(60*1000); - if (rate != null) { - double bytes = rate.getLastTotalValue(); - double bps = (bytes*1000.0d)/rate.getPeriod(); - getContext().statManager().addRateData("bw.sendBps", (long)bps, 60*1000); - } - } - } -} - -/** - * Update the routing Key modifier every day at midnight (plus on startup). - * This is done here because we want to make sure the key is updated before anyone - * uses it. - */ -private static class UpdateRoutingKeyModifierJob extends JobImpl { - private Log _log; - private Calendar _cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - public UpdateRoutingKeyModifierJob(RouterContext ctx) { - super(ctx); - } - public String getName() { return "Update Routing Key Modifier"; } - public void runJob() { - _log = getContext().logManager().getLog(getClass()); - getContext().routingKeyGenerator().generateDateBasedModData(); - requeue(getTimeTillMidnight()); - } - private long getTimeTillMidnight() { - long now = getContext().clock().now(); - _cal.setTime(new Date(now)); - _cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround - _cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround - _cal.add(Calendar.DATE, 1); - _cal.set(Calendar.HOUR_OF_DAY, 0); - _cal.set(Calendar.MINUTE, 0); - _cal.set(Calendar.SECOND, 0); - _cal.set(Calendar.MILLISECOND, 0); - long then = _cal.getTime().getTime(); - long howLong = then - now; - if (howLong < 0) // hi kaffe - howLong = 24*60*60*1000l + howLong; - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Time till midnight: " + howLong + "ms"); - return howLong; - } -} - -/** - * Write a timestamp to the ping file where - * other routers trying to use the same configuration can see it - */ -private static class MarkLiveliness implements SimpleTimer.TimedEvent { - private final Router _router; - private final File _pingFile; - - public MarkLiveliness(Router router, File pingFile) { - _router = router; - _pingFile = pingFile; - _pingFile.deleteOnExit(); - } - - public void timeReached() { - if (_router.isAlive()) - ping(); - else - _pingFile.delete(); - } - - private void ping() { - FileOutputStream fos = null; - try { - fos = new SecureFileOutputStream(_pingFile); - fos.write(("" + System.currentTimeMillis()).getBytes()); - } catch (IOException ioe) { - System.err.println("Error writing to ping file"); - ioe.printStackTrace(); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - } -} - -/** - * Just for failsafe. Standard shutdown should cancel this. - */ -private static class ShutdownHook extends Thread { - private final RouterContext _context; - private static int __id = 0; - private final int _id; - - public ShutdownHook(RouterContext ctx) { - _context = ctx; - _id = ++__id; - } - - @Override - public void run() { - setName("Router " + _id + " shutdown"); - Log l = _context.logManager().getLog(Router.class); - l.log(Log.CRIT, "Shutting down the router..."); - _context.router().shutdown2(Router.EXIT_HARD); - } -} - -/** update the router.info file whenever its, er, updated */ -private static class PersistRouterInfoJob extends JobImpl { - public PersistRouterInfoJob(RouterContext ctx) { - super(ctx); - } - - public String getName() { return "Persist Updated Router Information"; } - - public void runJob() { - Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Persisting updated router info"); - - String infoFilename = getContext().getProperty(PROP_INFO_FILENAME, PROP_INFO_FILENAME_DEFAULT); - File infoFile = new File(getContext().getRouterDir(), infoFilename); - - RouterInfo info = getContext().router().getRouterInfo(); - - FileOutputStream fos = null; - synchronized (getContext().router().routerInfoFileLock) { - try { - fos = new SecureFileOutputStream(infoFile); - info.writeBytes(fos); - } catch (DataFormatException dfe) { - _log.error("Error rebuilding the router information", dfe); - } catch (IOException ioe) { - _log.error("Error writing out the rebuilt router information", ioe); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - } - } -} - } diff --git a/router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java b/router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java new file mode 100644 index 0000000000..bb6613f1fa --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java @@ -0,0 +1,107 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataHelper; +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.stat.Rate; +import net.i2p.stat.RateStat; +import net.i2p.util.SimpleTimer; + +/** + * Coalesce the stats framework every minute + * + * @since 0.8.12 moved from Router.java + */ +public class CoalesceStatsEvent implements SimpleTimer.TimedEvent { + private final RouterContext _ctx; + private final long _maxMemory; + private static final long LOW_MEMORY_THRESHOLD = 5 * 1024 * 1024; + + public CoalesceStatsEvent(RouterContext ctx) { + _ctx = ctx; + // NOTE TO TRANSLATORS - each of these phrases is a description for a statistic + // to be displayed on /stats.jsp and in the graphs on /graphs.jsp. + // Please keep relatively short so it will fit on the graphs. + ctx.statManager().createRequiredRateStat("bw.receiveBps", _x("Message receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); + ctx.statManager().createRequiredRateStat("bw.sendBps", _x("Message send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); + ctx.statManager().createRequiredRateStat("bw.sendRate", _x("Low-level send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); + ctx.statManager().createRequiredRateStat("bw.recvRate", _x("Low-level receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); + ctx.statManager().createRequiredRateStat("router.activePeers", _x("How many peers we are actively talking with"), "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); + ctx.statManager().createRateStat("router.activeSendPeers", "How many peers we've sent to this minute", "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); + ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 }); + ctx.statManager().createRequiredRateStat("router.fastPeers", _x("Known fast peers"), "Throttle", new long[] { 5*60*1000, 60*60*1000 }); + _maxMemory = Runtime.getRuntime().maxMemory(); + String legend = "(Bytes)"; + if (_maxMemory < Long.MAX_VALUE) + legend += " Max is " + DataHelper.formatSize(_maxMemory) + 'B'; + // router.memoryUsed currently has the max size in the description so it can't be tagged + ctx.statManager().createRequiredRateStat("router.memoryUsed", legend, "Router", new long[] { 60*1000 }); + } + + private RouterContext getContext() { return _ctx; } + + public void timeReached() { + int active = getContext().commSystem().countActivePeers(); + getContext().statManager().addRateData("router.activePeers", active, 60*1000); + + int activeSend = getContext().commSystem().countActiveSendPeers(); + getContext().statManager().addRateData("router.activeSendPeers", activeSend, 60*1000); + + int fast = getContext().profileOrganizer().countFastPeers(); + getContext().statManager().addRateData("router.fastPeers", fast, 60*1000); + + int highCap = getContext().profileOrganizer().countHighCapacityPeers(); + getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000); + + getContext().statManager().addRateData("bw.sendRate", (long)getContext().bandwidthLimiter().getSendBps()); + getContext().statManager().addRateData("bw.recvRate", (long)getContext().bandwidthLimiter().getReceiveBps()); + + long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + getContext().statManager().addRateData("router.memoryUsed", used); + if (_maxMemory - used < LOW_MEMORY_THRESHOLD) + Router.clearCaches(); + + getContext().tunnelDispatcher().updateParticipatingStats(Router.COALESCE_TIME); + + getContext().statManager().coalesceStats(); + + RateStat receiveRate = getContext().statManager().getRate("transport.receiveMessageSize"); + if (receiveRate != null) { + Rate rate = receiveRate.getRate(60*1000); + if (rate != null) { + double bytes = rate.getLastTotalValue(); + double bps = (bytes*1000.0d)/rate.getPeriod(); + getContext().statManager().addRateData("bw.receiveBps", (long)bps, 60*1000); + } + } + + RateStat sendRate = getContext().statManager().getRate("transport.sendMessageSize"); + if (sendRate != null) { + Rate rate = sendRate.getRate(60*1000); + if (rate != null) { + double bytes = rate.getLastTotalValue(); + double bps = (bytes*1000.0d)/rate.getPeriod(); + getContext().statManager().addRateData("bw.sendBps", (long)bps, 60*1000); + } + } + } + + /** + * Mark a string for extraction by xgettext and translation. + * Use this only in static initializers. + * It does not translate! + * @return s + * @since 0.8.7 + */ + private static final String _x(String s) { + return s; + } +} diff --git a/router/java/src/net/i2p/router/tasks/MarkLiveliness.java b/router/java/src/net/i2p/router/tasks/MarkLiveliness.java new file mode 100644 index 0000000000..9c9f4f1291 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/MarkLiveliness.java @@ -0,0 +1,55 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import net.i2p.router.Router; +import net.i2p.util.SecureFileOutputStream; +import net.i2p.util.SimpleTimer; + +/** + * Write a timestamp to the ping file where + * other routers trying to use the same configuration can see it + * + * @since 0.8.12 moved from Router.java + */ +public class MarkLiveliness implements SimpleTimer.TimedEvent { + private final Router _router; + private final File _pingFile; + + public MarkLiveliness(Router router, File pingFile) { + _router = router; + _pingFile = pingFile; + _pingFile.deleteOnExit(); + } + + public void timeReached() { + if (_router.isAlive()) + ping(); + else + _pingFile.delete(); + } + + private void ping() { + FileOutputStream fos = null; + try { + fos = new SecureFileOutputStream(_pingFile); + fos.write(("" + System.currentTimeMillis()).getBytes()); + } catch (IOException ioe) { + System.err.println("Error writing to ping file"); + ioe.printStackTrace(); + } finally { + if (fos != null) try { fos.close(); } catch (IOException ioe) {} + } + } +} + diff --git a/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java b/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java new file mode 100644 index 0000000000..c29dd25772 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java @@ -0,0 +1,59 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import net.i2p.data.DataFormatException; +import net.i2p.data.RouterInfo; +import net.i2p.router.JobImpl; +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; +import net.i2p.util.SecureFileOutputStream; + +/** + * Update the router.info file whenever its, er, updated + * + * @since 0.8.12 moved from Router.java + */ +public class PersistRouterInfoJob extends JobImpl { + public PersistRouterInfoJob(RouterContext ctx) { + super(ctx); + } + + public String getName() { return "Persist Updated Router Information"; } + + public void runJob() { + Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Persisting updated router info"); + + String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT); + File infoFile = new File(getContext().getRouterDir(), infoFilename); + + RouterInfo info = getContext().router().getRouterInfo(); + + FileOutputStream fos = null; + synchronized (getContext().router().routerInfoFileLock) { + try { + fos = new SecureFileOutputStream(infoFile); + info.writeBytes(fos); + } catch (DataFormatException dfe) { + _log.error("Error rebuilding the router information", dfe); + } catch (IOException ioe) { + _log.error("Error writing out the rebuilt router information", ioe); + } finally { + if (fos != null) try { fos.close(); } catch (IOException ioe) {} + } + } + } +} diff --git a/router/java/src/net/i2p/router/tasks/Republish.java b/router/java/src/net/i2p/router/tasks/Republish.java new file mode 100644 index 0000000000..111456b896 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/Republish.java @@ -0,0 +1,38 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.util.SimpleTimer; +import net.i2p.util.Log; + +/** + * Periodically publish our RouterInfo to the netdb + * + * @since 0.8.12 moved from Router.java + */ +public class Republish implements SimpleTimer.TimedEvent { + private final RouterContext _context; + + public Republish(RouterContext ctx) { + _context = ctx; + } + + public void timeReached() { + try { + _context.netDb().publish(_context.router().getRouterInfo()); + } catch (IllegalArgumentException iae) { + Log log = _context.logManager().getLog(Router.class); + log.log(Log.CRIT, "Local router info is invalid? rebuilding a new identity", iae); + _context.router().rebuildNewIdentity(); + } + } +} + diff --git a/router/java/src/net/i2p/router/RouterWatchdog.java b/router/java/src/net/i2p/router/tasks/RouterWatchdog.java similarity index 97% rename from router/java/src/net/i2p/router/RouterWatchdog.java rename to router/java/src/net/i2p/router/tasks/RouterWatchdog.java index 80d7d9bcc9..7cc029b77a 100644 --- a/router/java/src/net/i2p/router/RouterWatchdog.java +++ b/router/java/src/net/i2p/router/tasks/RouterWatchdog.java @@ -1,8 +1,11 @@ -package net.i2p.router; +package net.i2p.router.tasks; import java.io.File; import net.i2p.data.DataHelper; +import net.i2p.router.Job; +import net.i2p.router.Router; +import net.i2p.router.RouterContext; import net.i2p.stat.Rate; import net.i2p.stat.RateStat; import net.i2p.util.ShellCommand; @@ -13,7 +16,7 @@ import net.i2p.util.Log; * they have, restart the JVM) * */ -class RouterWatchdog implements Runnable { +public class RouterWatchdog implements Runnable { private final Log _log; private final RouterContext _context; private int _consecutiveErrors; diff --git a/router/java/src/net/i2p/router/tasks/ShutdownHook.java b/router/java/src/net/i2p/router/tasks/ShutdownHook.java new file mode 100644 index 0000000000..9bc57d6435 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/ShutdownHook.java @@ -0,0 +1,37 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +/** + * Just for failsafe. Standard shutdown should cancel this. + * + * @since 0.8.12 moved from Router.java + */ +public class ShutdownHook extends Thread { + private final RouterContext _context; + private static int __id = 0; + private final int _id; + + public ShutdownHook(RouterContext ctx) { + _context = ctx; + _id = ++__id; + } + + @Override + public void run() { + setName("Router " + _id + " shutdown"); + Log l = _context.logManager().getLog(Router.class); + l.log(Log.CRIT, "Shutting down the router..."); + _context.router().shutdown2(Router.EXIT_HARD); + } +} diff --git a/router/java/src/net/i2p/router/tasks/Spinner.java b/router/java/src/net/i2p/router/tasks/Spinner.java new file mode 100644 index 0000000000..99c4f9ef30 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/Spinner.java @@ -0,0 +1,24 @@ +package net.i2p.router.tasks; + +/** + * A non-daemon thread to let + * the shutdown task get all the way to the end + * + * @since 0.8.12 moved from Router.java + */ +public class Spinner extends Thread { + + public Spinner() { + super(); + setName("Shutdown Spinner"); + setDaemon(false); + } + + @Override + public void run() { + try { + sleep(60*1000); + } catch (InterruptedException ie) {} + } +} + diff --git a/router/java/src/net/i2p/router/tasks/UpdateRoutingKeyModifierJob.java b/router/java/src/net/i2p/router/tasks/UpdateRoutingKeyModifierJob.java new file mode 100644 index 0000000000..600292e025 --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/UpdateRoutingKeyModifierJob.java @@ -0,0 +1,61 @@ +package net.i2p.router.tasks; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import net.i2p.router.JobImpl; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +/** + * Update the routing Key modifier every day at midnight (plus on startup). + * This is done here because we want to make sure the key is updated before anyone + * uses it. + * + * @since 0.8.12 moved from Router.java + */ +public class UpdateRoutingKeyModifierJob extends JobImpl { + private Log _log; + private Calendar _cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + public UpdateRoutingKeyModifierJob(RouterContext ctx) { + super(ctx); + } + + public String getName() { return "Update Routing Key Modifier"; } + + public void runJob() { + _log = getContext().logManager().getLog(getClass()); + getContext().routingKeyGenerator().generateDateBasedModData(); + requeue(getTimeTillMidnight()); + } + + private long getTimeTillMidnight() { + long now = getContext().clock().now(); + _cal.setTime(new Date(now)); + _cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround + _cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround + _cal.add(Calendar.DATE, 1); + _cal.set(Calendar.HOUR_OF_DAY, 0); + _cal.set(Calendar.MINUTE, 0); + _cal.set(Calendar.SECOND, 0); + _cal.set(Calendar.MILLISECOND, 0); + long then = _cal.getTime().getTime(); + long howLong = then - now; + if (howLong < 0) // hi kaffe + howLong = 24*60*60*1000l + howLong; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Time till midnight: " + howLong + "ms"); + return howLong; + } +} diff --git a/router/java/src/net/i2p/router/tasks/package.html b/router/java/src/net/i2p/router/tasks/package.html new file mode 100644 index 0000000000..e032edd6cb --- /dev/null +++ b/router/java/src/net/i2p/router/tasks/package.html @@ -0,0 +1,9 @@ +<html> +<body> +<p> +Miscellaneous classes, mostly things that are executed periodically as +Jobs, Threads, and SimpleTimer.TimedEvents. +These are used only by Router.java. +</p> +</body> +</html> -- GitLab