diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java
index 7c0518a92..c3641d40f 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java
@@ -34,8 +34,10 @@ public class ConfigNetHandler extends FormHandler {
private String _tcpPort;
private String _udpPort;
private String _inboundRate;
+ private String _inboundBurstRate;
private String _inboundBurst;
private String _outboundRate;
+ private String _outboundBurstRate;
private String _outboundBurst;
private String _reseedFrom;
private String _sharePct;
@@ -73,12 +75,18 @@ public class ConfigNetHandler extends FormHandler {
public void setInboundrate(String rate) {
_inboundRate = (rate != null ? rate.trim() : null);
}
+ public void setInboundburstrate(String rate) {
+ _inboundBurstRate = (rate != null ? rate.trim() : null);
+ }
public void setInboundburstfactor(String factor) {
_inboundBurst = (factor != null ? factor.trim() : null);
}
public void setOutboundrate(String rate) {
_outboundRate = (rate != null ? rate.trim() : null);
}
+ public void setOutboundburstrate(String rate) {
+ _outboundBurstRate = (rate != null ? rate.trim() : null);
+ }
public void setOutboundburstfactor(String factor) {
_outboundBurst = (factor != null ? factor.trim() : null);
}
@@ -293,14 +301,22 @@ public class ConfigNetHandler extends FormHandler {
_context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_KBPS, _outboundRate);
updated = true;
}
+ if ( (_inboundBurstRate != null) && (_inboundBurstRate.length() > 0) ) {
+ _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST_KBPS, _inboundBurstRate);
+ updated = true;
+ }
+ if ( (_outboundBurstRate != null) && (_outboundBurstRate.length() > 0) ) {
+ _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST_KBPS, _outboundBurstRate);
+ updated = true;
+ }
- String inRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_INBOUND_KBPS);
+ String inBurstRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST_KBPS);
if (_inboundBurst != null) {
int rateKBps = 0;
int burstSeconds = 0;
try {
- rateKBps = Integer.parseInt(inRate);
+ rateKBps = Integer.parseInt(inBurstRate);
burstSeconds = Integer.parseInt(_inboundBurst);
} catch (NumberFormatException nfe) {
// ignore
@@ -312,13 +328,13 @@ public class ConfigNetHandler extends FormHandler {
}
}
- String outRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_OUTBOUND_KBPS);
+ String outBurstRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST_KBPS);
if (_outboundBurst != null) {
int rateKBps = 0;
int burstSeconds = 0;
try {
- rateKBps = Integer.parseInt(outRate);
+ rateKBps = Integer.parseInt(outBurstRate);
burstSeconds = Integer.parseInt(_outboundBurst);
} catch (NumberFormatException nfe) {
// ignore
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
index c5ebb16cf..562d07b3a 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
@@ -84,6 +84,8 @@ public class ConfigNetHelper {
public static final String PROP_INBOUND_KBPS = "i2np.bandwidth.inboundKBytesPerSecond";
public static final String PROP_OUTBOUND_KBPS = "i2np.bandwidth.outboundKBytesPerSecond";
+ public static final String PROP_INBOUND_BURST_KBPS = "i2np.bandwidth.inboundBurstKBytesPerSecond";
+ public static final String PROP_OUTBOUND_BURST_KBPS = "i2np.bandwidth.outboundBurstKBytesPerSecond";
public static final String PROP_INBOUND_BURST = "i2np.bandwidth.inboundBurstKBytes";
public static final String PROP_OUTBOUND_BURST = "i2np.bandwidth.outboundBurstKBytes";
public static final String PROP_SHARE_PERCENTAGE = "router.sharePercentage";
@@ -94,14 +96,28 @@ public class ConfigNetHelper {
if (rate != null)
return rate;
else
- return "-1";
+ return "16";
}
public String getOutboundRate() {
String rate = _context.getProperty(PROP_OUTBOUND_KBPS);
if (rate != null)
return rate;
else
- return "-1";
+ return "16";
+ }
+ public String getInboundBurstRate() {
+ String rate = _context.getProperty(PROP_INBOUND_BURST_KBPS);
+ if (rate != null)
+ return rate;
+ else
+ return "32";
+ }
+ public String getOutboundBurstRate() {
+ String rate = _context.getProperty(PROP_OUTBOUND_BURST_KBPS);
+ if (rate != null)
+ return rate;
+ else
+ return "32";
}
public String getInboundBurstFactorBox() {
String rate = _context.getProperty(PROP_INBOUND_KBPS);
diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp
index 11b98ca41..bf214eef2 100644
--- a/apps/routerconsole/jsp/config.jsp
+++ b/apps/routerconsole/jsp/config.jsp
@@ -39,14 +39,17 @@
Bandwidth limiter
Inbound rate:
- " /> KBytes per second
+ " /> KBps
bursting up to
+ " /> KBps for
Outbound rate:
- " /> KBytes per second
+ " /> KBps
bursting up to
+ " /> KBps for
- A negative rate means a default limit of 16KBytes per second.
+ KBps = kilibytes per second = 1024 bytes per second.
+ A negative rate means a default limit of 16KBytes per second.
Bandwidth share percentage:
Sharing a higher percentage will improve your anonymity and help the network
diff --git a/history.txt b/history.txt
index d24fb36f6..2d3b79364 100644
--- a/history.txt
+++ b/history.txt
@@ -1,6 +1,11 @@
-$Id: history.txt,v 1.254 2005/09/17 02:31:50 jrandom Exp $
+$Id: history.txt,v 1.255 2005/09/17 15:08:26 jrandom Exp $
2005-09-17 jrandom
+ * Updated the bandwidth limiter to use two tiers of bandwidth - our normal
+ steady state rate, plus a new limit on how fast we transfer when
+ bursting. This is different from the old "burst as fast as possible
+ until we're out of tokens" policy, and should help those with congested
+ networks. See /config.jsp to manage this rate.
* Bugfixes in Syndie to handle missing cache files (no data was lost, the
old posts just didn't show up).
* Log properly in EepPost
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 60869ef0e..fe4b90586 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
- public final static String ID = "$Revision: 1.238 $ $Date: 2005/09/16 13:28:26 $";
+ public final static String ID = "$Revision: 1.239 $ $Date: 2005/09/16 16:24:43 $";
public final static String VERSION = "0.6.0.5";
- public final static long BUILD = 13;
+ public final static long BUILD = 14;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
index 0ed8f3e9d..df71d2749 100644
--- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
+++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
@@ -14,16 +14,34 @@ public class FIFOBandwidthLimiter {
private I2PAppContext _context;
private List _pendingInboundRequests;
private List _pendingOutboundRequests;
- private volatile int _availableInboundBytes;
- private volatile int _availableOutboundBytes;
+ /** how many bytes we can consume for inbound transmission immediately */
+ private volatile int _availableInbound;
+ /** how many bytes we can consume for outbound transmission immediately */
+ private volatile int _availableOutbound;
+ /** how many bytes we can queue up for bursting */
+ private volatile int _unavailableInboundBurst;
+ /** how many bytes we can queue up for bursting */
+ private volatile int _unavailableOutboundBurst;
+ /** how large _unavailableInbound can get */
+ private int _maxInboundBurst;
+ /** how large _unavailableInbound can get */
+ private int _maxOutboundBurst;
+ /** how large _availableInbound can get - aka our inbound rate duringa burst */
+ private int _maxInbound;
+ /** how large _availableOutbound can get - aka our outbound rate during a burst */
+ private int _maxOutbound;
+ /** shortcut of whether our outbound rate is unlimited */
private boolean _outboundUnlimited;
+ /** shortcut of whether our inbound rate is unlimited */
private boolean _inboundUnlimited;
+ /** lifetime counter of bytes received */
private volatile long _totalAllocatedInboundBytes;
+ /** lifetime counter of bytes sent */
private volatile long _totalAllocatedOutboundBytes;
+ /** lifetime counter of tokens available for use but exceeded our maxInboundBurst size */
private volatile long _totalWastedInboundBytes;
+ /** lifetime counter of tokens available for use but exceeded our maxOutboundBurst size */
private volatile long _totalWastedOutboundBytes;
- private int _maxInboundBytes;
- private int _maxOutboundBytes;
private FIFOBandwidthRefiller _refiller;
private long _lastTotalSent;
@@ -65,16 +83,16 @@ public class FIFOBandwidthLimiter {
t.start();
}
- public long getAvailableInboundBytes() { return _availableInboundBytes; }
- public long getAvailableOutboundBytes() { return _availableOutboundBytes; }
+ //public long getAvailableInboundBytes() { return _availableInboundBytes; }
+ //public long getAvailableOutboundBytes() { return _availableOutboundBytes; }
public long getTotalAllocatedInboundBytes() { return _totalAllocatedInboundBytes; }
public long getTotalAllocatedOutboundBytes() { return _totalAllocatedOutboundBytes; }
public long getTotalWastedInboundBytes() { return _totalWastedInboundBytes; }
public long getTotalWastedOutboundBytes() { return _totalWastedOutboundBytes; }
- public long getMaxInboundBytes() { return _maxInboundBytes; }
- public void setMaxInboundBytes(int numBytes) { _maxInboundBytes = numBytes; }
- public long getMaxOutboundBytes() { return _maxOutboundBytes; }
- public void setMaxOutboundBytes(int numBytes) { _maxOutboundBytes = numBytes; }
+ //public long getMaxInboundBytes() { return _maxInboundBytes; }
+ //public void setMaxInboundBytes(int numBytes) { _maxInboundBytes = numBytes; }
+ //public long getMaxOutboundBytes() { return _maxOutboundBytes; }
+ //public void setMaxOutboundBytes(int numBytes) { _maxOutboundBytes = numBytes; }
public boolean getInboundUnlimited() { return _inboundUnlimited; }
public void setInboundUnlimited(boolean isUnlimited) { _inboundUnlimited = isUnlimited; }
public boolean getOutboundUnlimited() { return _outboundUnlimited; }
@@ -83,8 +101,14 @@ public class FIFOBandwidthLimiter {
public void reinitialize() {
_pendingInboundRequests.clear();
_pendingOutboundRequests.clear();
- _availableInboundBytes = 0;
- _availableOutboundBytes = 0;
+ _availableInbound = 0;
+ _availableOutbound = 0;
+ _maxInbound = 0;
+ _maxOutbound = 0;
+ _maxInboundBurst = 0;
+ _maxOutboundBurst = 0;
+ _unavailableInboundBurst = 0;
+ _unavailableOutboundBurst = 0;
_inboundUnlimited = false;
_outboundUnlimited = false;
_refiller.reinitialize();
@@ -133,25 +157,94 @@ public class FIFOBandwidthLimiter {
return req;
}
+ void setInboundBurstKBps(int kbytesPerSecond) {
+ _maxInbound = kbytesPerSecond * 1024;
+ }
+ void setOutboundBurstKBps(int kbytesPerSecond) {
+ _maxOutbound = kbytesPerSecond * 1024;
+ }
+ int getInboundBurstBytes() { return _maxInboundBurst; }
+ int getOutboundBurstBytes() { return _maxOutboundBurst; }
+ void setInboundBurstBytes(int bytes) { _maxInboundBurst = bytes; }
+ void setOutboundBurstBytes(int bytes) { _maxOutboundBurst = bytes; }
+
+ StringBuffer getStatus() {
+ StringBuffer rv = new StringBuffer(64);
+ rv.append("Available: ").append(_availableInbound).append('/').append(_availableOutbound).append(' ');
+ rv.append("Max: ").append(_maxInbound).append('/').append(_maxOutbound).append(' ');
+ rv.append("Burst: ").append(_unavailableInboundBurst).append('/').append(_unavailableOutboundBurst).append(' ');
+ rv.append("Burst max: ").append(_maxInboundBurst).append('/').append(_maxOutboundBurst).append(' ');
+ return rv;
+ }
+
/**
* More bytes are available - add them to the queue and satisfy any requests
* we can
*/
final void refillBandwidthQueues(long bytesInbound, long bytesOutbound) {
if (_log.shouldLog(Log.DEBUG))
- _log.debug("Refilling the queues with " + bytesInbound + "/" + bytesOutbound + ", available " +
- _availableInboundBytes + '/' + _availableOutboundBytes + ", max " +
- _maxInboundBytes + '/' + _maxOutboundBytes);
- _availableInboundBytes += bytesInbound;
- _availableOutboundBytes += bytesOutbound;
- if (_availableInboundBytes > _maxInboundBytes) {
- _totalWastedInboundBytes += (_availableInboundBytes - _maxInboundBytes);
- _availableInboundBytes = _maxInboundBytes;
+ _log.debug("Refilling the queues with " + bytesInbound + "/" + bytesOutbound + ": " + getStatus().toString());
+ _availableInbound += bytesInbound;
+ _availableOutbound += bytesOutbound;
+
+ if (_availableInbound > _maxInbound) {
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("available inbound (" + _availableInbound + ") exceeds our inbound burst (" + _maxInbound + "), so no supplement");
+ _unavailableInboundBurst += _availableInbound - _maxInbound;
+ _availableInbound = _maxInbound;
+ if (_unavailableInboundBurst > _maxInboundBurst) {
+ _totalWastedInboundBytes += _unavailableInboundBurst - _maxInboundBurst;
+ _unavailableInboundBurst = _maxInboundBurst;
+ }
+ } else {
+ // try to pull in up to 1/10th of the max inbound rate (aka burst rate), since
+ // we refill every 100ms
+ int want = _maxInbound/10;
+ if (want > (_maxInbound - _availableInbound))
+ want = _maxInbound - _availableInbound;
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("want to pull " + want + " from the inbound burst (" + _unavailableInboundBurst + ") to supplement " + _availableInbound + " (max: " + _maxInbound + ")");
+
+ if (want > 0) {
+ if (want <= _unavailableInboundBurst) {
+ _availableInbound += want;
+ _unavailableInboundBurst -= want;
+ } else {
+ _availableInbound += _unavailableInboundBurst;
+ _unavailableInboundBurst = 0;
+ }
+ }
}
- if (_availableOutboundBytes > _maxOutboundBytes) {
- _totalWastedOutboundBytes += (_availableOutboundBytes - _maxOutboundBytes);
- _availableOutboundBytes = _maxOutboundBytes;
+
+ if (_availableOutbound > _maxOutbound) {
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("available outbound (" + _availableOutbound + ") exceeds our outbound burst (" + _maxOutbound + "), so no supplement");
+ _unavailableOutboundBurst += _availableOutbound - _maxOutbound;
+ _availableOutbound = _maxOutbound;
+ if (_unavailableOutboundBurst > _maxOutboundBurst) {
+ _totalWastedOutboundBytes += _unavailableOutboundBurst - _maxOutboundBurst;
+ _unavailableOutboundBurst = _maxOutboundBurst;
+ }
+ } else {
+ // try to pull in up to 1/10th of the max outbound rate (aka burst rate), since
+ // we refill every 100ms
+ int want = _maxOutbound/10;
+ if (want > (_maxOutbound - _availableOutbound))
+ want = _maxOutbound - _availableOutbound;
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("want to pull " + want + " from the outbound burst (" + _unavailableOutboundBurst + ") to supplement " + _availableOutbound + " (max: " + _maxOutbound + ")");
+
+ if (want > 0) {
+ if (want <= _unavailableOutboundBurst) {
+ _availableOutbound += want;
+ _unavailableOutboundBurst -= want;
+ } else {
+ _availableOutbound += _unavailableOutboundBurst;
+ _unavailableOutboundBurst = 0;
+ }
+ }
}
+
satisfyRequests();
updateStats();
}
@@ -204,15 +297,14 @@ public class FIFOBandwidthLimiter {
if (_inboundUnlimited) {
satisfied = locked_satisfyInboundUnlimited();
} else {
- if (_availableInboundBytes > 0) {
+ if (_availableInbound > 0) {
satisfied = locked_satisfyInboundAvailable();
} else {
// no bandwidth available
if (_log.shouldLog(Log.DEBUG))
_log.debug("Still denying the " + _pendingInboundRequests.size()
- + " pending inbound requests (available "
- + _availableInboundBytes + "/" + _availableOutboundBytes
- + " in/out, longest waited " + locked_getLongestInboundWait() + " in)");
+ + " pending inbound requests (status: " + getStatus().toString()
+ + ", longest waited " + locked_getLongestInboundWait() + " in)");
}
}
}
@@ -289,7 +381,7 @@ public class FIFOBandwidthLimiter {
List satisfied = null;
for (int i = 0; i < _pendingInboundRequests.size(); i++) {
- if (_availableInboundBytes <= 0) break;
+ if (_availableInbound <= 0) break;
SimpleRequest req = (SimpleRequest)_pendingInboundRequests.get(i);
long waited = now() - req.getRequestTime();
if (req.getAborted()) {
@@ -313,11 +405,11 @@ public class FIFOBandwidthLimiter {
// ok, they are really waiting for us to give them stuff
int requested = req.getPendingInboundRequested();
int allocated = 0;
- if (_availableInboundBytes > requested)
+ if (_availableInbound > requested)
allocated = requested;
else
- allocated = _availableInboundBytes;
- _availableInboundBytes -= allocated;
+ allocated = _availableInbound;
+ _availableInbound -= allocated;
_totalAllocatedInboundBytes += allocated;
req.allocateBytes(allocated, 0);
if (satisfied == null)
@@ -354,15 +446,14 @@ public class FIFOBandwidthLimiter {
if (_outboundUnlimited) {
satisfied = locked_satisfyOutboundUnlimited();
} else {
- if (_availableOutboundBytes > 0) {
+ if (_availableOutbound > 0) {
satisfied = locked_satisfyOutboundAvailable();
} else {
// no bandwidth available
if (_log.shouldLog(Log.DEBUG))
_log.debug("Still denying the " + _pendingOutboundRequests.size()
- + " pending outbound requests (available "
- + _availableInboundBytes + "/" + _availableOutboundBytes + " in/out, "
- + "longest waited " + locked_getLongestOutboundWait() + " out)");
+ + " pending outbound requests (status: " + getStatus().toString()
+ + ", longest waited " + locked_getLongestOutboundWait() + " out)");
}
}
}
@@ -414,7 +505,7 @@ public class FIFOBandwidthLimiter {
List satisfied = null;
for (int i = 0; i < _pendingOutboundRequests.size(); i++) {
- if (_availableOutboundBytes <= 0) break;
+ if (_availableOutbound <= 0) break;
SimpleRequest req = (SimpleRequest)_pendingOutboundRequests.get(i);
long waited = now() - req.getRequestTime();
if (req.getAborted()) {
@@ -438,11 +529,11 @@ public class FIFOBandwidthLimiter {
// ok, they are really waiting for us to give them stuff
int requested = req.getPendingOutboundRequested();
int allocated = 0;
- if (_availableOutboundBytes > requested)
+ if (_availableOutbound > requested)
allocated = requested;
else
- allocated = _availableOutboundBytes;
- _availableOutboundBytes -= allocated;
+ allocated = _availableOutbound;
+ _availableOutbound -= allocated;
_totalAllocatedOutboundBytes += allocated;
req.allocateBytes(0, allocated);
if (satisfied == null)
@@ -476,9 +567,8 @@ public class FIFOBandwidthLimiter {
public void renderStatusHTML(Writer out) throws IOException {
long now = now();
StringBuffer buf = new StringBuffer(4096);
- buf.append("
Pending bandwidth requests (with ");
- buf.append(_availableInboundBytes).append('/');
- buf.append(_availableOutboundBytes).append(" bytes inbound/outbound available):