* updated stats:

- sendsPerFailure: how many partial sends we make when they all fail
- timeoutCongestionInbound: describes how much faster than our average speed we were receiving data when each partial send timed out (in Bps)
- timeoutCongestionMessage: our send processing time when each partial send timed out (in ms)
- timeoutCongestionTunnel: our tunnel test time when each partial send timed out (in ms)
- participatingMessagesProcessedActive: # of messages more than the (most recent) average that a tunnel we were participating in transmitted (for tunnels with more than the average)
* updated to use Writer for rendering the console, so we can do partial writes (and hopefully help debug some kooky threading bugs on kaffe)
This commit is contained in:
jrandom
2004-09-29 22:49:19 +00:00
committed by zzz
parent 24966c812f
commit 62ed6c6a58
35 changed files with 355 additions and 241 deletions

View File

@ -2,11 +2,14 @@ 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 NetDbHelper {
private RouterContext _context;
private Writer _out;
/**
* Configure this bean to query a particular router context
*
@ -23,13 +26,21 @@ public class NetDbHelper {
public NetDbHelper() {}
public void setWriter(Writer writer) { _out = writer; }
public String getNetDbSummary() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
try {
_context.netDb().renderStatusHTML(baos);
if (_out != null) {
_context.netDb().renderStatusHTML(_out);
return "";
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
_context.netDb().renderStatusHTML(new OutputStreamWriter(baos));
return new String(baos.toByteArray());
}
} catch (IOException ioe) {
ioe.printStackTrace();
return "";
}
return new String(baos.toByteArray());
}
}

View File

@ -2,6 +2,8 @@ package net.i2p.router.web;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import net.i2p.router.RouterContext;
@ -9,6 +11,7 @@ import net.i2p.router.admin.StatsGenerator;
public class OldConsoleHelper {
private RouterContext _context;
private Writer _out;
/**
* Configure this bean to query a particular router context
*
@ -25,11 +28,20 @@ public class OldConsoleHelper {
public OldConsoleHelper() {}
public void setWriter(Writer writer) {
_out = writer;
}
public String getConsole() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(128*1024);
_context.router().renderStatusHTML(baos);
return baos.toString();
if (_out != null) {
_context.router().renderStatusHTML(_out);
return "";
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream(128*1024);
_context.router().renderStatusHTML(new OutputStreamWriter(baos));
return baos.toString();
}
} catch (IOException ioe) {
return "<b>Error rending the console</b>";
}
@ -38,9 +50,14 @@ public class OldConsoleHelper {
public String getStats() {
StatsGenerator gen = new StatsGenerator(_context);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
gen.generateStatsPage(baos);
return baos.toString();
if (_out != null) {
gen.generateStatsPage(_out);
return "";
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
gen.generateStatsPage(new OutputStreamWriter(baos));
return baos.toString();
}
} catch (IOException ioe) {
return "<b>Error rending the console</b>";
}

View File

@ -2,6 +2,7 @@ package net.i2p.router.web;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import net.i2p.router.RouterContext;
@ -26,7 +27,7 @@ public class ProfilesHelper {
public String getProfileSummary() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(16*1024);
try {
_context.profileOrganizer().renderStatusHTML(baos);
_context.profileOrganizer().renderStatusHTML(new OutputStreamWriter(baos));
} catch (IOException ioe) {
ioe.printStackTrace();
}
@ -36,7 +37,7 @@ public class ProfilesHelper {
public String getShitlistSummary() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
try {
_context.shitlist().renderStatusHTML(baos);
_context.shitlist().renderStatusHTML(new OutputStreamWriter(baos));
} catch (IOException ioe) {
ioe.printStackTrace();
}

View File

@ -2,6 +2,7 @@ package net.i2p.router.web;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import net.i2p.data.DataHelper;
@ -334,7 +335,7 @@ public class SummaryHelper {
public String getDestinations() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
_context.clientManager().renderStatusHTML(baos);
_context.clientManager().renderStatusHTML(new OutputStreamWriter(baos));
return new String(baos.toByteArray());
} catch (IOException ioe) {
_context.logManager().getLog(SummaryHelper.class).error("Error rendering client info", ioe);
@ -397,8 +398,7 @@ public class SummaryHelper {
if (_context == null)
return "0ms";
Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000);
return ((int)delayRate.getAverageValue()) + "ms";
return _context.throttle().getMessageDelay() + "ms";
}
/**
@ -410,7 +410,6 @@ public class SummaryHelper {
if (_context == null)
return "0ms";
Rate lagRate = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
return ((int)lagRate.getAverageValue()) + "ms";
return _context.throttle().getTunnelLag() + "ms";
}
}

View File

@ -13,6 +13,7 @@
<div class="main" id="main">
<jsp:useBean class="net.i2p.router.web.NetDbHelper" id="netdbHelper" scope="request" />
<jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="netdbHelper" property="writer" value="<%=out%>" />
<jsp:getProperty name="netdbHelper" property="netDbSummary" />
</div>

View File

@ -12,6 +12,7 @@
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="conhelper" scope="request" />
<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="conhelper" property="writer" value="<%=out%>" />
<div class="main" id="main">
<jsp:getProperty name="conhelper" property="console" />

View File

@ -12,6 +12,7 @@
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="oldhelper" scope="request" />
<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="oldhelper" property="writer" value="<%=out%>" />
<div class="main" id="main">
<jsp:getProperty name="oldhelper" property="stats" />

View File

@ -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 {

View File

@ -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(); }

View File

@ -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("<!-- jobQueue rendering -->\n".getBytes());
out.write("<!-- jobQueue rendering -->\n");
out.flush();
synchronized (_readyJobs) { readyJobs = new ArrayList(_readyJobs); }
out.write("<!-- jobQueue rendering: after readyJobs sync -->\n".getBytes());
out.write("<!-- jobQueue rendering: after readyJobs sync -->\n");
out.flush();
synchronized (_timedJobs) { timedJobs = new ArrayList(_timedJobs); }
out.write("<!-- jobQueue rendering: after timedJobs sync -->\n".getBytes());
out.write("<!-- jobQueue rendering: after timedJobs sync -->\n");
out.flush();
int numRunners = 0;
synchronized (_queueRunners) {
@ -586,7 +586,7 @@ public class JobQueue {
numRunners = _queueRunners.size();
}
out.write("<!-- jobQueue rendering: after queueRunners sync -->\n".getBytes());
out.write("<!-- jobQueue rendering: after queueRunners sync -->\n");
out.flush();
StringBuffer buf = new StringBuffer(32*1024);
@ -631,15 +631,15 @@ public class JobQueue {
}
buf.append("</ol>\n");
out.write("<!-- jobQueue rendering: after main buffer, before stats -->\n".getBytes());
out.write("<!-- jobQueue rendering: after main buffer, before stats -->\n");
out.flush();
getJobStats(buf);
out.write("<!-- jobQueue rendering: after stats -->\n".getBytes());
out.write("<!-- jobQueue rendering: after stats -->\n");
out.flush();
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
/** render the HTML for the job stats */

View File

@ -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 {}
}

View File

@ -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(("<h1>Router console</h1>\n" +
public void renderStatusHTML(Writer out) throws IOException {
out.write("<h1>Router console</h1>\n" +
"<i><a href=\"/oldconsole.jsp\">console</a> | <a href=\"/oldstats.jsp\">stats</a></i><br>\n" +
"<form action=\"/oldconsole.jsp\">" +
"<select name=\"go\" onChange='location.href=this.value'>" +
@ -331,7 +331,7 @@ public class Router {
"<option value=\"/oldconsole.jsp#netdb\">Network Database</option>\n" +
"<option value=\"/oldconsole.jsp#logs\">Log messages</option>\n" +
"</select> <input type=\"submit\" value=\"GO\" /> </form>" +
"<hr />\n").getBytes());
"<hr />\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]</i>");
buf.append("\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
_context.bandwidthLimiter().renderStatusHTML(out);
out.write("<hr /><a name=\"clients\"> </a>\n".getBytes());
out.write("<hr /><a name=\"clients\"> </a>\n");
_context.clientManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"transports\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"transports\"> </a>\n");
_context.commSystem().renderStatusHTML(out);
out.write("\n<hr /><a name=\"profiles\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"profiles\"> </a>\n");
_context.peerManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"tunnels\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"tunnels\"> </a>\n");
_context.tunnelManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"jobs\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"jobs\"> </a>\n");
_context.jobQueue().renderStatusHTML(out);
out.write("\n<hr /><a name=\"shitlist\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"shitlist\"> </a>\n");
_context.shitlist().renderStatusHTML(out);
out.write("\n<hr /><a name=\"pending\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"pending\"> </a>\n");
_context.messageRegistry().renderStatusHTML(out);
out.write("\n<hr /><a name=\"netdb\"> </a>\n".getBytes());
out.write("\n<hr /><a name=\"netdb\"> </a>\n");
_context.netDb().renderStatusHTML(out);
@ -500,7 +500,7 @@ public class Router {
buf.append("</pre></td></tr>\n");
}
buf.append("</table>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
private static int MAX_MSG_LENGTH = 120;

View File

@ -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();
}

