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);
|
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));
|
||||||
}
|
}
|
||||||
|
@ -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[]) {
|
||||||
|
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