From 4c6aaa32b675d294bdbae4cdefec1077c2be9a3c Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 15 Mar 2015 11:42:00 +0000 Subject: [PATCH] Router javadocs, stub out class P, throw ISE instead of exit() if another router running --- router/java/src/net/i2p/router/Router.java | 183 ++++++++++++++++++--- 1 file changed, 164 insertions(+), 19 deletions(-) diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 680d18616c..0b580bc46b 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -64,6 +64,8 @@ import net.i2p.util.Translate; /** * Main driver for the router. * + * For embedded use, instantiate and then call runRouter(). + * */ public class Router implements RouterClock.ClockShiftListener { private Log _log; @@ -72,11 +74,11 @@ public class Router implements RouterClock.ClockShiftListener { /** full path */ private String _configFilename; private RouterInfo _routerInfo; + /** not for external use */ public final Object routerInfoFileLock = new Object(); private final Object _configFileLock = new Object(); private long _started; private boolean _higherVersionSeen; - //private SessionKeyPersistenceHelper _sessionKeyPersistenceHelper; private boolean _killVMOnEnd; private int _gracefulExitCode; private I2PThread.OOMEventListener _oomListener; @@ -108,7 +110,7 @@ public class Router implements RouterClock.ClockShiftListener { private final static String PROP_SHUTDOWN_IN_PROGRESS = "__shutdownInProgress"; private static final String PROP_IB_RANDOM_KEY = TunnelPoolSettings.PREFIX_INBOUND_EXPLORATORY + TunnelPoolSettings.PROP_RANDOM_KEY; private static final String PROP_OB_RANDOM_KEY = TunnelPoolSettings.PREFIX_OUTBOUND_EXPLORATORY + TunnelPoolSettings.PROP_RANDOM_KEY; - public final static String DNS_CACHE_TIME = "" + (5*60); + private final static String DNS_CACHE_TIME = "" + (5*60); private static final String EVENTLOG = "eventlog.txt"; private static final String PROP_JBIGI = "jbigi.loadedResource"; @@ -141,6 +143,9 @@ public class Router implements RouterClock.ClockShiftListener { * Instantiation only. Starts no threads. Does not install updates. * RouterContext is created but not initialized. * You must call runRouter() after any constructor to start things up. + * + * Config file name is "router.config" unless router.configLocation set in system properties. + * @throws IllegalStateException since 0.9.19 if another router with this config is running */ public Router() { this(null, null); } @@ -148,6 +153,11 @@ public class Router implements RouterClock.ClockShiftListener { * Instantiation only. Starts no threads. Does not install updates. * RouterContext is created but not initialized. * You must call runRouter() after any constructor to start things up. + * + * Config file name is "router.config" unless router.configLocation set in envProps or system properties. + * + * @param envProps may be null + * @throws IllegalStateException since 0.9.19 if another router with this config is running */ public Router(Properties envProps) { this(null, envProps); } @@ -155,6 +165,9 @@ public class Router implements RouterClock.ClockShiftListener { * Instantiation only. Starts no threads. Does not install updates. * RouterContext is created but not initialized. * You must call runRouter() after any constructor to start things up. + * + * @param configFilename may be null + * @throws IllegalStateException since 0.9.19 if another router with this config is running */ public Router(String configFilename) { this(configFilename, null); } @@ -162,6 +175,30 @@ public class Router implements RouterClock.ClockShiftListener { * Instantiation only. Starts no threads. Does not install updates. * RouterContext is created but not initialized. * You must call runRouter() after any constructor to start things up. + * + * If configFilename is non-null, configuration is read in from there. + * Else if envProps is non-null, configuration is read in from the + * location given in the router.configLocation property. + * Else it's read in from the System property router.configLocation. + * Else from the file "router.config". + * + * The most important properties are i2p.dir.base (the install directory, may be read-only) + * and i2p.dir.config (the user's configuration/data directory). + * + * i2p.dir.base defaults to user.dir (CWD) but should almost always be set. + * + * i2p.dir.config default depends on OS, user name (to detect if running as a service or not), + * and auto-detection of whether there appears to be previous data files in the base dir. + * See WorkingDir for details. + * If the config dir does not exist, it will be created, and files migrated from the base dir, + * in this constructor. + * If files in an existing config dir indicate that another router is already running + * with this directory, the constructor will delay for several seconds to be sure, + * and then call System.exit(-1). + * + * @param configFilename may be null + * @param envProps may be null + * @throws IllegalStateException since 0.9.19 if another router with this config is running */ public Router(String configFilename, Properties envProps) { _killVMOnEnd = true; @@ -273,7 +310,13 @@ public class Router implements RouterClock.ClockShiftListener { System.err.println(" Please make sure to shut down old instances before starting up"); System.err.println(" a new one. If you are positive that no other instance is running,"); System.err.println(" please delete the file " + getPingFile().getAbsolutePath()); - System.exit(-1); + //System.exit(-1); + // throw exception instead, for embedded + throw new IllegalStateException( + "ERROR: There appears to be another router already running!" + + " Please make sure to shut down old instances before starting up" + + " a new one. If you are positive that no other instance is running," + + " please delete the file " + getPingFile().getAbsolutePath()); } } @@ -338,7 +381,6 @@ public class Router implements RouterClock.ClockShiftListener { _higherVersionSeen = false; _log = _context.logManager().getLog(Router.class); _log.info("New router created with config file " + _configFilename); - //_sessionKeyPersistenceHelper = new SessionKeyPersistenceHelper(_context); _oomListener = new OOMListener(_context); _shutdownHook = new ShutdownHook(_context); @@ -353,7 +395,10 @@ public class Router implements RouterClock.ClockShiftListener { } - /** @since 0.8.8 */ + /** + * Not for external use. + * @since 0.8.8 + */ public static final void clearCaches() { ByteCache.clearAll(); SimpleByteCache.clearAll(); @@ -368,6 +413,7 @@ public class Router implements RouterClock.ClockShiftListener { /** * Configure the router to kill the JVM when the router shuts down, as well * as whether to explicitly halt the JVM during the hard fail process. + * * Defaults to true. Set to false for embedded before calling runRouter() */ public void setKillVMOnEnd(boolean shouldDie) { _killVMOnEnd = shouldDie; } @@ -422,12 +468,14 @@ public class Router implements RouterClock.ClockShiftListener { } /** - * Warning, may be null if called very early + * Our current router info. + * Warning, may be null if called very early. */ public RouterInfo getRouterInfo() { return _routerInfo; } /** - * Caller must ensure info is valid - no validation done here + * Caller must ensure info is valid - no validation done here. + * Not for external use. */ public void setRouterInfo(RouterInfo info) { _routerInfo = info; @@ -451,6 +499,9 @@ public class Router implements RouterClock.ClockShiftListener { */ public void setHigherVersionSeen(boolean seen) { _higherVersionSeen = seen; } + /** + * @deprecated unused + */ public long getWhenStarted() { return _started; } /** wall clock uptime */ @@ -459,6 +510,12 @@ public class Router implements RouterClock.ClockShiftListener { return Math.max(1, _context.clock().now() - _context.clock().getOffset() - _started); } + /** + * Non-null, but take care when accessing context items before runRouter() is called + * as the context will not be initialized. + * + * @return non-null + */ public RouterContext getContext() { return _context; } /** @@ -508,7 +565,6 @@ public class Router implements RouterClock.ClockShiftListener { //_context.jobQueue().addJob(new CoalesceStatsJob(_context)); _context.simpleScheduler().addPeriodicEvent(new CoalesceStatsEvent(_context), COALESCE_TIME); _context.jobQueue().addJob(new UpdateRoutingKeyModifierJob(_context)); - //_sessionKeyPersistenceHelper.startup(); //_context.adminManager().startup(); _context.blocklist().startup(); @@ -541,7 +597,8 @@ public class Router implements RouterClock.ClockShiftListener { * It does not clear the config first, so settings not found in * the file will remain in the config. * - * This is synchronized with saveConfig() + * This is synchronized with saveConfig(). + * Not for external use. */ public void readConfig() { synchronized(_configFileLock) { @@ -661,7 +718,8 @@ public class Router implements RouterClock.ClockShiftListener { } /** - * Only for Restarter, after soft restart is complete + * Only for Restarter, after soft restart is complete. + * Not for external use. * @since 0.8.12 */ public void setIsAlive() { @@ -669,7 +727,8 @@ public class Router implements RouterClock.ClockShiftListener { } /** - * Only for NetDB, after RIs are loaded + * Only for NetDB, after RIs are loaded. + * Not for external use. * @since 0.9.18 */ public void setNetDbReady() { @@ -682,7 +741,8 @@ public class Router implements RouterClock.ClockShiftListener { } /** - * Only for Tunnel Building, after we have non-zero-hop expl. tunnels + * Only for Tunnel Building, after we have non-zero-hop expl. tunnels. + * Not for external use. * @since 0.9.18 */ public void setExplTunnelsReady() { @@ -726,9 +786,15 @@ public class Router implements RouterClock.ClockShiftListener { /** * Rebuild and republish our routerInfo since something significant * has changed. + * Not for external use. */ public void rebuildRouterInfo() { rebuildRouterInfo(false); } + /** + * Rebuild and republish our routerInfo since something significant + * has changed. + * Not for external use. + */ public void rebuildRouterInfo(boolean blockingRebuild) { if (_log.shouldLog(Log.INFO)) _log.info("Rebuilding new routerInfo"); @@ -777,15 +843,20 @@ public class Router implements RouterClock.ClockShiftListener { public static final char CAPABILITY_BW512 = 'P'; /** @since 0.9.18 */ public static final char CAPABILITY_BW_UNLIMITED = 'X'; + /** for testing */ public static final String PROP_FORCE_BWCLASS = "router.forceBandwidthClass"; public static final char CAPABILITY_REACHABLE = 'R'; public static final char CAPABILITY_UNREACHABLE = 'U'; + /** for testing */ public static final String PROP_FORCE_UNREACHABLE = "router.forceUnreachable"; /** @deprecated unused */ public static final char CAPABILITY_NEW_TUNNEL = 'T'; + /** + * For building our RI. Not for external use. + */ public void addCapabilities(RouterInfo ri) { int bwLim = Math.min(_context.bandwidthLimiter().getInboundKBytesPerSecond(), _context.bandwidthLimiter().getOutboundKBytesPerSecond()); @@ -804,8 +875,13 @@ public class Router implements RouterClock.ClockShiftListener { ri.addCapability(CAPABILITY_BW64); } else if (bwLim <= 128) { ri.addCapability(CAPABILITY_BW128); - } else { // ok, more than 128KBps... aka "lots" - // TODO 512, unlimited + } else if (bwLim <= 256) { + ri.addCapability(CAPABILITY_BW256); + } else { + // 512 supported as of 0.9.18; + // Add 256 as well for compatibility + // TODO uncomment + //ri.addCapability(CAPABILITY_BW512); ri.addCapability(CAPABILITY_BW256); } @@ -871,6 +947,9 @@ public class Router implements RouterClock.ClockShiftListener { "sessionKeys.dat" // no longer used }; + /** + * Not for external use. + */ public void killKeys() { //new Exception("Clearing identity files").printStackTrace(); for (int i = 0; i < _rebuildFiles.length; i++) { @@ -899,6 +978,7 @@ public class Router implements RouterClock.ClockShiftListener { * Rebuild a new identity the hard way - delete all of our old identity * files, then reboot the router. * + * Not for external use. */ public synchronized void rebuildNewIdentity() { if (_shutdownHook != null) { @@ -946,14 +1026,21 @@ public class Router implements RouterClock.ClockShiftListener { //_context.inNetMessagePool().registerHandlerJobBuilder(TunnelMessage.MESSAGE_TYPE, new TunnelMessageHandler(_context)); } + /** shut down after all tunnels are gone */ public static final int EXIT_GRACEFUL = 2; + /** shut down immediately */ public static final int EXIT_HARD = 3; + /** shut down immediately */ public static final int EXIT_OOM = 10; + /** shut down immediately, and tell the wrapper to restart */ public static final int EXIT_HARD_RESTART = 4; + /** shut down after all tunnels are gone, and tell the wrapper to restart */ public static final int EXIT_GRACEFUL_RESTART = 5; /** - * Shutdown with no chance of cancellation + * Shutdown with no chance of cancellation. + * Blocking, will call exit() and not return unless setKillVMOnExit(false) was previously called. + * May take several seconds as it runs all the shutdown hooks. */ public synchronized void shutdown(int exitCode) { synchronized(_stateLock) { @@ -1112,6 +1199,8 @@ public class Router implements RouterClock.ClockShiftListener { } /** + * Non-blocking shutdown. + * * Call this if we want the router to kill itself as soon as we aren't * participating in any more tunnels (etc). This will not block and doesn't * guarantee any particular time frame for shutting down. To shut the @@ -1119,16 +1208,21 @@ public class Router implements RouterClock.ClockShiftListener { * the graceful shutdown (prior to actual shutdown ;), call * {@link #cancelGracefulShutdown}. * + * Shutdown delay will be from zero to 11 minutes. */ public void shutdownGracefully() { shutdownGracefully(EXIT_GRACEFUL); } /** + * Non-blocking shutdown. + * * Call this with EXIT_HARD or EXIT_HARD_RESTART for a non-blocking, * hard, non-graceful shutdown with a brief delay to allow a UI response * * Returns silently if a final shutdown is already in progress. + * + * @param exitCode VM exit code */ public void shutdownGracefully(int exitCode) { synchronized(_stateLock) { @@ -1168,7 +1262,10 @@ public class Router implements RouterClock.ClockShiftListener { */ public int scheduledGracefulExitCode() { return _gracefulExitCode; } - /** How long until the graceful shutdown will kill us? */ + /** + * How long until the graceful shutdown will kill us? + * @return -1 if no shutdown in progress. + */ public long getShutdownTimeRemaining() { if (_gracefulExitCode <= 0) return -1; // maybe Long.MAX_VALUE would be better? if (_gracefulExitCode == EXIT_HARD || _gracefulExitCode == EXIT_HARD_RESTART) @@ -1205,7 +1302,7 @@ public class Router implements RouterClock.ClockShiftListener { } /** - * Updates the current config and then saves it. + * Updates the current config with the given key/value and then saves it. * Prevents a race in the interval between setConfigSetting() / removeConfigSetting() and saveConfig(), * Synchronized with getConfig() / saveConfig() * @@ -1281,6 +1378,8 @@ public class Router implements RouterClock.ClockShiftListener { * * As of 0.8.8, this returns immediately and does the actual restart in a separate thread. * Poll isAlive() if you need to know when the restart is complete. + * + * Not recommended for external use. */ public synchronized void restart() { synchronized(_stateLock) { @@ -1302,6 +1401,9 @@ public class Router implements RouterClock.ClockShiftListener { * Instantiates Router(), and either installs updates and exits, * or calls runRouter(). * + * Not recommended for embedded use. + * Applications bundling I2P should instantiate a Router and call runRouter(). + * * @param args null ok * @throws IllegalArgumentException */ @@ -1331,7 +1433,13 @@ public class Router implements RouterClock.ClockShiftListener { System.out.println("Starting I2P " + RouterVersion.FULL_VERSION); //verifyWrapperConfig(); - Router r = new Router(); + Router r; + try { + r = new Router(); + } catch (IllegalStateException ise) { + System.exit(-1); + return; + } if (rebuild) { r.rebuildNewIdentity(); } else { @@ -1560,7 +1668,7 @@ public class Router implements RouterClock.ClockShiftListener { return f; } - static final long LIVELINESS_DELAY = 60*1000; + private static final long LIVELINESS_DELAY = 60*1000; /** * Check the file "router.ping", but if @@ -1619,8 +1727,15 @@ public class Router implements RouterClock.ClockShiftListener { return DEFAULT_SHARE_PERCENTAGE / 100.0d; } + /** + * Max of inbound and outbound rate in bytes per second + */ public int get1sRate() { return get1sRate(false); } + /** + * When outboundOnly is false, outbound rate in bytes per second. + * When true, max of inbound and outbound rate in bytes per second. + */ public int get1sRate(boolean outboundOnly) { FIFOBandwidthLimiter bw = _context.bandwidthLimiter(); int out = (int)bw.getSendBps(); @@ -1629,13 +1744,23 @@ public class Router implements RouterClock.ClockShiftListener { return (int)Math.max(out, bw.getReceiveBps()); } + /** + * Inbound rate in bytes per second + */ public int get1sRateIn() { FIFOBandwidthLimiter bw = _context.bandwidthLimiter(); return (int) bw.getReceiveBps(); } + /** + * Max of inbound and outbound rate in bytes per second + */ public int get15sRate() { return get15sRate(false); } + /** + * When outboundOnly is false, outbound rate in bytes per second. + * When true, max of inbound and outbound rate in bytes per second. + */ public int get15sRate(boolean outboundOnly) { FIFOBandwidthLimiter bw = _context.bandwidthLimiter(); int out = (int)bw.getSendBps15s(); @@ -1644,13 +1769,23 @@ public class Router implements RouterClock.ClockShiftListener { return (int)Math.max(out, bw.getReceiveBps15s()); } + /** + * Inbound rate in bytes per second + */ public int get15sRateIn() { FIFOBandwidthLimiter bw = _context.bandwidthLimiter(); return (int) bw.getReceiveBps15s(); } + /** + * Max of inbound and outbound rate in bytes per second + */ public int get1mRate() { return get1mRate(false); } + /** + * When outboundOnly is false, outbound rate in bytes per second. + * When true, max of inbound and outbound rate in bytes per second. + */ public int get1mRate(boolean outboundOnly) { int send = 0; StatManager mgr = _context.statManager(); @@ -1666,6 +1801,9 @@ public class Router implements RouterClock.ClockShiftListener { return Math.max(send, recv); } + /** + * Inbound rate in bytes per second + */ public int get1mRateIn() { StatManager mgr = _context.statManager(); RateStat rs = mgr.getRate("bw.recvRate"); @@ -1675,8 +1813,15 @@ public class Router implements RouterClock.ClockShiftListener { return recv; } + /** + * Max of inbound and outbound rate in bytes per second + */ public int get5mRate() { return get5mRate(false); } + /** + * When outboundOnly is false, outbound rate in bytes per second. + * When true, max of inbound and outbound rate in bytes per second. + */ public int get5mRate(boolean outboundOnly) { int send = 0; RateStat rs = _context.statManager().getRate("bw.sendRate"); -- GitLab