forked from I2P_Developers/i2p.i2p
Util: New getEstimatedDowntime() method
This commit is contained in:
@ -105,6 +105,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
private boolean _familyKeyCryptoFail;
|
||||
public final Object _familyKeyLock = new Object();
|
||||
private UPnPScannerCallback _upnpScannerCallback;
|
||||
private long _downtime = -1;
|
||||
|
||||
public final static String PROP_CONFIG_FILE = "router.configLocation";
|
||||
|
||||
@ -711,7 +712,8 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
synchronized(_configFileLock) {
|
||||
// persistent key for peer ordering since 0.9.17
|
||||
// These will be replaced in CreateRouterInfoJob if we rekey
|
||||
if (!_config.containsKey(PROP_IB_RANDOM_KEY)) {
|
||||
if (!_config.containsKey(PROP_IB_RANDOM_KEY) ||
|
||||
getEstimatedDowntime() > 12*60*60*1000L) {
|
||||
byte rk[] = new byte[32];
|
||||
_context.random().nextBytes(rk);
|
||||
_config.put(PROP_IB_RANDOM_KEY, Base64.encode(rk));
|
||||
@ -1809,6 +1811,9 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
((RouterClock) _context.clock()).removeShiftListener(this);
|
||||
// Let's not stop accepting tunnels, etc
|
||||
//_started = _context.clock().now();
|
||||
synchronized(_configFileLock) {
|
||||
_downtime = 1;
|
||||
}
|
||||
Thread t = new I2PThread(new Restarter(_context), "Router Restart");
|
||||
t.setPriority(Thread.NORM_PRIORITY + 1);
|
||||
t.start();
|
||||
@ -1915,7 +1920,12 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
File f = getPingFile();
|
||||
if (f.exists()) {
|
||||
long lastWritten = f.lastModified();
|
||||
if (System.currentTimeMillis()-lastWritten > LIVELINESS_DELAY) {
|
||||
long downtime = System.currentTimeMillis() - lastWritten;
|
||||
synchronized(_configFileLock) {
|
||||
if (downtime > 0 && _downtime < 0)
|
||||
_downtime = downtime;
|
||||
}
|
||||
if (downtime > LIVELINESS_DELAY) {
|
||||
System.err.println("WARN: Old router was not shut down gracefully, deleting " + f);
|
||||
f.delete();
|
||||
} else {
|
||||
@ -1934,6 +1944,49 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
_context.simpleTimer2().addPeriodicEvent(new MarkLiveliness(this, f), 0, LIVELINESS_DELAY - (5*1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* How long this router was down before it started, or 0 if unknown.
|
||||
*
|
||||
* This may be used for a determination of whether to regenerate keys, for example.
|
||||
* We use the timestamp of the previous ping file left behind on crash,
|
||||
* as set by isOnlyRouterRunning(), if present.
|
||||
* Otherwise, the last STOPPED entry in the event log.
|
||||
*
|
||||
* May take a while to run the first time, if it has to go through the event log.
|
||||
* Once called, the result is cached.
|
||||
*
|
||||
* @since 0.0.47
|
||||
*/
|
||||
public long getEstimatedDowntime() {
|
||||
synchronized(_configFileLock) {
|
||||
if (_downtime >= 0)
|
||||
return _downtime;
|
||||
long begin = System.currentTimeMillis();
|
||||
long stopped = _eventLog.getLastEvent(EventLog.STOPPED, _context.clock().now() - 365*24*60*60*1000L);
|
||||
long downtime = stopped > 0 ? _started - stopped : 0;
|
||||
if (downtime < 0)
|
||||
downtime = 0;
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Downtime was " + DataHelper.formatDuration(downtime) +
|
||||
"; calculation took " + DataHelper.formatDuration(System.currentTimeMillis() - begin));
|
||||
_downtime = downtime;
|
||||
return downtime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for soft restart. Not for external use.
|
||||
*
|
||||
* @since 0.0.47
|
||||
*/
|
||||
public void setEstimatedDowntime(long downtime) {
|
||||
if (downtime <= 0)
|
||||
downtime = 1;
|
||||
synchronized(_configFileLock) {
|
||||
_downtime = downtime;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage";
|
||||
public static final int DEFAULT_SHARE_PERCENTAGE = 80;
|
||||
|
||||
|
@ -706,4 +706,24 @@ public class RouterContext extends I2PAppContext {
|
||||
public ECIESAEADEngine eciesEngine() {
|
||||
return _eciesEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* How long this router was down before it started, or 0 if unknown.
|
||||
*
|
||||
* This may be used for a determination of whether to regenerate keys, for example.
|
||||
* We use the timestamp of the previous ping file left behind on crash,
|
||||
* as set by isOnlyRouterRunning(), if present.
|
||||
* Otherwise, the last STOPPED entry in the event log.
|
||||
*
|
||||
* May take a while to run the first time, if it has to go through the event log.
|
||||
* Once called, the result is cached.
|
||||
*
|
||||
* @return downtime in ms or 0 if unknown
|
||||
* @since 0.0.47
|
||||
*/
|
||||
public long getEstimatedDowntime() {
|
||||
if (_router == null)
|
||||
return 0L;
|
||||
return _router.getEstimatedDowntime();
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public class Restarter implements Runnable {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Long start = System.currentTimeMillis();
|
||||
_context.router().eventLog().addEvent(EventLog.SOFT_RESTART);
|
||||
Log log = _context.logManager().getLog(Router.class);
|
||||
log.error("Stopping the router for a restart...");
|
||||
@ -36,6 +37,7 @@ public class Restarter implements Runnable {
|
||||
|
||||
log.logAlways(Log.WARN, "Router teardown complete, restarting the router...");
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
_context.router().setEstimatedDowntime(System.currentTimeMillis() - start);
|
||||
|
||||
log.logAlways(Log.WARN, "Restarting the comm system");
|
||||
log.logAlways(Log.WARN, "Restarting the tunnel manager");
|
||||
|
@ -252,12 +252,7 @@ public class NTCPTransport extends TransportImpl {
|
||||
String b64IV = null;
|
||||
String s = null;
|
||||
// try to determine if we've been down for 30 days or more
|
||||
// no stopping, no crashes, and only one start (this one)
|
||||
EventLog el = _context.router().eventLog();
|
||||
long since = _context.clock().now() - MIN_DOWNTIME_TO_REKEY;
|
||||
boolean shouldRekey = el.getEvents(EventLog.STOPPED, since).isEmpty() &&
|
||||
el.getEvents(EventLog.CRASHED, since).isEmpty() &&
|
||||
el.getEvents(EventLog.STARTED, since).size() <= 1;
|
||||
boolean shouldRekey = _context.getEstimatedDowntime() >= MIN_DOWNTIME_TO_REKEY;
|
||||
if (!shouldRekey) {
|
||||
s = ctx.getProperty(PROP_NTCP2_SP);
|
||||
if (s != null) {
|
||||
|
@ -190,4 +190,40 @@ public class EventLog {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of last event.
|
||||
*
|
||||
* @param event matching this event, case sensitive
|
||||
* @param since since this time, 0 for all
|
||||
* @return last event time, or 0 for none
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public synchronized long getLastEvent(String event, long since) {
|
||||
long rv = 0;
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(_file), "UTF-8"));
|
||||
String line = null;
|
||||
while ( (line = br.readLine()) != null) {
|
||||
try {
|
||||
String[] s = DataHelper.split(line.trim(), " ", 3);
|
||||
if (s.length < 2)
|
||||
continue;
|
||||
if (!s[1].equals(event))
|
||||
continue;
|
||||
long time = Long.parseLong(s[0]);
|
||||
if (time <= since)
|
||||
continue;
|
||||
rv = time;
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
} finally {
|
||||
if (br != null) try { br.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user