From 87889bb3224a6fad7681cd3fe1497a0b09d069c3 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 27 Apr 2014 18:46:11 +0000 Subject: [PATCH] * UDP: - Locking fixes on peer testing - More locking fixes on rebuilding address - Slow down peer test frequency, esp. when firewalled * Transports: - Deprecate unused recheckReachability() --- .../net/i2p/router/web/ConfigNetHandler.java | 6 +- .../src/net/i2p/router/CommSystemFacade.java | 5 ++ .../transport/CommSystemFacadeImpl.java | 4 + .../net/i2p/router/transport/Transport.java | 5 ++ .../i2p/router/transport/TransportImpl.java | 5 ++ .../router/transport/TransportManager.java | 3 + .../router/transport/udp/UDPTransport.java | 85 ++++++++++++++----- 7 files changed, 91 insertions(+), 22 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java index dd626fbfc9..c52634b885 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -57,8 +57,8 @@ public class ConfigNetHandler extends FormHandler { protected void processForm() { if (_saveRequested || ( (_action != null) && (_("Save changes").equals(_action)) )) { saveChanges(); - } else if (_recheckReachabilityRequested) { - recheckReachability(); + //} else if (_recheckReachabilityRequested) { + // recheckReachability(); } else { // noop } @@ -137,10 +137,12 @@ public class ConfigNetHandler extends FormHandler { _ipv6Mode = mode; } +/**** private void recheckReachability() { _context.commSystem().recheckReachability(); addFormNotice(_("Rechecking router reachability...")); } +****/ /** * The user made changes to the network config and wants to save them, so diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index 591fd81793..9c7d92338d 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -53,7 +53,12 @@ public abstract class CommSystemFacade implements Service { * */ public short getReachabilityStatus() { return STATUS_OK; } + + /** + * @deprecated unused + */ public void recheckReachability() {} + public boolean isBacklogged(Hash dest) { return false; } public boolean wasUnreachable(Hash dest) { return false; } public boolean isEstablished(Hash dest) { return false; } diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index 7a7887ef4b..c9242305eb 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -173,6 +173,10 @@ public class CommSystemFacadeImpl extends CommSystemFacade { return STATUS_OK; return rv; } + + /** + * @deprecated unused + */ @Override public void recheckReachability() { _manager.recheckReachability(); } diff --git a/router/java/src/net/i2p/router/transport/Transport.java b/router/java/src/net/i2p/router/transport/Transport.java index 3a44cdcea8..e232fa7e46 100644 --- a/router/java/src/net/i2p/router/transport/Transport.java +++ b/router/java/src/net/i2p/router/transport/Transport.java @@ -132,7 +132,12 @@ public interface Transport { public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException; public short getReachabilityStatus(); + + /** + * @deprecated unused + */ public void recheckReachability(); + public boolean isBacklogged(Hash peer); /** diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index 127bd39d9c..0e588df180 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -703,7 +703,12 @@ public abstract class TransportImpl implements Transport { public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { renderStatusHTML(out); } public short getReachabilityStatus() { return CommSystemFacade.STATUS_UNKNOWN; } + + /** + * @deprecated unused + */ public void recheckReachability() {} + public boolean isBacklogged(Hash dest) { return false; } public boolean isEstablished(Hash dest) { return false; } diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index afe937bb73..d9e0c37985 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -308,6 +308,9 @@ public class TransportManager implements TransportEventListener { return rv; } + /** + * @deprecated unused + */ public void recheckReachability() { for (Transport t : _transports.values()) t.recheckReachability(); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 415e8f7e97..87bf576a8b 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -77,6 +77,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private final PacketBuilder _destroyBuilder; private short _reachabilityStatus; private long _reachabilityStatusLastUpdated; + private int _reachabilityStatusUnchanged; private long _introducersSelectedOn; private long _lastInboundReceivedOn; private final DHSessionKeyBuilder.Factory _dhFactory; @@ -189,6 +190,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority public static final int DEFAULT_COST = 5; private static final int TEST_FREQUENCY = 13*60*1000; + private static final int MIN_TEST_FREQUENCY = 45*1000; static final long[] RATES = { 10*60*1000 }; private static final int[] BID_VALUES = { 15, 20, 50, 65, 80, 95, 100, 115, TransportBid.TRANSIENT_FAIL }; @@ -909,8 +911,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } _context.router().rebuildRouterInfo(); } - _testEvent.forceRun(); - _testEvent.reschedule(5*1000); + _testEvent.forceRunImmediately(); return updated; } @@ -1160,11 +1161,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (oldEstablishedOn > 0) _context.statManager().addRateData("udp.alreadyConnected", oldEstablishedOn, 0); - rebuildIfNecessary(); - - if (getReachabilityStatus() != CommSystemFacade.STATUS_OK) { - _testEvent.forceRun(); - _testEvent.reschedule(0); + synchronized(_rebuildLock) { + rebuildIfNecessary(); + if (getReachabilityStatus() != CommSystemFacade.STATUS_OK && + _reachabilityStatusUnchanged < 7) { + _testEvent.forceRunSoon(); + } } return true; } @@ -1831,6 +1833,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority boolean introducersRequired = (!isIPv6) && introducersRequired(); boolean introducersIncluded = false; if (introducersRequired || !directIncluded) { + // FIXME intro manager doesn't sort introducers, so + // deepEquals() below can fail even with same introducers. + // Only a problem when we have very very few peers to pick from. int found = _introManager.pickInbound(options, PUBLIC_RELAY_COUNT); if (found > 0) { if (_log.shouldLog(Log.INFO)) @@ -3014,14 +3019,25 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority //} break; } + _testEvent.setLastTested(); + if (status != CommSystemFacade.STATUS_UNKNOWN) { + if (status != old) + _reachabilityStatusUnchanged = 0; + else + _reachabilityStatusUnchanged++; + } if ( (status != old) && (status != CommSystemFacade.STATUS_UNKNOWN) ) { - if (_log.shouldLog(Log.INFO)) - _log.info("Old status: " + old + " New status: " + status + " from: ", new Exception("traceback")); + if (_log.shouldLog(Log.WARN)) + _log.warn("Old status: " + old + " New status: " + status + " from: ", new Exception("traceback")); // Always rebuild when the status changes, even if our address hasn't changed, // as rebuildExternalAddress() calls replaceAddress() which calls CSFI.notifyReplaceAddress() // which will start up NTCP inbound when we transition to OK. // if (needsRebuild()) rebuildExternalAddress(); + } else { + if (_log.shouldLog(Log.INFO)) + _log.info("Status unchanged: " + _reachabilityStatus + " (" + _reachabilityStatusUnchanged + " consecutive times), last updated " + + DataHelper.formatDuration(_context.clock().now() - _reachabilityStatusLastUpdated) + " ago"); } } @@ -3043,9 +3059,13 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return _reachabilityStatus; } + /** + * @deprecated unused + */ @Override public void recheckReachability() { - _testEvent.runTest(); + // FIXME locking if we do this again + //_testEvent.runTest(); } /** @@ -3105,7 +3125,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * Initiate a test (we are Alice) */ private class PeerTestEvent extends SimpleTimer2.TimedEvent { - private volatile boolean _alive; + private boolean _alive; /** when did we last test our reachability */ private long _lastTested; private boolean _forceRun; @@ -3114,22 +3134,20 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority super(_context.simpleTimer2()); } - public void timeReached() { + public synchronized void timeReached() { if (shouldTest()) { - long now = _context.clock().now(); - if ( (_forceRun) || (now - _lastTested >= TEST_FREQUENCY) ) { - runTest(); + long sinceRun = _context.clock().now() - _lastTested; + if ( (_forceRun && sinceRun >= MIN_TEST_FREQUENCY) || (sinceRun >= TEST_FREQUENCY) ) { + locked_runTest(); } } if (_alive) { long delay = (TEST_FREQUENCY / 2) + _context.random().nextInt(TEST_FREQUENCY); - if (delay <= 0) - throw new RuntimeException("wtf, delay is " + delay); schedule(delay); } } - private void runTest() { + private void locked_runTest() { PeerState bob = pickTestPeer(BOB, null); if (bob != null) { if (_log.shouldLog(Log.INFO)) @@ -3145,9 +3163,27 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _forceRun = false; } - void forceRun() { _forceRun = true; } + /** + * Run within the next 45 seconds at the latest + * @since 0.9.13 + */ + public synchronized void forceRunSoon() { + _forceRun = true; + reschedule(MIN_TEST_FREQUENCY); + } - public void setIsAlive(boolean isAlive) { + /** + * + * Run within the next 5 seconds at the latest + * @since 0.9.13 + */ + public synchronized void forceRunImmediately() { + _lastTested = 0; + _forceRun = true; + reschedule(5*1000); + } + + public synchronized void setIsAlive(boolean isAlive) { _alive = isAlive; if (isAlive) { long delay = _context.random().nextInt(2*TEST_FREQUENCY); @@ -3156,6 +3192,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority cancel(); } } + + /** + * Set the last-tested timer to now + * @since 0.9.13 + */ + public synchronized void setLastTested() { + _lastTested = _context.clock().now(); + } + } /** -- GitLab