From 43044586d13f2e95ee22b338ea670781ad976d35 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 3 Jul 2011 13:46:29 +0000 Subject: [PATCH] * AppContext: Add hasWrapper() method * Shutdown: - Clear more resources in peer manager, netdb, stat manager, session key manager, naming service, tunnel dispatcher, OCMOSJ (result of testing with jvisualvm) - Don't call wrapper on shutdown (starting two threads) if we were started with runplain --- .../src/net/i2p/router/web/ConfigNetHandler.java | 6 ++++-- .../net/i2p/router/web/ConfigRestartBean.java | 14 +++++++++----- .../net/i2p/router/web/ConfigServiceHandler.java | 16 ++++++++++++---- .../net/i2p/router/web/ConfigUpdateHelper.java | 2 +- .../i2p/router/web/UnsignedUpdateHandler.java | 2 +- .../src/net/i2p/router/web/UpdateHandler.java | 5 +++-- core/java/src/net/i2p/I2PAppContext.java | 8 ++++++++ .../client/naming/BlockfileNamingService.java | 3 ++- core/java/src/net/i2p/stat/StatManager.java | 6 ++++++ core/java/src/net/i2p/util/LogConsoleBuffer.java | 8 ++++++++ core/java/src/net/i2p/util/LogManager.java | 4 ++++ history.txt | 9 +++++++++ .../src/net/i2p/router/ClientMessagePool.java | 7 +++++++ router/java/src/net/i2p/router/Router.java | 14 +++++++++----- .../java/src/net/i2p/router/RouterVersion.java | 2 +- .../message/OutboundClientMessageOneShotJob.java | 16 ++++++++++++++++ .../router/networkdb/kademlia/KBucketSet.java | 9 +++++++++ .../kademlia/KademliaNetworkDatabaseFacade.java | 2 ++ .../i2p/router/networkdb/kademlia/LocalHash.java | 5 +++-- .../i2p/router/peermanager/ProfileOrganizer.java | 6 ++++-- .../net/i2p/router/tunnel/TunnelDispatcher.java | 6 ++++++ 21 files changed, 124 insertions(+), 26 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java index 541f6d73cc..82c175e922 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -271,7 +271,7 @@ public class ConfigNetHandler extends FormHandler { if (switchRequired) { hiddenSwitch(); } else if (restartRequired) { - if (System.getProperty("wrapper.version") == null) { + if (_context.hasWrapper()) { // Wow this dumps all conns immediately and really isn't nice addFormNotice("Performing a soft restart"); _context.router().restart(); @@ -289,7 +289,8 @@ public class ConfigNetHandler extends FormHandler { // There's a few changes that don't really require restart (e.g. enabling inbound TCP) // But it would be hard to get right, so just do a restart. addFormError(_("Gracefully restarting I2P to change published router address")); - _context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); + if (_context.hasWrapper()) + _context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } } @@ -297,6 +298,7 @@ public class ConfigNetHandler extends FormHandler { private void hiddenSwitch() { // Full restart required to generate new keys + // FIXME don't call wrapper if not present, only rekey _context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java index d36cfbaf90..e98dadcac3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java @@ -30,21 +30,25 @@ public class ConfigRestartBean { if ( (nonce != null) && (systemNonce.equals(nonce)) && (action != null) ) { // Normal browsers send value, IE sends button label if ("shutdownImmediate".equals(action) || _("Shutdown immediately", ctx).equals(action)) { - ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD)); + if (ctx.hasWrapper()) + ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD)); //ctx.router().shutdown(Router.EXIT_HARD); // never returns ctx.router().shutdownGracefully(Router.EXIT_HARD); // give the UI time to respond } else if ("cancelShutdown".equals(action) || _("Cancel shutdown", ctx).equals(action) || _("Cancel restart", ctx).equals(action)) { ctx.router().cancelGracefulShutdown(); } else if ("restartImmediate".equals(action) || _("Restart immediately", ctx).equals(action)) { - ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART)); + if (ctx.hasWrapper()) + ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART)); //ctx.router().shutdown(Router.EXIT_HARD_RESTART); // never returns ctx.router().shutdownGracefully(Router.EXIT_HARD_RESTART); // give the UI time to respond } else if ("restart".equals(action) || _("Restart", ctx).equals(action)) { - ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); + if (ctx.hasWrapper()) + ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); ctx.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } else if ("shutdown".equals(action) || _("Shutdown", ctx).equals(action)) { - ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL)); + if (ctx.hasWrapper()) + ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL)); ctx.router().shutdownGracefully(); } } @@ -71,7 +75,7 @@ public class ConfigRestartBean { buf.append("</b></center><br>"); buttons(ctx, buf, urlBase, systemNonce, SET2); } else { - if (System.getProperty("wrapper.version") != null) + if (ctx.hasWrapper()) buttons(ctx, buf, urlBase, systemNonce, SET3); else buttons(ctx, buf, urlBase, systemNonce, SET4); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java index 7b1d7bc629..304b624a03 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java @@ -51,30 +51,38 @@ public class ConfigServiceHandler extends FormHandler { if (_action == null) return; if (_("Shutdown gracefully").equals(_action)) { - _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL)); + if (_context.hasWrapper()) + _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL)); _context.router().shutdownGracefully(); addFormNotice(_("Graceful shutdown initiated")); } else if (_("Shutdown immediately").equals(_action)) { - _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD)); + if (_context.hasWrapper()) + _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD)); _context.router().shutdown(Router.EXIT_HARD); addFormNotice(_("Shutdown immediately! boom bye bye bad bwoy")); } else if (_("Cancel graceful shutdown").equals(_action)) { _context.router().cancelGracefulShutdown(); addFormNotice(_("Graceful shutdown cancelled")); } else if (_("Graceful restart").equals(_action)) { - _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); + // should have wrapper if restart button is visible + if (_context.hasWrapper()) + _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); addFormNotice(_("Graceful restart requested")); } else if (_("Hard restart").equals(_action)) { - _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART)); + // should have wrapper if restart button is visible + if (_context.hasWrapper()) + _context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART)); _context.router().shutdown(Router.EXIT_HARD_RESTART); addFormNotice(_("Hard restart requested")); } else if (_("Rekey and Restart").equals(_action)) { addFormNotice(_("Rekeying after graceful restart")); + // FIXME don't call wrapper if not present, only rekey _context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } else if (_("Rekey and Shutdown").equals(_action)) { addFormNotice(_("Rekeying after graceful shutdown")); + // FIXME don't call wrapper if not present, only rekey _context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL); } else if (_("Run I2P on startup").equals(_action)) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java index f74a295bbe..2ffa495755 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java @@ -117,7 +117,7 @@ public class ConfigUpdateHelper extends HelperBase { buf.append(" selected=\"true\""); buf.append('>').append(_("Download and verify only")).append("</option>"); - if (System.getProperty("wrapper.version") != null) { + if (_context.hasWrapper()) { buf.append("<option value=\"install\""); if (_dontInstall) buf.append(" disabled=\"true\""); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/UnsignedUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/UnsignedUpdateHandler.java index 5a52ee883a..2eb132b30b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/UnsignedUpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/UnsignedUpdateHandler.java @@ -115,7 +115,7 @@ public class UnsignedUpdateHandler extends UpdateHandler { _log.log(Log.CRIT, "Update was downloaded, will be installed at next restart"); StringBuilder buf = new StringBuilder(64); buf.append("<b>").append(_("Update downloaded")).append("</b><br>"); - if (System.getProperty("wrapper.version") != null) + if (_context.hasWrapper()) buf.append(_("Click Restart to install")); else buf.append(_("Click Shutdown and restart to install")); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java index 423b9e52ad..4581a346a7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java @@ -285,7 +285,7 @@ public class UpdateHandler { _log.log(Log.CRIT, "Update was VERIFIED, will be installed at next restart"); StringBuilder buf = new StringBuilder(64); buf.append("<b>").append(_("Update downloaded")).append("<br>"); - if (System.getProperty("wrapper.version") != null) + if (_context.hasWrapper()) buf.append(_("Click Restart to install")); else buf.append(_("Click Shutdown and restart to install")); @@ -312,7 +312,8 @@ public class UpdateHandler { } protected void restart() { - _context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); + if (_context.hasWrapper()) + _context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 146d4e0e41..b7ab613720 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -888,4 +888,12 @@ public class I2PAppContext { public InternalClientManager internalClientManager() { return null; } + + /** + * Is the wrapper present? + * @since 0.8.8 + */ + public boolean hasWrapper() { + return System.getProperty("wrapper.version") != null; + } } diff --git a/core/java/src/net/i2p/client/naming/BlockfileNamingService.java b/core/java/src/net/i2p/client/naming/BlockfileNamingService.java index fdd035c2e9..b0efc768fe 100644 --- a/core/java/src/net/i2p/client/naming/BlockfileNamingService.java +++ b/core/java/src/net/i2p/client/naming/BlockfileNamingService.java @@ -108,7 +108,7 @@ public class BlockfileNamingService extends DummyNamingService { * * If not in router context, the database will be opened read-only * unless the property i2p.naming.blockfile.writeInAppContext is true. - * Not designed for simultaneous access by multiple processes. + * Not designed for multiple instantiations or simultaneous use by multple JVMs. * * @throws RuntimeException on fatal error */ @@ -780,6 +780,7 @@ public class BlockfileNamingService extends DummyNamingService { } _isClosed = true; } + clearCache(); } /** for logging errors in the static serializers below */ diff --git a/core/java/src/net/i2p/stat/StatManager.java b/core/java/src/net/i2p/stat/StatManager.java index 870f8fc054..8846a026e6 100644 --- a/core/java/src/net/i2p/stat/StatManager.java +++ b/core/java/src/net/i2p/stat/StatManager.java @@ -57,6 +57,12 @@ public class StatManager { _statLog = new BufferedStatLog(context); } + /** @since 0.8.8 */ + public void shutdown() { + _frequencyStats.clear(); + _rateStats.clear(); + } + /** may be null */ public StatLog getStatLog() { return _statLog; } public void setStatLog(StatLog log) { diff --git a/core/java/src/net/i2p/util/LogConsoleBuffer.java b/core/java/src/net/i2p/util/LogConsoleBuffer.java index fba4a3c58f..051ffbf5b7 100644 --- a/core/java/src/net/i2p/util/LogConsoleBuffer.java +++ b/core/java/src/net/i2p/util/LogConsoleBuffer.java @@ -77,4 +77,12 @@ public class LogConsoleBuffer { public List<String> getMostRecentCriticalMessages() { return new ArrayList(_critBuffer); } + + /** + * @since 0.8.8 + */ + public void clear() { + _buffer.clear(); + _critBuffer.clear(); + } } diff --git a/core/java/src/net/i2p/util/LogManager.java b/core/java/src/net/i2p/util/LogManager.java index 81b1148b55..55b454da44 100644 --- a/core/java/src/net/i2p/util/LogManager.java +++ b/core/java/src/net/i2p/util/LogManager.java @@ -660,6 +660,10 @@ public class LogManager { _writer.notifyAll(); } } + _records.clear(); + _limits.clear(); + _logs.clear(); + _consoleBuffer.clear(); } private static int __id = 0; diff --git a/history.txt b/history.txt index d06b4ebdd4..913a2e3a0d 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,12 @@ +2011-07-03 zzz + * AppContext: Add hasWrapper() method + * Shutdown: + - Clear more resources in peer manager, netdb, stat manager, + session key manager, naming service, tunnel dispatcher, + OCMOSJ (result of testing with jvisualvm) + - Don't call wrapper on shutdown (starting two threads) if we + were started with runplain + 2011-07-01 zzz * EepGet: - Fix error output bug diff --git a/router/java/src/net/i2p/router/ClientMessagePool.java b/router/java/src/net/i2p/router/ClientMessagePool.java index 750c76915e..9a8c314da3 100644 --- a/router/java/src/net/i2p/router/ClientMessagePool.java +++ b/router/java/src/net/i2p/router/ClientMessagePool.java @@ -32,6 +32,13 @@ public class ClientMessagePool { OutboundClientMessageOneShotJob.init(_context); } + /** + * @since 0.8.8 + */ + public void shutdown() { + OutboundClientMessageOneShotJob.clearAllCaches(); + } + /** * Add a new message to the pool. The message can either be locally or * remotely destined. diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index ad53234bc2..74a098aa2d 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -258,7 +258,7 @@ public class Router { // but this is the same method used in LogsHelper and we have no complaints. // (we could look for the wrapper.config file and parse it I guess...) // If we don't have a wrapper, RouterLaunch does this for us. - if (System.getProperty("wrapper.version") != null) { + if (_context.hasWrapper()) { File f = new File(System.getProperty("java.io.tmpdir"), "wrapper.log"); if (!f.exists()) f = new File(_context.getBaseDir(), "wrapper.log"); @@ -650,7 +650,7 @@ public class Router { } _context.removeShutdownTasks(); // hard and ugly - if (System.getProperty("wrapper.version") != null) + if (_context.hasWrapper()) _log.log(Log.CRIT, "Restarting with new router identity"); else _log.log(Log.CRIT, "Shutting down because old router identity was invalid - restart I2P"); @@ -981,7 +981,8 @@ public class Router { 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.adminManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the admin manager", t); } - try { _context.statPublisher().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the stats manager", t); } + try { _context.statPublisher().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the stats publisher", t); } + try { _context.statManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the stats manager", t); } try { _context.tunnelManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the tunnel manager", t); } try { _context.tunnelDispatcher().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the tunnel dispatcher", t); } try { _context.netDb().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the networkDb", t); } @@ -991,7 +992,8 @@ public class Router { try { _context.messageRegistry().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the message registry", t); } try { _context.messageValidator().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the message validator", t); } try { _context.inNetMessagePool().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the inbound net pool", t); } - //try { _sessionKeyPersistenceHelper.shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the session key manager", t); } + try { _context.clientMessagePool().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the client msg pool", t); } + try { _context.sessionKeyManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the session key manager", t); } _context.deleteTempDir(); List<RouterContext> contexts = RouterContext.getContexts(); contexts.remove(_context); @@ -1054,6 +1056,8 @@ public class Router { if (_killVMOnEnd) { try { Thread.sleep(1000); } catch (InterruptedException ie) {} Runtime.getRuntime().halt(exitCode); + } else { + Runtime.getRuntime().gc(); } } @@ -1301,7 +1305,7 @@ public class Router { } } // exit whether ok or not - if (System.getProperty("wrapper.version") != null) + if (_context.hasWrapper()) System.out.println("INFO: Restarting after update"); else System.out.println("WARNING: Exiting after update, restart I2P"); diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 0725033fa6..f6e6df3a5c 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -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 = 3; + public final static long BUILD = 4; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java index 1fb4e31b33..11151424b3 100644 --- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java +++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java @@ -711,6 +711,22 @@ public class OutboundClientMessageOneShotJob extends JobImpl { } } + /** + * @since 0.8.8 + */ + public static void clearAllCaches() { + synchronized(_leaseSetCache) { + _leaseSetCache.clear(); + } + synchronized(_leaseCache) { + _leaseCache.clear(); + } + synchronized(_tunnelCache) { + _backloggedTunnelCache.clear(); + _tunnelCache.clear(); + } + } + /** * Clean out old leaseSets * Caller must synchronize on tc. diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java index c630e2e9d1..f27be069a4 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java @@ -90,6 +90,15 @@ class KBucketSet { return removed; } + /** @since 0.8.8 */ + public void clear() { + for (int i = 0; i < _buckets.length; i++) { + _buckets[i].setEntries(Collections.EMPTY_SET); + } + _size = 0; + _us.clearXorCache(); + } + public Set<Hash> getAll() { return getAll(Collections.EMPTY_SET); }; public Set<Hash> getAll(Set<Hash> toIgnore) { Set<Hash> all = new HashSet(1024); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 7a3b7741a9..eb76ecc454 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -193,6 +193,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { public void shutdown() { _initialized = false; + if (_kb != null) + _kb.clear(); // don't null out _kb, it can cause NPEs in concurrent operations //_kb = null; if (_ds != null) diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/LocalHash.java b/router/java/src/net/i2p/router/networkdb/kademlia/LocalHash.java index 641f8da54c..ebf787ad09 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/LocalHash.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/LocalHash.java @@ -107,9 +107,10 @@ class LocalHash extends Hash { return distance; } - /** @deprecated unused */ public void clearXorCache() { - _xorCache = null; + synchronized (_xorCache) { + _xorCache.clear(); + } } /******** diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index 155f88bbcc..fdc8881c13 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -229,7 +229,8 @@ public class ProfileOrganizer { /** @since 0.8.8 */ void clearProfiles() { - getReadLock(); + if (!getWriteLock()) + return; try { _failingPeers.clear(); _fastPeers.clear(); @@ -237,7 +238,8 @@ public class ProfileOrganizer { _notFailingPeers.clear(); _notFailingPeersList.clear(); _wellIntegratedPeers.clear(); - } finally { releaseReadLock(); } + _strictCapacityOrder.clear(); + } finally { releaseWriteLock(); } } /** diff --git a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java index 33f5b7ae75..a9e10b8b7c 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java @@ -722,7 +722,13 @@ public class TunnelDispatcher implements Service { _validator.destroy(); _validator = null; _pumper.stopPumping(); + _outboundGateways.clear(); + _outboundEndpoints.clear(); + _participants.clear(); + _inboundGateways.clear(); + _participatingConfig.clear(); } + public void restart() { shutdown(); startup(); -- GitLab