2005-12-09 zzz
* Create different strategies for exploratory tunnels (which are difficult to create) and client tunnels (which are much easier) * Gradually increase number of parallel build attempts as tunnel expiry nears. * Temporarily shorten attempted build tunnel length if builds using configured tunnel length are unsuccessful * React more aggressively to tunnel failure than routine tunnel replacement * Make tunnel creation times randomized - there is existing code to randomize the tunnels but it isn't effective due to the tunnel creation strategy. Currently, most tunnels get built all at once, at about 2 1/2 to 3 minutes before expiration. The patch fixes this by fixing the randomization, and by changing the overlap time (with old tunnels) to a range of 2 to 4 minutes. * Reduce number of excess tunnels. Lots of excess tunnels get created due to overlapping calls. Just about anything generated a call which could build many tunnels all at once, even if tunnel building was already in process. * Miscellaneous router console enhancements
This commit is contained in:
@ -59,6 +59,8 @@ public class ConfigLoggingHelper {
|
|||||||
buf.append(prefix).append('=').append(level).append('\n');
|
buf.append(prefix).append('=').append(level).append('\n');
|
||||||
}
|
}
|
||||||
buf.append("</textarea><br />\n");
|
buf.append("</textarea><br />\n");
|
||||||
|
buf.append("<i>Add additional logging statements above. Example: net.i2p.router.tunnel=WARN</i><br>");
|
||||||
|
buf.append("<i>Or put entries in the logger.config file. Example: logger.record.net.i2p.router.tunnel=WARN</i><br>");
|
||||||
buf.append("<i>Valid levels are DEBUG, INFO, WARN, ERROR, CRIT</i>\n");
|
buf.append("<i>Valid levels are DEBUG, INFO, WARN, ERROR, CRIT</i>\n");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ public class ConfigTunnelsHandler extends FormHandler {
|
|||||||
if (saveRequired) {
|
if (saveRequired) {
|
||||||
boolean saved = _context.router().saveConfig();
|
boolean saved = _context.router().saveConfig();
|
||||||
if (saved)
|
if (saved)
|
||||||
addFormNotice("Configuration saved successfully");
|
addFormNotice("Exploratory tunnel configuration saved successfully");
|
||||||
else
|
else
|
||||||
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
|
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package net.i2p.router.web;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
|
||||||
|
public class JobQueueHelper {
|
||||||
|
private RouterContext _context;
|
||||||
|
private Writer _out;
|
||||||
|
/**
|
||||||
|
* Configure this bean to query a particular router context
|
||||||
|
*
|
||||||
|
* @param contextId begging few characters of the routerHash, or null to pick
|
||||||
|
* the first one we come across.
|
||||||
|
*/
|
||||||
|
public void setContextId(String contextId) {
|
||||||
|
try {
|
||||||
|
_context = ContextHelper.getContext(contextId);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobQueueHelper() {}
|
||||||
|
|
||||||
|
public void setWriter(Writer writer) { _out = writer; }
|
||||||
|
|
||||||
|
public String getJobQueueSummary() {
|
||||||
|
try {
|
||||||
|
if (_out != null) {
|
||||||
|
_context.jobQueue().renderStatusHTML(_out);
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
||||||
|
_context.jobQueue().renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
|
return new String(baos.toByteArray());
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -83,14 +83,23 @@ public class SummaryHelper {
|
|||||||
|
|
||||||
long ms = _context.clock().getOffset();
|
long ms = _context.clock().getOffset();
|
||||||
|
|
||||||
if (ms < 60 * 1000) {
|
long diff = ms;
|
||||||
return now + " (" + (ms / 1000) + "s)";
|
if (diff < 0)
|
||||||
} else if (ms < 60 * 60 * 1000) {
|
diff = 0 - diff;
|
||||||
return now + " (" + (ms / (60 * 1000)) + "m)";
|
if (diff == 0) {
|
||||||
} else if (ms < 24 * 60 * 60 * 1000) {
|
return now + " (no skew)";
|
||||||
return now + " (" + (ms / (60 * 60 * 1000)) + "h)";
|
} else if (diff < 1000) {
|
||||||
|
return now + " (" + ms + "ms skew)";
|
||||||
|
} else if (diff < 5 * 1000) {
|
||||||
|
return now + " (" + (ms / 1000) + "s skew)";
|
||||||
|
} else if (diff < 60 * 1000) {
|
||||||
|
return now + " <b>(" + (ms / 1000) + "s skew)</b>";
|
||||||
|
} else if (diff < 60 * 60 * 1000) {
|
||||||
|
return now + " <b>(" + (ms / (60 * 1000)) + "m skew)</b>";
|
||||||
|
} else if (diff < 24 * 60 * 60 * 1000) {
|
||||||
|
return now + " <b>(" + (ms / (60 * 60 * 1000)) + "h skew)</b>";
|
||||||
} else {
|
} else {
|
||||||
return now + " (" + (ms / (24 * 60 * 60 * 1000)) + "d)";
|
return now + " <b>(" + (ms / (24 * 60 * 60 * 1000)) + "d skew)</b>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,6 +417,28 @@ public class SummaryHelper {
|
|||||||
return _context.tunnelManager().getOutboundTunnelCount();
|
return _context.tunnelManager().getOutboundTunnelCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many inbound client tunnels we have.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getInboundClientTunnels() {
|
||||||
|
if (_context == null)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return _context.tunnelManager().getInboundClientTunnelCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many active outbound client tunnels we have.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getOutboundClientTunnels() {
|
||||||
|
if (_context == null)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return _context.tunnelManager().getOutboundClientTunnelCount();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How many tunnels we are participating in.
|
* How many tunnels we are participating in.
|
||||||
*
|
*
|
||||||
@ -459,4 +490,4 @@ public class SummaryHelper {
|
|||||||
public boolean updateAvailable() {
|
public boolean updateAvailable() {
|
||||||
return NewsFetcher.getInstance(_context).updateAvailable();
|
return NewsFetcher.getInstance(_context).updateAvailable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
<input type="hidden" name="action" value="blah" />
|
<input type="hidden" name="action" value="blah" />
|
||||||
<jsp:getProperty name="tunnelshelper" property="form" />
|
<jsp:getProperty name="tunnelshelper" property="form" />
|
||||||
<hr />
|
<hr />
|
||||||
|
<i>Note - Exploratory tunnel setting changes are stored in the router.config file.</i></br>
|
||||||
|
<i>Client tunnel changes are temporary and are not saved.</i><br>
|
||||||
|
<i>To make permanent client tunnel changes see the </i><a href="i2ptunnel/index.jsp">i2ptunnel page</a>.<br>
|
||||||
<input type="submit" name="shouldsave" value="Save changes" /> <input type="reset" value="Cancel" />
|
<input type="submit" name="shouldsave" value="Save changes" /> <input type="reset" value="Cancel" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
21
apps/routerconsole/jsp/jobs.jsp
Normal file
21
apps/routerconsole/jsp/jobs.jsp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<%@page contentType="text/html"%>
|
||||||
|
<%@page pageEncoding="UTF-8"%>
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<html><head>
|
||||||
|
<title>I2P Router Console - job queue</title>
|
||||||
|
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<%@include file="nav.jsp" %>
|
||||||
|
<%@include file="summary.jsp" %>
|
||||||
|
|
||||||
|
<div class="main" id="main">
|
||||||
|
<jsp:useBean class="net.i2p.router.web.JobQueueHelper" id="jobQueueHelper" scope="request" />
|
||||||
|
<jsp:setProperty name="jobQueueHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||||
|
<jsp:setProperty name="jobQueueHelper" property="writer" value="<%=out%>" />
|
||||||
|
<jsp:getProperty name="jobQueueHelper" property="jobQueueSummary" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -18,11 +18,13 @@
|
|||||||
<a href="susimail/susimail">Susimail</a> |
|
<a href="susimail/susimail">Susimail</a> |
|
||||||
<a href="susidns/index.jsp">SusiDNS</a> |
|
<a href="susidns/index.jsp">SusiDNS</a> |
|
||||||
<a href="syndie/">Syndie</a> |
|
<a href="syndie/">Syndie</a> |
|
||||||
|
<a href="http://localhost:7658/">My Eepsite</a> <br>
|
||||||
<a href="i2ptunnel/index.jsp">I2PTunnel</a> |
|
<a href="i2ptunnel/index.jsp">I2PTunnel</a> |
|
||||||
<a href="tunnels.jsp">Tunnels</a> |
|
<a href="tunnels.jsp">Tunnels</a> |
|
||||||
<a href="profiles.jsp">Profiles</a> |
|
<a href="profiles.jsp">Profiles</a> |
|
||||||
<a href="netdb.jsp">NetDB</a> |
|
<a href="netdb.jsp">NetDB</a> |
|
||||||
<a href="logs.jsp">Logs</a> |
|
<a href="logs.jsp">Logs</a> |
|
||||||
|
<a href="jobs.jsp">Jobs</a> |
|
||||||
<a href="oldstats.jsp">Stats</a> |
|
<a href="oldstats.jsp">Stats</a> |
|
||||||
<a href="oldconsole.jsp">Internals</a>
|
<a href="oldconsole.jsp">Internals</a>
|
||||||
<jsp:useBean class="net.i2p.router.web.NavHelper" id="navhelper" scope="request" />
|
<jsp:useBean class="net.i2p.router.web.NavHelper" id="navhelper" scope="request" />
|
||||||
|
@ -72,9 +72,9 @@
|
|||||||
|
|
||||||
<jsp:getProperty name="helper" property="destinations" />
|
<jsp:getProperty name="helper" property="destinations" />
|
||||||
|
|
||||||
<u><b>Tunnels</b></u><br />
|
<u><b>Tunnels in/out</b></u><br />
|
||||||
<b>Inbound:</b> <jsp:getProperty name="helper" property="inboundTunnels" /><br />
|
<b>Exploratory:</b> <jsp:getProperty name="helper" property="inboundTunnels" />/<jsp:getProperty name="helper" property="outboundTunnels" /><br />
|
||||||
<b>Outbound:</b> <jsp:getProperty name="helper" property="outboundTunnels" /><br />
|
<b>Client:</b> <jsp:getProperty name="helper" property="inboundClientTunnels" />/<jsp:getProperty name="helper" property="outboundClientTunnels" /><br />
|
||||||
<b>Participating:</b> <jsp:getProperty name="helper" property="participatingTunnels" /><br />
|
<b>Participating:</b> <jsp:getProperty name="helper" property="participatingTunnels" /><br />
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
23
history.txt
23
history.txt
@ -1,4 +1,25 @@
|
|||||||
$Id: history.txt,v 1.350 2005/12/07 19:50:35 jrandom Exp $
|
$Id: history.txt,v 1.351 2005/12/08 15:53:43 jrandom Exp $
|
||||||
|
|
||||||
|
2005-12-09 zzz
|
||||||
|
* Create different strategies for exploratory tunnels (which are difficult
|
||||||
|
to create) and client tunnels (which are much easier)
|
||||||
|
* Gradually increase number of parallel build attempts as tunnel expiry
|
||||||
|
nears.
|
||||||
|
* Temporarily shorten attempted build tunnel length if builds using
|
||||||
|
configured tunnel length are unsuccessful
|
||||||
|
* React more aggressively to tunnel failure than routine tunnel
|
||||||
|
replacement
|
||||||
|
* Make tunnel creation times randomized - there is existing code to
|
||||||
|
randomize the tunnels but it isn't effective due to the tunnel creation
|
||||||
|
strategy. Currently, most tunnels get built all at once, at about 2 1/2
|
||||||
|
to 3 minutes before expiration. The patch fixes this by fixing the
|
||||||
|
randomization, and by changing the overlap time (with old tunnels) to a
|
||||||
|
range of 2 to 4 minutes.
|
||||||
|
* Reduce number of excess tunnels. Lots of excess tunnels get created due
|
||||||
|
to overlapping calls. Just about anything generated a call which could
|
||||||
|
build many tunnels all at once, even if tunnel building was already in
|
||||||
|
process.
|
||||||
|
* Miscellaneous router console enhancements
|
||||||
|
|
||||||
2005-12-08 jrandom
|
2005-12-08 jrandom
|
||||||
* Minor bugfix in SSU for dealing with corrupt packets
|
* Minor bugfix in SSU for dealing with corrupt packets
|
||||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RouterVersion {
|
public class RouterVersion {
|
||||||
public final static String ID = "$Revision: 1.307 $ $Date: 2005/12/01 12:16:54 $";
|
public final static String ID = "$Revision: 1.308 $ $Date: 2005/12/08 15:53:41 $";
|
||||||
public final static String VERSION = "0.6.1.7";
|
public final static String VERSION = "0.6.1.7";
|
||||||
public final static long BUILD = 1;
|
public final static long BUILD = 2;
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
||||||
System.out.println("Router ID: " + RouterVersion.ID);
|
System.out.println("Router ID: " + RouterVersion.ID);
|
||||||
|
@ -90,7 +90,9 @@ class RouterWatchdog implements Runnable {
|
|||||||
|
|
||||||
public void monitorRouter() {
|
public void monitorRouter() {
|
||||||
boolean ok = verifyJobQueueLiveliness();
|
boolean ok = verifyJobQueueLiveliness();
|
||||||
ok = ok && verifyClientLiveliness();
|
// If we aren't connected to the network that's why there's nobody to talk to
|
||||||
|
int netErrors = (int) _context.statManager().getRate("udp.sendException").getRate(60*1000).getLastEventCount();
|
||||||
|
ok = ok && (verifyClientLiveliness() || netErrors >= 5);
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
dumpStatus();
|
dumpStatus();
|
||||||
|
@ -48,6 +48,10 @@ public interface TunnelManagerFacade extends Service {
|
|||||||
public int getFreeTunnelCount();
|
public int getFreeTunnelCount();
|
||||||
/** how many outbound tunnels do we have available? */
|
/** how many outbound tunnels do we have available? */
|
||||||
public int getOutboundTunnelCount();
|
public int getOutboundTunnelCount();
|
||||||
|
/** how many free inbound client tunnels do we have available? */
|
||||||
|
public int getInboundClientTunnelCount();
|
||||||
|
/** how many outbound client tunnels do we have available? */
|
||||||
|
public int getOutboundClientTunnelCount();
|
||||||
|
|
||||||
/** When does the last tunnel we are participating in expire? */
|
/** When does the last tunnel we are participating in expire? */
|
||||||
public long getLastParticipatingExpiration();
|
public long getLastParticipatingExpiration();
|
||||||
@ -81,6 +85,8 @@ class DummyTunnelManagerFacade implements TunnelManagerFacade {
|
|||||||
public int getParticipatingCount() { return 0; }
|
public int getParticipatingCount() { return 0; }
|
||||||
public int getFreeTunnelCount() { return 0; }
|
public int getFreeTunnelCount() { return 0; }
|
||||||
public int getOutboundTunnelCount() { return 0; }
|
public int getOutboundTunnelCount() { return 0; }
|
||||||
|
public int getInboundClientTunnelCount() { return 0; }
|
||||||
|
public int getOutboundClientTunnelCount() { return 0; }
|
||||||
public long getLastParticipatingExpiration() { return -1; }
|
public long getLastParticipatingExpiration() { return -1; }
|
||||||
public void buildTunnels(Destination client, ClientTunnelSettings settings) {}
|
public void buildTunnels(Destination client, ClientTunnelSettings settings) {}
|
||||||
public TunnelPoolSettings getInboundSettings() { return null; }
|
public TunnelPoolSettings getInboundSettings() { return null; }
|
||||||
|
@ -18,6 +18,7 @@ public class TunnelPoolSettings {
|
|||||||
private int _duration;
|
private int _duration;
|
||||||
private int _length;
|
private int _length;
|
||||||
private int _lengthVariance;
|
private int _lengthVariance;
|
||||||
|
private int _lengthOverride;
|
||||||
private boolean _isInbound;
|
private boolean _isInbound;
|
||||||
private boolean _isExploratory;
|
private boolean _isExploratory;
|
||||||
private boolean _allowZeroHop;
|
private boolean _allowZeroHop;
|
||||||
@ -54,6 +55,7 @@ public class TunnelPoolSettings {
|
|||||||
_duration = DEFAULT_DURATION;
|
_duration = DEFAULT_DURATION;
|
||||||
_length = DEFAULT_LENGTH;
|
_length = DEFAULT_LENGTH;
|
||||||
_lengthVariance = DEFAULT_LENGTH_VARIANCE;
|
_lengthVariance = DEFAULT_LENGTH_VARIANCE;
|
||||||
|
_lengthOverride = 0;
|
||||||
_allowZeroHop = DEFAULT_ALLOW_ZERO_HOP;
|
_allowZeroHop = DEFAULT_ALLOW_ZERO_HOP;
|
||||||
_isInbound = false;
|
_isInbound = false;
|
||||||
_isExploratory = false;
|
_isExploratory = false;
|
||||||
@ -90,6 +92,10 @@ public class TunnelPoolSettings {
|
|||||||
*/
|
*/
|
||||||
public int getLengthVariance() { return _lengthVariance; }
|
public int getLengthVariance() { return _lengthVariance; }
|
||||||
public void setLengthVariance(int variance) { _lengthVariance = variance; }
|
public void setLengthVariance(int variance) { _lengthVariance = variance; }
|
||||||
|
|
||||||
|
/* Set to a nonzero value to override the length setting */
|
||||||
|
public int getLengthOverride() { return _lengthOverride; }
|
||||||
|
public void setLengthOverride(int variance) { _lengthOverride = variance; }
|
||||||
|
|
||||||
/** is this an inbound tunnel? */
|
/** is this an inbound tunnel? */
|
||||||
public boolean isInbound() { return _isInbound; }
|
public boolean isInbound() { return _isInbound; }
|
||||||
|
@ -25,11 +25,16 @@ class ExpireJob extends JobImpl {
|
|||||||
return "Expire exploratory outbound tunnel";
|
return "Expire exploratory outbound tunnel";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_pool.getSettings().isInbound()) {
|
StringBuffer rv = new StringBuffer(32);
|
||||||
return "Expire client inbound tunnel";
|
if (_pool.getSettings().isInbound())
|
||||||
} else {
|
rv.append("Expire inbound client tunnel for ");
|
||||||
return "Expire client outbound tunnel";
|
else
|
||||||
}
|
rv.append("Expire outbound client tunnel for ");
|
||||||
|
if (_pool.getSettings().getDestinationNickname() != null)
|
||||||
|
rv.append(_pool.getSettings().getDestinationNickname());
|
||||||
|
else
|
||||||
|
rv.append(_pool.getSettings().getDestination().toBase64().substring(0,4));
|
||||||
|
return rv.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void runJob() {
|
public void runJob() {
|
||||||
@ -44,4 +49,4 @@ class ExpireJob extends JobImpl {
|
|||||||
getContext().tunnelDispatcher().remove(_cfg);
|
getContext().tunnelDispatcher().remove(_cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ import net.i2p.router.tunnel.TunnelCreatorConfig;
|
|||||||
/**
|
/**
|
||||||
* Build a new tunnel to replace the existing one before it expires. This job
|
* Build a new tunnel to replace the existing one before it expires. This job
|
||||||
* should be removed (or scheduled to run immediately) if the tunnel fails.
|
* should be removed (or scheduled to run immediately) if the tunnel fails.
|
||||||
*
|
* If an exploratory tunnel build at a random time between 3 1/2 and 4 minutes early;
|
||||||
|
* else if only one tunnel in pool build 4 minutes early;
|
||||||
|
* otherwise build at a random time between 2 and 4 minutes early.
|
||||||
|
* Five build attempts in parallel if an exploratory tunnel.
|
||||||
*/
|
*/
|
||||||
class RebuildJob extends JobImpl {
|
class RebuildJob extends JobImpl {
|
||||||
private TunnelPool _pool;
|
private TunnelPool _pool;
|
||||||
@ -17,12 +20,42 @@ class RebuildJob extends JobImpl {
|
|||||||
super(ctx);
|
super(ctx);
|
||||||
_pool = pool;
|
_pool = pool;
|
||||||
_cfg = cfg;
|
_cfg = cfg;
|
||||||
long rebuildOn = cfg.getExpiration() - pool.getSettings().getRebuildPeriod();
|
long rebuildOn;
|
||||||
rebuildOn -= ctx.random().nextInt(pool.getSettings().getRebuildPeriod()*2);
|
if (_pool.getSettings().isExploratory()) {
|
||||||
|
rebuildOn = cfg.getExpiration() - (((pool.getSettings().getRebuildPeriod() * 7) / 2));
|
||||||
|
rebuildOn -= ctx.random().nextInt(pool.getSettings().getRebuildPeriod() / 2);
|
||||||
|
} else if ((pool.getSettings().getQuantity() + pool.getSettings().getBackupQuantity()) == 1) {
|
||||||
|
rebuildOn = cfg.getExpiration() - (pool.getSettings().getRebuildPeriod() * 4);
|
||||||
|
} else {
|
||||||
|
rebuildOn = cfg.getExpiration() - (pool.getSettings().getRebuildPeriod() * 2);
|
||||||
|
rebuildOn -= ctx.random().nextInt(pool.getSettings().getRebuildPeriod() * 2);
|
||||||
|
}
|
||||||
getTiming().setStartAfter(rebuildOn);
|
getTiming().setStartAfter(rebuildOn);
|
||||||
}
|
}
|
||||||
public String getName() { return "Rebuild tunnel"; }
|
public String getName() {
|
||||||
public void runJob() {
|
if (_pool.getSettings().isExploratory()) {
|
||||||
_pool.refreshBuilders();
|
if (_pool.getSettings().isInbound()) {
|
||||||
|
return "Rebuild exploratory inbound tunnel";
|
||||||
|
} else {
|
||||||
|
return "Rebuild exploratory outbound tunnel";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
StringBuffer rv = new StringBuffer(32);
|
||||||
|
if (_pool.getSettings().isInbound())
|
||||||
|
rv.append("Rebuild inbound client tunnel for ");
|
||||||
|
else
|
||||||
|
rv.append("Rebuild outbound client tunnel for ");
|
||||||
|
if (_pool.getSettings().getDestinationNickname() != null)
|
||||||
|
rv.append(_pool.getSettings().getDestinationNickname());
|
||||||
|
else
|
||||||
|
rv.append(_pool.getSettings().getDestination().toBase64().substring(0,4));
|
||||||
|
return rv.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
public void runJob() {
|
||||||
|
if (_pool.getSettings().isExploratory())
|
||||||
|
_pool.refreshBuilders(4, 4);
|
||||||
|
else
|
||||||
|
_pool.refreshBuilders(1, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -66,9 +66,15 @@ public class RequestTunnelJob extends JobImpl {
|
|||||||
ctx.statManager().createRateStat("tunnel.receiveRejectionBandwidth", "How often we are rejected due to bandwidth overload?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.receiveRejectionBandwidth", "How often we are rejected due to bandwidth overload?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.receiveRejectionCritical", "How often we are rejected due to critical failure?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.receiveRejectionCritical", "How often we are rejected due to critical failure?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildFailure", "What hop was being requested when a nonexploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildFailure", "What hop was being requested when a nonexploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildExploratoryFailure", "What hop was beiing requested when an exploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildExploratoryFailure", "What hop was being requested when an exploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratoryFailure1Hop", "What hop was being requested when a 1 hop exploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratoryFailure2Hop", "What hop was being requested when a 2 hop exploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratoryFailure3Hop", "What hop was being requested when a 3 hop exploratory tunnel request failed?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildSuccess", "How often we succeed building a non-exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildSuccess", "How often we succeed building a non-exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildExploratorySuccess", "How often we succeed building an exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildExploratorySuccess", "How often we succeed building an exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratorySuccess1Hop", "How often we succeed building a 1 hop exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratorySuccess2Hop", "How often we succeed building a 2 hop exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
ctx.statManager().createRateStat("tunnel.buildExploratorySuccess3Hop", "How often we succeed building a 3 hop exploratory tunnel?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildPartialTime", "How long a non-exploratory request took to be accepted?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildPartialTime", "How long a non-exploratory request took to be accepted?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
ctx.statManager().createRateStat("tunnel.buildExploratoryPartialTime", "How long an exploratory request took to be accepted?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
ctx.statManager().createRateStat("tunnel.buildExploratoryPartialTime", "How long an exploratory request took to be accepted?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||||
|
|
||||||
@ -263,9 +269,16 @@ public class RequestTunnelJob extends JobImpl {
|
|||||||
_log.info("tunnel building failed: " + _config + " at hop " + _currentHop);
|
_log.info("tunnel building failed: " + _config + " at hop " + _currentHop);
|
||||||
if (_onFailed != null)
|
if (_onFailed != null)
|
||||||
getContext().jobQueue().addJob(_onFailed);
|
getContext().jobQueue().addJob(_onFailed);
|
||||||
if (_isExploratory)
|
if (_isExploratory) {
|
||||||
getContext().statManager().addRateData("tunnel.buildExploratoryFailure", _currentHop, _config.getLength());
|
int i = _config.getLength();
|
||||||
else
|
getContext().statManager().addRateData("tunnel.buildExploratoryFailure", _currentHop, i);
|
||||||
|
if (i == 2)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratoryFailure1Hop", _currentHop, i);
|
||||||
|
else if (i == 3)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratoryFailure2Hop", _currentHop, i);
|
||||||
|
else if (i == 4)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratoryFailure3Hop", _currentHop, i);
|
||||||
|
} else
|
||||||
getContext().statManager().addRateData("tunnel.buildFailure", _currentHop, _config.getLength());
|
getContext().statManager().addRateData("tunnel.buildFailure", _currentHop, _config.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,9 +297,16 @@ public class RequestTunnelJob extends JobImpl {
|
|||||||
} else {
|
} else {
|
||||||
if (_onCreated != null)
|
if (_onCreated != null)
|
||||||
getContext().jobQueue().addJob(_onCreated);
|
getContext().jobQueue().addJob(_onCreated);
|
||||||
if (_isExploratory)
|
if (_isExploratory) {
|
||||||
|
int i = _config.getLength();
|
||||||
getContext().statManager().addRateData("tunnel.buildExploratorySuccess", 1, 0);
|
getContext().statManager().addRateData("tunnel.buildExploratorySuccess", 1, 0);
|
||||||
else
|
if (i == 2)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratorySuccess1Hop", 1, 0);
|
||||||
|
else if (i == 3)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratorySuccess2Hop", 1, 0);
|
||||||
|
else if (i == 4)
|
||||||
|
getContext().statManager().addRateData("tunnel.buildExploratorySuccess3Hop", 1, 0);
|
||||||
|
} else
|
||||||
getContext().statManager().addRateData("tunnel.buildSuccess", 1, 0);
|
getContext().statManager().addRateData("tunnel.buildSuccess", 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public class TunnelBuilder {
|
|||||||
public void runJob() {
|
public void runJob() {
|
||||||
// yikes, nothing left, lets get some backup (if we're allowed)
|
// yikes, nothing left, lets get some backup (if we're allowed)
|
||||||
_pool.getManager().buildComplete();
|
_pool.getManager().buildComplete();
|
||||||
_pool.refreshBuilders();
|
_pool.refreshBuilders(1, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,10 @@ abstract class TunnelPeerSelector {
|
|||||||
|
|
||||||
protected int getLength(RouterContext ctx, TunnelPoolSettings settings) {
|
protected int getLength(RouterContext ctx, TunnelPoolSettings settings) {
|
||||||
int length = settings.getLength();
|
int length = settings.getLength();
|
||||||
if (settings.getLengthVariance() != 0) {
|
int override = settings.getLengthOverride();
|
||||||
|
if (override != 0)
|
||||||
|
length = override;
|
||||||
|
else if (settings.getLengthVariance() != 0) {
|
||||||
int skew = settings.getLengthVariance();
|
int skew = settings.getLengthVariance();
|
||||||
if (skew > 0)
|
if (skew > 0)
|
||||||
length += ctx.random().nextInt(skew+1);
|
length += ctx.random().nextInt(skew+1);
|
||||||
|
@ -37,7 +37,7 @@ public class TunnelPool {
|
|||||||
private long _lastSelectionPeriod;
|
private long _lastSelectionPeriod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only 5 builds per minute per pool, even if we have failing tunnels,
|
* Only 10 builds per minute per pool, even if we have failing tunnels,
|
||||||
* etc. On overflow, the necessary additional tunnels are built by the
|
* etc. On overflow, the necessary additional tunnels are built by the
|
||||||
* RefreshJob
|
* RefreshJob
|
||||||
*/
|
*/
|
||||||
@ -65,7 +65,7 @@ public class TunnelPool {
|
|||||||
_alive = true;
|
_alive = true;
|
||||||
_refreshJob.getTiming().setStartAfter(_context.clock().now() + 60*1000);
|
_refreshJob.getTiming().setStartAfter(_context.clock().now() + 60*1000);
|
||||||
_context.jobQueue().addJob(_refreshJob);
|
_context.jobQueue().addJob(_refreshJob);
|
||||||
int added = refreshBuilders();
|
int added = refreshBuilders(0, 0);
|
||||||
if (added <= 0) {
|
if (added <= 0) {
|
||||||
// we just reconnected and didn't require any new tunnel builders.
|
// we just reconnected and didn't require any new tunnel builders.
|
||||||
// however, we /do/ want a leaseSet, so build one
|
// however, we /do/ want a leaseSet, so build one
|
||||||
@ -85,12 +85,17 @@ public class TunnelPool {
|
|||||||
_lastSelected = null;
|
_lastSelected = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int countUsableTunnels() {
|
/**
|
||||||
|
* Return number of tunnels expiring greater than
|
||||||
|
* timeFactor * RebuildPeriod from now
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private int countUsableTunnels(int timeFactor) {
|
||||||
int valid = 0;
|
int valid = 0;
|
||||||
synchronized (_tunnels) {
|
synchronized (_tunnels) {
|
||||||
for (int i = 0; i < _tunnels.size(); i++) {
|
for (int i = 0; i < _tunnels.size(); i++) {
|
||||||
TunnelInfo info = (TunnelInfo)_tunnels.get(i);
|
TunnelInfo info = (TunnelInfo)_tunnels.get(i);
|
||||||
if (info.getExpiration() > _context.clock().now() + 3*_settings.getRebuildPeriod())
|
if (info.getExpiration() > _context.clock().now() + (timeFactor * _settings.getRebuildPeriod()))
|
||||||
valid++;
|
valid++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,21 +104,31 @@ public class TunnelPool {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fire up as many buildTunnel tasks as necessary, returning how many
|
* Fire up as many buildTunnel tasks as necessary, returning how many
|
||||||
* were added
|
* were added.
|
||||||
|
* Build maxBuild tunnels (0 = unlimited), use timeFactor * RebuildPeriod.
|
||||||
|
* Fire off up to six extra jobs if an exploratory tunnel is
|
||||||
|
* requested by RebuildJob or tunnelFailed (maxBuild > 1).
|
||||||
|
* Throttle builds to a maximum per minute; reduce maximum if job lag is high,
|
||||||
|
* or if we have network errors which indicate we are disconnected from the network.
|
||||||
|
* Override pool length setting and build a 1-hop tunnel if time is short.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int refreshBuilders() {
|
int refreshBuilders(int maxBuild, int timeFactor) {
|
||||||
if ( (_settings.getDestination() != null) && (!_context.clientManager().isLocal(_settings.getDestination())) )
|
if ( (_settings.getDestination() != null) && (!_context.clientManager().isLocal(_settings.getDestination())) )
|
||||||
_alive = false;
|
_alive = false;
|
||||||
if (!_alive) return 0;
|
if (!_alive) return 0;
|
||||||
// only start up new build tasks if we need more of 'em
|
// only start up new build tasks if we need more of 'em
|
||||||
int target = _settings.getQuantity() + _settings.getBackupQuantity();
|
int baseTarget = _settings.getQuantity() + _settings.getBackupQuantity();
|
||||||
int usableTunnels = countUsableTunnels();
|
int target = baseTarget;
|
||||||
|
int usableTunnels = countUsableTunnels(timeFactor);
|
||||||
|
if (_settings.isExploratory() && target > 0 && maxBuild > 1)
|
||||||
|
target+= 6;
|
||||||
|
|
||||||
if ( (target > usableTunnels) && (_log.shouldLog(Log.INFO)) )
|
if ( (target > usableTunnels) )
|
||||||
_log.info(toString() + ": refreshing builders, previously had " + usableTunnels
|
if ( (target > usableTunnels) && (_log.shouldLog(Log.INFO)) )
|
||||||
|
_log.info(toString() + ": refreshing builders, previously had " + usableTunnels
|
||||||
+ ", want a total of " + target + ", creating "
|
+ ", want a total of " + target + ", creating "
|
||||||
+ (target-usableTunnels) + " new ones.");
|
+ (target-usableTunnels) + " new ones (" + maxBuild + " max).");
|
||||||
|
|
||||||
if (target > usableTunnels) {
|
if (target > usableTunnels) {
|
||||||
long minute = _context.clock().now();
|
long minute = _context.clock().now();
|
||||||
@ -123,9 +138,34 @@ public class TunnelPool {
|
|||||||
_buildsThisMinute = 0;
|
_buildsThisMinute = 0;
|
||||||
}
|
}
|
||||||
int build = (target - usableTunnels);
|
int build = (target - usableTunnels);
|
||||||
if (build > (MAX_BUILDS_PER_MINUTE - _buildsThisMinute))
|
if (maxBuild > 0 && build > maxBuild)
|
||||||
build = (MAX_BUILDS_PER_MINUTE - _buildsThisMinute);
|
build = maxBuild;
|
||||||
|
int buildThrottle = MAX_BUILDS_PER_MINUTE;
|
||||||
|
int lag = (int) _context.statManager().getRate("jobQueue.jobLag").getRate(60*1000).getAverageValue();
|
||||||
|
int netErrors = (int) _context.statManager().getRate("udp.sendException").getRate(60*1000).getLastEventCount();
|
||||||
|
if (lag > 3 * 1000 || netErrors > 5) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Throttling tunnel builds lag = " + lag + "; net errors = " + netErrors);
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
buildThrottle = 3;
|
||||||
|
else
|
||||||
|
buildThrottle = 1;
|
||||||
|
} else if (lag > 1 * 1000) {
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
buildThrottle = 5;
|
||||||
|
else
|
||||||
|
buildThrottle = 2;
|
||||||
|
}
|
||||||
|
if (build > (buildThrottle - _buildsThisMinute))
|
||||||
|
build = (buildThrottle - _buildsThisMinute);
|
||||||
|
if (build <= 0) return 0;
|
||||||
|
|
||||||
|
if ((_settings.isExploratory() && baseTarget > countUsableTunnels(1)) ||
|
||||||
|
((!_settings.isExploratory()) && baseTarget > countUsableTunnels(0)))
|
||||||
|
_settings.setLengthOverride(1);
|
||||||
|
else
|
||||||
|
_settings.setLengthOverride(0);
|
||||||
|
|
||||||
int wanted = build;
|
int wanted = build;
|
||||||
build = _manager.allocateBuilds(build);
|
build = _manager.allocateBuilds(build);
|
||||||
|
|
||||||
@ -255,7 +295,7 @@ public class TunnelPool {
|
|||||||
if (_settings != null) {
|
if (_settings != null) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info(toString() + ": Settings updated on the pool: " + settings);
|
_log.info(toString() + ": Settings updated on the pool: " + settings);
|
||||||
refreshBuilders(); // to start/stop new sequences, in case the quantities changed
|
refreshBuilders(1, 4); // to start/stop new sequences, in case the quantities changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public TunnelPeerSelector getSelector() { return _peerSelector; }
|
public TunnelPeerSelector getSelector() { return _peerSelector; }
|
||||||
@ -278,8 +318,6 @@ public class TunnelPool {
|
|||||||
|
|
||||||
if (ls != null)
|
if (ls != null)
|
||||||
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
|
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
|
||||||
|
|
||||||
refreshBuilders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeTunnel(TunnelInfo info) {
|
public void removeTunnel(TunnelInfo info) {
|
||||||
@ -319,7 +357,6 @@ public class TunnelPool {
|
|||||||
_manager.removeTunnels(_settings.getDestination());
|
_manager.removeTunnels(_settings.getDestination());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
refreshBuilders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tunnelFailed(PooledTunnelCreatorConfig cfg) {
|
public void tunnelFailed(PooledTunnelCreatorConfig cfg) {
|
||||||
@ -343,15 +380,27 @@ public class TunnelPool {
|
|||||||
if (_settings.isInbound() && (_settings.getDestination() != null) ) {
|
if (_settings.isInbound() && (_settings.getDestination() != null) ) {
|
||||||
if (ls != null) {
|
if (ls != null) {
|
||||||
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
|
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
refreshBuilders(3, 4);
|
||||||
|
else
|
||||||
|
refreshBuilders(1, 4);
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(toString() + ": unable to build a new leaseSet on failure (" + remaining
|
_log.warn(toString() + ": unable to build a new leaseSet on failure (" + remaining
|
||||||
+ " remaining), request a new tunnel");
|
+ " remaining), request a new tunnel");
|
||||||
if (remaining < _settings.getBackupQuantity() + _settings.getQuantity())
|
if (remaining < _settings.getBackupQuantity() + _settings.getQuantity())
|
||||||
buildFallback();
|
if (!buildFallback())
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
refreshBuilders(3, 4);
|
||||||
|
else
|
||||||
|
refreshBuilders(1, 4);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
refreshBuilders(3, 4);
|
||||||
|
else
|
||||||
|
refreshBuilders(1, 4);
|
||||||
}
|
}
|
||||||
refreshBuilders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshLeaseSet() {
|
void refreshLeaseSet() {
|
||||||
@ -377,18 +426,24 @@ public class TunnelPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildFallback() {
|
/**
|
||||||
|
* Return true if a fallback tunnel is built
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
boolean buildFallback() {
|
||||||
int quantity = _settings.getBackupQuantity() + _settings.getQuantity();
|
int quantity = _settings.getBackupQuantity() + _settings.getQuantity();
|
||||||
int usable = countUsableTunnels();
|
int usable = countUsableTunnels(1);
|
||||||
if (usable >= quantity) return;
|
if (usable >= quantity) return false;
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if ( (usable == 0) && (_settings.getAllowZeroHop()) ) {
|
||||||
_log.info(toString() + ": building a fallback tunnel (usable: " + usable + " needed: " + quantity + ")");
|
if (_log.shouldLog(Log.INFO))
|
||||||
if ( (usable == 0) && (_settings.getAllowZeroHop()) )
|
_log.info(toString() + ": building a fallback tunnel (usable: " + usable + " needed: " + quantity + ")");
|
||||||
_builder.buildTunnel(_context, this, true);
|
_builder.buildTunnel(_context, this, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
//else
|
//else
|
||||||
// _builder.buildTunnel(_context, this);
|
// _builder.buildTunnel(_context, this);
|
||||||
refreshBuilders();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -476,12 +531,16 @@ public class TunnelPool {
|
|||||||
public RefreshJob(RouterContext ctx) {
|
public RefreshJob(RouterContext ctx) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
}
|
}
|
||||||
public String getName() { return "Refresh pool"; }
|
public String getName() { return "Refresh " + TunnelPool.this.toString(); }
|
||||||
public void runJob() {
|
public void runJob() {
|
||||||
if (!_alive) return;
|
if (!_alive) return;
|
||||||
int added = refreshBuilders();
|
int added;
|
||||||
|
if (_settings.isExploratory())
|
||||||
|
added = refreshBuilders(0, 2);
|
||||||
|
else
|
||||||
|
added = refreshBuilders(0, 1);
|
||||||
if ( (added > 0) && (_log.shouldLog(Log.WARN)) )
|
if ( (added > 0) && (_log.shouldLog(Log.WARN)) )
|
||||||
_log.warn("Passive rebuilding a tunnel for " + TunnelPool.this.toString());
|
_log.warn("Additional parallel rebuilding of tunnel for " + TunnelPool.this.toString());
|
||||||
requeue(30*1000);
|
requeue(30*1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,38 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
else
|
else
|
||||||
return _outboundExploratory.size();
|
return _outboundExploratory.size();
|
||||||
}
|
}
|
||||||
|
public int getInboundClientTunnelCount() {
|
||||||
|
int count = 0;
|
||||||
|
List destinations = null;
|
||||||
|
synchronized (_clientInboundPools) {
|
||||||
|
destinations = new ArrayList(_clientInboundPools.keySet());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < destinations.size(); i++) {
|
||||||
|
Hash client = (Hash)destinations.get(i);
|
||||||
|
TunnelPool pool = null;
|
||||||
|
synchronized (_clientInboundPools) {
|
||||||
|
pool = (TunnelPool)_clientInboundPools.get(client);
|
||||||
|
}
|
||||||
|
count += pool.listTunnels().size();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
public int getOutboundClientTunnelCount() {
|
||||||
|
int count = 0;
|
||||||
|
List destinations = null;
|
||||||
|
synchronized (_clientInboundPools) {
|
||||||
|
destinations = new ArrayList(_clientOutboundPools.keySet());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < destinations.size(); i++) {
|
||||||
|
Hash client = (Hash)destinations.get(i);
|
||||||
|
TunnelPool pool = null;
|
||||||
|
synchronized (_clientOutboundPools) {
|
||||||
|
pool = (TunnelPool)_clientOutboundPools.get(client);
|
||||||
|
}
|
||||||
|
count += pool.listTunnels().size();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
public int getParticipatingCount() { return _context.tunnelDispatcher().getParticipatingCount(); }
|
public int getParticipatingCount() { return _context.tunnelDispatcher().getParticipatingCount(); }
|
||||||
public long getLastParticipatingExpiration() { return _context.tunnelDispatcher().getLastParticipatingExpiration(); }
|
public long getLastParticipatingExpiration() { return _context.tunnelDispatcher().getLastParticipatingExpiration(); }
|
||||||
|
|
||||||
@ -240,6 +272,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
inbound.startup();
|
inbound.startup();
|
||||||
|
try { Thread.sleep(3*1000); } catch (InterruptedException ie) {}
|
||||||
outbound.startup();
|
outbound.startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +349,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
_inboundExploratory = new TunnelPool(_context, this, inboundSettings, selector, builder);
|
_inboundExploratory = new TunnelPool(_context, this, inboundSettings, selector, builder);
|
||||||
_inboundExploratory.startup();
|
_inboundExploratory.startup();
|
||||||
|
|
||||||
|
try { Thread.sleep(3*1000); } catch (InterruptedException ie) {}
|
||||||
TunnelPoolSettings outboundSettings = new TunnelPoolSettings();
|
TunnelPoolSettings outboundSettings = new TunnelPoolSettings();
|
||||||
outboundSettings.setIsExploratory(true);
|
outboundSettings.setIsExploratory(true);
|
||||||
outboundSettings.setIsInbound(false);
|
outboundSettings.setIsInbound(false);
|
||||||
@ -406,10 +440,10 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
out.write("<td>n/a</td>");
|
out.write("<td>n/a</td>");
|
||||||
long timeLeft = cfg.getExpiration()-_context.clock().now();
|
long timeLeft = cfg.getExpiration()-_context.clock().now();
|
||||||
if (timeLeft > 0)
|
if (timeLeft > 0)
|
||||||
out.write("<td>" + DataHelper.formatDuration(timeLeft) + "</td>");
|
out.write("<td align=right>" + DataHelper.formatDuration(timeLeft) + "</td>");
|
||||||
else
|
else
|
||||||
out.write("<td>(grace period)</td>");
|
out.write("<td align=right>(grace period)</td>");
|
||||||
out.write("<td>" + cfg.getProcessedMessagesCount() + "KB</td>");
|
out.write("<td align=right>" + cfg.getProcessedMessagesCount() + "KB</td>");
|
||||||
out.write("</tr>\n");
|
out.write("</tr>\n");
|
||||||
processed += cfg.getProcessedMessagesCount();
|
processed += cfg.getProcessedMessagesCount();
|
||||||
}
|
}
|
||||||
@ -441,8 +475,8 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
out.write("<tr><td><b>inbound</b></td>");
|
out.write("<tr><td><b>inbound</b></td>");
|
||||||
else
|
else
|
||||||
out.write("<tr><td><b>outbound</b></td>");
|
out.write("<tr><td><b>outbound</b></td>");
|
||||||
out.write("<td>" + DataHelper.formatDuration(timeLeft) + "</td>\n");
|
out.write("<td align=right>" + DataHelper.formatDuration(timeLeft) + "</td>\n");
|
||||||
out.write("<td>" + info.getProcessedMessagesCount() + "KB</td>\n");
|
out.write("<td align=right>" + info.getProcessedMessagesCount() + "KB</td>\n");
|
||||||
for (int j = 0; j < info.getLength(); j++) {
|
for (int j = 0; j < info.getLength(); j++) {
|
||||||
Hash peer = info.getPeer(j);
|
Hash peer = info.getPeer(j);
|
||||||
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
|
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
|
||||||
|
Reference in New Issue
Block a user