* Soft restart:

- Allow NTP to reinitialize clock after the comm system
      in the first minute of uptime
    - Fix i2ptunnels not restarting
    - Increase minimum forward clock shift for soft restart
    - Reduce minimum backward clock shift for soft restart
    - Signal the I2CP client with a different message when restarting
    - I2CP client reconnects when receiving restart message
This commit is contained in:
zzz
2011-08-19 15:34:30 +00:00
parent 26c744ca45
commit c5e74fefe5
9 changed files with 65 additions and 13 deletions

View File

@ -12,6 +12,7 @@ package net.i2p.client;
import net.i2p.I2PAppContext;
import net.i2p.data.i2cp.DisconnectMessage;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -27,7 +28,26 @@ class DisconnectMessageHandler extends HandlerImpl {
public void handleMessage(I2CPMessage message, I2PSessionImpl session) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handle message " + message);
session.propogateError(((DisconnectMessage)message).getReason(), new I2PSessionException("Disconnect Message received"));
String reason = ((DisconnectMessage)message).getReason();
session.propogateError(reason, new I2PSessionException("Disconnect Message received"));
session.destroySession(false);
if (reason.contains("restart")) {
Thread t = new I2PAppThread(new Reconnector(session), "Reconnect " + session, true);
t.start();
}
}
/** @since 0.8.8 */
private static class Reconnector implements Runnable {
private final I2PSessionImpl _session;
public Reconnector(I2PSessionImpl session) {
_session = session;
}
public void run() {
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
_session.reconnect();
}
}
}

View File

@ -1,3 +1,13 @@
2011-08-19 zzz
* Soft restart:
- Allow NTP to reinitialize clock after the comm system
in the first minute of uptime
- Fix i2ptunnels not restarting
- Increase minimum forward clock shift for soft restart
- Reduce minimum backward clock shift for soft restart
- Signal the I2CP client with a different message when restarting
- I2CP client reconnects when receiving restart message
2011-08-17 kytv
* Fix #506: Don't attempt to load systray4j when using a 64bit JVM
in Windows.

View File

@ -94,4 +94,7 @@ public abstract class ClientManagerFacade implements Service {
public abstract SessionConfig getClientSessionConfig(Destination dest);
public abstract SessionKeyManager getClientSessionKeyManager(Hash dest);
public void renderStatusHTML(Writer out) throws IOException { }
/** @since 0.8.8 */
public abstract void shutdown(String msg);
}

View File

@ -36,6 +36,7 @@ public class DummyClientManagerFacade extends ClientManagerFacade {
public void startup() {}
public void stopAcceptingClients() { }
public void shutdown() {}
public void shutdown(String msg) {}
public void restart() {}
public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) {}

View File

@ -1308,7 +1308,8 @@ public class Router implements RouterClock.ClockShiftListener {
_started = _context.clock().now();
_log.error("Stopping the router for a restart...");
_log.logAlways(Log.WARN, "Stopping the client manager");
try { _context.clientManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error stopping the client manager", t); }
// NOTE: DisconnectMessageHandler keys off "restart"
try { _context.clientManager().shutdown("Router restart"); } catch (Throwable t) { _log.log(Log.CRIT, "Error stopping the client manager", t); }
_log.logAlways(Log.WARN, "Stopping the comm system");
try { _context.messageRegistry().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the message registry", t); }
try { _context.commSystem().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the comm system", t); }

View File

@ -40,11 +40,13 @@ public class RouterClock extends Clock {
private int _lastStratum;
/**
* If the system clock shifts by this much (positive or negative),
* If the system clock shifts by this much,
* call the callback, we probably need a soft restart.
* @since 0.8.8
*/
private static final long MASSIVE_SHIFT = 75*1000;
private static final long MASSIVE_SHIFT_FORWARD = 150*1000;
private static final long MASSIVE_SHIFT_BACKWARD = 61*1000;
private final Set<ClockShiftListener> _shiftListeners;
private volatile long _lastShiftNanos;
@ -137,7 +139,11 @@ public class RouterClock extends Clock {
} // check sanity
}
if (_alreadyChanged) {
// In first minute, allow a lower (better) stratum to do a step adjustment after
// a previous step adjustment.
// This allows NTP to trump a peer offset after a soft restart
if (_alreadyChanged &&
(stratum >= _lastStratum || _startedOn - System.currentTimeMillis() > 60*1000)) {
// Update the target offset, slewing will take care of the rest
if (delta > 15*1000)
getLog().error("Warning - Updating target clock offset to " + offsetMs + "ms from " + _offset + "ms, Stratum " + stratum);
@ -192,8 +198,8 @@ public class RouterClock extends Clock {
// copy the global, so two threads don't both increment or decrement _offset
long offset = _offset;
long sinceLastSlewed = systemNow - _lastSlewed;
if (sinceLastSlewed >= MASSIVE_SHIFT ||
sinceLastSlewed <= 0 - MASSIVE_SHIFT) {
if (sinceLastSlewed >= MASSIVE_SHIFT_FORWARD ||
sinceLastSlewed <= 0 - MASSIVE_SHIFT_BACKWARD) {
_lastSlewed = systemNow;
notifyMassive(sinceLastSlewed);
} else if (sinceLastSlewed >= MAX_SLEW) {
@ -224,7 +230,7 @@ public class RouterClock extends Clock {
long nowNanos = System.nanoTime();
// try to prevent dups, not guaranteed
// nanoTime() isn't guaranteed to be monotonic either :(
if (nowNanos < _lastShiftNanos + MASSIVE_SHIFT)
if (nowNanos < _lastShiftNanos + MASSIVE_SHIFT_FORWARD)
return;
_lastShiftNanos = nowNanos;

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 22;
public final static long BUILD = 23;
/** for example "-test" */
public final static String EXTRA = "-rc";

View File

@ -86,7 +86,7 @@ class ClientManager {
}
public void restart() {
shutdown();
shutdown("Router restart");
// to let the old listener die
try { Thread.sleep(2*1000); } catch (InterruptedException ie) {}
@ -96,7 +96,10 @@ class ClientManager {
startListeners(port);
}
public void shutdown() {
/**
* @param msg message to send to the clients
*/
public void shutdown(String msg) {
_isStarted = false;
_log.info("Shutting down the ClientManager");
if (_listener != null)
@ -116,7 +119,7 @@ class ClientManager {
}
for (Iterator<ClientConnectionRunner> iter = runners.iterator(); iter.hasNext(); ) {
ClientConnectionRunner runner = iter.next();
runner.disconnectClient("Router shutdown", Log.WARN);
runner.disconnectClient(msg, Log.WARN);
}
}

View File

@ -58,8 +58,16 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte
}
public void shutdown() {
shutdown("Router shutdown");
}
/**
* @param msg message to send to the clients
* @since 0.8.8
*/
public void shutdown(String msg) {
if (_manager != null)
_manager.shutdown();
_manager.shutdown(msg);
}
public void restart() {