From ebd150e47313b92ad20bb875f83ae3c1729bc3d6 Mon Sep 17 00:00:00 2001 From: jrandom <jrandom> Date: Tue, 27 Jul 2004 06:19:44 +0000 Subject: [PATCH] we don't need to build a tunnel so often (just enough to keep things fresh) cleaned up rebuild / verification process so that the select*TunnelIds will always return what is necessary for the moment, don't automatically kill all tunnels of a peer who fails just once (they can recover) logging --- .../PoolingTunnelManagerFacade.java | 4 + .../tunnelmanager/PoolingTunnelSelector.java | 73 +++++++++++++------ .../i2p/router/tunnelmanager/TunnelPool.java | 4 +- .../tunnelmanager/TunnelPoolManagerJob.java | 25 ++++--- 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java index f4539b7400..8eced3acfc 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java @@ -146,6 +146,10 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade { * */ public void peerFailed(Hash peer) { + if (true) { + _log.error("Peer " + peer.toBase64() + " failed, but we're not going to kill their tunnels", new Exception("wtf")); + return; + } int numFailed = 0; for (Iterator iter = _pool.getManagedTunnelIds().iterator(); iter.hasNext(); ) { TunnelId id = (TunnelId)iter.next(); diff --git a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelSelector.java b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelSelector.java index 396d16a3a4..4a429f140a 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelSelector.java +++ b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelSelector.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Iterator; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -30,20 +30,19 @@ class PoolingTunnelSelector { } public List selectOutboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) { - List tunnelIds = new LinkedList(); - - for (int i = pool.getOutboundTunnelCount(); i < criteria.getMinimumTunnelsRequired(); i++) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Building fake tunnels because the outbound tunnels weren't sufficient"); - pool.buildFakeTunnels(); - } + List tunnelIds = new ArrayList(criteria.getMinimumTunnelsRequired()); Set outIds = pool.getOutboundTunnels(); for (Iterator iter = outIds.iterator(); iter.hasNext(); ) { TunnelId id = (TunnelId)iter.next(); TunnelInfo info = pool.getOutboundTunnel(id); if ( (info != null) && (info.getIsReady()) ) { - tunnelIds.add(id); + if (isAlmostExpired(pool, id, POOL_USE_SAFETY_MARGIN)) { + if (_log.shouldLog(Log.INFO)) + _log.info("Tunnel " + id + " is almost expired"); + } else { + tunnelIds.add(id); + } } else { if (info == null) { if (_log.shouldLog(Log.WARN)) @@ -54,6 +53,17 @@ class PoolingTunnelSelector { } } } + + boolean rebuilt = false; + for (int i = outIds.size(); i < criteria.getMinimumTunnelsRequired(); i++) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Building fake tunnels because the outbound tunnels weren't sufficient"); + pool.buildFakeTunnels(); + rebuilt = true; + } + if (rebuilt) + return selectOutboundTunnelIds(pool, criteria); + List ordered = randomize(pool, tunnelIds); List rv = new ArrayList(criteria.getMinimumTunnelsRequired()); for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) { @@ -66,20 +76,19 @@ class PoolingTunnelSelector { } public List selectInboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) { - List tunnels = new LinkedList(); - - for (int i = pool.getFreeTunnelCount(); i < criteria.getMinimumTunnelsRequired(); i++) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Building fake tunnels because the inbound tunnels weren't sufficient"); - pool.buildFakeTunnels(); - } + List tunnels = new ArrayList(criteria.getMinimumTunnelsRequired()); for (Iterator iter = pool.getFreeTunnels().iterator(); iter.hasNext(); ) { TunnelId id = (TunnelId)iter.next(); TunnelInfo info = pool.getFreeTunnel(id); if (info == null) continue; if (info.getIsReady()) { - tunnels.add(id); + if (isAlmostExpired(pool, id, POOL_USE_SAFETY_MARGIN)) { + if (_log.shouldLog(Log.INFO)) + _log.info("Tunnel " + id + " is almost expired"); + } else { + tunnels.add(id); + } } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Inbound tunnel " + id + " is not ready?! " @@ -87,6 +96,16 @@ class PoolingTunnelSelector { } } + boolean rebuilt = false; + for (int i = tunnels.size(); i < criteria.getMinimumTunnelsRequired(); i++) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Building fake tunnels because the inbound tunnels weren't sufficient"); + pool.buildFakeTunnels(); + rebuilt = true; + } + if (rebuilt) + return selectInboundTunnelIds(pool, criteria); + List ordered = randomize(pool, tunnels); List rv = new ArrayList(criteria.getMinimumTunnelsRequired()); for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) { @@ -107,8 +126,6 @@ class PoolingTunnelSelector { List rv = new ArrayList(tunnelIds.size()); for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) { TunnelId id = (TunnelId)iter.next(); - if (isAlmostExpired(pool, id, POOL_USE_SAFETY_MARGIN)) - continue; rv.add(id); } Collections.shuffle(rv, _context.random()); @@ -117,9 +134,21 @@ class PoolingTunnelSelector { private boolean isAlmostExpired(TunnelPool pool, TunnelId id, long safetyMargin) { TunnelInfo info = pool.getTunnelInfo(id); - if (info == null) return true; - if (info.getSettings() == null) return true; - if (info.getSettings().getExpiration() <= 0) return true; + if (info == null) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Tunnel " + id.getTunnelId() + " is not known"); + return true; + } + if (info.getSettings() == null) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Tunnel " + id.getTunnelId() + " has no settings"); + return true; + } + if (info.getSettings().getExpiration() <= 0) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Tunnel " + id.getTunnelId() + " has no expiration"); + return true; + } if (info.getSettings().getExpiration() - safetyMargin <= _context.clock().now()) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Expiration of tunnel " + id.getTunnelId() diff --git a/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java b/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java index de352d1e37..dd83a0f0d0 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java @@ -524,8 +524,8 @@ class TunnelPool { public void tunnelFailed(TunnelId id) { if (!_isLive) return; - if (_log.shouldLog(Log.INFO)) - _log.info("Tunnel " + id + " marked as not ready, since it /failed/", new Exception("Failed tunnel")); + if (_log.shouldLog(Log.ERROR)) + _log.error("Tunnel " + id + " marked as not ready, since it /failed/", new Exception("Failed tunnel")); TunnelInfo info = getTunnelInfo(id); if (info == null) return; diff --git a/router/java/src/net/i2p/router/tunnelmanager/TunnelPoolManagerJob.java b/router/java/src/net/i2p/router/tunnelmanager/TunnelPoolManagerJob.java index 87b9b55e69..004f4aae47 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/TunnelPoolManagerJob.java +++ b/router/java/src/net/i2p/router/tunnelmanager/TunnelPoolManagerJob.java @@ -18,9 +18,6 @@ class TunnelPoolManagerJob extends JobImpl { private Log _log; private TunnelPool _pool; - /** whether we built tunnels on the last run */ - private boolean _builtOnLastRun; - /** * How frequently to check the pool (and fire appropriate refill jobs) * @@ -48,8 +45,8 @@ class TunnelPoolManagerJob extends JobImpl { boolean built = false; int targetClients = _pool.getTargetClients(); - int targetInboundTunnels = targetClients*_pool.getPoolSettings().getNumInboundTunnels() + 3; - int targetOutboundTunnels = targetClients*_pool.getPoolSettings().getNumOutboundTunnels() + 3; + int targetInboundTunnels = targetClients*_pool.getPoolSettings().getNumInboundTunnels() + 1; + int targetOutboundTunnels = targetClients*_pool.getPoolSettings().getNumOutboundTunnels() + 1; int curFreeInboundTunnels = getFreeTunnelCount(); if (curFreeInboundTunnels < targetInboundTunnels) { @@ -60,7 +57,8 @@ class TunnelPoolManagerJob extends JobImpl { //requestFakeInboundTunnels(1); built = true; } else { - if (_builtOnLastRun) { + // 10% chance of building a new tunnel + if (getContext().random().nextInt(9) > 0) { // all good, no need for more inbound tunnels if (_log.shouldLog(Log.DEBUG)) _log.debug("Sufficient inbound tunnels (" + curFreeInboundTunnels + ")"); @@ -81,7 +79,8 @@ class TunnelPoolManagerJob extends JobImpl { //requestFakeOutboundTunnels(1); built = true; } else { - if (_builtOnLastRun) { + // 10% chance of building a new tunnel + if (getContext().random().nextInt(9) > 0) { // all good, no need for more outbound tunnels if (_log.shouldLog(Log.DEBUG)) _log.debug("Sufficient outbound tunnels (" + curOutboundTunnels + ")"); @@ -94,7 +93,6 @@ class TunnelPoolManagerJob extends JobImpl { } _pool.buildFakeTunnels(); - _builtOnLastRun = built; } catch (Throwable t) { _log.log(Log.CRIT, "Unhandled exception managing the tunnel pool", t); } @@ -109,6 +107,7 @@ class TunnelPoolManagerJob extends JobImpl { private int getFreeTunnelCount() { Set freeTunnels = _pool.getFreeTunnels(); int free = 0; + int tooShort = 0; int minLength = _pool.getPoolSettings().getDepthInbound(); long mustExpireAfter = getContext().clock().now() + EXPIRE_FUDGE_PERIOD; for (Iterator iter = freeTunnels.iterator(); iter.hasNext(); ) { @@ -131,14 +130,20 @@ class TunnelPoolManagerJob extends JobImpl { // for the moment we'll keep these around so that we can use them // for tunnel management and db messages, rather than force all // tunnels to be the 2+ hop length as required for clients - free++; + tooShort++; // free++; } } else { _log.info("Inbound tunnel " + id + " is expiring in the upcoming period, consider it not-free"); } } } - return free; + if (free <= 0) { + if (_log.shouldLog(Log.WARN)) + _log.warn("No free tunnels that are long enough, but there are " + tooShort + " shorter ones"); + return tooShort; + } else { + return free; + } } /** -- GitLab