diff --git a/router/java/src/net/i2p/router/ClientManagerFacade.java b/router/java/src/net/i2p/router/ClientManagerFacade.java
index 980e6aeea..de3b8e51c 100644
--- a/router/java/src/net/i2p/router/ClientManagerFacade.java
+++ b/router/java/src/net/i2p/router/ClientManagerFacade.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
@@ -70,7 +70,7 @@ public abstract class ClientManagerFacade implements Service {
*
*/
public abstract SessionConfig getClientSessionConfig(Destination dest);
- public void renderStatusHTML(OutputStream out) throws IOException { }
+ public void renderStatusHTML(Writer out) throws IOException { }
}
class DummyClientManagerFacade extends ClientManagerFacade {
diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java
index 5c6f42878..9a03ebcb9 100644
--- a/router/java/src/net/i2p/router/CommSystemFacade.java
+++ b/router/java/src/net/i2p/router/CommSystemFacade.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -23,7 +23,7 @@ import java.util.Set;
public abstract class CommSystemFacade implements Service {
public abstract void processMessage(OutNetMessage msg);
- public void renderStatusHTML(OutputStream out) throws IOException { }
+ public void renderStatusHTML(Writer out) throws IOException { }
/** Create the set of RouterAddress structures based on the router's config */
public Set createAddresses() { return new HashSet(); }
diff --git a/router/java/src/net/i2p/router/JobQueue.java b/router/java/src/net/i2p/router/JobQueue.java
index c714d1285..beee90f38 100644
--- a/router/java/src/net/i2p/router/JobQueue.java
+++ b/router/java/src/net/i2p/router/JobQueue.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -558,18 +558,18 @@ public class JobQueue {
// the remainder are utility methods for dumping status info
////
- public void renderStatusHTML(OutputStream out) throws IOException {
+ public void renderStatusHTML(Writer out) throws IOException {
ArrayList readyJobs = null;
ArrayList timedJobs = null;
ArrayList activeJobs = new ArrayList(1);
ArrayList justFinishedJobs = new ArrayList(4);
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
synchronized (_readyJobs) { readyJobs = new ArrayList(_readyJobs); }
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
synchronized (_timedJobs) { timedJobs = new ArrayList(_timedJobs); }
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
int numRunners = 0;
synchronized (_queueRunners) {
@@ -586,7 +586,7 @@ public class JobQueue {
numRunners = _queueRunners.size();
}
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
StringBuffer buf = new StringBuffer(32*1024);
@@ -631,15 +631,15 @@ public class JobQueue {
}
buf.append("\n");
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
getJobStats(buf);
- out.write("\n".getBytes());
+ out.write("\n");
out.flush();
- out.write(buf.toString().getBytes());
+ out.write(buf.toString());
}
/** render the HTML for the job stats */
diff --git a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java
index 371cf2677..9c6ef0a8b 100644
--- a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -95,5 +95,5 @@ class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
public Set findNearestRouters(Hash key, int maxNumRouters, Set peersToIgnore) { return new HashSet(_routers.values()); }
- public void renderStatusHTML(OutputStream out) throws IOException {}
+ public void renderStatusHTML(Writer out) throws IOException {}
}
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index d835aa176..7b6c009c3 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -12,7 +12,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
@@ -315,8 +315,8 @@ public class Router {
_context.inNetMessagePool().registerHandlerJobBuilder(TunnelMessage.MESSAGE_TYPE, new TunnelMessageHandler(_context));
}
- public void renderStatusHTML(OutputStream out) throws IOException {
- out.write(("
Router console
\n" +
+ public void renderStatusHTML(Writer out) throws IOException {
+ out.write("
Router console
\n" +
"
console | stats\n" +
"
" +
- "
\n").getBytes());
+ "
\n");
StringBuffer buf = new StringBuffer(32*1024);
@@ -453,39 +453,39 @@ public class Router {
buf.append("trying to transfer data. Lifetime averages count how many elephants there are on the moon [like anyone reads this text]");
buf.append("\n");
- out.write(buf.toString().getBytes());
+ out.write(buf.toString());
_context.bandwidthLimiter().renderStatusHTML(out);
- out.write("
\n".getBytes());
+ out.write("
\n");
_context.clientManager().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.commSystem().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.peerManager().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.tunnelManager().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.jobQueue().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.shitlist().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.messageRegistry().renderStatusHTML(out);
- out.write("\n
\n".getBytes());
+ out.write("\n
\n");
_context.netDb().renderStatusHTML(out);
@@ -500,7 +500,7 @@ public class Router {
buf.append("\n");
}
buf.append("\n");
- out.write(buf.toString().getBytes());
+ out.write(buf.toString());
}
private static int MAX_MSG_LENGTH = 120;
diff --git a/router/java/src/net/i2p/router/RouterThrottle.java b/router/java/src/net/i2p/router/RouterThrottle.java
index 45d8bf9f5..4b22394a0 100644
--- a/router/java/src/net/i2p/router/RouterThrottle.java
+++ b/router/java/src/net/i2p/router/RouterThrottle.java
@@ -31,4 +31,15 @@ public interface RouterThrottle {
*
*/
public boolean acceptNetDbLookupRequest(Hash key);
+
+ /** How backed up we are at the moment processing messages (in milliseconds) */
+ public long getMessageDelay();
+ /** How backed up our tunnels are at the moment (in milliseconds) */
+ public long getTunnelLag();
+ /**
+ * How much faster (or if negative, slower) we are receiving data as
+ * opposed to our longer term averages?
+ *
+ */
+ public double getInboundRateDelta();
}
diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java
index 05fafe993..5e8a6f556 100644
--- a/router/java/src/net/i2p/router/RouterThrottleImpl.java
+++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java
@@ -154,5 +154,35 @@ class RouterThrottleImpl implements RouterThrottle {
return true;
}
+
+ public long getMessageDelay() {
+ Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000);
+ return (long)delayRate.getAverageValue();
+ }
+
+ public long getTunnelLag() {
+ Rate lagRate = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
+ return (long)lagRate.getAverageValue();
+ }
+
+ public double getInboundRateDelta() {
+ RateStat receiveRate = _context.statManager().getRate("transport.sendMessageSize");
+ double nowBps = getBps(receiveRate.getRate(60*1000));
+ double fiveMinBps = getBps(receiveRate.getRate(5*60*1000));
+ double hourBps = getBps(receiveRate.getRate(60*60*1000));
+ double dailyBps = getBps(receiveRate.getRate(24*60*60*1000));
+
+ if (nowBps < 0) return 0;
+ if (dailyBps > 0) return nowBps - dailyBps;
+ if (hourBps > 0) return nowBps - hourBps;
+ if (fiveMinBps > 0) return nowBps - fiveMinBps;
+ return 0;
+ }
+ private double getBps(Rate rate) {
+ if (rate == null) return -1;
+ double bytes = rate.getLastTotalValue();
+ return (bytes*1000.0d)/rate.getPeriod();
+ }
+
protected RouterContext getContext() { return _context; }
}
diff --git a/router/java/src/net/i2p/router/Service.java b/router/java/src/net/i2p/router/Service.java
index 0fe2f4639..31340ebee 100644
--- a/router/java/src/net/i2p/router/Service.java
+++ b/router/java/src/net/i2p/router/Service.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
/**
* Define the manageable service interface for the subsystems in the I2P router
@@ -37,5 +37,5 @@ public interface Service {
*/
public void restart();
- public void renderStatusHTML(OutputStream out) throws IOException;
+ public void renderStatusHTML(Writer out) throws IOException;
}
diff --git a/router/java/src/net/i2p/router/SessionKeyPersistenceHelper.java b/router/java/src/net/i2p/router/SessionKeyPersistenceHelper.java
index 03de1bfd9..93a35aba5 100644
--- a/router/java/src/net/i2p/router/SessionKeyPersistenceHelper.java
+++ b/router/java/src/net/i2p/router/SessionKeyPersistenceHelper.java
@@ -4,7 +4,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import net.i2p.crypto.PersistentSessionKeyManager;
import net.i2p.crypto.SessionKeyManager;
@@ -97,7 +97,7 @@ public class SessionKeyPersistenceHelper implements Service {
}
}
- public void renderStatusHTML(OutputStream out) { }
+ public void renderStatusHTML(Writer out) { }
private class SessionKeyWriterJob extends JobImpl {
public SessionKeyWriterJob() {
diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java
index cda6b21ea..adca46ec7 100644
--- a/router/java/src/net/i2p/router/Shitlist.java
+++ b/router/java/src/net/i2p/router/Shitlist.java
@@ -9,7 +9,7 @@ package net.i2p.router;
*/
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@@ -123,7 +123,7 @@ public class Shitlist {
}
- public void renderStatusHTML(OutputStream out) throws IOException {
+ public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(1024);
buf.append("
Shitlist
");
Map shitlist = null;
@@ -152,6 +152,6 @@ public class Shitlist {
buf.append("\n");
}
buf.append("\n");
- out.write(buf.toString().getBytes());
+ out.write(buf.toString());
}
}
diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java
index bf4ed7218..e1ae63930 100644
--- a/router/java/src/net/i2p/router/StatisticsManager.java
+++ b/router/java/src/net/i2p/router/StatisticsManager.java
@@ -8,7 +8,7 @@ package net.i2p.router;
*
*/
-import java.io.OutputStream;
+import java.io.Writer;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
@@ -107,32 +107,33 @@ public class StatisticsManager implements Service {
includeRate("jobQueue.jobLag", stats, new long[] { 60*1000, 60*60*1000 });
includeRate("jobQueue.jobRun", stats, new long[] { 60*1000, 60*60*1000 });
includeRate("crypto.elGamal.encrypt", stats, new long[] { 60*1000, 60*60*1000 });
- includeRate("crypto.garlic.decryptFail", stats, new long[] { 60*60*1000, 24*60*60*1000 });
+ //includeRate("crypto.garlic.decryptFail", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("tunnel.unknownTunnelTimeLeft", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("jobQueue.readyJobs", stats, new long[] { 60*1000, 60*60*1000 });
//includeRate("jobQueue.droppedJobs", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("inNetPool.dropped", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l });
- includeRate("tunnel.outboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
- includeRate("tunnel.inboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
+ //includeRate("tunnel.outboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
+ //includeRate("tunnel.inboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("tunnel.participatingMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
- includeRate("tunnel.expiredAfterAcceptTime", stats, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
+ includeRate("tunnel.participatingMessagesProcessedActive", stats, new long[] { 10*60*1000, 60*60*1000 });
+ //includeRate("tunnel.expiredAfterAcceptTime", stats, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
includeRate("tunnel.bytesAllocatedAtAccept", stats, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
includeRate("netDb.lookupsReceived", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsHandled", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsMatched", stats, new long[] { 5*60*1000, 60*60*1000 });
- includeRate("netDb.storeSent", stats, new long[] { 5*60*1000, 60*60*1000 });
+ //includeRate("netDb.storeSent", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.successPeers", stats, new long[] { 60*60*1000 });
includeRate("netDb.failedPeers", stats, new long[] { 60*60*1000 });
- includeRate("router.throttleNetDbDoSSend", stats, new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
- includeRate("router.throttleNetDbDoS", stats, new long[] { 10*60*1000, 60*60*1000 });
+ //includeRate("router.throttleNetDbDoSSend", stats, new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
+ //includeRate("router.throttleNetDbDoS", stats, new long[] { 10*60*1000, 60*60*1000 });
//includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
//includeRate("netDb.searchMessageCount", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
//includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
//includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
- includeRate("router.throttleNetworkCause", stats, new long[] { 10*60*1000, 60*60*1000 });
- includeRate("transport.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
+ //includeRate("router.throttleNetworkCause", stats, new long[] { 10*60*1000, 60*60*1000 });
+ //includeRate("transport.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
@@ -141,6 +142,10 @@ public class StatisticsManager implements Service {
//includeRate("transport.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.receiveMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("client.sendAckTime", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
+ includeRate("client.sendsPerFailure", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
+ includeRate("client.timeoutCongestionTunnel", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
+ includeRate("client.timeoutCongestionMessage", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
+ includeRate("client.timeoutCongestionInbound", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime()));
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
_log.debug("Publishing peer rankings");
@@ -266,5 +271,5 @@ public class StatisticsManager implements Service {
private final String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
- public void renderStatusHTML(OutputStream out) { }
+ public void renderStatusHTML(Writer out) { }
}
diff --git a/router/java/src/net/i2p/router/admin/AdminManager.java b/router/java/src/net/i2p/router/admin/AdminManager.java
index 06d8de594..531b5efce 100644
--- a/router/java/src/net/i2p/router/admin/AdminManager.java
+++ b/router/java/src/net/i2p/router/admin/AdminManager.java
@@ -1,6 +1,6 @@
package net.i2p.router.admin;
-import java.io.OutputStream;
+import java.io.Writer;
import net.i2p.router.RouterContext;
import net.i2p.router.Service;
@@ -20,7 +20,7 @@ public class AdminManager implements Service {
_log = context.logManager().getLog(AdminManager.class);
}
- public void renderStatusHTML(OutputStream out) { }
+ public void renderStatusHTML(Writer out) { }
public void shutdown() {
if (_listener != null) {
diff --git a/router/java/src/net/i2p/router/admin/AdminRunner.java b/router/java/src/net/i2p/router/admin/AdminRunner.java
index d8424e70b..0ded465eb 100644
--- a/router/java/src/net/i2p/router/admin/AdminRunner.java
+++ b/router/java/src/net/i2p/router/admin/AdminRunner.java
@@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Iterator;
import java.util.Set;
@@ -47,7 +48,7 @@ class AdminRunner implements Runnable {
} else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) {
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
- _generator.generateStatsPage(out);
+ _generator.generateStatsPage(new OutputStreamWriter(out));
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
@@ -61,7 +62,7 @@ class AdminRunner implements Runnable {
} else if (true || command.indexOf("routerConsole.html") > 0) {
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
- _context.router().renderStatusHTML(out);
+ _context.router().renderStatusHTML(new OutputStreamWriter(out));
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
diff --git a/router/java/src/net/i2p/router/admin/StatsGenerator.java b/router/java/src/net/i2p/router/admin/StatsGenerator.java
index 3a84bad95..e7bdfd719 100644
--- a/router/java/src/net/i2p/router/admin/StatsGenerator.java
+++ b/router/java/src/net/i2p/router/admin/StatsGenerator.java
@@ -2,6 +2,7 @@ package net.i2p.router.admin;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.Writer;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Iterator;
@@ -27,13 +28,13 @@ public class StatsGenerator {
_log = context.logManager().getLog(StatsGenerator.class);
}
- public void generateStatsPage(OutputStream out) throws IOException {
+ public void generateStatsPage(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(16*1024);
buf.append("
Router statistics
");
buf.append("
console | stats
");
buf.append("