more cleanup at shutdown

This commit is contained in:
zzz
2011-06-14 19:27:46 +00:00
parent 21b76f1ca1
commit 3c88c854bf
3 changed files with 37 additions and 5 deletions

View File

@ -1,6 +1,7 @@
package net.i2p; package net.i2p;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import java.util.Random; import java.util.Random;
@ -100,7 +101,7 @@ public class I2PAppContext {
private volatile boolean _randomInitialized; private volatile boolean _randomInitialized;
private volatile boolean _keyGeneratorInitialized; private volatile boolean _keyGeneratorInitialized;
protected volatile boolean _keyRingInitialized; // used in RouterContext protected volatile boolean _keyRingInitialized; // used in RouterContext
private Set<Runnable> _shutdownTasks; protected final Set<Runnable> _shutdownTasks;
private File _baseDir; private File _baseDir;
private File _configDir; private File _configDir;
private File _routerDir; private File _routerDir;
@ -185,7 +186,7 @@ public class I2PAppContext {
_elGamalAESEngineInitialized = false; _elGamalAESEngineInitialized = false;
_logManagerInitialized = false; _logManagerInitialized = false;
_keyRingInitialized = false; _keyRingInitialized = false;
_shutdownTasks = new ConcurrentHashSet(0); _shutdownTasks = new ConcurrentHashSet(16);
initializeDirs(); initializeDirs();
} }
@ -843,12 +844,24 @@ public class I2PAppContext {
} }
} }
/**
* WARNING - Shutdown tasks are not executed in an I2PAppContext.
* You must be in a RouterContext for the tasks to be executed
* at shutdown.
* This method moved from Router in 0.7.1 so that clients
* may use it without depending on router.jar.
* @since 0.7.1
*/
public void addShutdownTask(Runnable task) { public void addShutdownTask(Runnable task) {
_shutdownTasks.add(task); _shutdownTasks.add(task);
} }
/**
* @return an unmodifiable Set
* @since 0.7.1
*/
public Set<Runnable> getShutdownTasks() { public Set<Runnable> getShutdownTasks() {
return new HashSet(_shutdownTasks); return Collections.unmodifiableSet(_shutdownTasks);
} }
/** /**

View File

@ -49,6 +49,7 @@ import net.i2p.util.I2PAppThread;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleByteCache;
import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer;
@ -257,7 +258,7 @@ public class Router {
_killVMOnEnd = true; _killVMOnEnd = true;
_oomListener = new I2PThread.OOMEventListener() { _oomListener = new I2PThread.OOMEventListener() {
public void outOfMemory(OutOfMemoryError oom) { public void outOfMemory(OutOfMemoryError oom) {
ByteCache.clearAll(); clearCaches();
_log.log(Log.CRIT, "Thread ran out of memory", oom); _log.log(Log.CRIT, "Thread ran out of memory", oom);
for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs
try { try {
@ -280,6 +281,12 @@ public class Router {
} }
/** @since 0.8.8 */
private static final void clearCaches() {
ByteCache.clearAll();
SimpleByteCache.clearAll();
}
/** /**
* Configure the router to kill the JVM when the router shuts down, as well * Configure the router to kill the JVM when the router shuts down, as well
* as whether to explicitly halt the JVM during the hard fail process. * as whether to explicitly halt the JVM during the hard fail process.
@ -624,6 +631,7 @@ public class Router {
_log.log(Log.CRIT, "Error running shutdown task", t); _log.log(Log.CRIT, "Error running shutdown task", t);
} }
} }
_context.removeShutdownTasks();
// hard and ugly // hard and ugly
if (System.getProperty("wrapper.version") != null) if (System.getProperty("wrapper.version") != null)
_log.log(Log.CRIT, "Restarting with new router identity"); _log.log(Log.CRIT, "Restarting with new router identity");
@ -940,12 +948,15 @@ public class Router {
// Run the shutdown hooks first in case they want to send some goodbye messages // Run the shutdown hooks first in case they want to send some goodbye messages
// Maybe we need a delay after this too? // Maybe we need a delay after this too?
for (Runnable task : _context.getShutdownTasks()) { for (Runnable task : _context.getShutdownTasks()) {
if (_log.shouldLog(Log.WARN))
_log.warn("Running shutdown task " + task.getClass());
try { try {
task.run(); task.run();
} catch (Throwable t) { } catch (Throwable t) {
_log.log(Log.CRIT, "Error running shutdown task", t); _log.log(Log.CRIT, "Error running shutdown task", t);
} }
} }
_context.removeShutdownTasks();
try { _context.clientManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the client manager", t); } try { _context.clientManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the client manager", t); }
try { _context.namingService().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the naming service", t); } try { _context.namingService().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the naming service", t); }
try { _context.jobQueue().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the job queue", t); } try { _context.jobQueue().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the job queue", t); }
@ -972,6 +983,7 @@ public class Router {
private static final boolean ALLOW_DYNAMIC_KEYS = false; private static final boolean ALLOW_DYNAMIC_KEYS = false;
private void finalShutdown(int exitCode) { private void finalShutdown(int exitCode) {
clearCaches();
_log.log(Log.CRIT, "Shutdown(" + exitCode + ") complete" /* , new Exception("Shutdown") */ ); _log.log(Log.CRIT, "Shutdown(" + exitCode + ") complete" /* , new Exception("Shutdown") */ );
try { _context.logManager().shutdown(); } catch (Throwable t) { } try { _context.logManager().shutdown(); } catch (Throwable t) { }
if (ALLOW_DYNAMIC_KEYS) { if (ALLOW_DYNAMIC_KEYS) {
@ -1486,7 +1498,7 @@ private static class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
getContext().statManager().addRateData("router.memoryUsed", used, 0); getContext().statManager().addRateData("router.memoryUsed", used, 0);
if (_maxMemory - used < LOW_MEMORY_THRESHOLD) if (_maxMemory - used < LOW_MEMORY_THRESHOLD)
ByteCache.clearAll(); clearCaches();
getContext().tunnelDispatcher().updateParticipatingStats(COALESCE_TIME); getContext().tunnelDispatcher().updateParticipatingStats(COALESCE_TIME);

View File

@ -402,6 +402,13 @@ public class RouterContext extends I2PAppContext {
} }
} }
/**
* @since 0.8.8
*/
void removeShutdownTasks() {
_shutdownTasks.clear();
}
/** /**
* Use this instead of context instanceof RouterContext * Use this instead of context instanceof RouterContext
* @return true * @return true