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
This commit is contained in:
jrandom
2004-07-27 06:19:44 +00:00
committed by zzz
parent 9218f7b82c
commit ebd150e473
4 changed files with 72 additions and 34 deletions

View File

@ -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();

View File

@ -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()

View File

@ -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;

View File

@ -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;
}
}
/**