I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit ebd150e4 authored by jrandom's avatar jrandom Committed by zzz
Browse files

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
parent 9218f7b8
No related branches found
No related tags found
No related merge requests found
...@@ -146,6 +146,10 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade { ...@@ -146,6 +146,10 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade {
* *
*/ */
public void peerFailed(Hash peer) { 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; int numFailed = 0;
for (Iterator iter = _pool.getManagedTunnelIds().iterator(); iter.hasNext(); ) { for (Iterator iter = _pool.getManagedTunnelIds().iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next(); TunnelId id = (TunnelId)iter.next();
......
...@@ -4,7 +4,7 @@ import java.util.ArrayList; ...@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
...@@ -30,20 +30,19 @@ class PoolingTunnelSelector { ...@@ -30,20 +30,19 @@ class PoolingTunnelSelector {
} }
public List selectOutboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) { public List selectOutboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) {
List tunnelIds = new LinkedList(); List tunnelIds = new ArrayList(criteria.getMinimumTunnelsRequired());
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();
}
Set outIds = pool.getOutboundTunnels(); Set outIds = pool.getOutboundTunnels();
for (Iterator iter = outIds.iterator(); iter.hasNext(); ) { for (Iterator iter = outIds.iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next(); TunnelId id = (TunnelId)iter.next();
TunnelInfo info = pool.getOutboundTunnel(id); TunnelInfo info = pool.getOutboundTunnel(id);
if ( (info != null) && (info.getIsReady()) ) { 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 { } else {
if (info == null) { if (info == null) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
...@@ -54,6 +53,17 @@ class PoolingTunnelSelector { ...@@ -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 ordered = randomize(pool, tunnelIds);
List rv = new ArrayList(criteria.getMinimumTunnelsRequired()); List rv = new ArrayList(criteria.getMinimumTunnelsRequired());
for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) { for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) {
...@@ -66,20 +76,19 @@ class PoolingTunnelSelector { ...@@ -66,20 +76,19 @@ class PoolingTunnelSelector {
} }
public List selectInboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) { public List selectInboundTunnelIds(TunnelPool pool, TunnelSelectionCriteria criteria) {
List tunnels = new LinkedList(); List tunnels = new ArrayList(criteria.getMinimumTunnelsRequired());
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();
}
for (Iterator iter = pool.getFreeTunnels().iterator(); iter.hasNext(); ) { for (Iterator iter = pool.getFreeTunnels().iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next(); TunnelId id = (TunnelId)iter.next();
TunnelInfo info = pool.getFreeTunnel(id); TunnelInfo info = pool.getFreeTunnel(id);
if (info == null) continue; if (info == null) continue;
if (info.getIsReady()) { 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 { } else {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Inbound tunnel " + id + " is not ready?! " _log.debug("Inbound tunnel " + id + " is not ready?! "
...@@ -87,6 +96,16 @@ class PoolingTunnelSelector { ...@@ -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 ordered = randomize(pool, tunnels);
List rv = new ArrayList(criteria.getMinimumTunnelsRequired()); List rv = new ArrayList(criteria.getMinimumTunnelsRequired());
for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) { for (Iterator iter = ordered.iterator(); iter.hasNext() && (rv.size() < criteria.getMinimumTunnelsRequired()); ) {
...@@ -107,8 +126,6 @@ class PoolingTunnelSelector { ...@@ -107,8 +126,6 @@ class PoolingTunnelSelector {
List rv = new ArrayList(tunnelIds.size()); List rv = new ArrayList(tunnelIds.size());
for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) { for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next(); TunnelId id = (TunnelId)iter.next();
if (isAlmostExpired(pool, id, POOL_USE_SAFETY_MARGIN))
continue;
rv.add(id); rv.add(id);
} }
Collections.shuffle(rv, _context.random()); Collections.shuffle(rv, _context.random());
...@@ -117,9 +134,21 @@ class PoolingTunnelSelector { ...@@ -117,9 +134,21 @@ class PoolingTunnelSelector {
private boolean isAlmostExpired(TunnelPool pool, TunnelId id, long safetyMargin) { private boolean isAlmostExpired(TunnelPool pool, TunnelId id, long safetyMargin) {
TunnelInfo info = pool.getTunnelInfo(id); TunnelInfo info = pool.getTunnelInfo(id);
if (info == null) return true; if (info == null) {
if (info.getSettings() == null) return true; if (_log.shouldLog(Log.ERROR))
if (info.getSettings().getExpiration() <= 0) return true; _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 (info.getSettings().getExpiration() - safetyMargin <= _context.clock().now()) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Expiration of tunnel " + id.getTunnelId() _log.debug("Expiration of tunnel " + id.getTunnelId()
......
...@@ -524,8 +524,8 @@ class TunnelPool { ...@@ -524,8 +524,8 @@ class TunnelPool {
public void tunnelFailed(TunnelId id) { public void tunnelFailed(TunnelId id) {
if (!_isLive) return; if (!_isLive) return;
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.ERROR))
_log.info("Tunnel " + id + " marked as not ready, since it /failed/", new Exception("Failed tunnel")); _log.error("Tunnel " + id + " marked as not ready, since it /failed/", new Exception("Failed tunnel"));
TunnelInfo info = getTunnelInfo(id); TunnelInfo info = getTunnelInfo(id);
if (info == null) if (info == null)
return; return;
......
...@@ -18,9 +18,6 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -18,9 +18,6 @@ class TunnelPoolManagerJob extends JobImpl {
private Log _log; private Log _log;
private TunnelPool _pool; 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) * How frequently to check the pool (and fire appropriate refill jobs)
* *
...@@ -48,8 +45,8 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -48,8 +45,8 @@ class TunnelPoolManagerJob extends JobImpl {
boolean built = false; boolean built = false;
int targetClients = _pool.getTargetClients(); int targetClients = _pool.getTargetClients();
int targetInboundTunnels = targetClients*_pool.getPoolSettings().getNumInboundTunnels() + 3; int targetInboundTunnels = targetClients*_pool.getPoolSettings().getNumInboundTunnels() + 1;
int targetOutboundTunnels = targetClients*_pool.getPoolSettings().getNumOutboundTunnels() + 3; int targetOutboundTunnels = targetClients*_pool.getPoolSettings().getNumOutboundTunnels() + 1;
int curFreeInboundTunnels = getFreeTunnelCount(); int curFreeInboundTunnels = getFreeTunnelCount();
if (curFreeInboundTunnels < targetInboundTunnels) { if (curFreeInboundTunnels < targetInboundTunnels) {
...@@ -60,7 +57,8 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -60,7 +57,8 @@ class TunnelPoolManagerJob extends JobImpl {
//requestFakeInboundTunnels(1); //requestFakeInboundTunnels(1);
built = true; built = true;
} else { } else {
if (_builtOnLastRun) { // 10% chance of building a new tunnel
if (getContext().random().nextInt(9) > 0) {
// all good, no need for more inbound tunnels // all good, no need for more inbound tunnels
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Sufficient inbound tunnels (" + curFreeInboundTunnels + ")"); _log.debug("Sufficient inbound tunnels (" + curFreeInboundTunnels + ")");
...@@ -81,7 +79,8 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -81,7 +79,8 @@ class TunnelPoolManagerJob extends JobImpl {
//requestFakeOutboundTunnels(1); //requestFakeOutboundTunnels(1);
built = true; built = true;
} else { } else {
if (_builtOnLastRun) { // 10% chance of building a new tunnel
if (getContext().random().nextInt(9) > 0) {
// all good, no need for more outbound tunnels // all good, no need for more outbound tunnels
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Sufficient outbound tunnels (" + curOutboundTunnels + ")"); _log.debug("Sufficient outbound tunnels (" + curOutboundTunnels + ")");
...@@ -94,7 +93,6 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -94,7 +93,6 @@ class TunnelPoolManagerJob extends JobImpl {
} }
_pool.buildFakeTunnels(); _pool.buildFakeTunnels();
_builtOnLastRun = built;
} catch (Throwable t) { } catch (Throwable t) {
_log.log(Log.CRIT, "Unhandled exception managing the tunnel pool", t); _log.log(Log.CRIT, "Unhandled exception managing the tunnel pool", t);
} }
...@@ -109,6 +107,7 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -109,6 +107,7 @@ class TunnelPoolManagerJob extends JobImpl {
private int getFreeTunnelCount() { private int getFreeTunnelCount() {
Set freeTunnels = _pool.getFreeTunnels(); Set freeTunnels = _pool.getFreeTunnels();
int free = 0; int free = 0;
int tooShort = 0;
int minLength = _pool.getPoolSettings().getDepthInbound(); int minLength = _pool.getPoolSettings().getDepthInbound();
long mustExpireAfter = getContext().clock().now() + EXPIRE_FUDGE_PERIOD; long mustExpireAfter = getContext().clock().now() + EXPIRE_FUDGE_PERIOD;
for (Iterator iter = freeTunnels.iterator(); iter.hasNext(); ) { for (Iterator iter = freeTunnels.iterator(); iter.hasNext(); ) {
...@@ -131,14 +130,20 @@ class TunnelPoolManagerJob extends JobImpl { ...@@ -131,14 +130,20 @@ class TunnelPoolManagerJob extends JobImpl {
// for the moment we'll keep these around so that we can use them // for the moment we'll keep these around so that we can use them
// for tunnel management and db messages, rather than force all // for tunnel management and db messages, rather than force all
// tunnels to be the 2+ hop length as required for clients // tunnels to be the 2+ hop length as required for clients
free++; tooShort++; // free++;
} }
} else { } else {
_log.info("Inbound tunnel " + id + " is expiring in the upcoming period, consider it not-free"); _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;
}
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment