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:
@ -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();
|
||||
|
@ -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()) ) {
|
||||
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()) {
|
||||
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()
|
||||
|
@ -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;
|
||||
|
@ -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,15 +130,21 @@ 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How many outbound tunnels are available for use (safely)
|
||||
|
Reference in New Issue
Block a user