forked from I2P_Developers/i2p.i2p
* Router:
- More refactoring tasks to their own files - Adjust some thread priorities
This commit is contained in:
@ -342,6 +342,7 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
|
||||
Thread t = new I2PAppThread(new StatSummarizer(), "StatSummarizer", true);
|
||||
t.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
t.start();
|
||||
|
||||
List<RouterContext> contexts = RouterContext.listContexts();
|
||||
@ -350,10 +351,12 @@ public class RouterConsoleRunner {
|
||||
|
||||
NewsFetcher fetcher = NewsFetcher.getInstance(ctx);
|
||||
Thread newsThread = new I2PAppThread(fetcher, "NewsFetcher", true);
|
||||
newsThread.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
newsThread.start();
|
||||
|
||||
if (PluginStarter.pluginsEnabled(ctx)) {
|
||||
t = new I2PAppThread(new PluginStarter(ctx), "PluginStarter", true);
|
||||
t.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
t.start();
|
||||
ctx.addShutdownTask(new PluginStopper(ctx));
|
||||
}
|
||||
|
@ -275,32 +275,16 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
_log.info("New router created with config file " + _configFilename);
|
||||
//_sessionKeyPersistenceHelper = new SessionKeyPersistenceHelper(_context);
|
||||
_killVMOnEnd = true;
|
||||
_oomListener = new I2PThread.OOMEventListener() {
|
||||
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);
|
||||
}
|
||||
};
|
||||
_oomListener = new OOMListener(_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();
|
||||
|
||||
_watchdog = new RouterWatchdog(_context);
|
||||
_watchdogThread = new I2PAppThread(_watchdog, "RouterWatchdog", true);
|
||||
_watchdogThread.setPriority(Thread.NORM_PRIORITY + 1);
|
||||
_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_HARD = 3;
|
||||
public static final int EXIT_OOM = 10;
|
||||
@ -1170,13 +1133,27 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
_gracefulShutdownDetector.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
/**
|
||||
* Is a graceful shutdown in progress? This may be cancelled.
|
||||
*/
|
||||
public boolean gracefulShutdownInProgress() {
|
||||
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? */
|
||||
public long getShutdownTimeRemaining() {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* successful, false otherwise)
|
||||
@ -1308,46 +1240,18 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
return;
|
||||
((RouterClock) _context.clock()).removeShiftListener(this);
|
||||
_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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.8
|
||||
* Only for Restarter
|
||||
* @since 0.8.12
|
||||
*/
|
||||
private class Restarter implements Runnable {
|
||||
public void run() {
|
||||
_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); }
|
||||
|
||||
public void setIsAlive() {
|
||||
_isAlive = true;
|
||||
rebuildRouterInfo();
|
||||
|
||||
_log.logAlways(Log.WARN, "Restart complete");
|
||||
((RouterClock) _context.clock()).addShiftListener(Router.this);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
60
router/java/src/net/i2p/router/tasks/GracefulShutdown.java
Normal file
60
router/java/src/net/i2p/router/tasks/GracefulShutdown.java
Normal 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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
router/java/src/net/i2p/router/tasks/OOMListener.java
Normal file
39
router/java/src/net/i2p/router/tasks/OOMListener.java
Normal 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);
|
||||
}
|
||||
}
|
51
router/java/src/net/i2p/router/tasks/Restarter.java
Normal file
51
router/java/src/net/i2p/router/tasks/Restarter.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user