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(); t.start();
} }
public void waitForInitialization() {
try {
synchronized (this) {
if (!_initialized)
wait();
}
} catch (InterruptedException ie) {}
}
public void run() { public void run() {
try { Thread.sleep(1000); } catch (InterruptedException ie) {} try { Thread.sleep(1000); } catch (InterruptedException ie) {}
_log = _context.logManager().getLog(Timestamper.class); _log = _context.logManager().getLog(Timestamper.class);
@ -130,6 +139,9 @@ public class Timestamper implements Runnable {
lastFailed = true; lastFailed = true;
} }
} }
_initialized = true;
synchronized (this) { notifyAll(); }
long sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency; long sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency;
if (lastFailed) if (lastFailed)
sleepTime = 30*1000; sleepTime = 30*1000;
@ -137,6 +149,7 @@ public class Timestamper implements Runnable {
} }
} catch (Throwable t) { } catch (Throwable t) {
_log.log(Log.CRIT, "Timestamper died!", 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 2005-02-24 jrandom
* Cache temporary memory allocation in the DSA's SHA1 impl, and the packet * Cache temporary memory allocation in the DSA's SHA1 impl, and the packet

View File

@ -225,6 +225,14 @@ public class Router {
warmupCrypto(); warmupCrypto();
_sessionKeyPersistenceHelper.startup(); _sessionKeyPersistenceHelper.startup();
//_context.adminManager().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)); _context.jobQueue().addJob(new StartupJob(_context));
} }

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
* *
*/ */
public class RouterVersion { 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 String VERSION = "0.5.0.1";
public final static long BUILD = 2; public final static long BUILD = 3;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION); System.out.println("I2P Router version: " + VERSION);
System.out.println("Router ID: " + RouterVersion.ID); 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.LeaseSet;
import net.i2p.data.TunnelId; import net.i2p.data.TunnelId;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.TunnelPoolSettings; import net.i2p.router.TunnelPoolSettings;
import net.i2p.router.TunnelInfo; import net.i2p.router.TunnelInfo;
@ -29,6 +30,16 @@ public class TunnelPool {
private TunnelPoolManager _manager; private TunnelPoolManager _manager;
private boolean _alive; private boolean _alive;
private long _lifetimeProcessed; 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) { public TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel, TunnelBuilder builder) {
_context = ctx; _context = ctx;
@ -40,11 +51,16 @@ public class TunnelPool {
_builder = builder; _builder = builder;
_alive = false; _alive = false;
_lifetimeProcessed = 0; _lifetimeProcessed = 0;
_buildsThisMinute = 0;
_currentMinute = ctx.clock().now();
_refreshJob = new RefreshJob(ctx);
refreshSettings(); refreshSettings();
} }
public void startup() { public void startup() {
_alive = true; _alive = true;
_refreshJob.getTiming().setStartAfter(_context.clock().now() + 60*1000);
_context.jobQueue().addJob(_refreshJob);
int added = refreshBuilders(); int added = refreshBuilders();
if (added <= 0) { if (added <= 0) {
// we just reconnected and didn't require any new tunnel builders. // 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 _log.info(toString() + ": refreshing builders, previously had " + usableTunnels
+ ", want a total of " + target + ", creating " + ", want a total of " + target + ", creating "
+ (target-usableTunnels) + " new ones."); + (target-usableTunnels) + " new ones.");
for (int i = usableTunnels; i < target; i++)
_builder.buildTunnel(_context, this); if (target > usableTunnels) {
long minute = _context.clock().now();
return (target > usableTunnels ? target-usableTunnels : 0); 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() { 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);
}
}
} }