diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java index 2e2bb9fbe..3260a2119 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java @@ -55,6 +55,12 @@ public class GraphHelper { public String getImages() { try { + _out.write("\n"); + List listeners = StatSummarizer.instance().getListeners(); for (int i = 0; i < listeners.size(); i++) { SummaryListener lsnr = (SummaryListener)listeners.get(i); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java index 07fa08fc1..9c0e1c794 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -5,18 +5,27 @@ import java.util.*; import net.i2p.stat.*; import net.i2p.router.*; +import net.i2p.util.Log; + +import java.awt.Color; +import org.jrobin.graph.RrdGraph; +import org.jrobin.graph.RrdGraphDef; +import org.jrobin.graph.RrdGraphDefTemplate; +import org.jrobin.core.RrdException; /** * */ public class StatSummarizer implements Runnable { private RouterContext _context; + private Log _log; /** list of SummaryListener instances */ private List _listeners; private static StatSummarizer _instance; public StatSummarizer() { _context = (RouterContext)RouterContext.listContexts().get(0); // fuck it, only summarize one per jvm + _log = _context.logManager().getLog(getClass()); _listeners = new ArrayList(16); _instance = this; } @@ -128,6 +137,69 @@ public class StatSummarizer implements Runnable { return false; } + public boolean renderRatePng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException { + long end = _context.clock().now(); + if (periodCount <= 0) periodCount = SummaryListener.PERIODS; + if (periodCount > SummaryListener.PERIODS) + periodCount = SummaryListener.PERIODS; + long period = 60*1000; + long start = end - period*periodCount; + long begin = System.currentTimeMillis(); + try { + RrdGraphDef def = new RrdGraphDef(); + def.setTimePeriod(start/1000, end/1000); + String title = "Bandwidth usage"; + if (!hideTitle) + def.setTitle(title); + String sendName = SummaryListener.createName(_context, "bw.sendRate.60000"); + String recvName = SummaryListener.createName(_context, "bw.recvRate.60000"); + def.datasource(sendName, sendName, sendName, "AVERAGE", "MEMORY"); + def.datasource(recvName, recvName, recvName, "AVERAGE", "MEMORY"); + def.area(sendName, Color.BLUE, "Outbound bytes/second"); + //def.line(sendName, Color.BLUE, "Outbound bytes/second", 3); + //def.line(recvName, Color.RED, "Inbound bytes/second@r", 3); + def.area(recvName, Color.RED, "Inbound bytes/second@r"); + if (!hideLegend) { + def.gprint(sendName, "AVERAGE", "outbound average: @2@sbytes/second"); + def.gprint(sendName, "MAX", " max: @2@sbytes/second@r"); + def.gprint(recvName, "AVERAGE", "inbound average: @2bytes/second@s"); + def.gprint(recvName, "MAX", " max: @2@sbytes/second@r"); + } + if (!showCredit) + def.setShowSignature(false); + if (hideLegend) + def.setShowLegend(false); + if (hideGrid) { + def.setGridX(false); + def.setGridY(false); + } + //System.out.println("rendering: path=" + path + " dsNames[0]=" + dsNames[0] + " dsNames[1]=" + dsNames[1] + " lsnr.getName=" + _listener.getName()); + def.setAntiAliasing(false); + //System.out.println("Rendering: \n" + def.exportXmlTemplate()); + //System.out.println("*****************\nData: \n" + _listener.getData().dump()); + RrdGraph graph = new RrdGraph(def); + //System.out.println("Graph created"); + byte data[] = null; + if ( (width <= 0) || (height <= 0) ) + data = graph.getPNGBytes(); + else + data = graph.getPNGBytes(width, height); + long timeToPlot = System.currentTimeMillis() - begin; + out.write(data); + //File t = File.createTempFile("jrobinData", ".xml"); + //_listener.getData().dumpXml(new FileOutputStream(t)); + //System.out.println("plotted: " + (data != null ? data.length : 0) + " bytes in " + timeToPlot + // ); // + ", data written to " + t.getAbsolutePath()); + return true; + } catch (RrdException re) { + _log.error("Error rendering", re); + throw new IOException("Error plotting: " + re.getMessage()); + } catch (IOException ioe) { + _log.error("Error rendering", ioe); + throw ioe; + } + } + /** * @param specs statName.period,statName.period,statName.period * @return list of Rate objects diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java index 8cbc73f57..546968ea3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java @@ -78,7 +78,7 @@ class SummaryListener implements RateSummaryListener { * munged version from the user/developer-visible name. * */ - private static String createName(I2PAppContext ctx, String wanted) { + static String createName(I2PAppContext ctx, String wanted) { return ctx.sha().calculateHash(DataHelper.getUTF8(wanted)).toBase64().substring(0,20); } diff --git a/apps/routerconsole/jsp/viewstat.jsp b/apps/routerconsole/jsp/viewstat.jsp index 0c29f6560..1847f3731 100644 --- a/apps/routerconsole/jsp/viewstat.jsp +++ b/apps/routerconsole/jsp/viewstat.jsp @@ -9,18 +9,25 @@ if (templateFile != null) { net.i2p.stat.Rate rate = null; String stat = request.getParameter("stat"); String period = request.getParameter("period"); +boolean fakeBw = (stat != null && ("bw.combined".equals(stat))); net.i2p.stat.RateStat rs = net.i2p.I2PAppContext.getGlobalContext().statManager().getRate(stat); -if ( !rendered && (rs != null)) { +if ( !rendered && ((rs != null) || fakeBw) ) { long per = -1; try { - per = Long.parseLong(period); - rate = rs.getRate(per); - if (rate != null) { + if (fakeBw) + per = 60*1000; + else + per = Long.parseLong(period); + if (!fakeBw) + rate = rs.getRate(per); + if ( (rate != null) || (fakeBw) ) { java.io.OutputStream cout = response.getOutputStream(); String format = request.getParameter("format"); if ("xml".equals(format)) { - response.setContentType("text/xml"); - rendered = net.i2p.router.web.StatSummarizer.instance().getXML(rate, cout); + if (!fakeBw) { + response.setContentType("text/xml"); + rendered = net.i2p.router.web.StatSummarizer.instance().getXML(rate, cout); + } } else { response.setContentType("image/png"); int width = -1; @@ -39,7 +46,10 @@ if ( !rendered && (rs != null)) { boolean showCredit = true; if (request.getParameter("showCredit") != null) showCredit = Boolean.valueOf(""+request.getParameter("showCredit")).booleanValue(); - rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); + if (fakeBw) + rendered = net.i2p.router.web.StatSummarizer.instance().renderRatePng(cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); + else + rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); } if (rendered) cout.close(); diff --git a/history.txt b/history.txt index e6aa5b3eb..1e890b2aa 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,10 @@ -$Id: history.txt,v 1.449 2006/04/08 01:15:45 jrandom Exp $ +$Id: history.txt,v 1.450 2006/04/08 20:14:09 jrandom Exp $ + +2006-04-10 jrandom + * Include a combined send/receive graph (good idea cervantes!) + * Proactively drop inbound tunnel requests probabalistically as the + estimated queue time approaches our limit, rather than letting them all + through up to that limit. 2006-04-08 jrandom * Stat summarization fix (removing the occational holes in the jrobin diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 48b05de78..235bed417 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.389 $ $Date: 2006/04/08 01:15:46 $"; + public final static String ID = "$Revision: 1.390 $ $Date: 2006/04/08 20:14:10 $"; public final static String VERSION = "0.6.1.14"; - public final static long BUILD = 4; + public final static long BUILD = 5; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index 2ce132fae..0625054ef 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -603,7 +603,10 @@ class BuildHandler { _context.statManager().addRateData("tunnel.dropLoadBacklog", _inboundBuildMessages.size(), _inboundBuildMessages.size()); } else { int queueTime = estimateQueueTime(_inboundBuildMessages.size()); - if (queueTime > BuildRequestor.REQUEST_TIMEOUT/2) { + float pDrop = queueTime/(BuildRequestor.REQUEST_TIMEOUT/2); + pDrop = pDrop * pDrop * pDrop; + float f = _context.random().nextFloat(); + if (pDrop > f) { _context.statManager().addRateData("tunnel.dropLoadProactive", queueTime, _inboundBuildMessages.size()); } else { _inboundBuildMessages.add(new BuildMessageState(receivedMessage, from, fromHash));