View File

@ -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; }
}

View File

@ -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;
}

View File

@ -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() {

View File

@ -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("<h2>Shitlist</h2>");
Map shitlist = null;
@ -152,6 +152,6 @@ public class Shitlist {
buf.append("</li>\n");
}
buf.append("</ul>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
}

View File

@ -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) { }
}

View File

@ -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) {

View File

@ -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))

View File

@ -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("<h1>Router statistics</h1>");
buf.append("<i><a href=\"/oldconsole.jsp\">console</a> | <a href=\"/oldstats.jsp\">stats</a></i><hr />");
buf.append("<form action=\"/oldstats.jsp\">");
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
Map groups = _context.statManager().getStatsByGroup();
@ -50,7 +51,7 @@ public class StatsGenerator {
buf.append(stat);
buf.append("</option>\n");
}
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
}
buf.append("</select> <input type=\"submit\" value=\"GO\" />");
@ -61,7 +62,7 @@ public class StatsGenerator {
buf.append(DataHelper.formatDuration(uptime));
buf.append("). The data gathered is quantized over a 1 minute period, so should just be used as an estimate<p />");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
@ -73,7 +74,7 @@ public class StatsGenerator {
buf.append(group);
buf.append("</a></h2>");
buf.append("<ul>");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
String stat = (String)statIter.next();
@ -86,10 +87,10 @@ public class StatsGenerator {
renderFrequency(stat, buf);
else
renderRate(stat, buf);
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
}
out.write("</ul><hr />".getBytes());
out.write("</ul><hr />");
}
}

View File

