2004-04-08 04:41:54 +00:00
package net.i2p.router ;
/ *
* 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 .
*
* /
2004-07-31 23:25:02 +00:00
import java.io.File ;
2004-04-08 04:41:54 +00:00
import java.io.FileOutputStream ;
2004-07-31 23:25:02 +00:00
import java.io.FileInputStream ;
2004-04-08 04:41:54 +00:00
import java.io.IOException ;
2004-07-09 05:29:02 +00:00
import java.io.OutputStream ;
2004-04-08 04:41:54 +00:00
import java.text.DecimalFormat ;
import java.util.Calendar ;
import java.util.Date ;
import java.util.GregorianCalendar ;
import java.util.HashSet ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Properties ;
import java.util.Set ;
import java.util.TimeZone ;
2004-07-31 23:25:02 +00:00
import java.util.TreeSet ;
2004-04-08 04:41:54 +00:00
import net.i2p.CoreVersion ;
import net.i2p.crypto.DHSessionKeyBuilder ;
import net.i2p.data.DataFormatException ;
2004-04-10 11:39:00 +00:00
import net.i2p.data.DataHelper ;
2004-04-08 04:41:54 +00:00
import net.i2p.data.RouterInfo ;
import net.i2p.data.i2np.GarlicMessage ;
import net.i2p.data.i2np.TunnelMessage ;
import net.i2p.router.message.GarlicMessageHandler ;
import net.i2p.router.message.TunnelMessageHandler ;
import net.i2p.router.startup.StartupJob ;
2004-04-10 11:39:00 +00:00
import net.i2p.stat.Rate ;
import net.i2p.stat.RateStat ;
2004-04-08 04:41:54 +00:00
import net.i2p.util.I2PThread ;
import net.i2p.util.Log ;
/ * *
* Main driver for the router .
*
* /
public class Router {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
private Log _log ;
private RouterContext _context ;
2004-04-08 04:41:54 +00:00
private Properties _config ;
private String _configFilename ;
private RouterInfo _routerInfo ;
private long _started ;
private boolean _higherVersionSeen ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
private SessionKeyPersistenceHelper _sessionKeyPersistenceHelper ;
2004-04-26 03:30:20 +00:00
private boolean _killVMOnEnd ;
private boolean _isAlive ;
2004-09-06 05:20:40 +00:00
private int _gracefulExitCode ;
2004-04-26 03:30:20 +00:00
private I2PThread . OOMEventListener _oomListener ;
private ShutdownHook _shutdownHook ;
2004-08-23 07:33:14 +00:00
private I2PThread _gracefulShutdownDetector ;
2004-09-07 07:17:02 +00:00
private Set _shutdownTasks ;
2004-04-08 04:41:54 +00:00
public final static String PROP_CONFIG_FILE = " router.configLocation " ;
/** let clocks be off by 1 minute */
public final static long CLOCK_FUDGE_FACTOR = 1 * 60 * 1000 ;
public final static String PROP_INFO_FILENAME = " router.info.location " ;
public final static String PROP_INFO_FILENAME_DEFAULT = " router.info " ;
public final static String PROP_KEYS_FILENAME = " router.keys.location " ;
public final static String PROP_KEYS_FILENAME_DEFAULT = " router.keys " ;
2004-08-23 07:33:14 +00:00
public final static String PROP_SHUTDOWN_IN_PROGRESS = " __shutdownInProgress " ;
2004-04-08 04:41:54 +00:00
2004-04-26 03:30:20 +00:00
static {
2004-04-20 07:06:39 +00:00
// grumble about sun's java caching DNS entries *forever*
System . setProperty ( " sun.net.inetaddr.ttl " , " 0 " ) ;
System . setProperty ( " networkaddress.cache.ttl " , " 0 " ) ;
// (no need for keepalive)
System . setProperty ( " http.keepAlive " , " false " ) ;
2004-04-26 03:30:20 +00:00
}
public Router ( ) { this ( null , null ) ; }
public Router ( Properties envProps ) { this ( null , envProps ) ; }
public Router ( String configFilename ) { this ( configFilename , null ) ; }
public Router ( String configFilename , Properties envProps ) {
2004-09-04 21:54:08 +00:00
if ( ! beginMarkingLiveliness ( envProps ) ) {
System . err . println ( " ERROR: There appears to be another router already running! " ) ;
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 ( envProps ) ) ;
System . exit ( - 1 ) ;
}
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_config = new Properties ( ) ;
2004-04-26 03:30:20 +00:00
_context = new RouterContext ( this , envProps ) ;
if ( configFilename = = null )
_configFilename = _context . getProperty ( PROP_CONFIG_FILE , " router.config " ) ;
else
_configFilename = configFilename ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_routerInfo = null ;
_higherVersionSeen = false ;
_log = _context . logManager ( ) . getLog ( Router . class ) ;
2004-04-26 03:30:20 +00:00
_log . info ( " New router created with config file " + _configFilename ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_sessionKeyPersistenceHelper = new SessionKeyPersistenceHelper ( _context ) ;
2004-04-26 03:30:20 +00:00
_killVMOnEnd = true ;
_oomListener = new I2PThread . OOMEventListener ( ) {
public void outOfMemory ( OutOfMemoryError oom ) {
_log . log ( Log . CRIT , " Thread ran out of memory " , oom ) ;
2004-06-20 01:18:31 +00:00
for ( int i = 0 ; i < 5 ; i + + ) { // try this 5 times, in case it OOMs
try {
_log . log ( Log . CRIT , " free mem: " + Runtime . getRuntime ( ) . freeMemory ( ) +
" total mem: " + Runtime . getRuntime ( ) . totalMemory ( ) ) ;
break ; // w00t
} catch ( OutOfMemoryError oome ) {
// gobble
}
}
2004-08-23 21:34:22 +00:00
shutdown ( EXIT_OOM ) ;
2004-04-26 03:30:20 +00:00
}
} ;
_shutdownHook = new ShutdownHook ( ) ;
2004-08-23 07:33:14 +00:00
_gracefulShutdownDetector = new I2PThread ( new GracefulShutdown ( ) ) ;
2004-08-24 03:19:54 +00:00
_gracefulShutdownDetector . setDaemon ( true ) ;
_gracefulShutdownDetector . setName ( " Graceful shutdown hook " ) ;
2004-08-23 07:33:14 +00:00
_gracefulShutdownDetector . start ( ) ;
2004-09-07 07:17:02 +00:00
_shutdownTasks = new HashSet ( 0 ) ;
2004-04-08 04:41:54 +00:00
}
2004-04-26 03:30:20 +00:00
/ * *
* 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 .
*
* /
public void setKillVMOnEnd ( boolean shouldDie ) { _killVMOnEnd = shouldDie ; }
public boolean getKillVMOnEnd ( ) { return _killVMOnEnd ; }
2004-04-08 04:41:54 +00:00
public String getConfigFilename ( ) { return _configFilename ; }
public void setConfigFilename ( String filename ) { _configFilename = filename ; }
public String getConfigSetting ( String name ) { return _config . getProperty ( name ) ; }
public void setConfigSetting ( String name , String value ) { _config . setProperty ( name , value ) ; }
2004-08-16 20:27:06 +00:00
public void removeConfigSetting ( String name ) { _config . remove ( name ) ; }
2004-04-08 04:41:54 +00:00
public Set getConfigSettings ( ) { return new HashSet ( _config . keySet ( ) ) ; }
public Properties getConfigMap ( ) { return _config ; }
public RouterInfo getRouterInfo ( ) { return _routerInfo ; }
public void setRouterInfo ( RouterInfo info ) {
2004-04-20 07:06:39 +00:00
_routerInfo = info ;
if ( info ! = null )
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_context . jobQueue ( ) . addJob ( new PersistRouterInfoJob ( ) ) ;
2004-04-08 04:41:54 +00:00
}
/ * *
* True if the router has tried to communicate with another router who is running a higher
* incompatible protocol version .
*
* /
public boolean getHigherVersionSeen ( ) { return _higherVersionSeen ; }
public void setHigherVersionSeen ( boolean seen ) { _higherVersionSeen = seen ; }
public long getWhenStarted ( ) { return _started ; }
/** wall clock uptime */
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
public long getUptime ( ) { return _context . clock ( ) . now ( ) - _context . clock ( ) . getOffset ( ) - _started ; }
2004-04-08 04:41:54 +00:00
2004-08-30 22:28:15 +00:00
public RouterContext getContext ( ) { return _context ; }
2004-04-26 03:30:20 +00:00
void runRouter ( ) {
_isAlive = true ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_started = _context . clock ( ) . now ( ) ;
2004-04-26 03:30:20 +00:00
Runtime . getRuntime ( ) . addShutdownHook ( _shutdownHook ) ;
I2PThread . addOOMEventListener ( _oomListener ) ;
2004-07-31 23:25:02 +00:00
2004-09-06 05:20:40 +00:00
_context . keyManager ( ) . startup ( ) ;
2004-07-31 23:25:02 +00:00
readConfig ( ) ;
2004-04-20 07:06:39 +00:00
setupHandlers ( ) ;
startupQueue ( ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_context . jobQueue ( ) . addJob ( new CoallesceStatsJob ( ) ) ;
_context . jobQueue ( ) . addJob ( new UpdateRoutingKeyModifierJob ( ) ) ;
2004-04-20 07:06:39 +00:00
warmupCrypto ( ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_sessionKeyPersistenceHelper . startup ( ) ;
2004-09-03 07:22:24 +00:00
//_context.adminManager().startup();
2004-07-31 23:25:02 +00:00
_context . jobQueue ( ) . addJob ( new StartupJob ( _context ) ) ;
}
public void readConfig ( ) {
String f = getConfigFilename ( ) ;
Properties config = getConfig ( _context , f ) ;
for ( Iterator iter = config . keySet ( ) . iterator ( ) ; iter . hasNext ( ) ; ) {
String name = ( String ) iter . next ( ) ;
String val = config . getProperty ( name ) ;
setConfigSetting ( name , val ) ;
}
}
private static Properties getConfig ( RouterContext ctx , String filename ) {
Log log = ctx . logManager ( ) . getLog ( Router . class ) ;
if ( log . shouldLog ( Log . DEBUG ) )
log . debug ( " Config file: " + filename ) ;
Properties props = new Properties ( ) ;
FileInputStream fis = null ;
try {
File f = new File ( filename ) ;
if ( f . canRead ( ) ) {
2004-08-19 17:42:47 +00:00
DataHelper . loadProps ( props , f ) ;
2004-08-23 07:33:14 +00:00
// dont be a wanker
props . remove ( PROP_SHUTDOWN_IN_PROGRESS ) ;
2004-07-31 23:25:02 +00:00
} else {
2004-08-19 17:42:47 +00:00
log . warn ( " Configuration file " + filename + " does not exist " ) ;
2004-07-31 23:25:02 +00:00
}
} catch ( Exception ioe ) {
log . error ( " Error loading the router configuration from " + filename , ioe ) ;
} finally {
if ( fis ! = null ) try { fis . close ( ) ; } catch ( IOException ioe ) { }
}
return props ;
2004-04-08 04:41:54 +00:00
}
2004-04-26 03:30:20 +00:00
public boolean isAlive ( ) { return _isAlive ; }
2004-04-08 04:41:54 +00:00
/ * *
* coallesce the stats framework every minute
*
* /
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
private final class CoallesceStatsJob extends JobImpl {
public CoallesceStatsJob ( ) { super ( Router . this . _context ) ; }
2004-04-20 07:06:39 +00:00
public String getName ( ) { return " Coallesce stats " ; }
public void runJob ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
Router . this . _context . statManager ( ) . coallesceStats ( ) ;
2004-04-20 07:06:39 +00:00
requeue ( 60 * 1000 ) ;
}
2004-04-08 04:41:54 +00:00
}
/ * *
* 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 .
* /
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
private final class UpdateRoutingKeyModifierJob extends JobImpl {
2004-04-20 07:06:39 +00:00
private Calendar _cal = new GregorianCalendar ( TimeZone . getTimeZone ( " GMT " ) ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
public UpdateRoutingKeyModifierJob ( ) { super ( Router . this . _context ) ; }
2004-04-20 07:06:39 +00:00
public String getName ( ) { return " Update Routing Key Modifier " ; }
public void runJob ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
Router . this . _context . routingKeyGenerator ( ) . generateDateBasedModData ( ) ;
2004-04-20 07:06:39 +00:00
requeue ( getTimeTillMidnight ( ) ) ;
}
private long getTimeTillMidnight ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
long now = Router . this . _context . clock ( ) . now ( ) ;
2004-04-20 07:06:39 +00:00
_cal . setTime ( new Date ( now ) ) ;
_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 ( ) ;
2004-04-08 04:41:54 +00:00
_log . debug ( " Time till midnight: " + ( then - now ) + " ms " ) ;
if ( then - now < = 60 * 1000 ) {
// everyone wave at kaffe.
// "Hi Kaffe"
return 60 * 1000 ;
} else {
2004-04-20 07:06:39 +00:00
return then - now ;
2004-04-08 04:41:54 +00:00
}
2004-04-20 07:06:39 +00:00
}
2004-04-08 04:41:54 +00:00
}
private void warmupCrypto ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_context . random ( ) . nextBoolean ( ) ;
2004-04-20 07:06:39 +00:00
new DHSessionKeyBuilder ( ) ; // load the class so it starts the precalc process
2004-04-08 04:41:54 +00:00
}
private void startupQueue ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_context . jobQueue ( ) . runQueue ( 1 ) ;
2004-04-08 04:41:54 +00:00
}
private void setupHandlers ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
_context . inNetMessagePool ( ) . registerHandlerJobBuilder ( GarlicMessage . MESSAGE_TYPE , new GarlicMessageHandler ( _context ) ) ;
_context . inNetMessagePool ( ) . registerHandlerJobBuilder ( TunnelMessage . MESSAGE_TYPE , new TunnelMessageHandler ( _context ) ) ;
2004-04-08 04:41:54 +00:00
}
2004-07-09 05:29:02 +00:00
public void renderStatusHTML ( OutputStream out ) throws IOException {
2004-09-02 07:20:45 +00:00
out . write ( ( " <h1>Router console</h1> \ n " +
" <i><a href= \" /oldconsole.jsp \" >console</a> | <a href= \" /oldstats.jsp \" >stats</a></i><br> \ n " +
" <form action= \" /oldconsole.jsp \" > " +
2004-07-09 05:29:02 +00:00
" <select name= \" go \" onChange='location.href=this.value'> " +
2004-09-02 07:20:45 +00:00
" <option value= \" /oldconsole.jsp#bandwidth \" >Bandwidth</option> \ n " +
" <option value= \" /oldconsole.jsp#clients \" >Clients</option> \ n " +
" <option value= \" /oldconsole.jsp#transports \" >Transports</option> \ n " +
" <option value= \" /oldconsole.jsp#profiles \" >Peer Profiles</option> \ n " +
" <option value= \" /oldconsole.jsp#tunnels \" >Tunnels</option> \ n " +
" <option value= \" /oldconsole.jsp#jobs \" >Jobs</option> \ n " +
" <option value= \" /oldconsole.jsp#shitlist \" >Shitlist</option> \ n " +
" <option value= \" /oldconsole.jsp#pending \" >Pending messages</option> \ n " +
" <option value= \" /oldconsole.jsp#netdb \" >Network Database</option> \ n " +
" <option value= \" /oldconsole.jsp#logs \" >Log messages</option> \ n " +
" </select> <input type= \" submit \" value= \" GO \" /> </form> " +
2004-07-09 05:29:02 +00:00
" <hr /> \ n " ) . getBytes ( ) ) ;
2004-04-20 07:06:39 +00:00
2004-07-09 05:29:02 +00:00
StringBuffer buf = new StringBuffer ( 32 * 1024 ) ;
2004-04-20 07:06:39 +00:00
if ( ( _routerInfo ! = null ) & & ( _routerInfo . getIdentity ( ) ! = null ) )
buf . append ( " <b>Router: </b> " ) . append ( _routerInfo . getIdentity ( ) . getHash ( ) . toBase64 ( ) ) . append ( " <br /> \ n " ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
buf . append ( " <b>As of: </b> " ) . append ( new Date ( _context . clock ( ) . now ( ) ) ) . append ( " (uptime: " ) . append ( DataHelper . formatDuration ( getUptime ( ) ) ) . append ( " ) <br /> \ n " ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " <b>Started on: </b> " ) . append ( new Date ( getWhenStarted ( ) ) ) . append ( " <br /> \ n " ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
buf . append ( " <b>Clock offset: </b> " ) . append ( _context . clock ( ) . getOffset ( ) ) . append ( " ms (OS time: " ) . append ( new Date ( _context . clock ( ) . now ( ) - _context . clock ( ) . getOffset ( ) ) ) . append ( " )<br /> \ n " ) ;
2004-04-20 07:06:39 +00:00
long tot = Runtime . getRuntime ( ) . totalMemory ( ) / 1024 ;
long free = Runtime . getRuntime ( ) . freeMemory ( ) / 1024 ;
buf . append ( " <b>Memory:</b> In use: " ) . append ( ( tot - free ) ) . append ( " KB Free: " ) . append ( free ) . append ( " KB <br /> \ n " ) ;
buf . append ( " <b>Version:</b> Router: " ) . append ( RouterVersion . VERSION ) . append ( " / SDK: " ) . append ( CoreVersion . VERSION ) . append ( " <br /> \ n " ) ;
if ( _higherVersionSeen )
2004-09-02 07:20:45 +00:00
buf . append ( " <b><font color= \" red \" >HIGHER VERSION SEEN</font><b> - please <a href= \" http://www.i2p.net/ \" >check</a> to see if there is a new release out<br /> \ n " ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " <hr /><a name= \" bandwidth \" > </a><h2>Bandwidth</h2> \ n " ) ;
implemented the FIFO bandwidth limiter which, suprisingly, chokes read/write operations
if they would exceed the currently available # of tokens, letting through those operations
in the order they are called. like the old trivial bandwidth limiter, this uses a token
bucket approach (keeping a pool of 'available' bytes, decrementing on their use and
periodically refilling it [up to a max limit, to prevent absurd bursts]). on the other
hand, it doesn't have the starvation issues the old one had, which would continue to let
small operations go through (e.g. 8 byte write) and potentially block large operations
indefinitely (e.g. 32KB write). However, this new version is, how shall I put it, context
switch heavy? :) We'll revise with a scheduling / queueing algorithm once we're away
from transports that require threads per connection
The two directions (input and output) are managed on their own queues, and if/when things
are backed up, you can see the details of what operations have been requested on the
router console.
Since we still need better router throttling code (to reject tunnels and back off more
accurately), I've included a minimum KBps on the limiter, currently set to 6KBps both
ways. Once there is good throttling code, we can drop that to 1-2KBps, and maybe even
less after we do some bandwidth usage tuning.
There were also a few minor touch ups to handle message data being discarded earlier
than it had been before (since write/read operations can now take a long period of time
in the face of contention)
The five config properties for the bandwidth limiter are:
* i2np.bandwidth.inboundKBytesPerSecond
* i2np.bandwidth.outboundKBytesPerSecond
(you can guess what those are)
* i2np.bandwidth.inboundBurstKBytes
* i2np.bandwidth.outboundBurstKBytes
the burst KBytes specify how many bytes we'll let accumulate in the bucket, allowing
us to burst after a period of inactivity. excess tokens greater than this limit are
discarded.
* i2np.bandwidth.replenishFrequencyMs
this is an internal setting, used to specify how frequently to refil the buckets (min
value of 1s, which is the default)
You may want to hold off on using these parameters though until the next release,
leaving it to the default of unlimited. They are read periodically from the config file
however, so you can update them without restart / etc. (if you want to have no limit on
the bandwidth, set the KBytesPerSecond to a value <= 0)
2004-07-04 04:33:17 +00:00
long sent = _context . bandwidthLimiter ( ) . getTotalAllocatedOutboundBytes ( ) ;
long received = _context . bandwidthLimiter ( ) . getTotalAllocatedInboundBytes ( ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " <ul> " ) ;
buf . append ( " <li> " ) . append ( sent ) . append ( " bytes sent, " ) ;
buf . append ( received ) . append ( " bytes received</li> " ) ;
2004-07-28 23:35:48 +00:00
long notSent = _context . bandwidthLimiter ( ) . getTotalWastedOutboundBytes ( ) ;
long notReceived = _context . bandwidthLimiter ( ) . getTotalWastedInboundBytes ( ) ;
buf . append ( " <li> " ) . append ( notSent ) . append ( " bytes outbound bytes unused, " ) ;
buf . append ( notReceived ) . append ( " bytes inbound bytes unused</li> " ) ;
2004-04-20 07:06:39 +00:00
DecimalFormat fmt = new DecimalFormat ( " ##0.00 " ) ;
2004-04-08 04:41:54 +00:00
2004-04-20 07:06:39 +00:00
// we use the unadjusted time, since thats what getWhenStarted is based off
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
long lifetime = _context . clock ( ) . now ( ) - _context . clock ( ) . getOffset ( ) - getWhenStarted ( ) ;
2004-04-20 07:06:39 +00:00
lifetime / = 1000 ;
if ( ( sent > 0 ) & & ( received > 0 ) ) {
double sendKBps = sent / ( lifetime * 1024 . 0 ) ;
double receivedKBps = received / ( lifetime * 1024 . 0 ) ;
buf . append ( " <li>Lifetime rate: " ) ;
buf . append ( fmt . format ( sendKBps ) ) . append ( " KBps sent " ) ;
buf . append ( fmt . format ( receivedKBps ) ) . append ( " KBps received " ) ;
buf . append ( " </li> " ) ;
2004-07-28 23:35:48 +00:00
}
if ( ( notSent > 0 ) & & ( notReceived > 0 ) ) {
double notSendKBps = notSent / ( lifetime * 1024 . 0 ) ;
double notReceivedKBps = notReceived / ( lifetime * 1024 . 0 ) ;
2004-07-29 05:37:10 +00:00
buf . append ( " <li>Lifetime unused rate: " ) ;
2004-07-28 23:35:48 +00:00
buf . append ( fmt . format ( notSendKBps ) ) . append ( " KBps outbound unused " ) ;
buf . append ( fmt . format ( notReceivedKBps ) ) . append ( " KBps inbound unused " ) ;
buf . append ( " </li> " ) ;
}
2004-04-20 07:06:39 +00:00
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
RateStat sendRate = _context . statManager ( ) . getRate ( " transport.sendMessageSize " ) ;
2004-04-20 07:06:39 +00:00
for ( int i = 0 ; i < sendRate . getPeriods ( ) . length ; i + + ) {
Rate rate = sendRate . getRate ( sendRate . getPeriods ( ) [ i ] ) ;
2004-06-23 19:54:12 +00:00
double bytes = rate . getLastTotalValue ( ) ;
2004-04-20 07:06:39 +00:00
long ms = rate . getLastTotalEventTime ( ) + rate . getLastTotalEventTime ( ) ;
if ( ms < = 0 ) {
bytes = 0 ;
ms = 1 ;
}
buf . append ( " <li> " ) ;
buf . append ( DataHelper . formatDuration ( rate . getPeriod ( ) ) ) . append ( " instantaneous send avg: " ) ;
double bps = bytes * 1000 . 0d / ms ;
if ( bps > 2048 ) {
bps / = 1024 . 0d ;
buf . append ( fmt . format ( bps ) ) . append ( " KBps " ) ;
} else {
buf . append ( fmt . format ( bps ) ) . append ( " Bps " ) ;
}
buf . append ( " over " ) . append ( ( long ) bytes ) . append ( " bytes " ) ;
buf . append ( " </li><li> " ) ;
buf . append ( DataHelper . formatDuration ( rate . getPeriod ( ) ) ) . append ( " period send avg: " ) ;
2004-06-23 19:54:12 +00:00
bps = bytes * 1000 . 0d / ( rate . getPeriod ( ) ) ;
2004-04-20 07:06:39 +00:00
if ( bps > 2048 ) {
bps / = 1024 . 0d ;
buf . append ( fmt . format ( bps ) ) . append ( " KBps " ) ;
} else {
buf . append ( fmt . format ( bps ) ) . append ( " Bps " ) ;
}
buf . append ( " over " ) . append ( ( long ) bytes ) . append ( " bytes " ) ;
buf . append ( " </li> " ) ;
}
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
RateStat receiveRate = _context . statManager ( ) . getRate ( " transport.receiveMessageSize " ) ;
2004-04-20 07:06:39 +00:00
for ( int i = 0 ; i < receiveRate . getPeriods ( ) . length ; i + + ) {
Rate rate = receiveRate . getRate ( receiveRate . getPeriods ( ) [ i ] ) ;
2004-06-20 01:18:31 +00:00
double bytes = rate . getLastTotalValue ( ) ;
long ms = rate . getLastTotalEventTime ( ) ;
2004-04-20 07:06:39 +00:00
if ( ms < = 0 ) {
bytes = 0 ;
ms = 1 ;
}
buf . append ( " <li> " ) ;
buf . append ( DataHelper . formatDuration ( rate . getPeriod ( ) ) ) . append ( " instantaneous receive avg: " ) ;
double bps = bytes * 1000 . 0d / ms ;
if ( bps > 2048 ) {
bps / = 1024 . 0d ;
buf . append ( fmt . format ( bps ) ) . append ( " KBps " ) ;
} else {
buf . append ( fmt . format ( bps ) ) . append ( " Bps " ) ;
}
buf . append ( " over " ) . append ( ( long ) bytes ) . append ( " bytes " ) ;
buf . append ( " </li><li> " ) ;
buf . append ( DataHelper . formatDuration ( rate . getPeriod ( ) ) ) . append ( " period receive avg: " ) ;
2004-06-20 01:18:31 +00:00
bps = bytes * 1000 . 0d / ( rate . getPeriod ( ) ) ;
2004-04-20 07:06:39 +00:00
if ( bps > 2048 ) {
bps / = 1024 . 0d ;
buf . append ( fmt . format ( bps ) ) . append ( " KBps " ) ;
} else {
buf . append ( fmt . format ( bps ) ) . append ( " Bps " ) ;
}
buf . append ( " over " ) . append ( ( long ) bytes ) . append ( " bytes " ) ;
buf . append ( " </li> " ) ;
}
buf . append ( " </ul> \ n " ) ;
buf . append ( " <i>Instantaneous averages count how fast the transfers go when we're trying to transfer data, " ) ;
buf . append ( " while period averages count how fast the transfers go across the entire period, even when we're not " ) ;
buf . append ( " trying to transfer data. Lifetime averages count how many elephants there are on the moon [like anyone reads this text]</i> " ) ;
buf . append ( " \ n " ) ;
implemented the FIFO bandwidth limiter which, suprisingly, chokes read/write operations
if they would exceed the currently available # of tokens, letting through those operations
in the order they are called. like the old trivial bandwidth limiter, this uses a token
bucket approach (keeping a pool of 'available' bytes, decrementing on their use and
periodically refilling it [up to a max limit, to prevent absurd bursts]). on the other
hand, it doesn't have the starvation issues the old one had, which would continue to let
small operations go through (e.g. 8 byte write) and potentially block large operations
indefinitely (e.g. 32KB write). However, this new version is, how shall I put it, context
switch heavy? :) We'll revise with a scheduling / queueing algorithm once we're away
from transports that require threads per connection
The two directions (input and output) are managed on their own queues, and if/when things
are backed up, you can see the details of what operations have been requested on the
router console.
Since we still need better router throttling code (to reject tunnels and back off more
accurately), I've included a minimum KBps on the limiter, currently set to 6KBps both
ways. Once there is good throttling code, we can drop that to 1-2KBps, and maybe even
less after we do some bandwidth usage tuning.
There were also a few minor touch ups to handle message data being discarded earlier
than it had been before (since write/read operations can now take a long period of time
in the face of contention)
The five config properties for the bandwidth limiter are:
* i2np.bandwidth.inboundKBytesPerSecond
* i2np.bandwidth.outboundKBytesPerSecond
(you can guess what those are)
* i2np.bandwidth.inboundBurstKBytes
* i2np.bandwidth.outboundBurstKBytes
the burst KBytes specify how many bytes we'll let accumulate in the bucket, allowing
us to burst after a period of inactivity. excess tokens greater than this limit are
discarded.
* i2np.bandwidth.replenishFrequencyMs
this is an internal setting, used to specify how frequently to refil the buckets (min
value of 1s, which is the default)
You may want to hold off on using these parameters though until the next release,
leaving it to the default of unlimited. They are read periodically from the config file
however, so you can update them without restart / etc. (if you want to have no limit on
the bandwidth, set the KBytesPerSecond to a value <= 0)
2004-07-04 04:33:17 +00:00
2004-07-09 05:29:02 +00:00
out . write ( buf . toString ( ) . getBytes ( ) ) ;
_context . bandwidthLimiter ( ) . renderStatusHTML ( out ) ;
2004-04-20 07:06:39 +00:00
2004-07-09 05:29:02 +00:00
out . write ( " <hr /><a name= \" clients \" > </a> \ n " . getBytes ( ) ) ;
_context . clientManager ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" transports \" > </a> \ n " . getBytes ( ) ) ;
_context . commSystem ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" profiles \" > </a> \ n " . getBytes ( ) ) ;
_context . peerManager ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" tunnels \" > </a> \ n " . getBytes ( ) ) ;
_context . tunnelManager ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" jobs \" > </a> \ n " . getBytes ( ) ) ;
_context . jobQueue ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" shitlist \" > </a> \ n " . getBytes ( ) ) ;
_context . shitlist ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" pending \" > </a> \ n " . getBytes ( ) ) ;
_context . messageRegistry ( ) . renderStatusHTML ( out ) ;
out . write ( " \ n<hr /><a name= \" netdb \" > </a> \ n " . getBytes ( ) ) ;
_context . netDb ( ) . renderStatusHTML ( out ) ;
buf . setLength ( 0 ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " \ n<hr /><a name= \" logs \" > </a> \ n " ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
List msgs = _context . logManager ( ) . getBuffer ( ) . getMostRecentMessages ( ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " \ n<h2>Most recent console messages:</h2><table border= \" 1 \" > \ n " ) ;
for ( Iterator iter = msgs . iterator ( ) ; iter . hasNext ( ) ; ) {
String msg = ( String ) iter . next ( ) ;
2004-07-20 03:34:52 +00:00
buf . append ( " <tr><td valign= \" top \" align= \" left \" ><pre> " ) ;
appendLogMessage ( buf , msg ) ;
2004-04-20 07:06:39 +00:00
buf . append ( " </pre></td></tr> \ n " ) ;
}
2004-09-02 07:20:45 +00:00
buf . append ( " </table> \ n " ) ;
2004-07-09 05:29:02 +00:00
out . write ( buf . toString ( ) . getBytes ( ) ) ;
2004-04-08 04:41:54 +00:00
}
2004-07-20 03:34:52 +00:00
private static int MAX_MSG_LENGTH = 120 ;
private static final void appendLogMessage ( StringBuffer buf , String msg ) {
// disable this code for the moment because i think it
// looks ugly (on the router console)
if ( true ) {
buf . append ( msg ) ;
return ;
}
if ( msg . length ( ) < MAX_MSG_LENGTH ) {
buf . append ( msg ) ;
return ;
}
int newline = msg . indexOf ( '\n' ) ;
int len = msg . length ( ) ;
while ( ( msg ! = null ) & & ( len > 0 ) ) {
if ( newline < 0 ) {
// last line, trim if necessary
if ( len > MAX_MSG_LENGTH )
msg = msg . substring ( len - MAX_MSG_LENGTH ) ;
buf . append ( msg ) ;
return ;
} else if ( newline > = MAX_MSG_LENGTH ) {
// not the last line, but too long.
// trim the first few chars
String cur = msg . substring ( newline - MAX_MSG_LENGTH , newline ) . trim ( ) ;
msg = msg . substring ( newline + 1 ) ;
if ( cur . length ( ) > 0 )
buf . append ( cur ) . append ( '\n' ) ;
} else {
// newline <= max_msg_length, so its not the last,
// and not too long
String cur = msg . substring ( 0 , newline ) . trim ( ) ;
msg = msg . substring ( newline + 1 ) ;
if ( cur . length ( ) > 0 )
buf . append ( cur ) . append ( '\n' ) ;
}
newline = msg . indexOf ( '\n' ) ;
len = msg . length ( ) ;
}
}
/** main-ish method for testing appendLogMessage */
private static final void testAppendLog ( ) {
StringBuffer buf = new StringBuffer ( 1024 ) ;
Router . appendLogMessage ( buf , " hi \ nhow are you \ nh0h0h0 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " \ nfine thanks \ nh0h0h0 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " liar \ nblah blah \ n " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " \ n " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " .........10........20........30........40........50........6 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " .........10........ \ n20........30........40........50........6 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " .........10........20 \ n........30........40........50........6 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " .........10....... \ n.20........30........40........50........6 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
Router . appendLogMessage ( buf , " \ n.........10........20........30........40........50........6 " ) ;
System . out . println ( " line: [ " + buf . toString ( ) + " ] " ) ;
buf . setLength ( 0 ) ;
}
2004-09-07 07:17:02 +00:00
public void addShutdownTask ( Runnable task ) {
synchronized ( _shutdownTasks ) {
_shutdownTasks . add ( task ) ;
}
}
2004-08-23 21:34:22 +00:00
public static final int EXIT_GRACEFUL = 2 ;
public static final int EXIT_HARD = 3 ;
public static final int EXIT_OOM = 10 ;
2004-08-24 18:02:48 +00:00
public static final int EXIT_HARD_RESTART = 4 ;
2004-09-06 05:20:40 +00:00
public static final int EXIT_GRACEFUL_RESTART = 5 ;
2004-08-23 21:34:22 +00:00
public void shutdown ( int exitCode ) {
2004-04-26 03:30:20 +00:00
_isAlive = false ;
I2PThread . removeOOMEventListener ( _oomListener ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
try { _context . jobQueue ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the job queue " , t ) ; }
2004-09-03 07:22:24 +00:00
//try { _context.adminManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the admin manager", t); }
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
try { _context . statPublisher ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the stats manager " , t ) ; }
try { _context . clientManager ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the client manager " , t ) ; }
try { _context . tunnelManager ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the tunnel manager " , t ) ; }
try { _context . netDb ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the networkDb " , t ) ; }
try { _context . commSystem ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the comm system " , t ) ; }
try { _context . peerManager ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the peer manager " , t ) ; }
2004-05-16 04:54:50 +00:00
try { _context . messageRegistry ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the message registry " , t ) ; }
try { _context . messageValidator ( ) . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the message validator " , t ) ; }
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
try { _sessionKeyPersistenceHelper . shutdown ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error shutting down the session key manager " , t ) ; }
2004-07-23 17:36:29 +00:00
_context . listContexts ( ) . remove ( _context ) ;
2004-04-20 07:06:39 +00:00
dumpStats ( ) ;
2004-09-07 07:17:02 +00:00
try {
for ( Iterator iter = _shutdownTasks . iterator ( ) ; iter . hasNext ( ) ; ) {
Runnable task = ( Runnable ) iter . next ( ) ;
task . run ( ) ;
}
} catch ( Throwable t ) {
_log . log ( Log . CRIT , " Error running shutdown task " , t ) ;
}
2004-08-23 21:34:22 +00:00
_log . log ( Log . CRIT , " Shutdown( " + exitCode + " ) complete " , new Exception ( " Shutdown " ) ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
try { _context . logManager ( ) . shutdown ( ) ; } catch ( Throwable t ) { }
2004-09-04 21:54:08 +00:00
File f = new File ( getPingFile ( ) ) ;
f . delete ( ) ;
2004-04-26 03:30:20 +00:00
if ( _killVMOnEnd ) {
try { Thread . sleep ( 1000 ) ; } catch ( InterruptedException ie ) { }
2004-08-23 21:34:22 +00:00
Runtime . getRuntime ( ) . halt ( exitCode ) ;
2004-04-26 03:30:20 +00:00
}
2004-04-08 04:41:54 +00:00
}
2004-08-23 07:33:14 +00:00
/ * *
* 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
* router down immediately , use { @link # shutdown } . If you want to cancel
* the graceful shutdown ( prior to actual shutdown ; ) , call
* { @link # cancelGracefulShutdown } .
*
* /
public void shutdownGracefully ( ) {
2004-09-06 05:20:40 +00:00
shutdownGracefully ( EXIT_GRACEFUL ) ;
}
public void shutdownGracefully ( int exitCode ) {
_gracefulExitCode = exitCode ;
2004-08-23 07:33:14 +00:00
_config . setProperty ( PROP_SHUTDOWN_IN_PROGRESS , " true " ) ;
synchronized ( _gracefulShutdownDetector ) {
_gracefulShutdownDetector . notifyAll ( ) ;
}
}
/ * *
* Cancel any prior request to shut the router down gracefully .
*
* /
public void cancelGracefulShutdown ( ) {
_config . remove ( PROP_SHUTDOWN_IN_PROGRESS ) ;
synchronized ( _gracefulShutdownDetector ) {
_gracefulShutdownDetector . notifyAll ( ) ;
}
}
public boolean gracefulShutdownInProgress ( ) {
return ( null ! = _config . getProperty ( PROP_SHUTDOWN_IN_PROGRESS ) ) ;
}
/ * *
* Simple thread that sits and waits forever , managing the
* graceful shutdown " process " ( describing it would take more text
* than just reading the code . . . )
*
* /
private class GracefulShutdown implements Runnable {
public void run ( ) {
while ( true ) {
boolean shutdown = ( null ! = _config . getProperty ( PROP_SHUTDOWN_IN_PROGRESS ) ) ;
if ( shutdown ) {
if ( _context . tunnelManager ( ) . getParticipatingCount ( ) < = 0 ) {
if ( _log . shouldLog ( Log . CRIT ) )
_log . log ( Log . CRIT , " Graceful shutdown progress - no more tunnels, safe to die " ) ;
2004-09-06 05:20:40 +00:00
shutdown ( _gracefulExitCode ) ;
2004-08-23 07:33:14 +00:00
return ;
} else {
try {
synchronized ( Thread . currentThread ( ) ) {
Thread . currentThread ( ) . wait ( 10 * 1000 ) ;
}
} catch ( InterruptedException ie ) { }
}
} else {
try {
synchronized ( Thread . currentThread ( ) ) {
Thread . currentThread ( ) . wait ( ) ;
}
} catch ( InterruptedException ie ) { }
}
}
}
}
2004-07-31 02:21:46 +00:00
/ * *
* Save the current config options ( returning true if save was
* successful , false otherwise )
*
* /
public boolean saveConfig ( ) {
FileOutputStream fos = null ;
try {
fos = new FileOutputStream ( _configFilename ) ;
2004-07-31 23:25:02 +00:00
TreeSet ordered = new TreeSet ( _config . keySet ( ) ) ;
StringBuffer buf = new StringBuffer ( 8 * 1024 ) ;
for ( Iterator iter = ordered . iterator ( ) ; iter . hasNext ( ) ; ) {
String key = ( String ) iter . next ( ) ;
String val = _config . getProperty ( key ) ;
buf . append ( key ) . append ( '=' ) . append ( val ) . append ( '\n' ) ;
}
fos . write ( buf . toString ( ) . getBytes ( ) ) ;
2004-07-31 02:21:46 +00:00
} catch ( IOException ioe ) {
if ( _log . shouldLog ( Log . ERROR ) )
_log . error ( " Error saving the config to " + _configFilename , ioe ) ;
return false ;
} finally {
if ( fos ! = null ) try { fos . close ( ) ; } catch ( IOException ioe ) { }
}
return true ;
}
public void restart ( ) {
_isAlive = false ;
try { _context . commSystem ( ) . restart ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error restarting the comm system " , t ) ; }
2004-09-03 07:22:24 +00:00
//try { _context.adminManager().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the client manager", t); }
2004-07-31 02:21:46 +00:00
try { _context . clientManager ( ) . restart ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error restarting the client manager " , t ) ; }
try { _context . tunnelManager ( ) . restart ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error restarting the tunnel manager " , t ) ; }
try { _context . peerManager ( ) . restart ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error restarting the peer manager " , t ) ; }
try { _context . netDb ( ) . restart ( ) ; } catch ( Throwable t ) { _log . log ( Log . CRIT , " Error restarting the networkDb " , t ) ; }
//try { _context.jobQueue().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the job queue", t); }
_log . log ( Log . CRIT , " Restart teardown complete... " ) ;
try { Thread . sleep ( 10 * 1000 ) ; } catch ( InterruptedException ie ) { }
_log . log ( Log . CRIT , " Restarting... " ) ;
_isAlive = true ;
_started = _context . clock ( ) . now ( ) ;
_log . log ( Log . CRIT , " Restart complete " ) ;
}
2004-04-08 04:41:54 +00:00
private void dumpStats ( ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
//_log.log(Log.CRIT, "Lifetime stats:\n\n" + StatsGenerator.generateStatsPage());
2004-04-08 04:41:54 +00:00
}
public static void main ( String args [ ] ) {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
Router r = new Router ( ) ;
r . runRouter ( ) ;
2004-04-08 04:41:54 +00:00
}
2004-09-04 21:54:08 +00:00
private static String getPingFile ( Properties envProps ) {
if ( envProps ! = null )
return envProps . getProperty ( " router.pingFile " , " router.ping " ) ;
else
return " router.ping " ;
}
private String getPingFile ( ) {
return _context . getProperty ( " router.pingFile " , " router.ping " ) ;
}
private static final long LIVELINESS_DELAY = 60 * 1000 ;
/ * *
* Start a thread that will periodically update the file " router.ping " , but if
* that file already exists and was recently written to , return false as there is
* another instance running
*
* @return true if the router is the only one running
* /
private boolean beginMarkingLiveliness ( Properties envProps ) {
String filename = getPingFile ( envProps ) ;
File f = new File ( filename ) ;
if ( f . exists ( ) ) {
long lastWritten = f . lastModified ( ) ;
if ( System . currentTimeMillis ( ) - lastWritten > LIVELINESS_DELAY ) {
System . err . println ( " WARN: Old router was not shut down gracefully, deleting router.ping " ) ;
f . delete ( ) ;
} else {
return false ;
}
}
// not an I2PThread for context creation issues
Thread t = new Thread ( new MarkLiveliness ( f ) ) ;
t . setName ( " Mark router liveliness " ) ;
t . setDaemon ( true ) ;
t . start ( ) ;
return true ;
}
private class MarkLiveliness implements Runnable {
private File _pingFile ;
public MarkLiveliness ( File f ) {
_pingFile = f ;
}
public void run ( ) {
_pingFile . deleteOnExit ( ) ;
do {
ping ( ) ;
try { Thread . sleep ( LIVELINESS_DELAY ) ; } catch ( InterruptedException ie ) { }
} while ( _isAlive ) ;
_pingFile . delete ( ) ;
}
private void ping ( ) {
FileOutputStream fos = null ;
try {
fos = new FileOutputStream ( _pingFile ) ;
fos . write ( ( " " + System . currentTimeMillis ( ) ) . getBytes ( ) ) ;
} catch ( IOException ioe ) {
if ( _log ! = null ) {
_log . log ( Log . CRIT , " Error writing to ping file " , ioe ) ;
} else {
System . err . println ( " Error writing to ping file " ) ;
ioe . printStackTrace ( ) ;
}
} finally {
if ( fos ! = null ) try { fos . close ( ) ; } catch ( IOException ioe ) { }
}
}
}
2004-06-20 01:18:31 +00:00
private static int __id = 0 ;
2004-04-08 04:41:54 +00:00
private class ShutdownHook extends Thread {
2004-06-20 01:18:31 +00:00
private int _id ;
public ShutdownHook ( ) {
_id = + + __id ;
}
2004-04-20 07:06:39 +00:00
public void run ( ) {
2004-06-20 01:18:31 +00:00
setName ( " Router " + _id + " shutdown " ) ;
2004-05-16 04:54:50 +00:00
_log . log ( Log . CRIT , " Shutting down the router... " ) ;
2004-08-23 21:34:22 +00:00
shutdown ( EXIT_HARD ) ;
2004-04-20 07:06:39 +00:00
}
2004-04-08 04:41:54 +00:00
}
/** update the router.info file whenever its, er, updated */
2004-09-02 07:20:45 +00:00
private class PersistRouterInfoJob extends JobImpl {
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
public PersistRouterInfoJob ( ) { super ( Router . this . _context ) ; }
2004-04-20 07:06:39 +00:00
public String getName ( ) { return " Persist Updated Router Information " ; }
public void runJob ( ) {
if ( _log . shouldLog ( Log . DEBUG ) )
_log . debug ( " Persisting updated router info " ) ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
String infoFilename = getConfigSetting ( PROP_INFO_FILENAME ) ;
2004-04-20 07:06:39 +00:00
if ( infoFilename = = null )
infoFilename = PROP_INFO_FILENAME_DEFAULT ;
big ol' update to strip out the singletons, replacing them with
a rooted app context. The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons. The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
2004-04-24 11:54:35 +00:00
RouterInfo info = getRouterInfo ( ) ;
2004-04-20 07:06:39 +00:00
FileOutputStream fos = null ;
try {
fos = new FileOutputStream ( infoFilename ) ;
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 ) { }
}
}
2004-04-08 04:41:54 +00:00
}
}