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):
    "); + buf.append("
    Limiter status: ").append(getStatus().toString()).append("
    \n"); + buf.append("Pending bandwidth requests:
      "); buf.append("
    • Inbound requests:
        "); synchronized (_pendingInboundRequests) { for (int i = 0; i < _pendingInboundRequests.size(); i++) { diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java index 37f47765a..021860041 100644 --- a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java +++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java @@ -11,8 +11,10 @@ class FIFOBandwidthRefiller implements Runnable { private int _inboundKBytesPerSecond; /** how many KBps do we want to allow? */ private int _outboundKBytesPerSecond; - /** how frequently do we want to replenish the available queues? */ - private long _replenishFrequency; + /** how many KBps do we want to allow during burst? */ + private int _inboundBurstKBytesPerSecond; + /** how many KBps do we want to allow during burst? */ + private int _outboundBurstKBytesPerSecond; /** when did we last replenish the queue? */ private long _lastRefillTime; /** when did we last check the config for updates? */ @@ -22,6 +24,8 @@ class FIFOBandwidthRefiller implements Runnable { public static final String PROP_INBOUND_BANDWIDTH = "i2np.bandwidth.inboundKBytesPerSecond"; public static final String PROP_OUTBOUND_BANDWIDTH = "i2np.bandwidth.outboundKBytesPerSecond"; + public static final String PROP_INBOUND_BURST_BANDWIDTH = "i2np.bandwidth.inboundBurstKBytesPerSecond"; + public static final String PROP_OUTBOUND_BURST_BANDWIDTH = "i2np.bandwidth.outboundBurstKBytesPerSecond"; public static final String PROP_INBOUND_BANDWIDTH_PEAK = "i2np.bandwidth.inboundBurstKBytes"; public static final String PROP_OUTBOUND_BANDWIDTH_PEAK = "i2np.bandwidth.outboundBurstKBytes"; //public static final String PROP_REPLENISH_FREQUENCY = "i2np.bandwidth.replenishFrequencyMs"; @@ -29,6 +33,8 @@ class FIFOBandwidthRefiller implements Runnable { // no longer allow unlimited bandwidth - the user must specify a value, and if they do not, it is 16KBps public static final int DEFAULT_INBOUND_BANDWIDTH = 16; public static final int DEFAULT_OUTBOUND_BANDWIDTH = 16; + public static final int DEFAULT_INBOUND_BURST_BANDWIDTH = 32; + public static final int DEFAULT_OUTBOUND_BURST_BANDWIDTH = 32; public static final int DEFAULT_BURST_SECONDS = 60; @@ -40,10 +46,12 @@ class FIFOBandwidthRefiller implements Runnable { public static final int MIN_INBOUND_BANDWIDTH_PEAK = 10; /** For now, until there is some tuning and safe throttling, we set the floor at a 10 second burst */ public static final int MIN_OUTBOUND_BANDWIDTH_PEAK = 10; - /** Updating the bandwidth more than once a second is silly. once every 2 or 5 seconds is less so. */ - public static final long MIN_REPLENISH_FREQUENCY = 100; - private static final long DEFAULT_REPLENISH_FREQUENCY = 100; + /** + * how often we replenish the queues. + * the bandwidth limiter is configured to expect an update 10 times per second + */ + private static final long REPLENISH_FREQUENCY = 100; public FIFOBandwidthRefiller(I2PAppContext context, FIFOBandwidthLimiter limiter) { _limiter = limiter; @@ -67,7 +75,7 @@ class FIFOBandwidthRefiller implements Runnable { _lastRefillTime = now; } - try { Thread.sleep(_replenishFrequency); } catch (InterruptedException ie) {} + try { Thread.sleep(REPLENISH_FREQUENCY); } catch (InterruptedException ie) {} } } @@ -80,12 +88,11 @@ class FIFOBandwidthRefiller implements Runnable { private boolean updateQueues(long now) { long numMs = (now - _lastRefillTime); if (_log.shouldLog(Log.INFO)) - _log.info("Updating bandwidth after " + numMs + " (available in=" - + _limiter.getAvailableInboundBytes() + ", out=" - + _limiter.getAvailableOutboundBytes()+ ", rate in=" + _log.info("Updating bandwidth after " + numMs + " (status: " + _limiter.getStatus().toString() + + " rate in=" + _inboundKBytesPerSecond + ", out=" + _outboundKBytesPerSecond +")"); - if (numMs >= MIN_REPLENISH_FREQUENCY) { + if (numMs >= REPLENISH_FREQUENCY) { long inboundToAdd = (1024*_inboundKBytesPerSecond * numMs)/1000; long outboundToAdd = (1024*_outboundKBytesPerSecond * numMs)/1000; @@ -122,10 +129,10 @@ class FIFOBandwidthRefiller implements Runnable { private void checkConfig() { updateInboundRate(); updateOutboundRate(); + updateInboundBurstRate(); + updateOutboundBurstRate(); updateInboundPeak(); updateOutboundPeak(); - - _replenishFrequency = DEFAULT_REPLENISH_FREQUENCY; if (_inboundKBytesPerSecond <= 0) { _limiter.setInboundUnlimited(true); @@ -196,69 +203,127 @@ class FIFOBandwidthRefiller implements Runnable { _outboundKBytesPerSecond = DEFAULT_OUTBOUND_BANDWIDTH; } + private void updateInboundBurstRate() { + String inBwStr = _context.getProperty(PROP_INBOUND_BURST_BANDWIDTH); + if ( (inBwStr != null) && + (inBwStr.trim().length() > 0) && + (!(inBwStr.equals(String.valueOf(_inboundBurstKBytesPerSecond)))) ) { + // bandwidth was specified *and* changed + try { + int in = Integer.parseInt(inBwStr); + if ( (in <= 0) || (in > MIN_INBOUND_BANDWIDTH) ) + _inboundBurstKBytesPerSecond = in; + else + _inboundBurstKBytesPerSecond = MIN_INBOUND_BANDWIDTH; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Updating inbound burst rate to " + _inboundBurstKBytesPerSecond); + } catch (NumberFormatException nfe) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Invalid inbound bandwidth burst limit [" + inBwStr + + "], keeping as " + _inboundBurstKBytesPerSecond); + } + } else { + if ( (inBwStr == null) && (_log.shouldLog(Log.DEBUG)) ) + _log.debug("Inbound bandwidth burst limits not specified in the config via " + PROP_INBOUND_BURST_BANDWIDTH); + } + + if (_inboundBurstKBytesPerSecond <= 0) + _inboundBurstKBytesPerSecond = DEFAULT_INBOUND_BURST_BANDWIDTH; + _limiter.setInboundBurstKBps(_inboundBurstKBytesPerSecond); + } + + private void updateOutboundBurstRate() { + String outBwStr = _context.getProperty(PROP_OUTBOUND_BURST_BANDWIDTH); + + if ( (outBwStr != null) && + (outBwStr.trim().length() > 0) && + (!(outBwStr.equals(String.valueOf(_outboundBurstKBytesPerSecond)))) ) { + // bandwidth was specified *and* changed + try { + int out = Integer.parseInt(outBwStr); + if ( (out <= 0) || (out >= MIN_OUTBOUND_BANDWIDTH) ) + _outboundBurstKBytesPerSecond = out; + else + _outboundBurstKBytesPerSecond = MIN_OUTBOUND_BANDWIDTH; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Updating outbound burst rate to " + _outboundBurstKBytesPerSecond); + } catch (NumberFormatException nfe) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Invalid outbound bandwidth burst limit [" + outBwStr + + "], keeping as " + _outboundBurstKBytesPerSecond); + } + } else { + if ( (outBwStr == null) && (_log.shouldLog(Log.DEBUG)) ) + _log.debug("Outbound bandwidth burst limits not specified in the config via " + PROP_OUTBOUND_BURST_BANDWIDTH); + } + + if (_outboundBurstKBytesPerSecond <= 0) + _outboundBurstKBytesPerSecond = DEFAULT_OUTBOUND_BURST_BANDWIDTH; + _limiter.setOutboundBurstKBps(_outboundBurstKBytesPerSecond); + } + private void updateInboundPeak() { String inBwStr = _context.getProperty(PROP_INBOUND_BANDWIDTH_PEAK); if ( (inBwStr != null) && (inBwStr.trim().length() > 0) && - (!(inBwStr.equals(String.valueOf(_limiter.getMaxInboundBytes())))) ) { + (!(inBwStr.equals(String.valueOf(_limiter.getInboundBurstBytes())))) ) { // peak bw was specified *and* changed try { int in = Integer.parseInt(inBwStr); if (in >= MIN_INBOUND_BANDWIDTH_PEAK) { - if (in < _inboundKBytesPerSecond) - _limiter.setMaxInboundBytes(_inboundKBytesPerSecond * 1024); + if (in < _inboundBurstKBytesPerSecond) + _limiter.setInboundBurstBytes(_inboundBurstKBytesPerSecond * 1024); else - _limiter.setMaxInboundBytes(in * 1024); + _limiter.setInboundBurstBytes(in * 1024); } else { - if (MIN_INBOUND_BANDWIDTH_PEAK < _inboundKBytesPerSecond) - _limiter.setMaxInboundBytes(_inboundKBytesPerSecond * 1024); + if (MIN_INBOUND_BANDWIDTH_PEAK < _inboundBurstKBytesPerSecond) + _limiter.setInboundBurstBytes(_inboundBurstKBytesPerSecond * 1024); else - _limiter.setMaxInboundBytes(MIN_INBOUND_BANDWIDTH_PEAK * 1024); + _limiter.setInboundBurstBytes(MIN_INBOUND_BANDWIDTH_PEAK * 1024); } } catch (NumberFormatException nfe) { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid inbound bandwidth burst limit [" + inBwStr + "]"); - _limiter.setMaxInboundBytes(DEFAULT_BURST_SECONDS * _inboundKBytesPerSecond * 1024); + _limiter.setInboundBurstBytes(DEFAULT_BURST_SECONDS * _inboundBurstKBytesPerSecond * 1024); } } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Inbound bandwidth burst limits not specified in the config via " + PROP_INBOUND_BANDWIDTH_PEAK); - _limiter.setMaxInboundBytes(DEFAULT_BURST_SECONDS * _inboundKBytesPerSecond * 1024); + _limiter.setInboundBurstBytes(DEFAULT_BURST_SECONDS * _inboundBurstKBytesPerSecond * 1024); } } private void updateOutboundPeak() { - String outBwStr = _context.getProperty(PROP_OUTBOUND_BANDWIDTH_PEAK); - if ( (outBwStr != null) && - (outBwStr.trim().length() > 0) && - (!(outBwStr.equals(String.valueOf(_limiter.getMaxOutboundBytes())))) ) { + String inBwStr = _context.getProperty(PROP_OUTBOUND_BANDWIDTH_PEAK); + if ( (inBwStr != null) && + (inBwStr.trim().length() > 0) && + (!(inBwStr.equals(String.valueOf(_limiter.getOutboundBurstBytes())))) ) { // peak bw was specified *and* changed try { - int out = Integer.parseInt(outBwStr); - if (out >= MIN_OUTBOUND_BANDWIDTH_PEAK) { - if (out < _outboundKBytesPerSecond) - _limiter.setMaxOutboundBytes(_outboundKBytesPerSecond * 1024); - else - _limiter.setMaxOutboundBytes(out * 1024); + int in = Integer.parseInt(inBwStr); + if (in >= MIN_OUTBOUND_BANDWIDTH_PEAK) { + if (in < _outboundBurstKBytesPerSecond) + _limiter.setOutboundBurstBytes(_outboundBurstKBytesPerSecond * 1024); + else + _limiter.setOutboundBurstBytes(in * 1024); } else { - if (MIN_OUTBOUND_BANDWIDTH_PEAK < _outboundKBytesPerSecond) - _limiter.setMaxOutboundBytes(_outboundKBytesPerSecond * 1024); + if (MIN_OUTBOUND_BANDWIDTH_PEAK < _outboundBurstKBytesPerSecond) + _limiter.setOutboundBurstBytes(_outboundBurstKBytesPerSecond * 1024); else - _limiter.setMaxOutboundBytes(MIN_OUTBOUND_BANDWIDTH_PEAK * 1024); + _limiter.setOutboundBurstBytes(MIN_OUTBOUND_BANDWIDTH_PEAK * 1024); } } catch (NumberFormatException nfe) { if (_log.shouldLog(Log.WARN)) - _log.warn("Invalid outbound bandwidth burst limit [" + outBwStr + _log.warn("Invalid outbound bandwidth burst limit [" + inBwStr + "]"); - _limiter.setMaxOutboundBytes(DEFAULT_BURST_SECONDS * _outboundKBytesPerSecond * 1024); + _limiter.setOutboundBurstBytes(DEFAULT_BURST_SECONDS * _outboundBurstKBytesPerSecond * 1024); } } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Outbound bandwidth burst limits not specified in the config via " + PROP_OUTBOUND_BANDWIDTH_PEAK); - _limiter.setMaxOutboundBytes(DEFAULT_BURST_SECONDS * _outboundKBytesPerSecond * 1024); + _limiter.setOutboundBurstBytes(DEFAULT_BURST_SECONDS * _outboundBurstKBytesPerSecond * 1024); } } - } \ No newline at end of file