@ -9,7 +9,7 @@ package net.i2p.router.client;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -332,7 +332,7 @@ public class ClientManager {
}
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(8*1024);
buf.append("<u><b>Local destinations</b></u><br />");
@ -376,7 +376,7 @@ public class ClientManager {
}
buf.append("\n<hr />\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
public void messageReceived(ClientMessage msg) {

View File

@ -9,7 +9,7 @@ package net.i2p.router.client;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
@ -158,7 +158,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade {
}
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
if (_manager != null)
_manager.renderStatusHTML(out);
}

View File

@ -104,7 +104,11 @@ public class OutboundClientMessageJob extends JobImpl {
ctx.statManager().createRateStat("client.sendMessageSize", "How large are messages sent by the client?", "Client Messages", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.sendAttemptAverage", "How many different tunnels do we have to try when sending a client message?", "Client Messages", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.sendAckTime", "How long does it take to get an ACK back from a message?", "Client Messages", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.sendsPerFailure", "How many send attempts do we make when they all fail?", "Client Messages", new long[] { 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.timeoutCongestionTunnel", "How lagged our tunnels are when a send times out?", "Client Messages", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.timeoutCongestionMessage", "How fast we process messages locally when a send times out?", "Client Messages", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("client.timeoutCongestionInbound", "How much faster we are receiving data than our average bps when a send times out?", "Client Messages", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
long timeoutMs = OVERALL_TIMEOUT_MS_DEFAULT;
String param = msg.getSenderConfig().getOptions().getProperty(OVERALL_TIMEOUT_MS_PARAM);
@ -122,7 +126,7 @@ public class OutboundClientMessageJob extends JobImpl {
}
_overallExpiration = timeoutMs + getContext().clock().now();
_status = new OutboundClientMessageStatus(msg);
_status = new OutboundClientMessageStatus(ctx, msg);
_nextStep = new NextStepJob();
_lookupLeaseSetFailed = new LookupLeaseSetFailedJob();
_shouldBundle = getShouldBundle();
@ -423,6 +427,7 @@ public class OutboundClientMessageJob extends JobImpl {
getContext().clientManager().messageDeliveryStatusUpdate(msg.getFromDestination(), msg.getMessageId(), false);
getContext().statManager().updateFrequency("client.sendMessageFailFrequency");
getContext().statManager().addRateData("client.sendAttemptAverage", _status.getNumSent(), sendTime);
getContext().statManager().addRateData("client.sendsPerFailure", _status.getNumSent(), sendTime);
}
/** build the payload clove that will be used for all of the messages, placing the clove in the status structure */
@ -455,126 +460,6 @@ public class OutboundClientMessageJob extends JobImpl {
_log.debug(getJobId() + ": Built payload clove with id " + clove.getId());
}
/**
* Good ol' fashioned struct with the send status
*
*/
private class OutboundClientMessageStatus {
private ClientMessage _msg;
private PayloadGarlicConfig _clove;
private LeaseSet _leaseSet;
private Set _sent;
private int _numLookups;
private boolean _success;
private boolean _failure;
private long _start;
private int _previousSent;
public OutboundClientMessageStatus(ClientMessage msg) {
_msg = msg;
_clove = null;
_leaseSet = null;
_sent = new HashSet(4);
_success = false;
_failure = false;
_numLookups = 0;
_previousSent = 0;
_start = getContext().clock().now();
}
/** raw payload */
public Payload getPayload() { return _msg.getPayload(); }
/** clove, if we've built it */
public PayloadGarlicConfig getClove() { return _clove; }
public void setClove(PayloadGarlicConfig clove) { _clove = clove; }
public ClientMessage getMessage() { return _msg; }
/** date we started the process on */
public long getStart() { return _start; }
public int getNumLookups() { return _numLookups; }
public void incrementLookups() { _numLookups++; }
public void clearAlreadySent() {
synchronized (_sent) {
_previousSent += _sent.size();
_sent.clear();
}
}
/** who sent the message? */
public Destination getFrom() { return _msg.getFromDestination(); }
/** who is the message going to? */
public Destination getTo() { return _msg.getDestination(); }
/** what is the target's current leaseSet (or null if we don't know yet) */
public LeaseSet getLeaseSet() { return _leaseSet; }
public void setLeaseSet(LeaseSet ls) { _leaseSet = ls; }
/** have we already sent the message down this tunnel? */
public boolean alreadySent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
return _sent.contains(t);
}
}
public void sent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
_sent.add(t);
}
}
/** how many messages have we sent through various leases? */
public int getNumSent() {
synchronized (_sent) {
return _sent.size() + _previousSent;
}
}
/** did we totally fail? */
public boolean getFailure() { return _failure; }
/** we failed. returns true if we had already failed before */
public boolean failed() {
boolean already = _failure;
_failure = true;
return already;
}
/** have we totally succeeded? */
public boolean getSuccess() { return _success; }
/** we succeeded. returns true if we had already succeeded before */
public boolean success() {
boolean already = _success;
_success = true;
return already;
}
/** represent a unique tunnel at any given time */
private class Tunnel {
private Hash _gateway;
private TunnelId _tunnel;
public Tunnel(Hash tunnelGateway, TunnelId tunnel) {
_gateway = tunnelGateway;
_tunnel = tunnel;
}
public Hash getGateway() { return _gateway; }
public TunnelId getTunnel() { return _tunnel; }
public int hashCode() {
int rv = 0;
if (_gateway != null)
rv += _gateway.hashCode();
if (_tunnel != null)
rv += 7*_tunnel.getTunnelId();
return rv;
}
public boolean equals(Object o) {
if (o == null) return false;
if (o.getClass() != Tunnel.class) return false;
Tunnel t = (Tunnel)o;
return (getTunnel() == t.getTunnel()) &&
getGateway().equals(t.getGateway());
}
}
}
/**
* Keep an eye out for any of the delivery status message tokens that have been
* sent down the various tunnels to deliver this message
@ -712,6 +597,14 @@ public class OutboundClientMessageJob extends JobImpl {
if (_log.shouldLog(Log.DEBUG))
_log.debug(OutboundClientMessageJob.this.getJobId()
+ ": Soft timeout through the lease " + _lease);
long messageDelay = getContext().throttle().getMessageDelay();
long tunnelLag = getContext().throttle().getTunnelLag();
long inboundDelta = (long)getContext().throttle().getInboundRateDelta();
getContext().statManager().addRateData("client.timeoutCongestionTunnel", tunnelLag, 1);
getContext().statManager().addRateData("client.timeoutCongestionMessage", messageDelay, 1);
getContext().statManager().addRateData("client.timeoutCongestionInbound", inboundDelta, 1);
_lease.setNumFailure(_lease.getNumFailure()+1);
sendNext();
}

View File

@ -0,0 +1,133 @@
package net.i2p.router.message;
import java.util.HashSet;
import java.util.Set;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.data.Payload;
import net.i2p.data.TunnelId;
import net.i2p.router.ClientMessage;
import net.i2p.router.RouterContext;
/**
* Good ol' fashioned struct with the send status
*
*/
class OutboundClientMessageStatus {
private RouterContext _context;
private ClientMessage _msg;
private PayloadGarlicConfig _clove;
private LeaseSet _leaseSet;
private Set _sent;
private int _numLookups;
private boolean _success;
private boolean _failure;
private long _start;
private int _previousSent;
public OutboundClientMessageStatus(RouterContext ctx, ClientMessage msg) {
_context = ctx;
_msg = msg;
_clove = null;
_leaseSet = null;
_sent = new HashSet(4);
_success = false;
_failure = false;
_numLookups = 0;
_previousSent = 0;
_start = ctx.clock().now();
}
/** raw payload */
public Payload getPayload() { return _msg.getPayload(); }
/** clove, if we've built it */
public PayloadGarlicConfig getClove() { return _clove; }
public void setClove(PayloadGarlicConfig clove) { _clove = clove; }
public ClientMessage getMessage() { return _msg; }
/** date we started the process on */
public long getStart() { return _start; }
public int getNumLookups() { return _numLookups; }
public void incrementLookups() { _numLookups++; }
public void clearAlreadySent() {
synchronized (_sent) {
_previousSent += _sent.size();
_sent.clear();
}
}
/** who sent the message? */
public Destination getFrom() { return _msg.getFromDestination(); }
/** who is the message going to? */
public Destination getTo() { return _msg.getDestination(); }
/** what is the target's current leaseSet (or null if we don't know yet) */
public LeaseSet getLeaseSet() { return _leaseSet; }
public void setLeaseSet(LeaseSet ls) { _leaseSet = ls; }
/** have we already sent the message down this tunnel? */
public boolean alreadySent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
return _sent.contains(t);
}
}
public void sent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
_sent.add(t);
}
}
/** how many messages have we sent through various leases? */
public int getNumSent() {
synchronized (_sent) {
return _sent.size() + _previousSent;
}
}
/** did we totally fail? */
public boolean getFailure() { return _failure; }
/** we failed. returns true if we had already failed before */
public boolean failed() {
boolean already = _failure;
_failure = true;
return already;
}
/** have we totally succeeded? */
public boolean getSuccess() { return _success; }
/** we succeeded. returns true if we had already succeeded before */
public boolean success() {
boolean already = _success;
_success = true;
return already;
}
/** represent a unique tunnel at any given time */
private class Tunnel {
private Hash _gateway;
private TunnelId _tunnel;
public Tunnel(Hash tunnelGateway, TunnelId tunnel) {
_gateway = tunnelGateway;
_tunnel = tunnel;
}
public Hash getGateway() { return _gateway; }
public TunnelId getTunnel() { return _tunnel; }
public int hashCode() {
int rv = 0;
if (_gateway != null)
rv += _gateway.hashCode();
if (_tunnel != null)
rv += 7*_tunnel.getTunnelId();
return rv;
}
public boolean equals(Object o) {
if (o == null) return false;
if (o.getClass() != Tunnel.class) return false;
Tunnel t = (Tunnel)o;
return (getTunnel() == t.getTunnel()) &&
getGateway().equals(t.getGateway());
}
}
}

