* Router:

- More refactoring tasks to their own files
    - Adjust some thread priorities
This commit is contained in:
zzz
2011-12-05 16:18:35 +00:00
parent 5362e7cf15
commit 0f384c86fe
5 changed files with 180 additions and 123 deletions

View File

@ -342,6 +342,7 @@ public class RouterConsoleRunner {
} }
Thread t = new I2PAppThread(new StatSummarizer(), "StatSummarizer", true); Thread t = new I2PAppThread(new StatSummarizer(), "StatSummarizer", true);
t.setPriority(Thread.NORM_PRIORITY - 1);
t.start(); t.start();
List<RouterContext> contexts = RouterContext.listContexts(); List<RouterContext> contexts = RouterContext.listContexts();
@ -350,10 +351,12 @@ public class RouterConsoleRunner {
NewsFetcher fetcher = NewsFetcher.getInstance(ctx); NewsFetcher fetcher = NewsFetcher.getInstance(ctx);
Thread newsThread = new I2PAppThread(fetcher, "NewsFetcher", true); Thread newsThread = new I2PAppThread(fetcher, "NewsFetcher", true);
newsThread.setPriority(Thread.NORM_PRIORITY - 1);
newsThread.start(); newsThread.start();
if (PluginStarter.pluginsEnabled(ctx)) { if (PluginStarter.pluginsEnabled(ctx)) {
t = new I2PAppThread(new PluginStarter(ctx), "PluginStarter", true); t = new I2PAppThread(new PluginStarter(ctx), "PluginStarter", true);
t.setPriority(Thread.NORM_PRIORITY - 1);
t.start(); t.start();
ctx.addShutdownTask(new PluginStopper(ctx)); ctx.addShutdownTask(new PluginStopper(ctx));
} }

View File

@ -275,32 +275,16 @@ public class Router implements RouterClock.ClockShiftListener {
_log.info("New router created with config file " + _configFilename); _log.info("New router created with config file " + _configFilename);
//_sessionKeyPersistenceHelper = new SessionKeyPersistenceHelper(_context); //_sessionKeyPersistenceHelper = new SessionKeyPersistenceHelper(_context);
_killVMOnEnd = true; _killVMOnEnd = true;
_oomListener = new I2PThread.OOMEventListener() { _oomListener = new OOMListener(_context);
public void outOfMemory(OutOfMemoryError oom) {
clearCaches();
_log.log(Log.CRIT, "Thread ran out of memory, shutting down I2P", oom);
// prevent multiple parallel shutdowns (when you OOM, you OOM a lot...)
if (_shutdownInProgress)
return;
for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs
try {
_log.log(Log.CRIT, "free mem: " + Runtime.getRuntime().freeMemory() +
" total mem: " + Runtime.getRuntime().totalMemory());
break; // w00t
} catch (OutOfMemoryError oome) {
// gobble
}
}
_log.log(Log.CRIT, "To prevent future shutdowns, increase wrapper.java.maxmemory in $I2P/wrapper.config");
shutdown(EXIT_OOM);
}
};
_shutdownHook = new ShutdownHook(_context); _shutdownHook = new ShutdownHook(_context);
_gracefulShutdownDetector = new I2PAppThread(new GracefulShutdown(), "Graceful shutdown hook", true); _gracefulShutdownDetector = new I2PAppThread(new GracefulShutdown(_context), "Graceful shutdown hook", true);
_gracefulShutdownDetector.setPriority(Thread.NORM_PRIORITY + 1);
_gracefulShutdownDetector.start(); _gracefulShutdownDetector.start();
_watchdog = new RouterWatchdog(_context); _watchdog = new RouterWatchdog(_context);
_watchdogThread = new I2PAppThread(_watchdog, "RouterWatchdog", true); _watchdogThread = new I2PAppThread(_watchdog, "RouterWatchdog", true);
_watchdogThread.setPriority(Thread.NORM_PRIORITY + 1);
_watchdogThread.start(); _watchdogThread.start();
} }
@ -973,27 +957,6 @@ public class Router implements RouterClock.ClockShiftListener {
} }
******/ ******/
/**
* A non-daemon thread to let
* the shutdown task get all the way to the end
* @since 0.8.8
*/
private static class Spinner extends Thread {
public Spinner() {
super();
setName("Shutdown Spinner");
setDaemon(false);
}
@Override
public void run() {
try {
sleep(60*1000);
} catch (InterruptedException ie) {}
}
}
public static final int EXIT_GRACEFUL = 2; public static final int EXIT_GRACEFUL = 2;
public static final int EXIT_HARD = 3; public static final int EXIT_HARD = 3;
public static final int EXIT_OOM = 10; public static final int EXIT_OOM = 10;
@ -1170,13 +1133,27 @@ public class Router implements RouterClock.ClockShiftListener {
_gracefulShutdownDetector.notifyAll(); _gracefulShutdownDetector.notifyAll();
} }
} }
/** /**
* What exit code do we plan on using when we shut down (or -1, if there isn't a graceful shutdown planned) * What exit code do we plan on using when we shut down (or -1, if there isn't a graceful shutdown planned)
*/ */
public int scheduledGracefulExitCode() { return _gracefulExitCode; } public int scheduledGracefulExitCode() { return _gracefulExitCode; }
/**
* Is a graceful shutdown in progress? This may be cancelled.
*/
public boolean gracefulShutdownInProgress() { public boolean gracefulShutdownInProgress() {
return (null != _config.get(PROP_SHUTDOWN_IN_PROGRESS)); return (null != _config.get(PROP_SHUTDOWN_IN_PROGRESS));
} }
/**
* Is a final shutdown in progress? This may not be cancelled.
* @since 0.8.12
*/
public boolean isFinalShutdownInProgress() {
return _shutdownInProgress;
}
/** How long until the graceful shutdown will kill us? */ /** How long until the graceful shutdown will kill us? */
public long getShutdownTimeRemaining() { public long getShutdownTimeRemaining() {
if (_gracefulExitCode <= 0) return -1; // maybe Long.MAX_VALUE would be better? if (_gracefulExitCode <= 0) return -1; // maybe Long.MAX_VALUE would be better?
@ -1189,51 +1166,6 @@ public class Router implements RouterClock.ClockShiftListener {
return exp + 2*CLOCK_FUDGE_FACTOR - _context.clock().now(); return exp + 2*CLOCK_FUDGE_FACTOR - _context.clock().now();
} }
/**
* Simple thread that sits and waits forever, managing the
* graceful shutdown "process" (describing it would take more text
* than just reading the code...)
*
*/
private class GracefulShutdown implements Runnable {
public void run() {
while (true) {
boolean shutdown = (null != _config.get(PROP_SHUTDOWN_IN_PROGRESS));
if (shutdown) {
if (_gracefulExitCode == EXIT_HARD || _gracefulExitCode == EXIT_HARD_RESTART ||
_context.tunnelManager().getParticipatingCount() <= 0) {
if (_gracefulExitCode == EXIT_HARD)
_log.log(Log.CRIT, "Shutting down after a brief delay");
else if (_gracefulExitCode == EXIT_HARD_RESTART)
_log.log(Log.CRIT, "Restarting after a brief delay");
else
_log.log(Log.CRIT, "Graceful shutdown progress - no more tunnels, safe to die");
// Allow time for a UI reponse
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(2*1000);
}
} catch (InterruptedException ie) {}
shutdown(_gracefulExitCode);
return;
} else {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(10*1000);
}
} catch (InterruptedException ie) {}
}
} else {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait();
}
} catch (InterruptedException ie) {}
}
}
}
}
/** /**
* Save the current config options (returning true if save was * Save the current config options (returning true if save was
* successful, false otherwise) * successful, false otherwise)
@ -1308,46 +1240,18 @@ public class Router implements RouterClock.ClockShiftListener {
return; return;
((RouterClock) _context.clock()).removeShiftListener(this); ((RouterClock) _context.clock()).removeShiftListener(this);
_isAlive = false; _isAlive = false;
Thread t = new Thread(new Restarter(), "Router Restart"); _started = _context.clock().now();
Thread t = new Thread(new Restarter(_context), "Router Restart");
t.setPriority(Thread.NORM_PRIORITY + 1);
t.start(); t.start();
} }
/** /**
* @since 0.8.8 * Only for Restarter
* @since 0.8.12
*/ */
private class Restarter implements Runnable { public void setIsAlive() {
public void run() { _isAlive = true;
_started = _context.clock().now();
_log.error("Stopping the router for a restart...");
_log.logAlways(Log.WARN, "Stopping the client manager");
// 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");
_context.bandwidthLimiter().reinitialize();
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); }
_log.logAlways(Log.WARN, "Stopping the tunnel manager");
try { _context.tunnelManager().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the tunnel manager", t); }
//try { _context.peerManager().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the peer manager", t); }
//try { _context.netDb().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the networkDb", t); }
//try { _context.jobQueue().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the job queue", t); }
_log.logAlways(Log.WARN, "Router teardown complete, restarting the router...");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
_log.logAlways(Log.WARN, "Restarting the comm system");
_log.logAlways(Log.WARN, "Restarting the tunnel manager");
_log.logAlways(Log.WARN, "Restarting the client manager");
try { _context.clientMessagePool().restart(); } catch (Throwable t) { _log.log(Log.CRIT, "Error restarting the CMP", t); }
try { _context.clientManager().startup(); } catch (Throwable t) { _log.log(Log.CRIT, "Error starting the client manager", t); }
_isAlive = true;
rebuildRouterInfo();
_log.logAlways(Log.WARN, "Restart complete");
((RouterClock) _context.clock()).addShiftListener(Router.this);
}
} }
public static void main(String args[]) { public static void main(String args[]) {

View File

@ -0,0 +1,60 @@
package net.i2p.router.tasks;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Simple thread that sits and waits forever, managing the
* graceful shutdown "process" (describing it would take more text
* than just reading the code...)
*
* @since 0.8.12 moved from Router
*/
public class GracefulShutdown implements Runnable {
private final RouterContext _context;
public GracefulShutdown(RouterContext ctx) {
_context = ctx;
}
public void run() {
Log log = _context.logManager().getLog(Router.class);
while (true) {
boolean shutdown = _context.router().gracefulShutdownInProgress();
if (shutdown) {
int gracefulExitCode = _context.router().scheduledGracefulExitCode();
if (gracefulExitCode == Router.EXIT_HARD || gracefulExitCode == Router.EXIT_HARD_RESTART ||
_context.tunnelManager().getParticipatingCount() <= 0) {
if (gracefulExitCode == Router.EXIT_HARD)
log.log(Log.CRIT, "Shutting down after a brief delay");
else if (gracefulExitCode == Router.EXIT_HARD_RESTART)
log.log(Log.CRIT, "Restarting after a brief delay");
else
log.log(Log.CRIT, "Graceful shutdown progress - no more tunnels, safe to die");
// Allow time for a UI reponse
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(2*1000);
}
} catch (InterruptedException ie) {}
_context.router().shutdown(gracefulExitCode);
return;
} else {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(10*1000);
}
} catch (InterruptedException ie) {}
}
} else {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait();
}
} catch (InterruptedException ie) {}
}
}
}
}

