2006-03-16 jrandom

* Integrate basic hooks for jrobin (http://jrobin.org) into the router
      console.  Selected stats can be harvested automatically and fed into
      in-memory RRD databases, and those databases can be served up either as
      PNG images or as RRDtool compatible XML dumps (see oldstats.jsp for
      details).  A base set of stats are harvested by default, but an
      alternate list can be specified by setting the 'stat.summaries' list on
      the advanced config.  For instance:
      stat.summaries=bw.recvRate.60000,bw.sendRate.60000
    * HTML tweaking for the general config page (thanks void!)
    * Odd NPE fix (thanks Complication!)
This commit is contained in:
jrandom
2006-03-16 21:45:17 +00:00
committed by zzz
parent 349adf6690
commit 65dc803fb7
19 changed files with 468 additions and 32 deletions

Binary file not shown.

View File

@ -25,6 +25,7 @@
<pathelement location="../../systray/java/build/systray.jar" />
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../../installer/lib/wrapper/win32/wrapper.jar" /> <!-- we dont care if we're not on win32 -->
<pathelement location="../../jrobin/jrobin-1.4.0.jar" />
</classpath>
</javac>
</target>
@ -34,6 +35,12 @@
<attribute name="Class-Path" value="i2p.jar router.jar" />
</manifest>
</jar>
<delete dir="./tmpextract" />
<unjar src="../../jrobin/jrobin-1.4.0.jar" dest="./tmpextract" />
<jar destfile="./build/routerconsole.jar" basedir="./tmpextract" update="true" />
<delete dir="./tmpextract" />
<ant target="war" />
</target>
<target name="war" depends="precompilejsp">
@ -60,6 +67,7 @@
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../../installer/lib/wrapper/win32/wrapper.jar" />
<pathelement location="build/routerconsole.jar" />
<pathelement location="build/" />
<pathelement location="../../../router/java/build/router.jar" />
<pathelement location="../../../core/java/build/i2p.jar" />
</classpath>
@ -86,6 +94,7 @@
<pathelement location="../../systray/java/lib/systray4j.jar" />
<pathelement location="../../../installer/lib/wrapper/win32/wrapper.jar" />
<pathelement location="build/routerconsole.jar" />
<pathelement location="build" />
<pathelement location="../../../router/java/build/router.jar" />
<pathelement location="../../../core/java/build/i2p.jar" />
</classpath>

View File

@ -25,6 +25,7 @@ public class RouterConsoleRunner {
static {
System.setProperty("org.mortbay.http.Version.paranoid", "true");
System.setProperty("java.awt.headless", "true");
}
public RouterConsoleRunner(String args[]) {
@ -95,6 +96,10 @@ public class RouterConsoleRunner {
I2PThread t = new I2PThread(fetcher, "NewsFetcher");
t.setDaemon(true);
t.start();
I2PThread st = new I2PThread(new StatSummarizer(), "StatSummarizer");
st.setDaemon(true);
st.start();
}
private void initialize(WebApplicationContext context) {

View File

@ -0,0 +1,140 @@
package net.i2p.router.web;
import java.io.*;
import java.util.*;
import net.i2p.stat.*;
import net.i2p.router.*;
/**
*
*/
public class StatSummarizer implements Runnable {
private RouterContext _context;
/** 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
_listeners = new ArrayList(16);
_instance = this;
}
public static StatSummarizer instance() { return _instance; }
public void run() {
String specs = "";
while (_context.router().isAlive()) {
specs = adjustDatabases(specs);
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
}
}
private static final String DEFAULT_DATABASES = "bw.sendRate.60000" +
",bw.recvRate.60000" +
",tunnel.testSuccessTime.60000" +
",udp.outboundActiveCount.60000" +
",udp.receivePacketSize.60000" +
",udp.receivePacketSkew.60000" +
",udp.sendConfirmTime.60000" +
",udp.sendPacketSize.60000" +
",router.activePeers.60000" +
",router.activeSendPeers.60000";
private String adjustDatabases(String oldSpecs) {
String spec = _context.getProperty("stat.summaries", DEFAULT_DATABASES);
if ( ( (spec == null) && (oldSpecs == null) ) ||
( (spec != null) && (oldSpecs != null) && (oldSpecs.equals(spec))) )
return oldSpecs;
List old = parseSpecs(oldSpecs);
List newSpecs = parseSpecs(spec);
// remove old ones
for (int i = 0; i < old.size(); i++) {
Rate r = (Rate)old.get(i);
if (!newSpecs.contains(r))
removeDb(r);
}
// add new ones
StringBuffer buf = new StringBuffer();
for (int i = 0; i < newSpecs.size(); i++) {
Rate r = (Rate)newSpecs.get(i);
if (!old.contains(r))
addDb(r);
buf.append(r.getRateStat().getName()).append(".").append(r.getPeriod());
if (i + 1 < newSpecs.size())
buf.append(',');
}
return buf.toString();
}
private void removeDb(Rate r) {
for (int i = 0; i < _listeners.size(); i++) {
SummaryListener lsnr = (SummaryListener)_listeners.get(i);
if (lsnr.getRate().equals(r)) {
_listeners.remove(i);
lsnr.stopListening();
return;
}
}
}
private void addDb(Rate r) {
SummaryListener lsnr = new SummaryListener(r);
_listeners.add(lsnr);
lsnr.startListening();
//System.out.println("Start listening for " + r.getRateStat().getName() + ": " + r.getPeriod());
}
public boolean renderPng(Rate rate, OutputStream out) throws IOException { return renderPng(rate, out, -1, -1); }
public boolean renderPng(Rate rate, OutputStream out, int width, int height) throws IOException {
for (int i = 0; i < _listeners.size(); i++) {
SummaryListener lsnr = (SummaryListener)_listeners.get(i);
if (lsnr.getRate().equals(rate)) {
lsnr.renderPng(out, width, height);
return true;
}
}
return false;
}
public boolean getXML(Rate rate, OutputStream out) throws IOException {
for (int i = 0; i < _listeners.size(); i++) {
SummaryListener lsnr = (SummaryListener)_listeners.get(i);
if (lsnr.getRate().equals(rate)) {
lsnr.getData().exportXml(out);
out.write(("<!-- Rate: " + lsnr.getRate().getRateStat().getName() + " for period " + lsnr.getRate().getPeriod() + " -->\n").getBytes());
out.write(("<!-- Average data soure name: " + lsnr.getName() + " event count data source name: " + lsnr.getEventName() + " -->\n").getBytes());
return true;
}
}
return false;
}
/**
* @param specs statName.period,statName.period,statName.period
* @return list of Rate objects
*/
private List parseSpecs(String specs) {
StringTokenizer tok = new StringTokenizer(specs, ",");
List rv = new ArrayList();
while (tok.hasMoreTokens()) {
String spec = tok.nextToken();
int split = spec.lastIndexOf('.');
if ( (split <= 0) || (split + 1 >= spec.length()) )
continue;
String name = spec.substring(0, split);
String per = spec.substring(split+1);
long period = -1;
try {
period = Long.parseLong(per);
RateStat rs = _context.statManager().getRate(name);
if (rs != null) {
Rate r = rs.getRate(period);
if (r != null)
rv.add(r);
}
} catch (NumberFormatException nfe) {}
}
return rv;
}
}

View File

@ -0,0 +1,182 @@
package net.i2p.router.web;
import java.io.*;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.stat.RateSummaryListener;
import net.i2p.util.Log;
import org.jrobin.core.RrdDb;
import org.jrobin.core.RrdDef;
import org.jrobin.core.RrdBackendFactory;
import org.jrobin.core.RrdMemoryBackendFactory;
import org.jrobin.core.Sample;
import java.awt.Color;
import org.jrobin.graph.RrdGraph;
import org.jrobin.graph.RrdGraphDef;
import org.jrobin.core.RrdException;
class SummaryListener implements RateSummaryListener {
private I2PAppContext _context;
private Log _log;
private Rate _rate;
private String _name;
private String _eventName;
private RrdDb _db;
private Sample _sample;
private RrdMemoryBackendFactory _factory;
private SummaryRenderer _renderer;
static final int PERIODS = 600;
static {
try {
RrdBackendFactory.setDefaultFactory("MEMORY");
} catch (RrdException re) {
re.printStackTrace();
}
}
public SummaryListener(Rate r) {
_context = I2PAppContext.getGlobalContext();
_rate = r;
_log = _context.logManager().getLog(SummaryListener.class);
}
public void add(double totalValue, long eventCount, double totalEventTime, long period) {
if (_db != null) {
// add one value to the db (the average value for the period)
try {
_sample.setTime(now()/1000);
double val = eventCount > 0 ? (totalValue / (double)eventCount) : 0d;
_sample.setValue(_name, val);
_sample.setValue(_eventName, eventCount);
//_sample.setValue(0, val);
//_sample.setValue(1, eventCount);
_sample.update();
//String names[] = _sample.getDsNames();
//System.out.println("Add " + val + " over " + eventCount + " for " + _name
// + " [" + names[0] + ", " + names[1] + "]");
} catch (IOException ioe) {
_log.error("Error adding", ioe);
} catch (RrdException re) {
_log.error("Error adding", re);
}
}
}
/**
* JRobin can only deal with 20 character data source names, so we need to create a unique,
* munged version from the user/developer-visible name.
*
*/
private static String createName(I2PAppContext ctx, String wanted) {
return ctx.sha().calculateHash(DataHelper.getUTF8(wanted)).toBase64().substring(0,20);
}
public Rate getRate() { return _rate; }
public void startListening() {
RateStat rs = _rate.getRateStat();
long period = _rate.getPeriod();
String baseName = rs.getName() + "." + period;
_name = createName(_context, baseName);
_eventName = createName(_context, baseName + ".events");
try {
RrdDef def = new RrdDef(_name, now()/1000, period/1000);
long heartbeat = period*3/1000; // max seconds between events
def.addDatasource(_name, "GAUGE", heartbeat, Double.NaN, Double.NaN);
def.addDatasource(_eventName, "GAUGE", heartbeat, 0, Double.NaN);
double xff = 0.5;
int steps = 1;
int rows = PERIODS;
def.addArchive("AVERAGE", xff, steps, rows);
_factory = (RrdMemoryBackendFactory)RrdBackendFactory.getDefaultFactory();
_db = new RrdDb(def, _factory);
_sample = _db.createSample();
_renderer = new SummaryRenderer(_context, this);
_rate.setSummaryListener(this);
} catch (RrdException re) {
_log.error("Error starting", re);
} catch (IOException ioe) {
_log.error("Error starting", ioe);
}
}
public void stopListening() {
if (_db == null) return;
try {
_db.close();
} catch (IOException ioe) {
_log.error("Error closing", ioe);
}
_rate.setSummaryListener(null);
_factory.delete(_db.getPath());
_db = null;
}
public void renderPng(OutputStream out, int width, int height) throws IOException { _renderer.render(out, width, height); }
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(); }
public boolean equals(Object obj) {
return ((obj instanceof SummaryListener) && ((SummaryListener)obj)._rate.equals(_rate));
}
public int hashCode() { return _rate.hashCode(); }
}
class SummaryRenderer {
private Log _log;
private SummaryListener _listener;
public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) {
_log = ctx.logManager().getLog(SummaryRenderer.class);
_listener = lsnr;
}
public void render(OutputStream out) throws IOException { render(out, -1, -1); }
public void render(OutputStream out, int width, int height) throws IOException {
long end = _listener.now();
long start = end - _listener.getRate().getPeriod()*SummaryListener.PERIODS;
long begin = System.currentTimeMillis();
try {
RrdGraphDef def = new RrdGraphDef();
def.setTimePeriod(start/1000, end/1000);
String title = _listener.getRate().getRateStat().getName() + " averaged for "
+ DataHelper.formatDuration(_listener.getRate().getPeriod());
def.setTitle(title);
String path = _listener.getData().getPath();
String dsNames[] = _listener.getData().getDsNames();
def.datasource(_listener.getName(), path, dsNames[0], "AVERAGE", "MEMORY");
// include the average event count on the plot
//def.datasource(_listener.getName(), path, dsNames[1], "AVERAGE", "MEMORY");
def.area(dsNames[0], Color.BLUE, _listener.getRate().getRateStat().getDescription());
//def.line(dsNames[1], Color.RED, "Events per period");
//System.out.println("rendering: path=" + path + " dsNames[0]=" + dsNames[0] + " dsNames[1]=" + dsNames[1] + " lsnr.getName=" + _listener.getName());
def.setAntiAliasing(false);
RrdGraph graph = new RrdGraph(def);
//System.out.println("Graph created");em.
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());
} 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;
}
}
}