View File

@ -11,7 +11,7 @@ package net.i2p.router.networkdb.kademlia;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@ -810,17 +810,17 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
return routers;
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(10*1024);
buf.append("<h2>Kademlia Network DB Contents</h2>\n");
if (!_initialized) {
buf.append("<i>Not initialized</i>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
return;
}
Set leases = getLeases();
buf.append("<h3>Leases</h3>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
long now = _context.clock().now();
for (Iterator iter = leases.iterator(); iter.hasNext(); ) {
@ -838,17 +838,17 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
buf.append("</i> tunnelId <i>").append(ls.getLease(i).getTunnelId().getTunnelId()).append("</i><br />\n");
}
buf.append("<hr />\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
}
Hash us = _context.routerHash();
Set routers = getRouters();
out.write("<h3>Routers</h3>\n".getBytes());
out.write("<h3>Routers</h3>\n");
RouterInfo ourInfo = _context.router().getRouterInfo();
renderRouterInfo(buf, ourInfo, true);
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
/* coreVersion to Map of routerVersion to Integer */
@ -860,7 +860,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
boolean isUs = key.equals(us);
if (!isUs) {
renderRouterInfo(buf, ri, false);
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
String coreVersion = ri.getOptions().getProperty("coreVersion");
String routerVersion = ri.getOptions().getProperty("router.version");
@ -895,7 +895,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
}
buf.append("</table>\n");
}
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) {

View File

@ -9,7 +9,7 @@ package net.i2p.router.peermanager;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
@ -116,7 +116,7 @@ class PeerManager {
return new ArrayList(peers);
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
_organizer.renderStatusHTML(out);
}
}

