* 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:
@ -2,11 +2,14 @@ package net.i2p.router.web;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
|
|
||||||
public class NetDbHelper {
|
public class NetDbHelper {
|
||||||
private RouterContext _context;
|
private RouterContext _context;
|
||||||
|
private Writer _out;
|
||||||
/**
|
/**
|
||||||
* Configure this bean to query a particular router context
|
* Configure this bean to query a particular router context
|
||||||
*
|
*
|
||||||
@ -23,13 +26,21 @@ public class NetDbHelper {
|
|||||||
|
|
||||||
public NetDbHelper() {}
|
public NetDbHelper() {}
|
||||||
|
|
||||||
|
public void setWriter(Writer writer) { _out = writer; }
|
||||||
|
|
||||||
public String getNetDbSummary() {
|
public String getNetDbSummary() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
|
||||||
try {
|
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) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
return new String(baos.toByteArray());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package net.i2p.router.web;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
@ -9,6 +11,7 @@ import net.i2p.router.admin.StatsGenerator;
|
|||||||
|
|
||||||
public class OldConsoleHelper {
|
public class OldConsoleHelper {
|
||||||
private RouterContext _context;
|
private RouterContext _context;
|
||||||
|
private Writer _out;
|
||||||
/**
|
/**
|
||||||
* Configure this bean to query a particular router context
|
* Configure this bean to query a particular router context
|
||||||
*
|
*
|
||||||
@ -25,11 +28,20 @@ public class OldConsoleHelper {
|
|||||||
|
|
||||||
public OldConsoleHelper() {}
|
public OldConsoleHelper() {}
|
||||||
|
|
||||||
|
public void setWriter(Writer writer) {
|
||||||
|
_out = writer;
|
||||||
|
}
|
||||||
|
|
||||||
public String getConsole() {
|
public String getConsole() {
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(128*1024);
|
if (_out != null) {
|
||||||
_context.router().renderStatusHTML(baos);
|
_context.router().renderStatusHTML(_out);
|
||||||
return baos.toString();
|
return "";
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(128*1024);
|
||||||
|
_context.router().renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
|
return baos.toString();
|
||||||
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
return "<b>Error rending the console</b>";
|
return "<b>Error rending the console</b>";
|
||||||
}
|
}
|
||||||
@ -38,9 +50,14 @@ public class OldConsoleHelper {
|
|||||||
public String getStats() {
|
public String getStats() {
|
||||||
StatsGenerator gen = new StatsGenerator(_context);
|
StatsGenerator gen = new StatsGenerator(_context);
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
if (_out != null) {
|
||||||
gen.generateStatsPage(baos);
|
gen.generateStatsPage(_out);
|
||||||
return baos.toString();
|
return "";
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
||||||
|
gen.generateStatsPage(new OutputStreamWriter(baos));
|
||||||
|
return baos.toString();
|
||||||
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
return "<b>Error rending the console</b>";
|
return "<b>Error rending the console</b>";
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.i2p.router.web;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ public class ProfilesHelper {
|
|||||||
public String getProfileSummary() {
|
public String getProfileSummary() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(16*1024);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(16*1024);
|
||||||
try {
|
try {
|
||||||
_context.profileOrganizer().renderStatusHTML(baos);
|
_context.profileOrganizer().renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -36,7 +37,7 @@ public class ProfilesHelper {
|
|||||||
public String getShitlistSummary() {
|
public String getShitlistSummary() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
|
||||||
try {
|
try {
|
||||||
_context.shitlist().renderStatusHTML(baos);
|
_context.shitlist().renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.i2p.router.web;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
@ -334,7 +335,7 @@ public class SummaryHelper {
|
|||||||
public String getDestinations() {
|
public String getDestinations() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||||
try {
|
try {
|
||||||
_context.clientManager().renderStatusHTML(baos);
|
_context.clientManager().renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
return new String(baos.toByteArray());
|
return new String(baos.toByteArray());
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_context.logManager().getLog(SummaryHelper.class).error("Error rendering client info", ioe);
|
_context.logManager().getLog(SummaryHelper.class).error("Error rendering client info", ioe);
|
||||||
@ -397,8 +398,7 @@ public class SummaryHelper {
|
|||||||
if (_context == null)
|
if (_context == null)
|
||||||
return "0ms";
|
return "0ms";
|
||||||
|
|
||||||
Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000);
|
return _context.throttle().getMessageDelay() + "ms";
|
||||||
return ((int)delayRate.getAverageValue()) + "ms";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -410,7 +410,6 @@ public class SummaryHelper {
|
|||||||
if (_context == null)
|
if (_context == null)
|
||||||
return "0ms";
|
return "0ms";
|
||||||
|
|
||||||
Rate lagRate = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
|
return _context.throttle().getTunnelLag() + "ms";
|
||||||
return ((int)lagRate.getAverageValue()) + "ms";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@
|
|||||||
<div class="main" id="main">
|
<div class="main" id="main">
|
||||||
<jsp:useBean class="net.i2p.router.web.NetDbHelper" id="netdbHelper" scope="request" />
|
<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="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||||
|
<jsp:setProperty name="netdbHelper" property="writer" value="<%=out%>" />
|
||||||
<jsp:getProperty name="netdbHelper" property="netDbSummary" />
|
<jsp:getProperty name="netdbHelper" property="netDbSummary" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="conhelper" scope="request" />
|
<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="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||||
|
<jsp:setProperty name="conhelper" property="writer" value="<%=out%>" />
|
||||||
|
|
||||||
<div class="main" id="main">
|
<div class="main" id="main">
|
||||||
<jsp:getProperty name="conhelper" property="console" />
|
<jsp:getProperty name="conhelper" property="console" />
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="oldhelper" scope="request" />
|
<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="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||||
|
<jsp:setProperty name="oldhelper" property="writer" value="<%=out%>" />
|
||||||
|
|
||||||
<div class="main" id="main">
|
<div class="main" id="main">
|
||||||
<jsp:getProperty name="oldhelper" property="stats" />
|
<jsp:getProperty name="oldhelper" property="stats" />
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
@ -70,7 +70,7 @@ public abstract class ClientManagerFacade implements Service {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract SessionConfig getClientSessionConfig(Destination dest);
|
public abstract SessionConfig getClientSessionConfig(Destination dest);
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException { }
|
public void renderStatusHTML(Writer out) throws IOException { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyClientManagerFacade extends ClientManagerFacade {
|
class DummyClientManagerFacade extends ClientManagerFacade {
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,7 +23,7 @@ import java.util.Set;
|
|||||||
public abstract class CommSystemFacade implements Service {
|
public abstract class CommSystemFacade implements Service {
|
||||||
public abstract void processMessage(OutNetMessage msg);
|
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 */
|
/** Create the set of RouterAddress structures based on the router's config */
|
||||||
public Set createAddresses() { return new HashSet(); }
|
public Set createAddresses() { return new HashSet(); }
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -558,18 +558,18 @@ public class JobQueue {
|
|||||||
// the remainder are utility methods for dumping status info
|
// 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 readyJobs = null;
|
||||||
ArrayList timedJobs = null;
|
ArrayList timedJobs = null;
|
||||||
ArrayList activeJobs = new ArrayList(1);
|
ArrayList activeJobs = new ArrayList(1);
|
||||||
ArrayList justFinishedJobs = new ArrayList(4);
|
ArrayList justFinishedJobs = new ArrayList(4);
|
||||||
out.write("<!-- jobQueue rendering -->\n".getBytes());
|
out.write("<!-- jobQueue rendering -->\n");
|
||||||
out.flush();
|
out.flush();
|
||||||
synchronized (_readyJobs) { readyJobs = new ArrayList(_readyJobs); }
|
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();
|
out.flush();
|
||||||
synchronized (_timedJobs) { timedJobs = new ArrayList(_timedJobs); }
|
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();
|
out.flush();
|
||||||
int numRunners = 0;
|
int numRunners = 0;
|
||||||
synchronized (_queueRunners) {
|
synchronized (_queueRunners) {
|
||||||
@ -586,7 +586,7 @@ public class JobQueue {
|
|||||||
numRunners = _queueRunners.size();
|
numRunners = _queueRunners.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write("<!-- jobQueue rendering: after queueRunners sync -->\n".getBytes());
|
out.write("<!-- jobQueue rendering: after queueRunners sync -->\n");
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
StringBuffer buf = new StringBuffer(32*1024);
|
StringBuffer buf = new StringBuffer(32*1024);
|
||||||
@ -631,15 +631,15 @@ public class JobQueue {
|
|||||||
}
|
}
|
||||||
buf.append("</ol>\n");
|
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();
|
out.flush();
|
||||||
|
|
||||||
getJobStats(buf);
|
getJobStats(buf);
|
||||||
|
|
||||||
out.write("<!-- jobQueue rendering: after stats -->\n".getBytes());
|
out.write("<!-- jobQueue rendering: after stats -->\n");
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** render the HTML for the job stats */
|
/** render the HTML for the job stats */
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
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 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 {}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -315,8 +315,8 @@ public class Router {
|
|||||||
_context.inNetMessagePool().registerHandlerJobBuilder(TunnelMessage.MESSAGE_TYPE, new TunnelMessageHandler(_context));
|
_context.inNetMessagePool().registerHandlerJobBuilder(TunnelMessage.MESSAGE_TYPE, new TunnelMessageHandler(_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
out.write(("<h1>Router console</h1>\n" +
|
out.write("<h1>Router console</h1>\n" +
|
||||||
"<i><a href=\"/oldconsole.jsp\">console</a> | <a href=\"/oldstats.jsp\">stats</a></i><br>\n" +
|
"<i><a href=\"/oldconsole.jsp\">console</a> | <a href=\"/oldstats.jsp\">stats</a></i><br>\n" +
|
||||||
"<form action=\"/oldconsole.jsp\">" +
|
"<form action=\"/oldconsole.jsp\">" +
|
||||||
"<select name=\"go\" onChange='location.href=this.value'>" +
|
"<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#netdb\">Network Database</option>\n" +
|
||||||
"<option value=\"/oldconsole.jsp#logs\">Log messages</option>\n" +
|
"<option value=\"/oldconsole.jsp#logs\">Log messages</option>\n" +
|
||||||
"</select> <input type=\"submit\" value=\"GO\" /> </form>" +
|
"</select> <input type=\"submit\" value=\"GO\" /> </form>" +
|
||||||
"<hr />\n").getBytes());
|
"<hr />\n");
|
||||||
|
|
||||||
StringBuffer buf = new StringBuffer(32*1024);
|
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("trying to transfer data. Lifetime averages count how many elephants there are on the moon [like anyone reads this text]</i>");
|
||||||
buf.append("\n");
|
buf.append("\n");
|
||||||
|
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
|
|
||||||
_context.bandwidthLimiter().renderStatusHTML(out);
|
_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);
|
_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);
|
_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);
|
_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);
|
_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);
|
_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);
|
_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);
|
_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);
|
_context.netDb().renderStatusHTML(out);
|
||||||
|
|
||||||
@ -500,7 +500,7 @@ public class Router {
|
|||||||
buf.append("</pre></td></tr>\n");
|
buf.append("</pre></td></tr>\n");
|
||||||
}
|
}
|
||||||
buf.append("</table>\n");
|
buf.append("</table>\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int MAX_MSG_LENGTH = 120;
|
private static int MAX_MSG_LENGTH = 120;
|
||||||
|
@ -31,4 +31,15 @@ public interface RouterThrottle {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public boolean acceptNetDbLookupRequest(Hash key);
|
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();
|
||||||
}
|
}
|
||||||
|
@ -154,5 +154,35 @@ class RouterThrottleImpl implements RouterThrottle {
|
|||||||
return true;
|
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; }
|
protected RouterContext getContext() { return _context; }
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the manageable service interface for the subsystems in the I2P router
|
* Define the manageable service interface for the subsystems in the I2P router
|
||||||
@ -37,5 +37,5 @@ public interface Service {
|
|||||||
*/
|
*/
|
||||||
public void restart();
|
public void restart();
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException;
|
public void renderStatusHTML(Writer out) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.i2p.crypto.PersistentSessionKeyManager;
|
import net.i2p.crypto.PersistentSessionKeyManager;
|
||||||
import net.i2p.crypto.SessionKeyManager;
|
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 {
|
private class SessionKeyWriterJob extends JobImpl {
|
||||||
public SessionKeyWriterJob() {
|
public SessionKeyWriterJob() {
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
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);
|
StringBuffer buf = new StringBuffer(1024);
|
||||||
buf.append("<h2>Shitlist</h2>");
|
buf.append("<h2>Shitlist</h2>");
|
||||||
Map shitlist = null;
|
Map shitlist = null;
|
||||||
@ -152,6 +152,6 @@ public class Shitlist {
|
|||||||
buf.append("</li>\n");
|
buf.append("</li>\n");
|
||||||
}
|
}
|
||||||
buf.append("</ul>\n");
|
buf.append("</ul>\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ package net.i2p.router;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.Locale;
|
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.jobLag", stats, new long[] { 60*1000, 60*60*1000 });
|
||||||
includeRate("jobQueue.jobRun", 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.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("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.readyJobs", stats, new long[] { 60*1000, 60*60*1000 });
|
||||||
//includeRate("jobQueue.droppedJobs", stats, new long[] { 60*60*1000, 24*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("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.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.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.outboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||||
includeRate("tunnel.inboundMessagesProcessed", 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.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("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.lookupsReceived", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||||
includeRate("netDb.lookupsHandled", 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.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.successPeers", stats, new long[] { 60*60*1000 });
|
||||||
includeRate("netDb.failedPeers", 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.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.throttleNetDbDoS", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||||
//includeRate("netDb.searchCount", stats, new long[] { 3*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("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("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("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("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.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||||
//includeRate("transport.sendMessageSize", 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.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||||
//includeRate("transport.sendMessageMedium", 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.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||||
//includeRate("transport.receiveMessageLarge", 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.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_uptime", DataHelper.formatDuration(_context.router().getUptime()));
|
||||||
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
|
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
|
||||||
_log.debug("Publishing peer rankings");
|
_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 num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
|
||||||
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
|
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) { }
|
public void renderStatusHTML(Writer out) { }
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.i2p.router.admin;
|
package net.i2p.router.admin;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.router.Service;
|
import net.i2p.router.Service;
|
||||||
@ -20,7 +20,7 @@ public class AdminManager implements Service {
|
|||||||
_log = context.logManager().getLog(AdminManager.class);
|
_log = context.logManager().getLog(AdminManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) { }
|
public void renderStatusHTML(Writer out) { }
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (_listener != null) {
|
if (_listener != null) {
|
||||||
|
@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -47,7 +48,7 @@ class AdminRunner implements Runnable {
|
|||||||
} else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) {
|
} else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) {
|
||||||
try {
|
try {
|
||||||
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
|
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();
|
out.close();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
@ -61,7 +62,7 @@ class AdminRunner implements Runnable {
|
|||||||
} else if (true || command.indexOf("routerConsole.html") > 0) {
|
} else if (true || command.indexOf("routerConsole.html") > 0) {
|
||||||
try {
|
try {
|
||||||
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
|
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();
|
out.close();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
@ -2,6 +2,7 @@ package net.i2p.router.admin;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.Writer;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -27,13 +28,13 @@ public class StatsGenerator {
|
|||||||
_log = context.logManager().getLog(StatsGenerator.class);
|
_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);
|
StringBuffer buf = new StringBuffer(16*1024);
|
||||||
buf.append("<h1>Router statistics</h1>");
|
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("<i><a href=\"/oldconsole.jsp\">console</a> | <a href=\"/oldstats.jsp\">stats</a></i><hr />");
|
||||||
buf.append("<form action=\"/oldstats.jsp\">");
|
buf.append("<form action=\"/oldstats.jsp\">");
|
||||||
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
|
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
|
|
||||||
Map groups = _context.statManager().getStatsByGroup();
|
Map groups = _context.statManager().getStatsByGroup();
|
||||||
@ -50,7 +51,7 @@ public class StatsGenerator {
|
|||||||
buf.append(stat);
|
buf.append(stat);
|
||||||
buf.append("</option>\n");
|
buf.append("</option>\n");
|
||||||
}
|
}
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
buf.append("</select> <input type=\"submit\" value=\"GO\" />");
|
buf.append("</select> <input type=\"submit\" value=\"GO\" />");
|
||||||
@ -61,7 +62,7 @@ public class StatsGenerator {
|
|||||||
buf.append(DataHelper.formatDuration(uptime));
|
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 />");
|
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);
|
buf.setLength(0);
|
||||||
|
|
||||||
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
||||||
@ -73,7 +74,7 @@ public class StatsGenerator {
|
|||||||
buf.append(group);
|
buf.append(group);
|
||||||
buf.append("</a></h2>");
|
buf.append("</a></h2>");
|
||||||
buf.append("<ul>");
|
buf.append("<ul>");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
||||||
String stat = (String)statIter.next();
|
String stat = (String)statIter.next();
|
||||||
@ -86,10 +87,10 @@ public class StatsGenerator {
|
|||||||
renderFrequency(stat, buf);
|
renderFrequency(stat, buf);
|
||||||
else
|
else
|
||||||
renderRate(stat, buf);
|
renderRate(stat, buf);
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
out.write("</ul><hr />".getBytes());
|
out.write("</ul><hr />");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.client;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
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);
|
StringBuffer buf = new StringBuffer(8*1024);
|
||||||
buf.append("<u><b>Local destinations</b></u><br />");
|
buf.append("<u><b>Local destinations</b></u><br />");
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.append("\n<hr />\n");
|
buf.append("\n<hr />\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void messageReceived(ClientMessage msg) {
|
public void messageReceived(ClientMessage msg) {
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.client;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
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)
|
if (_manager != null)
|
||||||
_manager.renderStatusHTML(out);
|
_manager.renderStatusHTML(out);
|
||||||
}
|
}
|
||||||
|
@ -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.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.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.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;
|
long timeoutMs = OVERALL_TIMEOUT_MS_DEFAULT;
|
||||||
|
|
||||||
String param = msg.getSenderConfig().getOptions().getProperty(OVERALL_TIMEOUT_MS_PARAM);
|
String param = msg.getSenderConfig().getOptions().getProperty(OVERALL_TIMEOUT_MS_PARAM);
|
||||||
@ -122,7 +126,7 @@ public class OutboundClientMessageJob extends JobImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_overallExpiration = timeoutMs + getContext().clock().now();
|
_overallExpiration = timeoutMs + getContext().clock().now();
|
||||||
_status = new OutboundClientMessageStatus(msg);
|
_status = new OutboundClientMessageStatus(ctx, msg);
|
||||||
_nextStep = new NextStepJob();
|
_nextStep = new NextStepJob();
|
||||||
_lookupLeaseSetFailed = new LookupLeaseSetFailedJob();
|
_lookupLeaseSetFailed = new LookupLeaseSetFailedJob();
|
||||||
_shouldBundle = getShouldBundle();
|
_shouldBundle = getShouldBundle();
|
||||||
@ -423,6 +427,7 @@ public class OutboundClientMessageJob extends JobImpl {
|
|||||||
getContext().clientManager().messageDeliveryStatusUpdate(msg.getFromDestination(), msg.getMessageId(), false);
|
getContext().clientManager().messageDeliveryStatusUpdate(msg.getFromDestination(), msg.getMessageId(), false);
|
||||||
getContext().statManager().updateFrequency("client.sendMessageFailFrequency");
|
getContext().statManager().updateFrequency("client.sendMessageFailFrequency");
|
||||||
getContext().statManager().addRateData("client.sendAttemptAverage", _status.getNumSent(), sendTime);
|
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 */
|
/** 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());
|
_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
|
* Keep an eye out for any of the delivery status message tokens that have been
|
||||||
* sent down the various tunnels to deliver this message
|
* sent down the various tunnels to deliver this message
|
||||||
@ -712,6 +597,14 @@ public class OutboundClientMessageJob extends JobImpl {
|
|||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug(OutboundClientMessageJob.this.getJobId()
|
_log.debug(OutboundClientMessageJob.this.getJobId()
|
||||||
+ ": Soft timeout through the lease " + _lease);
|
+ ": 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);
|
_lease.setNumFailure(_lease.getNumFailure()+1);
|
||||||
sendNext();
|
sendNext();
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ package net.i2p.router.networkdb.kademlia;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -810,17 +810,17 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
return routers;
|
return routers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
StringBuffer buf = new StringBuffer(10*1024);
|
StringBuffer buf = new StringBuffer(10*1024);
|
||||||
buf.append("<h2>Kademlia Network DB Contents</h2>\n");
|
buf.append("<h2>Kademlia Network DB Contents</h2>\n");
|
||||||
if (!_initialized) {
|
if (!_initialized) {
|
||||||
buf.append("<i>Not initialized</i>\n");
|
buf.append("<i>Not initialized</i>\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set leases = getLeases();
|
Set leases = getLeases();
|
||||||
buf.append("<h3>Leases</h3>\n");
|
buf.append("<h3>Leases</h3>\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
for (Iterator iter = leases.iterator(); iter.hasNext(); ) {
|
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("</i> tunnelId <i>").append(ls.getLease(i).getTunnelId().getTunnelId()).append("</i><br />\n");
|
||||||
}
|
}
|
||||||
buf.append("<hr />\n");
|
buf.append("<hr />\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash us = _context.routerHash();
|
Hash us = _context.routerHash();
|
||||||
Set routers = getRouters();
|
Set routers = getRouters();
|
||||||
out.write("<h3>Routers</h3>\n".getBytes());
|
out.write("<h3>Routers</h3>\n");
|
||||||
|
|
||||||
RouterInfo ourInfo = _context.router().getRouterInfo();
|
RouterInfo ourInfo = _context.router().getRouterInfo();
|
||||||
renderRouterInfo(buf, ourInfo, true);
|
renderRouterInfo(buf, ourInfo, true);
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
|
|
||||||
/* coreVersion to Map of routerVersion to Integer */
|
/* coreVersion to Map of routerVersion to Integer */
|
||||||
@ -860,7 +860,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
boolean isUs = key.equals(us);
|
boolean isUs = key.equals(us);
|
||||||
if (!isUs) {
|
if (!isUs) {
|
||||||
renderRouterInfo(buf, ri, false);
|
renderRouterInfo(buf, ri, false);
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
String coreVersion = ri.getOptions().getProperty("coreVersion");
|
String coreVersion = ri.getOptions().getProperty("coreVersion");
|
||||||
String routerVersion = ri.getOptions().getProperty("router.version");
|
String routerVersion = ri.getOptions().getProperty("router.version");
|
||||||
@ -895,7 +895,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
}
|
}
|
||||||
buf.append("</table>\n");
|
buf.append("</table>\n");
|
||||||
}
|
}
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) {
|
private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) {
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.peermanager;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -116,7 +116,7 @@ class PeerManager {
|
|||||||
return new ArrayList(peers);
|
return new ArrayList(peers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
_organizer.renderStatusHTML(out);
|
_organizer.renderStatusHTML(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.peermanager;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade {
|
|||||||
return _manager.selectPeers(criteria);
|
return _manager.selectPeers(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
_manager.renderStatusHTML(out);
|
_manager.renderStatusHTML(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.i2p.router.peermanager;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.Writer;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -203,7 +204,7 @@ public class ProfileOrganizer {
|
|||||||
_persistenceHelper.writeProfile(prof, out);
|
_persistenceHelper.writeProfile(prof, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
ProfileOrganizerRenderer rend = new ProfileOrganizerRenderer(this, _context);
|
ProfileOrganizerRenderer rend = new ProfileOrganizerRenderer(this, _context);
|
||||||
rend.renderStatusHTML(out);
|
rend.renderStatusHTML(out);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.i2p.router.peermanager;
|
package net.i2p.router.peermanager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
@ -27,7 +27,7 @@ class ProfileOrganizerRenderer {
|
|||||||
_context = context;
|
_context = context;
|
||||||
_organizer = organizer;
|
_organizer = organizer;
|
||||||
}
|
}
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
Set peers = _organizer.selectAllPeers();
|
Set peers = _organizer.selectAllPeers();
|
||||||
|
|
||||||
long hideBefore = _context.clock().now() - 3*60*60*1000;
|
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>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>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 />");
|
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));
|
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.i2p.router.transport;
|
package net.i2p.router.transport;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -407,7 +407,7 @@ public class FIFOBandwidthLimiter {
|
|||||||
return satisfied;
|
return satisfied;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
StringBuffer buf = new StringBuffer(4096);
|
StringBuffer buf = new StringBuffer(4096);
|
||||||
buf.append("<br /><b>Pending bandwidth requests (with ");
|
buf.append("<br /><b>Pending bandwidth requests (with ");
|
||||||
@ -436,7 +436,7 @@ public class FIFOBandwidthLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.append("</ol></li></ul>\n");
|
buf.append("</ol></li></ul>\n");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long __requestId = 0;
|
private static long __requestId = 0;
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.transport;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
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);
|
StringBuffer buf = new StringBuffer(8192);
|
||||||
buf.append("<h2>Pending messages</h2>\n");
|
buf.append("<h2>Pending messages</h2>\n");
|
||||||
Map msgs = null;
|
Map msgs = null;
|
||||||
@ -295,7 +295,7 @@ public class OutboundMessageRegistry {
|
|||||||
buf.append("</li>\n");
|
buf.append("</li>\n");
|
||||||
}
|
}
|
||||||
buf.append("</ul>");
|
buf.append("</ul>");
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ package net.i2p.router.transport;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -265,7 +265,7 @@ public class TransportManager implements TransportEventListener {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
StringBuffer buf = new StringBuffer(8*1024);
|
StringBuffer buf = new StringBuffer(8*1024);
|
||||||
buf.append("<h2>Transport Manager</h2>\n");
|
buf.append("<h2>Transport Manager</h2>\n");
|
||||||
buf.append("Listening on: <br /><pre>\n");
|
buf.append("Listening on: <br /><pre>\n");
|
||||||
@ -283,6 +283,6 @@ public class TransportManager implements TransportEventListener {
|
|||||||
if (str != null)
|
if (str != null)
|
||||||
buf.append(str);
|
buf.append(str);
|
||||||
}
|
}
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.i2p.router.tunnelmanager;
|
package net.i2p.router.tunnelmanager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -229,7 +229,7 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade {
|
|||||||
* Aint she pretty?
|
* Aint she pretty?
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
if (_pool != null)
|
if (_pool != null)
|
||||||
_pool.renderStatusHTML(out);
|
_pool.renderStatusHTML(out);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.i2p.router.tunnelmanager;
|
package net.i2p.router.tunnelmanager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.Writer;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
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.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.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.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;
|
_isLive = true;
|
||||||
_persistenceHelper = new TunnelPoolPersistenceHelper(_context);
|
_persistenceHelper = new TunnelPoolPersistenceHelper(_context);
|
||||||
_tunnelBuilder = new TunnelBuilder(_context);
|
_tunnelBuilder = new TunnelBuilder(_context);
|
||||||
@ -603,8 +604,8 @@ class TunnelPool {
|
|||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (_log.shouldLog(Log.INFO)) _log.info("Shutting down tunnel pool");
|
if (_log.shouldLog(Log.INFO)) _log.info("Shutting down tunnel pool");
|
||||||
if (_persistenceHelper != null)
|
//if (_persistenceHelper != null)
|
||||||
_persistenceHelper.writePool(this);
|
// _persistenceHelper.writePool(this);
|
||||||
_isLive = false; // the subjobs [should] check getIsLive() on each run
|
_isLive = false; // the subjobs [should] check getIsLive() on each run
|
||||||
_outboundTunnels = null;
|
_outboundTunnels = null;
|
||||||
_freeInboundTunnels = null;
|
_freeInboundTunnels = null;
|
||||||
@ -633,10 +634,17 @@ class TunnelPool {
|
|||||||
info.getSettings().getCreated());
|
info.getSettings().getCreated());
|
||||||
break;
|
break;
|
||||||
case TunnelId.TYPE_PARTICIPANT:
|
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",
|
_context.statManager().addRateData("tunnel.participatingMessagesProcessed",
|
||||||
info.getMessagesProcessed(),
|
numMsgs,
|
||||||
info.getSettings().getExpiration() -
|
info.getSettings().getExpiration() -
|
||||||
info.getSettings().getCreated());
|
info.getSettings().getCreated());
|
||||||
|
if (numMsgs > lastAvg)
|
||||||
|
_context.statManager().addRateData("tunnel.participatingMessagesProcessedActive",
|
||||||
|
numMsgs-lastAvg,
|
||||||
|
info.getSettings().getExpiration() -
|
||||||
|
info.getSettings().getCreated());
|
||||||
break;
|
break;
|
||||||
case TunnelId.TYPE_UNSPECIFIED:
|
case TunnelId.TYPE_UNSPECIFIED:
|
||||||
default:
|
default:
|
||||||
@ -651,9 +659,9 @@ class TunnelPool {
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderStatusHTML(OutputStream out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
if (!_isLive) return;
|
if (!_isLive) return;
|
||||||
out.write("<h2>Tunnel Pool</h2>\n".getBytes());
|
out.write("<h2>Tunnel Pool</h2>\n");
|
||||||
StringBuffer buf = new StringBuffer(4096);
|
StringBuffer buf = new StringBuffer(4096);
|
||||||
renderTunnels(out, buf, "Free inbound tunnels", getFreeTunnels());
|
renderTunnels(out, buf, "Free inbound tunnels", getFreeTunnels());
|
||||||
renderTunnels(out, buf, "Outbound tunnels", getOutboundTunnels());
|
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");
|
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);
|
buf.setLength(0);
|
||||||
for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) {
|
for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) {
|
||||||
TunnelId id = (TunnelId)iter.next();
|
TunnelId id = (TunnelId)iter.next();
|
||||||
TunnelInfo tunnel = getTunnelInfo(id);
|
TunnelInfo tunnel = getTunnelInfo(id);
|
||||||
renderTunnel(out, buf, id, tunnel);
|
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);
|
buf.setLength(0);
|
||||||
if (tunnel == null) {
|
if (tunnel == null) {
|
||||||
buf.append("<li>Tunnel: ").append(id.getTunnelId()).append(" is not known</li>\n");
|
buf.append("<li>Tunnel: ").append(id.getTunnelId()).append(" is not known</li>\n");
|
||||||
@ -713,7 +721,7 @@ class TunnelPool {
|
|||||||
|
|
||||||
buf.append("\n</pre>");
|
buf.append("\n</pre>");
|
||||||
}
|
}
|
||||||
out.write(buf.toString().getBytes());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user