View File

@ -44,6 +44,7 @@
Bandwidth share percentage:
<jsp:getProperty name="nethelper" property="sharePercentageBox" /><br />
Sharing a higher percentage will improve your anonymity and help the network
<input type="submit" name="save" value="Save changes" /> <input type="reset" value="Cancel" /><br />
<hr />
<b>Enable load testing: </b>
<input type="checkbox" name="enableloadtesting" value="true" <jsp:getProperty name="nethelper" property="enableLoadTesting" /> />

View File

@ -0,0 +1,37 @@
<%
net.i2p.stat.Rate rate = null;
String stat = request.getParameter("stat");
String period = request.getParameter("period");
net.i2p.stat.RateStat rs = net.i2p.I2PAppContext.getGlobalContext().statManager().getRate(stat);
boolean rendered = false;
if (rs != null) {
long per = -1;
try {
per = Long.parseLong(period);
rate = rs.getRate(per);
if (rate != null) {
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);
} else {
response.setContentType("image/png");
int width = -1;
int height = -1;
String str = request.getParameter("width");
if (str != null) try { width = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
str = request.getParameter("height");
if (str != null) try { height = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height);
}
if (rendered)
cout.close();
//System.out.println("Rendered period " + per + " for the stat " + stat + "? " + rendered);
}
} catch (NumberFormatException nfe) {}
}
if (!rendered) {
response.sendError(404, "That stat is not available");
}
%>