View File

@ -9,7 +9,7 @@ package net.i2p.router.peermanager;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
@ -59,7 +59,7 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade {
return _manager.selectPeers(criteria);
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
_manager.renderStatusHTML(out);
}
}

View File

@ -2,6 +2,7 @@ package net.i2p.router.peermanager;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
@ -203,7 +204,7 @@ public class ProfileOrganizer {
_persistenceHelper.writeProfile(prof, out);
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
ProfileOrganizerRenderer rend = new ProfileOrganizerRenderer(this, _context);
rend.renderStatusHTML(out);
}

View File

@ -1,7 +1,7 @@
package net.i2p.router.peermanager;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@ -27,7 +27,7 @@ class ProfileOrganizerRenderer {
_context = context;
_organizer = organizer;
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
Set peers = _organizer.selectAllPeers();
long hideBefore = _context.clock().now() - 3*60*60*1000;
@ -126,7 +126,7 @@ class ProfileOrganizerRenderer {
buf.append("<b>Speed:</b> ").append(num(_organizer.getSpeedThreshold())).append(" (").append(fast).append(" fast peers)<br />");
buf.append("<b>Capacity:</b> ").append(num(_organizer.getCapacityThreshold())).append(" (").append(reliable).append(" high capacity peers)<br />");
buf.append("<b>Integration:</b> ").append(num(_organizer.getIntegrationThreshold())).append(" (").append(integrated).append(" well integrated peers)<br />");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));

View File

@ -1,7 +1,7 @@
package net.i2p.router.transport;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
@ -407,7 +407,7 @@ public class FIFOBandwidthLimiter {
return satisfied;
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
long now = _context.clock().now();
StringBuffer buf = new StringBuffer(4096);
buf.append("<br /><b>Pending bandwidth requests (with ");
@ -436,7 +436,7 @@ public class FIFOBandwidthLimiter {
}
}
buf.append("</ol></li></ul>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
private static long __requestId = 0;

View File

@ -9,7 +9,7 @@ package net.i2p.router.transport;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
@ -275,7 +275,7 @@ public class OutboundMessageRegistry {
}
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(8192);
buf.append("<h2>Pending messages</h2>\n");
Map msgs = null;
@ -295,7 +295,7 @@ public class OutboundMessageRegistry {
buf.append("</li>\n");
}
buf.append("</ul>");
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
/**

View File

@ -9,7 +9,7 @@ package net.i2p.router.transport;
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@ -265,7 +265,7 @@ public class TransportManager implements TransportEventListener {
return rv;
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(8*1024);
buf.append("<h2>Transport Manager</h2>\n");
buf.append("Listening on: <br /><pre>\n");
@ -283,6 +283,6 @@ public class TransportManager implements TransportEventListener {
if (str != null)
buf.append(str);
}
out.write(buf.toString().getBytes());
out.write(buf.toString());
}
}

View File

@ -1,7 +1,7 @@
package net.i2p.router.tunnelmanager;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@ -229,7 +229,7 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade {
* Aint she pretty?
*
*/
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
if (_pool != null)
_pool.renderStatusHTML(out);
}

