|
|
|
@ -1,403 +1,27 @@
|
|
|
|
|
package net.i2p.router.peermanager;
|
|
|
|
|
|
|
|
|
|
import net.i2p.data.DataHelper;
|
|
|
|
|
import net.i2p.router.RouterContext;
|
|
|
|
|
import net.i2p.stat.Rate;
|
|
|
|
|
import net.i2p.stat.RateStat;
|
|
|
|
|
import net.i2p.util.Log;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Quantify how fast the peer is - how fast they respond to our requests, how fast
|
|
|
|
|
* they pass messages on, etc. This should be affected both by their bandwidth/latency,
|
|
|
|
|
* as well as their load. The essence of the current algorithm is to determine
|
|
|
|
|
* approximately how many 2KB messages the peer can pass round trip within a single
|
|
|
|
|
* minute - not based just on itself though, but including the delays of other peers
|
|
|
|
|
* in the tunnels. As such, more events make it more accurate.
|
|
|
|
|
* as well as their load.
|
|
|
|
|
*
|
|
|
|
|
* IMPORTANT -
|
|
|
|
|
* This code has been through many iterations, and some versions were quite complex.
|
|
|
|
|
* If you are considering changes, review the change control history, and
|
|
|
|
|
* see the previous versions in change control to get 400+ lines of old code.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public class SpeedCalculator extends Calculator {
|
|
|
|
|
private Log _log;
|
|
|
|
|
private RouterContext _context;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* minimum number of events to use a particular period's data. If this many
|
|
|
|
|
* events haven't occurred in the period yet, the next largest period is tried.
|
|
|
|
|
*/
|
|
|
|
|
public static final String PROP_EVENT_THRESHOLD = "speedCalculator.eventThreshold";
|
|
|
|
|
public static final int DEFAULT_EVENT_THRESHOLD = 50;
|
|
|
|
|
/** should the calculator use instantaneous rates, or period averages? */
|
|
|
|
|
public static final String PROP_USE_INSTANTANEOUS_RATES = "speedCalculator.useInstantaneousRates";
|
|
|
|
|
public static final boolean DEFAULT_USE_INSTANTANEOUS_RATES = false;
|
|
|
|
|
/** should the calculator use tunnel test time only, or include all data? */
|
|
|
|
|
public static final String PROP_USE_TUNNEL_TEST_ONLY = "speedCalculator.useTunnelTestOnly";
|
|
|
|
|
public static final boolean DEFAULT_USE_TUNNEL_TEST_ONLY = false;
|
|
|
|
|
|
|
|
|
|
public SpeedCalculator(RouterContext context) {
|
|
|
|
|
_context = context;
|
|
|
|
|
_log = context.logManager().getLog(SpeedCalculator.class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double calc(PeerProfile profile) {
|
|
|
|
|
if (true) // measures 1 minute throughput of individual tunnels
|
|
|
|
|
return profile.getPeakTunnel1mThroughputKBps()*1024d;
|
|
|
|
|
if (true) // measures throughput of individual tunnels
|
|
|
|
|
return profile.getPeakTunnelThroughputKBps()*1024d;
|
|
|
|
|
if (true) // measures throughput across all tunnels
|
|
|
|
|
return profile.getPeakThroughputKBps()*1024d;
|
|
|
|
|
if (true)
|
|
|
|
|
return calcAverage(profile);
|
|
|
|
|
long threshold = getEventThreshold();
|
|
|
|
|
boolean tunnelTestOnly = getUseTunnelTestOnly();
|
|
|
|
|
|
|
|
|
|
long period = 10*60*1000;
|
|
|
|
|
long events = getEventCount(profile, period, tunnelTestOnly);
|
|
|
|
|
if (events < threshold) {
|
|
|
|
|
period = 60*60*1000l;
|
|
|
|
|
events = getEventCount(profile, period, tunnelTestOnly);
|
|
|
|
|
if (events < threshold) {
|
|
|
|
|
period = 24*60*60*1000;
|
|
|
|
|
events = getEventCount(profile, period, tunnelTestOnly);
|
|
|
|
|
if (events < threshold) {
|
|
|
|
|
period = -1;
|
|
|
|
|
events = getEventCount(profile, period, tunnelTestOnly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double measuredRoundTripTime = getMeasuredRoundTripTime(profile, period, tunnelTestOnly);
|
|
|
|
|
double measuredRTPerMinute = 0;
|
|
|
|
|
if (measuredRoundTripTime > 0)
|
|
|
|
|
measuredRTPerMinute = (60000.0d / measuredRoundTripTime);
|
|
|
|
|
|
|
|
|
|
double estimatedRTPerMinute = 0;
|
|
|
|
|
double estimatedRoundTripTime = 0;
|
|
|
|
|
if (!tunnelTestOnly) {
|
|
|
|
|
estimatedRoundTripTime = getEstimatedRoundTripTime(profile, period);
|
|
|
|
|
if (estimatedRoundTripTime > 0)
|
|
|
|
|
estimatedRTPerMinute = (60000.0d / estimatedRoundTripTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double estimateFactor = getEstimateFactor(threshold, events);
|
|
|
|
|
double rv = (1-estimateFactor)*measuredRTPerMinute + (estimateFactor)*estimatedRTPerMinute;
|
|
|
|
|
|
|
|
|
|
long slowCount = 0;
|
|
|
|
|
RateStat rs = profile.getTunnelTestResponseTimeSlow();
|
|
|
|
|
if (rs != null) {
|
|
|
|
|
Rate r = rs.getRate(period);
|
|
|
|
|
if (r != null)
|
|
|
|
|
slowCount = r.getCurrentEventCount();
|
|
|
|
|
}
|
|
|
|
|
long fastCount = 0;
|
|
|
|
|
rs = profile.getTunnelTestResponseTime();
|
|
|
|
|
if (rs != null) {
|
|
|
|
|
Rate r = rs.getRate(period);
|
|
|
|
|
if (r != null)
|
|
|
|
|
fastCount = r.getCurrentEventCount();
|
|
|
|
|
}
|
|
|
|
|
double slowPct = 0;
|
|
|
|
|
if (fastCount > 0)
|
|
|
|
|
slowPct = slowCount / fastCount;
|
|
|
|
|
else
|
|
|
|
|
rv /= 100; // if there are no tunnel tests, weigh against it
|
|
|
|
|
if (slowPct > 0.01) // if 1% of the traffic is dogshit slow, the peer probably sucks
|
|
|
|
|
rv /= 100.0*slowPct;
|
|
|
|
|
|
|
|
|
|
rv = adjust(period, rv);
|
|
|
|
|
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG)) {
|
|
|
|
|
_log.debug("\n\nrv: " + rv + " events: " + events + " threshold: " + threshold + " period: " + period + " useTunnelTestOnly? " + tunnelTestOnly + "\n"
|
|
|
|
|
+ "measuredRTT: " + measuredRoundTripTime + " measured events per minute: " + measuredRTPerMinute + "\n"
|
|
|
|
|
+ "estimateRTT: " + estimatedRoundTripTime + " estimated events per minute: " + estimatedRTPerMinute + "\n"
|
|
|
|
|
+ "slow count: " + slowCount + " fast count: " + fastCount + "\n"
|
|
|
|
|
+ "estimateFactor: " + estimateFactor + "\n"
|
|
|
|
|
+ "for peer: " + profile.getPeer().toBase64());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv += profile.getSpeedBonus();
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calcAverage(PeerProfile profile) {
|
|
|
|
|
double avg = profile.getTunnelTestTimeAverage();
|
|
|
|
|
if (avg == 0)
|
|
|
|
|
return 0.0;
|
|
|
|
|
else
|
|
|
|
|
return (60.0*1000.0) / avg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double adjust(long period, double value) {
|
|
|
|
|
switch ((int)period) {
|
|
|
|
|
case 10*60*1000:
|
|
|
|
|
return value;
|
|
|
|
|
case 60*60*1000:
|
|
|
|
|
return value * 0.75;
|
|
|
|
|
case 24*60*60*1000:
|
|
|
|
|
return value * 0.1;
|
|
|
|
|
default:
|
|
|
|
|
return value * 0.01;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* How much do we want to prefer the measured values more than the estimated
|
|
|
|
|
* values, as a fraction. The value 1 means ignore the measured values, while
|
|
|
|
|
* the value 0 means ignore the estimate, and everything inbetween means, well
|
|
|
|
|
* everything inbetween.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private double getEstimateFactor(long eventThreshold, long numEvents) {
|
|
|
|
|
if (true) return 0.0d; // never use the estimate
|
|
|
|
|
if (numEvents > eventThreshold)
|
|
|
|
|
return 0.0d;
|
|
|
|
|
else
|
|
|
|
|
return numEvents / eventThreshold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* How many measured events do we have for the given period? If the period is negative,
|
|
|
|
|
* return the lifetime events.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private long getEventCount(PeerProfile profile, long period, boolean tunnelTestOnly) {
|
|
|
|
|
if (period < 0) {
|
|
|
|
|
Rate dbResponseRate = profile.getDbResponseTime().getRate(60*60*1000l);
|
|
|
|
|
Rate tunnelResponseRate = profile.getTunnelCreateResponseTime().getRate(60*60*1000l);
|
|
|
|
|
Rate tunnelTestRate = profile.getTunnelTestResponseTime().getRate(60*60*1000l);
|
|
|
|
|
|
|
|
|
|
long dbResponses = tunnelTestOnly ? 0 : dbResponseRate.getLifetimeEventCount();
|
|
|
|
|
long tunnelResponses = tunnelTestOnly ? 0 : tunnelResponseRate.getLifetimeEventCount();
|
|
|
|
|
long tunnelTests = tunnelTestRate.getLifetimeEventCount();
|
|
|
|
|
|
|
|
|
|
return dbResponses + tunnelResponses + tunnelTests;
|
|
|
|
|
} else {
|
|
|
|
|
Rate dbResponseRate = profile.getDbResponseTime().getRate(period);
|
|
|
|
|
Rate tunnelResponseRate = profile.getTunnelCreateResponseTime().getRate(period);
|
|
|
|
|
Rate tunnelTestRate = profile.getTunnelTestResponseTime().getRate(period);
|
|
|
|
|
|
|
|
|
|
long dbResponses = tunnelTestOnly ? 0 : dbResponseRate.getCurrentEventCount() + dbResponseRate.getLastEventCount();
|
|
|
|
|
long tunnelResponses = tunnelTestOnly ? 0 : tunnelResponseRate.getCurrentEventCount() + tunnelResponseRate.getLastEventCount();
|
|
|
|
|
long tunnelTests = tunnelTestRate.getCurrentEventCount() + tunnelTestRate.getLastEventCount();
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("TunnelTests for period " + period + ": " + tunnelTests +
|
|
|
|
|
" last: " + tunnelTestRate.getLastEventCount() + " lifetime: " +
|
|
|
|
|
tunnelTestRate.getLifetimeEventCount());
|
|
|
|
|
|
|
|
|
|
return dbResponses + tunnelResponses + tunnelTests;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieve the average measured round trip time within the period specified (including
|
|
|
|
|
* db responses, tunnel create responses, and tunnel tests). If the period is negative,
|
|
|
|
|
* it uses the lifetime stats. In addition, it weights each of those three measurements
|
|
|
|
|
* equally according to their event count (e.g. 4 dbResponses @ 10 seconds and 1 tunnel test
|
|
|
|
|
* at 5 seconds will leave the average at 9 seconds)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private double getMeasuredRoundTripTime(PeerProfile profile, long period, boolean tunnelTestOnly) {
|
|
|
|
|
double activityTime = 0;
|
|
|
|
|
double rtt = 0;
|
|
|
|
|
double dbResponseTime = 0;
|
|
|
|
|
double tunnelResponseTime = 0;
|
|
|
|
|
double tunnelTestTime = 0;
|
|
|
|
|
|
|
|
|
|
long dbResponses = 0;
|
|
|
|
|
long tunnelResponses = 0;
|
|
|
|
|
long tunnelTests = 0;
|
|
|
|
|
|
|
|
|
|
long events = 0;
|
|
|
|
|
|
|
|
|
|
if (period < 0) {
|
|
|
|
|
Rate dbResponseRate = profile.getDbResponseTime().getRate(60*60*1000l);
|
|
|
|
|
Rate tunnelResponseRate = profile.getTunnelCreateResponseTime().getRate(60*60*1000l);
|
|
|
|
|
Rate tunnelTestRate = profile.getTunnelTestResponseTime().getRate(60*60*1000l);
|
|
|
|
|
|
|
|
|
|
dbResponses = tunnelTestOnly ? 0 : dbResponseRate.getLifetimeEventCount();
|
|
|
|
|
tunnelResponses = tunnelTestOnly ? 0 : tunnelResponseRate.getLifetimeEventCount();
|
|
|
|
|
tunnelTests = tunnelTestRate.getLifetimeEventCount();
|
|
|
|
|
|
|
|
|
|
dbResponseTime = tunnelTestOnly ? 0 : dbResponseRate.getLifetimeAverageValue();
|
|
|
|
|
tunnelResponseTime = tunnelTestOnly ? 0 : tunnelResponseRate.getLifetimeAverageValue();
|
|
|
|
|
tunnelTestTime = tunnelTestRate.getLifetimeAverageValue();
|
|
|
|
|
|
|
|
|
|
events = dbResponses + tunnelResponses + tunnelTests;
|
|
|
|
|
if (events <= 0) return 0;
|
|
|
|
|
activityTime = (dbResponses*dbResponseTime + tunnelResponses*tunnelResponseTime + tunnelTests*tunnelTestTime);
|
|
|
|
|
rtt = activityTime / events;
|
|
|
|
|
} else {
|
|
|
|
|
Rate dbResponseRate = profile.getDbResponseTime().getRate(period);
|
|
|
|
|
Rate tunnelResponseRate = profile.getTunnelCreateResponseTime().getRate(period);
|
|
|
|
|
Rate tunnelTestRate = profile.getTunnelTestResponseTime().getRate(period);
|
|
|
|
|
|
|
|
|
|
dbResponses = tunnelTestOnly ? 0 : dbResponseRate.getCurrentEventCount() + dbResponseRate.getLastEventCount();
|
|
|
|
|
tunnelResponses = tunnelTestOnly ? 0 : tunnelResponseRate.getCurrentEventCount() + tunnelResponseRate.getLastEventCount();
|
|
|
|
|
tunnelTests = tunnelTestRate.getCurrentEventCount() + tunnelTestRate.getLastEventCount();
|
|
|
|
|
|
|
|
|
|
if (!tunnelTestOnly) {
|
|
|
|
|
dbResponseTime = avg(dbResponseRate);
|
|
|
|
|
tunnelResponseTime = avg(tunnelResponseRate);
|
|
|
|
|
}
|
|
|
|
|
tunnelTestTime = avg(tunnelTestRate);
|
|
|
|
|
|
|
|
|
|
events = dbResponses + tunnelResponses + tunnelTests;
|
|
|
|
|
if (events <= 0) return 0;
|
|
|
|
|
activityTime = (dbResponses*dbResponseTime + tunnelResponses*tunnelResponseTime + tunnelTests*tunnelTestTime);
|
|
|
|
|
rtt = activityTime / events;
|
|
|
|
|
}
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("\nMeasured response time for " + profile.getPeer().toBase64() + " over "
|
|
|
|
|
+ DataHelper.formatDuration(period) + " with activityTime of " + activityTime
|
|
|
|
|
+ ": " + rtt + "\nover " + events + " events ("
|
|
|
|
|
+ dbResponses + " dbResponses, " + tunnelResponses + " tunnelResponses, "
|
|
|
|
|
+ tunnelTests + " tunnelTests)\ntimes ("
|
|
|
|
|
+ dbResponseTime + "ms, " + tunnelResponseTime + "ms, "
|
|
|
|
|
+ tunnelTestTime + "ms respectively)");
|
|
|
|
|
return rtt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double avg(Rate rate) {
|
|
|
|
|
long events = rate.getCurrentEventCount() + rate.getLastEventCount();
|
|
|
|
|
long time = rate.getCurrentTotalEventTime() + rate.getLastTotalEventTime();
|
|
|
|
|
if ( (events > 0) && (time > 0) )
|
|
|
|
|
return time / events;
|
|
|
|
|
else
|
|
|
|
|
// measures 1 minute throughput of individual tunnels
|
|
|
|
|
double d = (profile.getPeakTunnel1mThroughputKBps()*1024d) + profile.getSpeedBonus();
|
|
|
|
|
if (d >= 0) return d;
|
|
|
|
|
return 0.0d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double getEstimatedRoundTripTime(PeerProfile profile, long period) {
|
|
|
|
|
double estSendTime = getEstimatedSendTime(profile, period);
|
|
|
|
|
double estRecvTime = getEstimatedReceiveTime(profile, period);
|
|
|
|
|
return estSendTime + estRecvTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double getEstimatedSendTime(PeerProfile profile, long period) {
|
|
|
|
|
double bps = calcRate(profile.getSendSuccessSize(), period);
|
|
|
|
|
if (bps <= 0)
|
|
|
|
|
return 0.0d;
|
|
|
|
|
else
|
|
|
|
|
return 2048.0d / bps;
|
|
|
|
|
}
|
|
|
|
|
private double getEstimatedReceiveTime(PeerProfile profile, long period) {
|
|
|
|
|
double bps = calcRate(profile.getReceiveSize(), period);
|
|
|
|
|
if (bps <= 0)
|
|
|
|
|
return 0.0d;
|
|
|
|
|
else
|
|
|
|
|
return 2048.0d / bps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calcRate(RateStat stat, long period) {
|
|
|
|
|
Rate rate = stat.getRate(period);
|
|
|
|
|
if (rate == null) return 0.0d;
|
|
|
|
|
return calcRate(rate, period);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calcRate(Rate rate, long period) {
|
|
|
|
|
long events = rate.getCurrentEventCount();
|
|
|
|
|
if (events >= 1) {
|
|
|
|
|
double ms = rate.getCurrentTotalEventTime();
|
|
|
|
|
double bytes = rate.getCurrentTotalValue();
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("calculating rate: ms=" + ((int)ms) + " bytes=" + ((int)bytes));
|
|
|
|
|
if ( (bytes > 0) && (ms > 0) ) {
|
|
|
|
|
if (getUseInstantaneousRates()) {
|
|
|
|
|
return (bytes * 1000.0d) / ms;
|
|
|
|
|
} else {
|
|
|
|
|
// period average
|
|
|
|
|
return (bytes * 1000.0d) / period;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0.0d;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* What is the minimum number of measured events we want in a period before
|
|
|
|
|
* trusting the values? This first checks the router's configuration, then
|
|
|
|
|
* the context, and then finally falls back on a static default (100).
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private long getEventThreshold() {
|
|
|
|
|
if (_context.router() != null) {
|
|
|
|
|
String threshold = _context.router().getConfigSetting(PROP_EVENT_THRESHOLD);
|
|
|
|
|
if (threshold != null) {
|
|
|
|
|
try {
|
|
|
|
|
return Long.parseLong(threshold);
|
|
|
|
|
} catch (NumberFormatException nfe) {
|
|
|
|
|
if (_log.shouldLog(Log.WARN))
|
|
|
|
|
_log.warn("Event threshold for speed improperly set in the router config [" + threshold + "]", nfe);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String threshold = _context.getProperty(PROP_EVENT_THRESHOLD, ""+DEFAULT_EVENT_THRESHOLD);
|
|
|
|
|
if (threshold != null) {
|
|
|
|
|
try {
|
|
|
|
|
return Long.parseLong(threshold);
|
|
|
|
|
} catch (NumberFormatException nfe) {
|
|
|
|
|
if (_log.shouldLog(Log.WARN))
|
|
|
|
|
_log.warn("Event threshold for speed improperly set in the router environment [" + threshold + "]", nfe);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return DEFAULT_EVENT_THRESHOLD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Should we use instantaneous rates for the estimated speed, or the period rates?
|
|
|
|
|
* This first checks the router's configuration, then the context, and then
|
|
|
|
|
* finally falls back on a static default (true).
|
|
|
|
|
*
|
|
|
|
|
* @return true if we should use instantaneous rates, false if we should use period averages
|
|
|
|
|
*/
|
|
|
|
|
private boolean getUseInstantaneousRates() {
|
|
|
|
|
if (_context.router() != null) {
|
|
|
|
|
String val = _context.router().getConfigSetting(PROP_USE_INSTANTANEOUS_RATES);
|
|
|
|
|
if (val != null) {
|
|
|
|
|
return Boolean.valueOf(val).booleanValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String val = _context.getProperty(PROP_USE_INSTANTANEOUS_RATES, ""+DEFAULT_USE_INSTANTANEOUS_RATES);
|
|
|
|
|
if (val != null) {
|
|
|
|
|
return Boolean.valueOf(val).booleanValue();
|
|
|
|
|
}
|
|
|
|
|
return DEFAULT_USE_INSTANTANEOUS_RATES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Should we only use the measured tunnel testing time, or should we include
|
|
|
|
|
* measurements on the db responses and tunnel create responses. This first
|
|
|
|
|
* checks the router's configuration, then the context, and then finally falls
|
|
|
|
|
* back on a static default (true).
|
|
|
|
|
*
|
|
|
|
|
* @return true if we should use tunnel test time only, false if we should use all available
|
|
|
|
|
*/
|
|
|
|
|
private boolean getUseTunnelTestOnly() {
|
|
|
|
|
if (_context.router() != null) {
|
|
|
|
|
String val = _context.router().getConfigSetting(PROP_USE_TUNNEL_TEST_ONLY);
|
|
|
|
|
if (val != null) {
|
|
|
|
|
try {
|
|
|
|
|
boolean rv = Boolean.getBoolean(val);
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("router config said " + PROP_USE_TUNNEL_TEST_ONLY + '=' + val);
|
|
|
|
|
return rv;
|
|
|
|
|
} catch (NumberFormatException nfe) {
|
|
|
|
|
if (_log.shouldLog(Log.WARN))
|
|
|
|
|
_log.warn("Tunnel test only for speed improperly set in the router config [" + val + "]", nfe);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String val = _context.getProperty(PROP_USE_TUNNEL_TEST_ONLY, ""+DEFAULT_USE_TUNNEL_TEST_ONLY);
|
|
|
|
|
if (val != null) {
|
|
|
|
|
try {
|
|
|
|
|
boolean rv = Boolean.getBoolean(val);
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("router context said " + PROP_USE_TUNNEL_TEST_ONLY + '=' + val);
|
|
|
|
|
} catch (NumberFormatException nfe) {
|
|
|
|
|
if (_log.shouldLog(Log.WARN))
|
|
|
|
|
_log.warn("Tunnel test only for speed improperly set in the router environment [" + val + "]", nfe);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_log.shouldLog(Log.DEBUG))
|
|
|
|
|
_log.debug("no config for " + PROP_USE_TUNNEL_TEST_ONLY + ", using " + DEFAULT_USE_TUNNEL_TEST_ONLY);
|
|
|
|
|
return DEFAULT_USE_TUNNEL_TEST_ONLY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|