View File

@ -1,7 +1,7 @@
package gnu.crypto.hash;
// ----------------------------------------------------------------------------
// $Id: Sha256.java,v 1.2 2005/10/06 04:24:14 rsdio Exp $
// $Id: Sha256Standalone.java,v 1.1 2006/02/26 16:30:59 jrandom Exp $
//
// Copyright (C) 2003 Free Software Foundation, Inc.
//
@ -59,7 +59,7 @@ package gnu.crypto.hash;
* renamed from Sha256 to avoid conflicts with JVMs using gnu-crypto as their JCE
* provider.
*
* @version $Revision: 1.2 $
* @version $Revision: 1.1 $
*/
public class Sha256Standalone extends BaseHash {
// Constants and variables
@ -127,10 +127,12 @@ public class Sha256Standalone extends BaseHash {
// Class methods
// -------------------------------------------------------------------------
/*
public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
int hh5, int hh6, int hh7, byte[] in, int offset) {
return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
}
*/
// Instance methods
// -------------------------------------------------------------------------
@ -143,17 +145,19 @@ public class Sha256Standalone extends BaseHash {
// Implementation of concrete methods in BaseHash --------------------------
private int transformResult[] = new int[8];
protected void transform(byte[] in, int offset) {
int[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
//int[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset, transformResult);
h0 = result[0];
h1 = result[1];
h2 = result[2];
h3 = result[3];
h4 = result[4];
h5 = result[5];
h6 = result[6];
h7 = result[7];
h0 = transformResult[0];
h1 = transformResult[1];
h2 = transformResult[2];
h3 = transformResult[3];
h4 = transformResult[4];
h5 = transformResult[5];
h6 = transformResult[6];
h7 = transformResult[7];
}
protected byte[] padBuffer() {
@ -218,8 +222,8 @@ public class Sha256Standalone extends BaseHash {
// SHA specific methods ----------------------------------------------------
private static final synchronized int[]
sha(int hh0, int hh1, int hh2, int hh3, int hh4, int hh5, int hh6, int hh7, byte[] in, int offset) {
private static final synchronized void
sha(int hh0, int hh1, int hh2, int hh3, int hh4, int hh5, int hh6, int hh7, byte[] in, int offset, int out[]) {
int A = hh0;
int B = hh1;
int C = hh2;
@ -255,8 +259,18 @@ public class Sha256Standalone extends BaseHash {
A = T + T2;
}
/*
return new int[] {
hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F, hh6 + G, hh7 + H
};
*/
out[0] = hh0 + A;
out[1] = hh1 + B;
out[2] = hh2 + C;
out[3] = hh3 + D;
out[4] = hh4 + E;
out[5] = hh5 + F;
out[6] = hh6 + G;
out[7] = hh7 + H;
}
}

View File

@ -26,6 +26,8 @@ public class Rate {
private volatile double _lifetimeTotalValue;
private volatile long _lifetimeEventCount;
private volatile long _lifetimeTotalEventTime;
private RateSummaryListener _summaryListener;
private RateStat _stat;
private volatile long _lastCoalesceDate;
private long _creationDate;
@ -108,6 +110,9 @@ public class Rate {
public long getPeriod() {
return _period;
}
public RateStat getRateStat() { return _stat; }
public void setRateStat(RateStat rs) { _stat = rs; }
/**
*
@ -203,8 +208,13 @@ public class Rate {
_currentEventCount = 0;
_currentTotalEventTime = 0;
}
if (_summaryListener != null)
_summaryListener.add(_lastTotalValue, _lastEventCount, _lastTotalEventTime, _period);
}
public void setSummaryListener(RateSummaryListener listener) { _summaryListener = listener; }
public RateSummaryListener getSummaryListener() { return _summaryListener; }
/** what was the average value across the events in the last period? */
public double getAverageValue() {
if ((_lastTotalValue != 0) && (_lastEventCount > 0))

View File

@ -27,8 +27,10 @@ public class RateStat {
_description = description;
_groupName = group;
_rates = new Rate[periods.length];
for (int i = 0; i < periods.length; i++)
for (int i = 0; i < periods.length; i++) {
_rates[i] = new Rate(periods[i]);
_rates[i].setRateStat(this);
}
}
public void setStatLog(StatLog sl) { _statLog = sl; }
@ -159,6 +161,7 @@ public class RateStat {
_rates[i].load(props, curPrefix, treatAsCurrent);
} catch (IllegalArgumentException iae) {
_rates[i] = new Rate(period);
_rates[i].setRateStat(this);
if (_log.shouldLog(Log.WARN))
_log.warn("Rate for " + prefix + " is corrupt, reinitializing that period");
}

View File

@ -1,4 +1,16 @@
$Id: history.txt,v 1.430 2006/03/15 17:26:45 jrandom Exp $
$Id: history.txt,v 1.431 2006/03/15 19:49:22 complication Exp $
2006-03-16 jrandom
* Integrate basic hooks for jrobin (http://jrobin.org) into the router
console. Selected stats can be harvested automatically and fed into
in-memory RRD databases, and those databases can be served up either as
PNG images or as RRDtool compatible XML dumps (see oldstats.jsp for
details). A base set of stats are harvested by default, but an
alternate list can be specified by setting the 'stat.summaries' list on
the advanced config. For instance:
stat.summaries=bw.recvRate.60000,bw.sendRate.60000
* HTML tweaking for the general config page (thanks void!)
* Odd NPE fix (thanks Complication!)
2006-03-15 Complication
* Trim out an old, inactive IP second-guessing method

View File

@ -1018,8 +1018,8 @@ class CoalesceStatsJob extends JobImpl {
ctx.statManager().createRateStat("bw.sendBps", "How fast we send data (in KBps)", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("bw.sendRate", "Low level bandwidth send rate, averaged every minute", "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
ctx.statManager().createRateStat("bw.recvRate", "Low level bandwidth receive rate, averaged every minute", "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
ctx.statManager().createRateStat("router.activePeers", "How many peers we are actively talking with", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("router.activeSendPeers", "How many peers have sent messages to this minute", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("router.activePeers", "How many peers we are actively talking with", "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("router.activeSendPeers", "How many peers have sent messages to this minute", "Throttle", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("router.fastPeers", "How many fast peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
}

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.371 $ $Date: 2006/03/15 17:26:45 $";
public final static String ID = "$Revision: 1.372 $ $Date: 2006/03/15 19:49:23 $";
public final static String VERSION = "0.6.1.12";
public final static long BUILD = 9;
public final static long BUILD = 10;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -180,6 +180,15 @@ public class StatsGenerator {
buf.append(num(curRate.getExtremeEventCount()));
buf.append(")");
}
if (curRate.getSummaryListener() != null) {
buf.append(" <a href=\"viewstat.jsp?stat=").append(name);
buf.append("&amp;period=").append(periods[i]);
buf.append("\" title=\"Render summarized data\">render</a>");
buf.append(" (as <a href=\"viewstat.jsp?stat=").append(name);
buf.append("&amp;period=").append(periods[i]);
buf.append("&amp;format=xml\" title=\"Dump stat history as XML\">XML</a>");
buf.append(" in a format <a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool\">RRDTool</a> understands)");
}
buf.append("</li>");
if (i + 1 == periods.length) {
// last one, so lets display the strict average

View File

@ -16,6 +16,7 @@ import net.i2p.data.Lease;
import net.i2p.data.LeaseSet;
import net.i2p.data.PublicKey;
import net.i2p.data.SessionKey;
import net.i2p.data.Payload;
import net.i2p.data.i2cp.MessageId;
import net.i2p.data.i2np.DataMessage;
@ -334,7 +335,11 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
if (wantACK)
_inTunnel = selectInboundTunnel();
buildClove();
boolean ok = buildClove();
if (!ok) {
dieFatal();
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Clove built to " + _toString);
long msgExpiration = _overallExpiration; // getContext().clock().now() + OVERALL_TIMEOUT_MS_DEFAULT;
@ -475,7 +480,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
}
/** build the payload clove that will be used for all of the messages, placing the clove in the status structure */
private void buildClove() {
private boolean buildClove() {
PayloadGarlicConfig clove = new PayloadGarlicConfig();
DeliveryInstructions instructions = new DeliveryInstructions();
@ -492,7 +497,13 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
clove.setId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));
DataMessage msg = new DataMessage(getContext());
msg.setData(_clientMessage.getPayload().getEncryptedData());
Payload p = _clientMessage.getPayload();
if (p == null)
return false;
byte d[] = p.getEncryptedData();
if (d == null)
return false;
msg.setData(d);
msg.setMessageExpiration(clove.getExpiration());
clove.setPayload(msg);
@ -504,6 +515,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Built payload clove with id " + clove.getId());
return true;
}
/**

View File

@ -64,6 +64,8 @@ public class FIFOBandwidthLimiter {
_context.statManager().createRateStat("bwLimiter.pendingInboundRequests", "How many inbound requests are ahead of the current one (ignoring ones with 0)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
_context.statManager().createRateStat("bwLimiter.outboundDelayedTime", "How long it takes to honor an outbound request (ignoring ones with that go instantly)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
_context.statManager().createRateStat("bwLimiter.inboundDelayedTime", "How long it takes to honor an inbound request (ignoring ones with that go instantly)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
_context.statManager().createRateStat("bw.sendBps1s", "How fast we are transmitting for the 1s quantization (period is the number of bytes transmitted)?", "Bandwidth", new long[] { 60*1000l, 10*60*1000l });
_context.statManager().createRateStat("bw.recvBps1s", "How fast we are receiving for the 1s quantization (period is the number of bytes transmitted)?", "Bandwidth", new long[] { 60*1000l, 10*60*1000l });
_pendingInboundRequests = new ArrayList(16);
_pendingOutboundRequests = new ArrayList(16);
_lastTotalSent = _totalAllocatedOutboundBytes;

View File

@ -160,7 +160,7 @@ public class OutboundMessageFragments {
}
_activePeers.notifyAll();
}
msg.timestamp("made active along with: " + active);
//msg.timestamp("made active along with: " + active);
_context.statManager().addRateData("udp.outboundActiveCount", active, 0);
} else {
if (_log.shouldLog(Log.WARN))

View File

@ -42,19 +42,19 @@ class TestJob extends JobImpl {
_log.error("Invalid tunnel test configuration: no pool for " + cfg, new Exception("origin"));
getTiming().setStartAfter(getDelay() + ctx.clock().now());
ctx.statManager().createRateStat("tunnel.testFailedTime", "How long did the failure take (max of 60s for full timeout)?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testExploratoryFailedTime", "How long did the failure of an exploratory tunnel take (max of 60s for full timeout)?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testFailedCompletelyTime", "How long did the complete failure take (max of 60s for full timeout)?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testExploratoryFailedCompletelyTime", "How long did the complete failure of an exploratory tunnel take (max of 60s for full timeout)?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testSuccessLength", "How long were the tunnels that passed the test?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testSuccessTime", "How long did tunnel testing take?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.testAborted", "Tunnel test could not occur, since there weren't any tunnels to test with", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
}
public String getName() { return "Test tunnel"; }
public void runJob() {

View File

@ -58,10 +58,10 @@ public class TunnelPoolManager implements TunnelManagerFacade {
ctx.statManager().createRateStat("tunnel.testSuccessTime",
"How long do successful tunnel tests take?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.participatingTunnels",
"How many tunnels are we participating in?", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*1000, 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
}
/** pick an inbound tunnel not bound to a particular destination */