forked from I2P_Developers/i2p.i2p
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:
@ -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(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user