View File

@ -1,7 +1,7 @@
package net.i2p.router.tunnelmanager;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -66,7 +66,8 @@ class TunnelPool {
_context.statManager().createRateStat("tunnel.inboundMessagesProcessed", "How many messages does an inbound tunnel process in its lifetime?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
_context.statManager().createRateStat("tunnel.outboundMessagesProcessed", "How many messages does an inbound tunnel process in its lifetime?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
_context.statManager().createRateStat("tunnel.participatingMessagesProcessed", "How many messages does an inbound tunnel process in its lifetime?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
_context.statManager().createRateStat("tunnel.participatingMessagesProcessedActive", "How many messages beyond the average were processed in a more-than-average tunnel's lifetime?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
_isLive = true;
_persistenceHelper = new TunnelPoolPersistenceHelper(_context);
_tunnelBuilder = new TunnelBuilder(_context);
@ -603,8 +604,8 @@ class TunnelPool {
public void shutdown() {
if (_log.shouldLog(Log.INFO)) _log.info("Shutting down tunnel pool");
if (_persistenceHelper != null)
_persistenceHelper.writePool(this);
//if (_persistenceHelper != null)
// _persistenceHelper.writePool(this);
_isLive = false; // the subjobs [should] check getIsLive() on each run
_outboundTunnels = null;
_freeInboundTunnels = null;
@ -633,10 +634,17 @@ class TunnelPool {
info.getSettings().getCreated());
break;
case TunnelId.TYPE_PARTICIPANT:
long numMsgs = info.getMessagesProcessed();
long lastAvg = (long)_context.statManager().getRate("tunnel.participatingMessagesProcessed").getRate(10*60*1000l).getAverageValue();
_context.statManager().addRateData("tunnel.participatingMessagesProcessed",
info.getMessagesProcessed(),
numMsgs,
info.getSettings().getExpiration() -
info.getSettings().getCreated());
if (numMsgs > lastAvg)
_context.statManager().addRateData("tunnel.participatingMessagesProcessedActive",
numMsgs-lastAvg,
info.getSettings().getExpiration() -
info.getSettings().getCreated());
break;
case TunnelId.TYPE_UNSPECIFIED:
default:
@ -651,9 +659,9 @@ class TunnelPool {
return settings;
}
public void renderStatusHTML(OutputStream out) throws IOException {
public void renderStatusHTML(Writer out) throws IOException {
if (!_isLive) return;
out.write("<h2>Tunnel Pool</h2>\n".getBytes());
out.write("<h2>Tunnel Pool</h2>\n");
StringBuffer buf = new StringBuffer(4096);
renderTunnels(out, buf, "Free inbound tunnels", getFreeTunnels());
renderTunnels(out, buf, "Outbound tunnels", getOutboundTunnels());
@ -665,19 +673,19 @@ class TunnelPool {
}
}
private void renderTunnels(OutputStream out, StringBuffer buf, String msg, Set tunnelIds) throws IOException {
private void renderTunnels(Writer out, StringBuffer buf, String msg, Set tunnelIds) throws IOException {
buf.append("<b>").append(msg).append(":</b> <i>(").append(tunnelIds.size()).append(" tunnels)</i><ul>\n");
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next();
TunnelInfo tunnel = getTunnelInfo(id);
renderTunnel(out, buf, id, tunnel);
}
out.write("</ul>\n".getBytes());
out.write("</ul>\n");
}
private final void renderTunnel(OutputStream out, StringBuffer buf, TunnelId id, TunnelInfo tunnel) throws IOException {
private final void renderTunnel(Writer out, StringBuffer buf, TunnelId id, TunnelInfo tunnel) throws IOException {
buf.setLength(0);
if (tunnel == null) {
buf.append("<li>Tunnel: ").append(id.getTunnelId()).append(" is not known</li>\n");
@ -713,7 +721,7 @@ class TunnelPool {
buf.append("\n</pre>");
}
out.write(buf.toString().getBytes());
out.write(buf.toString());
buf.setLength(0);
}