forked from I2P_Developers/i2p.i2p
* Router: Refactor periodic tasks to their own files
This commit is contained in:
@ -44,7 +44,7 @@ fi
|
|||||||
# list specific files in core/ and router/ here, so we don't scan the whole tree
|
# list specific files in core/ and router/ here, so we don't scan the whole tree
|
||||||
ROUTERFILES="\
|
ROUTERFILES="\
|
||||||
../../../core/java/src/net/i2p/data/DataHelper.java \
|
../../../core/java/src/net/i2p/data/DataHelper.java \
|
||||||
../../../router/java/src/net/i2p/router/Router.java \
|
../../../router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java \
|
||||||
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
|
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
|
||||||
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \
|
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \
|
||||||
../../../router/java/src/net/i2p/router/transport/TransportManager.java \
|
../../../router/java/src/net/i2p/router/transport/TransportManager.java \
|
||||||
|
@ -15,11 +15,8 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -43,9 +40,9 @@ import net.i2p.router.message.GarlicMessageHandler;
|
|||||||
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||||
import net.i2p.router.startup.StartupJob;
|
import net.i2p.router.startup.StartupJob;
|
||||||
import net.i2p.router.startup.WorkingDir;
|
import net.i2p.router.startup.WorkingDir;
|
||||||
|
import net.i2p.router.tasks.*;
|
||||||
import net.i2p.router.transport.FIFOBandwidthLimiter;
|
import net.i2p.router.transport.FIFOBandwidthLimiter;
|
||||||
import net.i2p.router.transport.udp.UDPTransport;
|
import net.i2p.router.transport.udp.UDPTransport;
|
||||||
import net.i2p.stat.Rate;
|
|
||||||
import net.i2p.stat.RateStat;
|
import net.i2p.stat.RateStat;
|
||||||
import net.i2p.stat.StatManager;
|
import net.i2p.stat.StatManager;
|
||||||
import net.i2p.util.ByteCache;
|
import net.i2p.util.ByteCache;
|
||||||
@ -57,7 +54,6 @@ import net.i2p.util.Log;
|
|||||||
import net.i2p.util.SecureFileOutputStream;
|
import net.i2p.util.SecureFileOutputStream;
|
||||||
import net.i2p.util.SimpleByteCache;
|
import net.i2p.util.SimpleByteCache;
|
||||||
import net.i2p.util.SimpleScheduler;
|
import net.i2p.util.SimpleScheduler;
|
||||||
import net.i2p.util.SimpleTimer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main driver for the router.
|
* Main driver for the router.
|
||||||
@ -94,7 +90,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
public static final int NETWORK_ID = 2;
|
public static final int NETWORK_ID = 2;
|
||||||
|
|
||||||
/** coalesce stats this often - should be a little less than one minute, so the graphs get updated */
|
/** coalesce stats this often - should be a little less than one minute, so the graphs get updated */
|
||||||
private static final int COALESCE_TIME = 50*1000;
|
public static final int COALESCE_TIME = 50*1000;
|
||||||
|
|
||||||
/** this puts an 'H' in your routerInfo **/
|
/** this puts an 'H' in your routerInfo **/
|
||||||
public final static String PROP_HIDDEN = "router.hiddenMode";
|
public final static String PROP_HIDDEN = "router.hiddenMode";
|
||||||
@ -310,7 +306,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @since 0.8.8 */
|
/** @since 0.8.8 */
|
||||||
private static final void clearCaches() {
|
public static final void clearCaches() {
|
||||||
ByteCache.clearAll();
|
ByteCache.clearAll();
|
||||||
SimpleByteCache.clearAll();
|
SimpleByteCache.clearAll();
|
||||||
}
|
}
|
||||||
@ -510,7 +506,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
setRouterInfo(ri);
|
setRouterInfo(ri);
|
||||||
if (!ri.isValid())
|
if (!ri.isValid())
|
||||||
throw new DataFormatException("Our RouterInfo has a bad signature");
|
throw new DataFormatException("Our RouterInfo has a bad signature");
|
||||||
Republish r = new Republish();
|
Republish r = new Republish(_context);
|
||||||
if (blockingRebuild)
|
if (blockingRebuild)
|
||||||
r.timeReached();
|
r.timeReached();
|
||||||
else
|
else
|
||||||
@ -519,18 +515,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
_log.log(Log.CRIT, "Internal error - unable to sign our own address?!", dfe);
|
_log.log(Log.CRIT, "Internal error - unable to sign our own address?!", dfe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Republish implements SimpleTimer.TimedEvent {
|
|
||||||
public void timeReached() {
|
|
||||||
try {
|
|
||||||
_context.netDb().publish(getRouterInfo());
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
_log.log(Log.CRIT, "Local router info is invalid? rebuilding a new identity", iae);
|
|
||||||
rebuildNewIdentity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// publicize our ballpark capacity
|
// publicize our ballpark capacity
|
||||||
public static final char CAPABILITY_BW12 = 'K';
|
public static final char CAPABILITY_BW12 = 'K';
|
||||||
public static final char CAPABILITY_BW32 = 'L';
|
public static final char CAPABILITY_BW32 = 'L';
|
||||||
@ -1032,8 +1017,9 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the JVM runtime hook before calling this.
|
* Cancel the JVM runtime hook before calling this.
|
||||||
|
* NOT to be called by others, use shutdown().
|
||||||
*/
|
*/
|
||||||
private void shutdown2(int exitCode) {
|
public void shutdown2(int exitCode) {
|
||||||
// So we can get all the way to the end
|
// So we can get all the way to the end
|
||||||
// No, you can't do Thread.currentThread.setDaemon(false)
|
// No, you can't do Thread.currentThread.setDaemon(false)
|
||||||
if (_killVMOnEnd) {
|
if (_killVMOnEnd) {
|
||||||
@ -1739,224 +1725,4 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
recv = (int)rs.getRate(5*60*1000).getAverageValue();
|
recv = (int)rs.getRate(5*60*1000).getAverageValue();
|
||||||
return Math.max(send, recv);
|
return Math.max(send, recv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a string for extraction by xgettext and translation.
|
|
||||||
* Use this only in static initializers.
|
|
||||||
* It does not translate!
|
|
||||||
* @return s
|
|
||||||
* @since 0.8.7
|
|
||||||
*/
|
|
||||||
private static final String _x(String s) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* following classes are now private static inner classes, didn't bother to reindent */
|
|
||||||
|
|
||||||
private static final long LOW_MEMORY_THRESHOLD = 5 * 1024 * 1024;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* coalesce the stats framework every minute
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
|
|
||||||
private RouterContext _ctx;
|
|
||||||
private long _maxMemory;
|
|
||||||
|
|
||||||
public CoalesceStatsEvent(RouterContext ctx) {
|
|
||||||
_ctx = ctx;
|
|
||||||
// NOTE TO TRANSLATORS - each of these phrases is a description for a statistic
|
|
||||||
// to be displayed on /stats.jsp and in the graphs on /graphs.jsp.
|
|
||||||
// Please keep relatively short so it will fit on the graphs.
|
|
||||||
ctx.statManager().createRequiredRateStat("bw.receiveBps", _x("Message receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
|
||||||
ctx.statManager().createRequiredRateStat("bw.sendBps", _x("Message send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
|
||||||
ctx.statManager().createRequiredRateStat("bw.sendRate", _x("Low-level send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
|
|
||||||
ctx.statManager().createRequiredRateStat("bw.recvRate", _x("Low-level receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
|
|
||||||
ctx.statManager().createRequiredRateStat("router.activePeers", _x("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 we've sent 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().createRequiredRateStat("router.fastPeers", _x("Known fast peers"), "Throttle", new long[] { 5*60*1000, 60*60*1000 });
|
|
||||||
_maxMemory = Runtime.getRuntime().maxMemory();
|
|
||||||
String legend = "(Bytes)";
|
|
||||||
if (_maxMemory < Long.MAX_VALUE)
|
|
||||||
legend += " Max is " + DataHelper.formatSize(_maxMemory) + 'B';
|
|
||||||
// router.memoryUsed currently has the max size in the description so it can't be tagged
|
|
||||||
ctx.statManager().createRequiredRateStat("router.memoryUsed", legend, "Router", new long[] { 60*1000 });
|
|
||||||
}
|
|
||||||
private RouterContext getContext() { return _ctx; }
|
|
||||||
public void timeReached() {
|
|
||||||
int active = getContext().commSystem().countActivePeers();
|
|
||||||
getContext().statManager().addRateData("router.activePeers", active, 60*1000);
|
|
||||||
|
|
||||||
int activeSend = getContext().commSystem().countActiveSendPeers();
|
|
||||||
getContext().statManager().addRateData("router.activeSendPeers", activeSend, 60*1000);
|
|
||||||
|
|
||||||
int fast = getContext().profileOrganizer().countFastPeers();
|
|
||||||
getContext().statManager().addRateData("router.fastPeers", fast, 60*1000);
|
|
||||||
|
|
||||||
int highCap = getContext().profileOrganizer().countHighCapacityPeers();
|
|
||||||
getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000);
|
|
||||||
|
|
||||||
getContext().statManager().addRateData("bw.sendRate", (long)getContext().bandwidthLimiter().getSendBps(), 0);
|
|
||||||
getContext().statManager().addRateData("bw.recvRate", (long)getContext().bandwidthLimiter().getReceiveBps(), 0);
|
|
||||||
|
|
||||||
long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
|
||||||
getContext().statManager().addRateData("router.memoryUsed", used, 0);
|
|
||||||
if (_maxMemory - used < LOW_MEMORY_THRESHOLD)
|
|
||||||
clearCaches();
|
|
||||||
|
|
||||||
getContext().tunnelDispatcher().updateParticipatingStats(COALESCE_TIME);
|
|
||||||
|
|
||||||
getContext().statManager().coalesceStats();
|
|
||||||
|
|
||||||
RateStat receiveRate = getContext().statManager().getRate("transport.receiveMessageSize");
|
|
||||||
if (receiveRate != null) {
|
|
||||||
Rate rate = receiveRate.getRate(60*1000);
|
|
||||||
if (rate != null) {
|
|
||||||
double bytes = rate.getLastTotalValue();
|
|
||||||
double bps = (bytes*1000.0d)/rate.getPeriod();
|
|
||||||
getContext().statManager().addRateData("bw.receiveBps", (long)bps, 60*1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RateStat sendRate = getContext().statManager().getRate("transport.sendMessageSize");
|
|
||||||
if (sendRate != null) {
|
|
||||||
Rate rate = sendRate.getRate(60*1000);
|
|
||||||
if (rate != null) {
|
|
||||||
double bytes = rate.getLastTotalValue();
|
|
||||||
double bps = (bytes*1000.0d)/rate.getPeriod();
|
|
||||||
getContext().statManager().addRateData("bw.sendBps", (long)bps, 60*1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the routing Key modifier every day at midnight (plus on startup).
|
|
||||||
* This is done here because we want to make sure the key is updated before anyone
|
|
||||||
* uses it.
|
|
||||||
*/
|
|
||||||
private static class UpdateRoutingKeyModifierJob extends JobImpl {
|
|
||||||
private Log _log;
|
|
||||||
private Calendar _cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
|
||||||
public UpdateRoutingKeyModifierJob(RouterContext ctx) {
|
|
||||||
super(ctx);
|
|
||||||
}
|
|
||||||
public String getName() { return "Update Routing Key Modifier"; }
|
|
||||||
public void runJob() {
|
|
||||||
_log = getContext().logManager().getLog(getClass());
|
|
||||||
getContext().routingKeyGenerator().generateDateBasedModData();
|
|
||||||
requeue(getTimeTillMidnight());
|
|
||||||
}
|
|
||||||
private long getTimeTillMidnight() {
|
|
||||||
long now = getContext().clock().now();
|
|
||||||
_cal.setTime(new Date(now));
|
|
||||||
_cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround
|
|
||||||
_cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround
|
|
||||||
_cal.add(Calendar.DATE, 1);
|
|
||||||
_cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
_cal.set(Calendar.MINUTE, 0);
|
|
||||||
_cal.set(Calendar.SECOND, 0);
|
|
||||||
_cal.set(Calendar.MILLISECOND, 0);
|
|
||||||
long then = _cal.getTime().getTime();
|
|
||||||
long howLong = then - now;
|
|
||||||
if (howLong < 0) // hi kaffe
|
|
||||||
howLong = 24*60*60*1000l + howLong;
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
|
||||||
_log.debug("Time till midnight: " + howLong + "ms");
|
|
||||||
return howLong;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a timestamp to the ping file where
|
|
||||||
* other routers trying to use the same configuration can see it
|
|
||||||
*/
|
|
||||||
private static class MarkLiveliness implements SimpleTimer.TimedEvent {
|
|
||||||
private final Router _router;
|
|
||||||
private final File _pingFile;
|
|
||||||
|
|
||||||
public MarkLiveliness(Router router, File pingFile) {
|
|
||||||
_router = router;
|
|
||||||
_pingFile = pingFile;
|
|
||||||
_pingFile.deleteOnExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void timeReached() {
|
|
||||||
if (_router.isAlive())
|
|
||||||
ping();
|
|
||||||
else
|
|
||||||
_pingFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ping() {
|
|
||||||
FileOutputStream fos = null;
|
|
||||||
try {
|
|
||||||
fos = new SecureFileOutputStream(_pingFile);
|
|
||||||
fos.write(("" + System.currentTimeMillis()).getBytes());
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
System.err.println("Error writing to ping file");
|
|
||||||
ioe.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Just for failsafe. Standard shutdown should cancel this.
|
|
||||||
*/
|
|
||||||
private static class ShutdownHook extends Thread {
|
|
||||||
private final RouterContext _context;
|
|
||||||
private static int __id = 0;
|
|
||||||
private final int _id;
|
|
||||||
|
|
||||||
public ShutdownHook(RouterContext ctx) {
|
|
||||||
_context = ctx;
|
|
||||||
_id = ++__id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
setName("Router " + _id + " shutdown");
|
|
||||||
Log l = _context.logManager().getLog(Router.class);
|
|
||||||
l.log(Log.CRIT, "Shutting down the router...");
|
|
||||||
_context.router().shutdown2(Router.EXIT_HARD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** update the router.info file whenever its, er, updated */
|
|
||||||
private static class PersistRouterInfoJob extends JobImpl {
|
|
||||||
public PersistRouterInfoJob(RouterContext ctx) {
|
|
||||||
super(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() { return "Persist Updated Router Information"; }
|
|
||||||
|
|
||||||
public void runJob() {
|
|
||||||
Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class);
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
|
||||||
_log.debug("Persisting updated router info");
|
|
||||||
|
|
||||||
String infoFilename = getContext().getProperty(PROP_INFO_FILENAME, PROP_INFO_FILENAME_DEFAULT);
|
|
||||||
File infoFile = new File(getContext().getRouterDir(), infoFilename);
|
|
||||||
|
|
||||||
RouterInfo info = getContext().router().getRouterInfo();
|
|
||||||
|
|
||||||
FileOutputStream fos = null;
|
|
||||||
synchronized (getContext().router().routerInfoFileLock) {
|
|
||||||
try {
|
|
||||||
fos = new SecureFileOutputStream(infoFile);
|
|
||||||
info.writeBytes(fos);
|
|
||||||
} catch (DataFormatException dfe) {
|
|
||||||
_log.error("Error rebuilding the router information", dfe);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
_log.error("Error writing out the rebuilt router information", ioe);
|
|
||||||
} finally {
|
|
||||||
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
107
router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java
Normal file
107
router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.stat.Rate;
|
||||||
|
import net.i2p.stat.RateStat;
|
||||||
|
import net.i2p.util.SimpleTimer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coalesce the stats framework every minute
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
|
||||||
|
private final RouterContext _ctx;
|
||||||
|
private final long _maxMemory;
|
||||||
|
private static final long LOW_MEMORY_THRESHOLD = 5 * 1024 * 1024;
|
||||||
|
|
||||||
|
public CoalesceStatsEvent(RouterContext ctx) {
|
||||||
|
_ctx = ctx;
|
||||||
|
// NOTE TO TRANSLATORS - each of these phrases is a description for a statistic
|
||||||
|
// to be displayed on /stats.jsp and in the graphs on /graphs.jsp.
|
||||||
|
// Please keep relatively short so it will fit on the graphs.
|
||||||
|
ctx.statManager().createRequiredRateStat("bw.receiveBps", _x("Message receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||||
|
ctx.statManager().createRequiredRateStat("bw.sendBps", _x("Message send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||||
|
ctx.statManager().createRequiredRateStat("bw.sendRate", _x("Low-level send rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
|
||||||
|
ctx.statManager().createRequiredRateStat("bw.recvRate", _x("Low-level receive rate (bytes/sec)"), "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l });
|
||||||
|
ctx.statManager().createRequiredRateStat("router.activePeers", _x("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 we've sent 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().createRequiredRateStat("router.fastPeers", _x("Known fast peers"), "Throttle", new long[] { 5*60*1000, 60*60*1000 });
|
||||||
|
_maxMemory = Runtime.getRuntime().maxMemory();
|
||||||
|
String legend = "(Bytes)";
|
||||||
|
if (_maxMemory < Long.MAX_VALUE)
|
||||||
|
legend += " Max is " + DataHelper.formatSize(_maxMemory) + 'B';
|
||||||
|
// router.memoryUsed currently has the max size in the description so it can't be tagged
|
||||||
|
ctx.statManager().createRequiredRateStat("router.memoryUsed", legend, "Router", new long[] { 60*1000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
private RouterContext getContext() { return _ctx; }
|
||||||
|
|
||||||
|
public void timeReached() {
|
||||||
|
int active = getContext().commSystem().countActivePeers();
|
||||||
|
getContext().statManager().addRateData("router.activePeers", active, 60*1000);
|
||||||
|
|
||||||
|
int activeSend = getContext().commSystem().countActiveSendPeers();
|
||||||
|
getContext().statManager().addRateData("router.activeSendPeers", activeSend, 60*1000);
|
||||||
|
|
||||||
|
int fast = getContext().profileOrganizer().countFastPeers();
|
||||||
|
getContext().statManager().addRateData("router.fastPeers", fast, 60*1000);
|
||||||
|
|
||||||
|
int highCap = getContext().profileOrganizer().countHighCapacityPeers();
|
||||||
|
getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000);
|
||||||
|
|
||||||
|
getContext().statManager().addRateData("bw.sendRate", (long)getContext().bandwidthLimiter().getSendBps());
|
||||||
|
getContext().statManager().addRateData("bw.recvRate", (long)getContext().bandwidthLimiter().getReceiveBps());
|
||||||
|
|
||||||
|
long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||||
|
getContext().statManager().addRateData("router.memoryUsed", used);
|
||||||
|
if (_maxMemory - used < LOW_MEMORY_THRESHOLD)
|
||||||
|
Router.clearCaches();
|
||||||
|
|
||||||
|
getContext().tunnelDispatcher().updateParticipatingStats(Router.COALESCE_TIME);
|
||||||
|
|
||||||
|
getContext().statManager().coalesceStats();
|
||||||
|
|
||||||
|
RateStat receiveRate = getContext().statManager().getRate("transport.receiveMessageSize");
|
||||||
|
if (receiveRate != null) {
|
||||||
|
Rate rate = receiveRate.getRate(60*1000);
|
||||||
|
if (rate != null) {
|
||||||
|
double bytes = rate.getLastTotalValue();
|
||||||
|
double bps = (bytes*1000.0d)/rate.getPeriod();
|
||||||
|
getContext().statManager().addRateData("bw.receiveBps", (long)bps, 60*1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RateStat sendRate = getContext().statManager().getRate("transport.sendMessageSize");
|
||||||
|
if (sendRate != null) {
|
||||||
|
Rate rate = sendRate.getRate(60*1000);
|
||||||
|
if (rate != null) {
|
||||||
|
double bytes = rate.getLastTotalValue();
|
||||||
|
double bps = (bytes*1000.0d)/rate.getPeriod();
|
||||||
|
getContext().statManager().addRateData("bw.sendBps", (long)bps, 60*1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a string for extraction by xgettext and translation.
|
||||||
|
* Use this only in static initializers.
|
||||||
|
* It does not translate!
|
||||||
|
* @return s
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
private static final String _x(String s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
55
router/java/src/net/i2p/router/tasks/MarkLiveliness.java
Normal file
55
router/java/src/net/i2p/router/tasks/MarkLiveliness.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.util.SecureFileOutputStream;
|
||||||
|
import net.i2p.util.SimpleTimer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a timestamp to the ping file where
|
||||||
|
* other routers trying to use the same configuration can see it
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class MarkLiveliness implements SimpleTimer.TimedEvent {
|
||||||
|
private final Router _router;
|
||||||
|
private final File _pingFile;
|
||||||
|
|
||||||
|
public MarkLiveliness(Router router, File pingFile) {
|
||||||
|
_router = router;
|
||||||
|
_pingFile = pingFile;
|
||||||
|
_pingFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void timeReached() {
|
||||||
|
if (_router.isAlive())
|
||||||
|
ping();
|
||||||
|
else
|
||||||
|
_pingFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ping() {
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new SecureFileOutputStream(_pingFile);
|
||||||
|
fos.write(("" + System.currentTimeMillis()).getBytes());
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
System.err.println("Error writing to ping file");
|
||||||
|
ioe.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.i2p.data.DataFormatException;
|
||||||
|
import net.i2p.data.RouterInfo;
|
||||||
|
import net.i2p.router.JobImpl;
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.SecureFileOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the router.info file whenever its, er, updated
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class PersistRouterInfoJob extends JobImpl {
|
||||||
|
public PersistRouterInfoJob(RouterContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() { return "Persist Updated Router Information"; }
|
||||||
|
|
||||||
|
public void runJob() {
|
||||||
|
Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class);
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Persisting updated router info");
|
||||||
|
|
||||||
|
String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
|
||||||
|
File infoFile = new File(getContext().getRouterDir(), infoFilename);
|
||||||
|
|
||||||
|
RouterInfo info = getContext().router().getRouterInfo();
|
||||||
|
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
synchronized (getContext().router().routerInfoFileLock) {
|
||||||
|
try {
|
||||||
|
fos = new SecureFileOutputStream(infoFile);
|
||||||
|
info.writeBytes(fos);
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
_log.error("Error rebuilding the router information", dfe);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
_log.error("Error writing out the rebuilt router information", ioe);
|
||||||
|
} finally {
|
||||||
|
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
router/java/src/net/i2p/router/tasks/Republish.java
Normal file
38
router/java/src/net/i2p/router/tasks/Republish.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.util.SimpleTimer;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Periodically publish our RouterInfo to the netdb
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class Republish implements SimpleTimer.TimedEvent {
|
||||||
|
private final RouterContext _context;
|
||||||
|
|
||||||
|
public Republish(RouterContext ctx) {
|
||||||
|
_context = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void timeReached() {
|
||||||
|
try {
|
||||||
|
_context.netDb().publish(_context.router().getRouterInfo());
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
Log log = _context.logManager().getLog(Router.class);
|
||||||
|
log.log(Log.CRIT, "Local router info is invalid? rebuilding a new identity", iae);
|
||||||
|
_context.router().rebuildNewIdentity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,11 @@
|
|||||||
package net.i2p.router;
|
package net.i2p.router.tasks;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.router.Job;
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.stat.Rate;
|
import net.i2p.stat.Rate;
|
||||||
import net.i2p.stat.RateStat;
|
import net.i2p.stat.RateStat;
|
||||||
import net.i2p.util.ShellCommand;
|
import net.i2p.util.ShellCommand;
|
||||||
@ -13,7 +16,7 @@ import net.i2p.util.Log;
|
|||||||
* they have, restart the JVM)
|
* they have, restart the JVM)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class RouterWatchdog implements Runnable {
|
public class RouterWatchdog implements Runnable {
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
private final RouterContext _context;
|
private final RouterContext _context;
|
||||||
private int _consecutiveErrors;
|
private int _consecutiveErrors;
|
37
router/java/src/net/i2p/router/tasks/ShutdownHook.java
Normal file
37
router/java/src/net/i2p/router/tasks/ShutdownHook.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just for failsafe. Standard shutdown should cancel this.
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class ShutdownHook extends Thread {
|
||||||
|
private final RouterContext _context;
|
||||||
|
private static int __id = 0;
|
||||||
|
private final int _id;
|
||||||
|
|
||||||
|
public ShutdownHook(RouterContext ctx) {
|
||||||
|
_context = ctx;
|
||||||
|
_id = ++__id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setName("Router " + _id + " shutdown");
|
||||||
|
Log l = _context.logManager().getLog(Router.class);
|
||||||
|
l.log(Log.CRIT, "Shutting down the router...");
|
||||||
|
_context.router().shutdown2(Router.EXIT_HARD);
|
||||||
|
}
|
||||||
|
}
|
24
router/java/src/net/i2p/router/tasks/Spinner.java
Normal file
24
router/java/src/net/i2p/router/tasks/Spinner.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non-daemon thread to let
|
||||||
|
* the shutdown task get all the way to the end
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class Spinner extends Thread {
|
||||||
|
|
||||||
|
public Spinner() {
|
||||||
|
super();
|
||||||
|
setName("Shutdown Spinner");
|
||||||
|
setDaemon(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
sleep(60*1000);
|
||||||
|
} catch (InterruptedException ie) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
package net.i2p.router.tasks;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by jrandom in 2003 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import net.i2p.router.JobImpl;
|
||||||
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the routing Key modifier every day at midnight (plus on startup).
|
||||||
|
* This is done here because we want to make sure the key is updated before anyone
|
||||||
|
* uses it.
|
||||||
|
*
|
||||||
|
* @since 0.8.12 moved from Router.java
|
||||||
|
*/
|
||||||
|
public class UpdateRoutingKeyModifierJob extends JobImpl {
|
||||||
|
private Log _log;
|
||||||
|
private Calendar _cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
||||||
|
|
||||||
|
public UpdateRoutingKeyModifierJob(RouterContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() { return "Update Routing Key Modifier"; }
|
||||||
|
|
||||||
|
public void runJob() {
|
||||||
|
_log = getContext().logManager().getLog(getClass());
|
||||||
|
getContext().routingKeyGenerator().generateDateBasedModData();
|
||||||
|
requeue(getTimeTillMidnight());
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getTimeTillMidnight() {
|
||||||
|
long now = getContext().clock().now();
|
||||||
|
_cal.setTime(new Date(now));
|
||||||
|
_cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround
|
||||||
|
_cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround
|
||||||
|
_cal.add(Calendar.DATE, 1);
|
||||||
|
_cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
_cal.set(Calendar.MINUTE, 0);
|
||||||
|
_cal.set(Calendar.SECOND, 0);
|
||||||
|
_cal.set(Calendar.MILLISECOND, 0);
|
||||||
|
long then = _cal.getTime().getTime();
|
||||||
|
long howLong = then - now;
|
||||||
|
if (howLong < 0) // hi kaffe
|
||||||
|
howLong = 24*60*60*1000l + howLong;
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Time till midnight: " + howLong + "ms");
|
||||||
|
return howLong;
|
||||||
|
}
|
||||||
|
}
|
9
router/java/src/net/i2p/router/tasks/package.html
Normal file
9
router/java/src/net/i2p/router/tasks/package.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Miscellaneous classes, mostly things that are executed periodically as
|
||||||
|
Jobs, Threads, and SimpleTimer.TimedEvents.
|
||||||
|
These are used only by Router.java.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user