View File

@ -0,0 +1,39 @@
package net.i2p.router.tasks;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Kaboom
*
* @since 0.8.12 moved from Router.java
*/
public class OOMListener implements I2PThread.OOMEventListener {
private final RouterContext _context;
public OOMListener(RouterContext ctx) {
_context = ctx;
}
public void outOfMemory(OutOfMemoryError oom) {
Router.clearCaches();
Log log = _context.logManager().getLog(Router.class);
log.log(Log.CRIT, "Thread ran out of memory, shutting down I2P", oom);
// prevent multiple parallel shutdowns (when you OOM, you OOM a lot...)
if (_context.router().isFinalShutdownInProgress())
return;
for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs
try {
log.log(Log.CRIT, "free mem: " + Runtime.getRuntime().freeMemory() +
" total mem: " + Runtime.getRuntime().totalMemory());
break; // w00t
} catch (OutOfMemoryError oome) {
// gobble
}
}
log.log(Log.CRIT, "To prevent future shutdowns, increase wrapper.java.maxmemory in $I2P/wrapper.config");
_context.router().shutdown(Router.EXIT_OOM);
}
}

View File

@ -0,0 +1,51 @@
package net.i2p.router.tasks;
import net.i2p.router.Router;
import net.i2p.router.RouterClock;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* @since 0.8.8, moved from Router in 0.8.12
*/
public class Restarter implements Runnable {
private final RouterContext _context;
public Restarter(RouterContext ctx) {
_context = ctx;
}
public void run() {
Log log = _context.logManager().getLog(Router.class);
log.error("Stopping the router for a restart...");
log.logAlways(Log.WARN, "Stopping the client manager");
// 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");
_context.bandwidthLimiter().reinitialize();
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); }
log.logAlways(Log.WARN, "Stopping the tunnel manager");
try { _context.tunnelManager().restart(); } catch (Throwable t) { log.log(Log.CRIT, "Error restarting the tunnel manager", t); }
//try { _context.peerManager().restart(); } catch (Throwable t) { log.log(Log.CRIT, "Error restarting the peer manager", t); }
//try { _context.netDb().restart(); } catch (Throwable t) { log.log(Log.CRIT, "Error restarting the networkDb", t); }
//try { _context.jobQueue().restart(); } catch (Throwable t) { log.log(Log.CRIT, "Error restarting the job queue", t); }
log.logAlways(Log.WARN, "Router teardown complete, restarting the router...");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
log.logAlways(Log.WARN, "Restarting the comm system");
log.logAlways(Log.WARN, "Restarting the tunnel manager");
log.logAlways(Log.WARN, "Restarting the client manager");
try { _context.clientMessagePool().restart(); } catch (Throwable t) { log.log(Log.CRIT, "Error restarting the CMP", t); }
try { _context.clientManager().startup(); } catch (Throwable t) { log.log(Log.CRIT, "Error starting the client manager", t); }
_context.router().setIsAlive();
_context.router().rebuildRouterInfo();
log.logAlways(Log.WARN, "Restart complete");
((RouterClock) _context.clock()).addShiftListener(_context.router());
}
}