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 a1d8fd8b35..485ef3da58 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -24,7 +24,17 @@ import org.jrobin.graph.RrdGraph; import org.jrobin.graph.RrdGraphDef; /** + * A thread started by RouterConsoleRunner that + * checks the configuration for stats to be tracked via jrobin, + * and adds or deletes RRDs as necessary. * + * This also contains methods to generate xml or png image output. + * The actual png rendering code is here for the special dual-rate graph; + * the rendering for standard graphs is in SummaryRenderer. + * + * To control memory, the number of simultaneous renderings is limited. + * + * @since 0.6.1.13 */ public class StatSummarizer implements Runnable { private final RouterContext _context; @@ -148,7 +158,7 @@ public class StatSummarizer implements Runnable { return locked_renderPng(rate, out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); } finally { - _sem.release(); + _sem.release(); } } @@ -180,6 +190,17 @@ public class StatSummarizer implements Runnable { } public boolean getXML(Rate rate, OutputStream out) throws IOException { + try { + try { + _sem.acquire(); + } catch (InterruptedException ie) {} + return locked_getXML(rate, out); + } finally { + _sem.release(); + } + } + + private boolean locked_getXML(Rate rate, OutputStream out) throws IOException { for (int i = 0; i < _listeners.size(); i++) { SummaryListener lsnr = _listeners.get(i); if (lsnr.getRate().equals(rate)) { @@ -208,7 +229,7 @@ public class StatSummarizer implements Runnable { return locked_renderRatePng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); } finally { - _sem.release(); + _sem.release(); } } 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 0d066233ed..cba9553737 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java @@ -1,6 +1,5 @@ package net.i2p.router.web; -import java.awt.Color; import java.io.IOException; import java.io.OutputStream; @@ -21,10 +20,16 @@ import org.jrobin.graph.RrdGraph; import org.jrobin.graph.RrdGraphDef; import org.jrobin.graph.RrdGraphDefTemplate; +/** + * Creates and updates the in-memory RRD database, + * and provides methods to generate graphs of the data + * + * @since 0.6.1.13 + */ class SummaryListener implements RateSummaryListener { - private I2PAppContext _context; - private Log _log; - private Rate _rate; + private final I2PAppContext _context; + private final Log _log; + private final Rate _rate; private String _name; private String _eventName; private RrdDb _db; @@ -86,6 +91,7 @@ class SummaryListener implements RateSummaryListener { } public Rate getRate() { return _rate; } + public void startListening() { RateStat rs = _rate.getRateStat(); long period = _rate.getPeriod(); @@ -108,12 +114,16 @@ class SummaryListener implements RateSummaryListener { _sample = _db.createSample(); _renderer = new SummaryRenderer(_context, this); _rate.setSummaryListener(this); + // Typical usage is 23456 bytes ~= 1440 * 16 + if (_log.shouldLog(Log.INFO)) + _log.info("New RRD " + baseName + " consuming " + _db.getRrdBackend().getLength() + " bytes"); } catch (RrdException re) { _log.error("Error starting", re); } catch (IOException ioe) { _log.error("Error starting", ioe); } } + public void stopListening() { if (_db == null) return; try { @@ -125,20 +135,26 @@ class SummaryListener implements RateSummaryListener { _factory.delete(_db.getPath()); _db = null; } + public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException { _renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit); } + public void renderPng(OutputStream out) throws IOException { _renderer.render(out); } String getName() { return _name; } + String getEventName() { return _eventName; } + RrdDb getData() { return _db; } + long now() { return _context.clock().now(); } @Override public boolean equals(Object obj) { return ((obj instanceof SummaryListener) && ((SummaryListener)obj)._rate.equals(_rate)); } + @Override public int hashCode() { return _rate.hashCode(); } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java index 4a192ac0b2..a5fd3dcbff 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java @@ -18,20 +18,22 @@ import net.i2p.stat.RateStat; import net.i2p.stat.RateSummaryListener; import net.i2p.util.Log; -import org.jrobin.core.RrdBackendFactory; -import org.jrobin.core.RrdDb; -import org.jrobin.core.RrdDef; import org.jrobin.core.RrdException; -import org.jrobin.core.RrdMemoryBackendFactory; -import org.jrobin.core.Sample; import org.jrobin.graph.RrdGraph; import org.jrobin.graph.RrdGraphDef; import org.jrobin.graph.RrdGraphDefTemplate; +/** + * Generate the RRD graph png images, + * except for the combined rate graph, which is + * generated in StatSummarizer. + * + * @since 0.6.1.13 + */ class SummaryRenderer { - private Log _log; - private SummaryListener _listener; - private I2PAppContext _context; + private final Log _log; + private final SummaryListener _listener; + private final I2PAppContext _context; public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) { _log = ctx.logManager().getLog(SummaryRenderer.class);