diff --git a/core/src/main/groovy/com/muwire/core/MuWireSettings.groovy b/core/src/main/groovy/com/muwire/core/MuWireSettings.groovy index 5fb08622..298a782a 100644 --- a/core/src/main/groovy/com/muwire/core/MuWireSettings.groovy +++ b/core/src/main/groovy/com/muwire/core/MuWireSettings.groovy @@ -24,7 +24,7 @@ class MuWireSettings { boolean shareDownloadedFiles Set watchedDirectories float downloadSequentialRatio - int hostClearInterval, hostHopelessInterval + int hostClearInterval, hostHopelessInterval, hostRejectInterval int meshExpiration boolean embeddedRouter int inBw, outBw @@ -52,6 +52,7 @@ class MuWireSettings { downloadSequentialRatio = Float.valueOf(props.getProperty("downloadSequentialRatio","0.8")) hostClearInterval = Integer.valueOf(props.getProperty("hostClearInterval","15")) hostHopelessInterval = Integer.valueOf(props.getProperty("hostHopelessInterval", "1440")) + hostRejectInterval = Integer.valueOf(props.getProperty("hostRejectInterval", "1")) meshExpiration = Integer.valueOf(props.getProperty("meshExpiration","60")) embeddedRouter = Boolean.valueOf(props.getProperty("embeddedRouter","false")) inBw = Integer.valueOf(props.getProperty("inBw","256")) @@ -88,6 +89,7 @@ class MuWireSettings { props.setProperty("downloadSequentialRatio", String.valueOf(downloadSequentialRatio)) props.setProperty("hostClearInterval", String.valueOf(hostClearInterval)) props.setProperty("hostHopelessInterval", String.valueOf(hostHopelessInterval)) + props.setProperty("hostRejectInterval", String.valueOf(hostRejectInterval)) props.setProperty("meshExpiration", String.valueOf(meshExpiration)) props.setProperty("embeddedRouter", String.valueOf(embeddedRouter)) props.setProperty("inBw", String.valueOf(inBw)) diff --git a/core/src/main/groovy/com/muwire/core/hostcache/Host.groovy b/core/src/main/groovy/com/muwire/core/hostcache/Host.groovy index 1278bc43..88c6defa 100644 --- a/core/src/main/groovy/com/muwire/core/hostcache/Host.groovy +++ b/core/src/main/groovy/com/muwire/core/hostcache/Host.groovy @@ -7,23 +7,34 @@ class Host { private static final int MAX_FAILURES = 3 final Destination destination - private final int clearInterval, hopelessInterval + private final int clearInterval, hopelessInterval, rejectionInterval int failures,successes long lastAttempt long lastSuccessfulAttempt + long lastRejection - public Host(Destination destination, int clearInterval, int hopelessInterval) { + public Host(Destination destination, int clearInterval, int hopelessInterval, int rejectionInterval) { this.destination = destination this.clearInterval = clearInterval this.hopelessInterval = hopelessInterval + this.rejectionInterval = rejectionInterval } - - synchronized void onConnect() { + + private void connectSuccessful() { failures = 0 successes++ lastAttempt = System.currentTimeMillis() + } + + synchronized void onConnect() { + connectSuccessful() lastSuccessfulAttempt = lastAttempt } + + synchronized void onReject() { + connectSuccessful() + lastRejection = lastAttempt; + } synchronized void onFailure() { failures++ @@ -43,13 +54,17 @@ class Host { failures = 0 } - synchronized void canTryAgain() { + synchronized boolean canTryAgain() { lastSuccessfulAttempt > 0 && System.currentTimeMillis() - lastAttempt > (clearInterval * 60 * 1000) } - synchronized void isHopeless() { + synchronized boolean isHopeless() { isFailed() && System.currentTimeMillis() - lastSuccessfulAttempt > (hopelessInterval * 60 * 1000) } + + synchronized boolean isRecentlyRejected() { + System.currentTimeMillis() - lastRejection < (rejectionInterval * 60 * 1000) + } } diff --git a/core/src/main/groovy/com/muwire/core/hostcache/HostCache.groovy b/core/src/main/groovy/com/muwire/core/hostcache/HostCache.groovy index ce3c99e7..d59e1a37 100644 --- a/core/src/main/groovy/com/muwire/core/hostcache/HostCache.groovy +++ b/core/src/main/groovy/com/muwire/core/hostcache/HostCache.groovy @@ -52,7 +52,7 @@ class HostCache extends Service { hosts.get(e.destination).clearFailures() return } - Host host = new Host(e.destination, settings.hostClearInterval, settings.hostHopelessInterval) + Host host = new Host(e.destination, settings.hostClearInterval, settings.hostHopelessInterval, settings.hostRejectInterval) if (allowHost(host)) { hosts.put(e.destination, host) } @@ -64,15 +64,17 @@ class HostCache extends Service { Destination dest = e.endpoint.destination Host host = hosts.get(dest) if (host == null) { - host = new Host(dest, settings.hostClearInterval, settings.hostHopelessInterval) + host = new Host(dest, settings.hostClearInterval, settings.hostHopelessInterval, settings.hostRejectInterval) hosts.put(dest, host) } switch(e.status) { case ConnectionAttemptStatus.SUCCESSFUL: - case ConnectionAttemptStatus.REJECTED: host.onConnect() break + case ConnectionAttemptStatus.REJECTED: + host.onReject() + break case ConnectionAttemptStatus.FAILED: host.onFailure() break @@ -84,7 +86,7 @@ class HostCache extends Service { rv.retainAll {allowHost(hosts[it])} rv.removeAll { def h = hosts[it]; - h.isFailed() && !h.canTryAgain() + (h.isFailed() && !h.canTryAgain()) || h.isRecentlyRejected() } if (rv.size() <= n) return rv @@ -110,13 +112,15 @@ class HostCache extends Service { storage.eachLine { def entry = slurper.parseText(it) Destination dest = new Destination(entry.destination) - Host host = new Host(dest, settings.hostClearInterval, settings.hostHopelessInterval) + Host host = new Host(dest, settings.hostClearInterval, settings.hostHopelessInterval, settings.hostRejectInterval) host.failures = Integer.valueOf(String.valueOf(entry.failures)) host.successes = Integer.valueOf(String.valueOf(entry.successes)) if (entry.lastAttempt != null) host.lastAttempt = entry.lastAttempt if (entry.lastSuccessfulAttempt != null) host.lastSuccessfulAttempt = entry.lastSuccessfulAttempt + if (entry.lastRejection != null) + host.lastRejection = entry.lastRejection if (allowHost(host)) hosts.put(dest, host) } @@ -151,6 +155,7 @@ class HostCache extends Service { map.successes = host.successes map.lastAttempt = host.lastAttempt map.lastSuccessfulAttempt = host.lastSuccessfulAttempt + map.lastRejection = host.lastRejection def json = JsonOutput.toJson(map) writer.println json }