diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
index a761a5ac24..68dfa0df60 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
@@ -81,12 +81,13 @@ public class TunnelRenderer {
int displayed = 0;
for (int i = 0; i < participating.size(); i++) {
HopConfig cfg = participating.get(i);
- long count = cfg.getProcessedMessagesCount();
+ int count = cfg.getProcessedMessagesCount();
if (count <= 0) {
inactive++;
continue;
}
- processed += count;
+ // everything that isn't 'recent' is already in the tunnel.participatingMessageCount stat
+ processed += cfg.getRecentMessagesCount();
if (++displayed > DISPLAY_LIMIT)
continue;
out.write("
");
@@ -111,13 +112,13 @@ public class TunnelRenderer {
out.write("" + DataHelper.formatDuration2(timeLeft) + " | ");
else
out.write("(" + _t("grace period") + ") | ");
- out.write("" + cfg.getProcessedMessagesCount() + " KB | ");
+ out.write("" + count + " KB | ");
int lifetime = (int) ((_context.clock().now() - cfg.getCreation()) / 1000);
if (lifetime <= 0)
lifetime = 1;
if (lifetime > 10*60)
lifetime = 10*60;
- int bps = 1024 * cfg.getProcessedMessagesCount() / lifetime;
+ int bps = 1024 * count / lifetime;
out.write("" + bps + " Bps | ");
if (cfg.getSendTo() == null)
out.write("" + _t("Outbound Endpoint") + " | ");
@@ -188,7 +189,8 @@ public class TunnelRenderer {
else
out.write("
 | ");
out.write(" " + DataHelper.formatDuration2(timeLeft) + " | \n");
- out.write(" " + info.getProcessedMessagesCount() + " KB | \n");
+ int count = info.getProcessedMessagesCount();
+ out.write(" " + count + " KB | \n");
for (int j = 0; j < info.getLength(); j++) {
Hash peer = info.getPeer(j);
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
@@ -206,9 +208,9 @@ public class TunnelRenderer {
out.write("
\n");
if (info.isInbound())
- processedIn += info.getProcessedMessagesCount();
+ processedIn += count;
else
- processedOut += info.getProcessedMessagesCount();
+ processedOut += count;
}
out.write("\n");
if (in != null) {
diff --git a/history.txt b/history.txt
index 3debcdab40..3d35346344 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,6 @@
+2015-11-13 zzz
+ * Console: Fix lifetime participating bandwidth display (ticket #1706)
+
2015-11-12 zzz
* Console /configclients:
= Fix filtering and escaping
diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java
index aafdea9fd6..9d0d0ddceb 100644
--- a/router/java/src/net/i2p/router/RouterThrottleImpl.java
+++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java
@@ -276,7 +276,7 @@ class RouterThrottleImpl implements RouterThrottle {
// ok, we're not hosed, but can we handle the bandwidth requirements
// of another tunnel?
- rs = _context.statManager().getRate("tunnel.participatingMessageCount");
+ rs = _context.statManager().getRate("tunnel.participatingMessageCountAvgPerTunnel");
r = null;
double messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE;
if (rs != null) {
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 0e04b1445c..33006bcb1f 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
- public final static long BUILD = 26;
+ public final static long BUILD = 27;
/** for example "-test" */
public final static String EXTRA = "-rc";
diff --git a/router/java/src/net/i2p/router/tunnel/HopConfig.java b/router/java/src/net/i2p/router/tunnel/HopConfig.java
index 447f6a0834..0e317cd79e 100644
--- a/router/java/src/net/i2p/router/tunnel/HopConfig.java
+++ b/router/java/src/net/i2p/router/tunnel/HopConfig.java
@@ -26,6 +26,7 @@ public class HopConfig {
// these 4 were longs, let's save some space
// 2 billion * 1KB / 10 minutes = 3 GBps in a single tunnel
+ // we use synchronization instead of an AtomicInteger here to save space
private int _messagesProcessed;
private int _oldMessagesProcessed;
//private int _messagesSent;
@@ -125,12 +126,29 @@ public class HopConfig {
/**
* Take note of a message being pumped through this tunnel.
* "processed" is for incoming and "sent" is for outgoing (could be dropped in between)
+ * We use synchronization instead of an AtomicInteger here to save space.
*/
- public void incrementProcessedMessages() { _messagesProcessed++; }
+ public synchronized void incrementProcessedMessages() { _messagesProcessed++; }
- public int getProcessedMessagesCount() { return _messagesProcessed; }
+ public synchronized int getProcessedMessagesCount() { return _messagesProcessed; }
- public int getRecentMessagesCount() {
+ /**
+ * This returns the number of processed messages since
+ * the last time getAndResetRecentMessagesCount() was called.
+ * As of 0.9.23, does NOT reset the count, see getAndResetRecentMessagesCount().
+ */
+ public synchronized int getRecentMessagesCount() {
+ return _messagesProcessed - _oldMessagesProcessed;
+ }
+
+ /**
+ * This returns the number of processed messages since the last time this was called,
+ * and resets the count. It should only be called by code that updates the router stats.
+ * See TunnelDispatcher.updateParticipatingStats().
+ *
+ * @since 0.9.23
+ */
+ synchronized int getAndResetRecentMessagesCount() {
int rv = _messagesProcessed - _oldMessagesProcessed;
_oldMessagesProcessed = _messagesProcessed;
return rv;
@@ -169,8 +187,9 @@ public class HopConfig {
}
buf.append(" exp. ").append(TunnelCreatorConfig.format(_expiration));
- if (_messagesProcessed > 0)
- buf.append(" used ").append(_messagesProcessed).append("KB");
+ int messagesProcessed = getProcessedMessagesCount();
+ if (messagesProcessed > 0)
+ buf.append(" used ").append(messagesProcessed).append("KB");
return buf.toString();
}
}
diff --git a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
index 4e945b9db1..8e4d433353 100644
--- a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
+++ b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
@@ -163,9 +163,14 @@ public class TunnelDispatcher implements Service {
ctx.statManager().createRateStat("tunnel.participatingMessageDropped",
"Dropped for exceeding share limit", "Tunnels",
new long[] { 60*1000l, 60*10*1000l });
+ // count for console
ctx.statManager().createRequiredRateStat("tunnel.participatingMessageCount",
"Number of 1KB participating messages", "Tunnels",
new long[] { 60*1000l, 60*10*1000l, 60*60*1000l });
+ // estimate for RouterThrottleImpl
+ ctx.statManager().createRequiredRateStat("tunnel.participatingMessageCountAvgPerTunnel",
+ "Estimate of participating messages per tunnel lifetime", "Tunnels",
+ new long[] { 60*1000l });
ctx.statManager().createRateStat("tunnel.ownedMessageCount",
"How many messages are sent through a tunnel we created (period == failures)?", "Tunnels",
new long[] { 60*1000l, 10*60*1000l, 60*60*1000l });
@@ -711,7 +716,7 @@ public class TunnelDispatcher implements Service {
long tooYoung = _context.clock().now() - 60*1000;
long tooOld = tooYoung - 9*60*1000;
for (HopConfig cfg : _participatingConfig.values()) {
- long c = cfg.getRecentMessagesCount();
+ long c = cfg.getAndResetRecentMessagesCount();
bw += c;
//bwOut += cfg.getRecentSentMessagesCount();
long created = cfg.getCreation();
@@ -720,9 +725,15 @@ public class TunnelDispatcher implements Service {
tcount++;
count += c;
}
+ // This is an estimate of the average number of participating messages per tunnel
+ // in a tunnel lifetime, used only by RouterThrottleImpl
+ // 10 minutes / 50 seconds = 12
if (tcount > 0)
- count = count * 30 / tcount;
- _context.statManager().addRateData("tunnel.participatingMessageCount", count, ms);
+ count = count * (10*60*1000 / ms) / tcount;
+ _context.statManager().addRateData("tunnel.participatingMessageCountAvgPerTunnel", count, ms);
+ // This is a straight count of the total participating messages, used in the router console
+ _context.statManager().addRateData("tunnel.participatingMessageCount", bw, ms);
+ // Bandwidth in bits per second
_context.statManager().addRateData("tunnel.participatingBandwidth", bw*1024/(ms/1000), ms);
// moved to FIFOBandwidthRefiller
//_context.statManager().addRateData("tunnel.participatingBandwidthOut", bwOut*1024/(ms/1000), ms);