2005-02-24 jrandom

* Throttle the number of tunnel rebuilds per minute, preventing CPU
      overload under catastrophic failures (thanks Tracker and cervantes!)
    * Block the router startup process until we've initialized the clock
This commit is contained in:
jrandom
2005-02-24 23:53:35 +00:00
committed by zzz
parent 00f27d4400
commit 4cec9da0a6
5 changed files with 84 additions and 7 deletions

View File

@ -101,6 +101,15 @@ public class Timestamper implements Runnable {
t.start();
}
public void waitForInitialization() {
try {
synchronized (this) {
if (!_initialized)
wait();
}
} catch (InterruptedException ie) {}
}
public void run() {
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
_log = _context.logManager().getLog(Timestamper.class);
@ -130,6 +139,9 @@ public class Timestamper implements Runnable {
lastFailed = true;
}
}
_initialized = true;
synchronized (this) { notifyAll(); }
long sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency;
if (lastFailed)
sleepTime = 30*1000;
@ -137,6 +149,7 @@ public class Timestamper implements Runnable {
}
} catch (Throwable t) {
_log.log(Log.CRIT, "Timestamper died!", t);
synchronized (this) { notifyAll(); }
}
}

View File

@ -1,4 +1,9 @@
$Id: history.txt,v 1.155 2005/02/23 16:44:32 jrandom Exp $
$Id: history.txt,v 1.156 2005/02/24 13:05:26 jrandom Exp $
2005-02-24 jrandom
* Throttle the number of tunnel rebuilds per minute, preventing CPU
overload under catastrophic failures (thanks Tracker and cervantes!)
* Block the router startup process until we've initialized the clock
2005-02-24 jrandom
* Cache temporary memory allocation in the DSA's SHA1 impl, and the packet

View File

@ -225,6 +225,14 @@ public class Router {
warmupCrypto();
_sessionKeyPersistenceHelper.startup();
//_context.adminManager().startup();
// let the timestamper get us sync'ed
long before = System.currentTimeMillis();
_context.clock().getTimestamper().waitForInitialization();
long waited = System.currentTimeMillis() - before;
if (_log.shouldLog(Log.INFO))
_log.info("Waited " + waited + "ms to initialize");
_context.jobQueue().addJob(new StartupJob(_context));
}

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.150 $ $Date: 2005/02/23 16:44:32 $";
public final static String ID = "$Revision: 1.151 $ $Date: 2005/02/24 13:05:26 $";
public final static String VERSION = "0.5.0.1";
public final static long BUILD = 2;
public final static long BUILD = 3;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -11,6 +11,7 @@ import net.i2p.data.Lease;
import net.i2p.data.LeaseSet;
import net.i2p.data.TunnelId;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelPoolSettings;
import net.i2p.router.TunnelInfo;
@ -29,6 +30,16 @@ public class TunnelPool {
private TunnelPoolManager _manager;
private boolean _alive;
private long _lifetimeProcessed;
private int _buildsThisMinute;
private long _currentMinute;
private RefreshJob _refreshJob;
/**
* Only 3 builds per minute per pool, even if we have failing tunnels,
* etc. On overflow, the necessary additional tunnels are built by the
* RefreshJob
*/
private static final int MAX_BUILDS_PER_MINUTE = 3;
public TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel, TunnelBuilder builder) {
_context = ctx;
@ -40,11 +51,16 @@ public class TunnelPool {
_builder = builder;
_alive = false;
_lifetimeProcessed = 0;
_buildsThisMinute = 0;
_currentMinute = ctx.clock().now();
_refreshJob = new RefreshJob(ctx);
refreshSettings();
}
public void startup() {
_alive = true;
_refreshJob.getTiming().setStartAfter(_context.clock().now() + 60*1000);
_context.jobQueue().addJob(_refreshJob);
int added = refreshBuilders();
if (added <= 0) {
// we just reconnected and didn't require any new tunnel builders.
@ -92,10 +108,26 @@ public class TunnelPool {
_log.info(toString() + ": refreshing builders, previously had " + usableTunnels
+ ", want a total of " + target + ", creating "
+ (target-usableTunnels) + " new ones.");
for (int i = usableTunnels; i < target; i++)
_builder.buildTunnel(_context, this);
return (target > usableTunnels ? target-usableTunnels : 0);
if (target > usableTunnels) {
long minute = _context.clock().now();
minute = minute - (minute % 60*1000);
if (_currentMinute < minute) {
_currentMinute = minute;
_buildsThisMinute = 0;
}
int build = (target - usableTunnels);
if (build > (MAX_BUILDS_PER_MINUTE - _buildsThisMinute))
build = (MAX_BUILDS_PER_MINUTE - _buildsThisMinute);
for (int i = 0; i < build; i++)
_builder.buildTunnel(_context, this);
_buildsThisMinute += build;
return build;
} else {
return 0;
}
}
void refreshSettings() {
@ -386,4 +418,23 @@ public class TunnelPool {
}
}
/**
* We choke the # of rebuilds per pool per minute, so we need this to
* make sure to build enough tunnels.
*
*/
private class RefreshJob extends JobImpl {
public RefreshJob(RouterContext ctx) {
super(ctx);
}
public String getName() { return "Refresh pool"; }
public void runJob() {
if (!_alive) return;
int added = refreshBuilders();
if ( (added > 0) && (_log.shouldLog(Log.WARN)) )
_log.warn("Passive rebuilding a tunnel");
requeue(60*1000);
}
}
}