diff --git a/tracker/src/main/groovy/com/muwire/tracker/Host.groovy b/tracker/src/main/groovy/com/muwire/tracker/Host.groovy index 8b38920c..eae0d24c 100644 --- a/tracker/src/main/groovy/com/muwire/tracker/Host.groovy +++ b/tracker/src/main/groovy/com/muwire/tracker/Host.groovy @@ -10,18 +10,19 @@ class Host { final Persona persona long lastPinged long lastResponded + int failures volatile String xHave Host(Persona persona) { this.persona = persona } - boolean isExpired(long cutoff) { - lastPinged > lastResponded && lastResponded <= cutoff + boolean isExpired(long cutoff, int maxFailures) { + lastPinged > lastResponded && lastResponded <= cutoff && failures >= maxFailures } @Override public String toString() { - "Host:[${persona.getHumanReadableName()} lastPinged:$lastPinged lastResponded:$lastResponded xHave:$xHave]" + "Host:[${persona.getHumanReadableName()} lastPinged:$lastPinged lastResponded:$lastResponded failures:$failures xHave:$xHave]" } } diff --git a/tracker/src/main/groovy/com/muwire/tracker/Swarm.groovy b/tracker/src/main/groovy/com/muwire/tracker/Swarm.groovy index 7cf95093..0cb71ee0 100644 --- a/tracker/src/main/groovy/com/muwire/tracker/Swarm.groovy +++ b/tracker/src/main/groovy/com/muwire/tracker/Swarm.groovy @@ -46,17 +46,17 @@ class Swarm { /** * @param cutoff expire hosts older than this */ - synchronized void expire(long cutoff) { - doExpire(cutoff, seeds) - doExpire(cutoff, leeches) - doExpire(cutoff, unknown) + synchronized void expire(long cutoff, int maxFailures) { + doExpire(cutoff, maxFailures, seeds) + doExpire(cutoff, maxFailures, leeches) + doExpire(cutoff, maxFailures, unknown) } - private static void doExpire(long cutoff, Map map) { + private static void doExpire(long cutoff, int maxFailures, Map map) { for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { Persona p = iter.next() Host h = map.get(p) - if (h.isExpired(cutoff)) + if (h.isExpired(cutoff, maxFailures)) iter.remove() } } @@ -90,7 +90,8 @@ class Swarm { if (responder != h) log.warning("received a response mismatch from host $responder vs $h") - responder.lastResponded = System.currentTimeMillis() + responder.lastResponded = System.currentTimeMillis() + responder.failures = 0 switch(code) { case 200: addSeed(responder); break case 206 : addLeech(responder); break; @@ -103,6 +104,7 @@ class Swarm { Host h = inFlight.remove(failed.persona) if (h != failed) log.warning("failed a host that wasn't in flight $failed vs $h") + h.failures++ } private void addSeed(Host h) { @@ -163,17 +165,18 @@ class Swarm { public Info info() { List seeders = seeds.keySet().collect { it.getHumanReadableName() } List leechers = leeches.keySet().collect { it.getHumanReadableName() } - return new Info(seeders, leechers, unknown.size()) + return new Info(seeders, leechers, unknown.size(), negative.size()) } public static class Info { final List seeders, leechers - final int unknown + final int unknown, negative - Info(List seeders, List leechers, int unknown) { + Info(List seeders, List leechers, int unknown, int negative) { this.seeders = seeders this.leechers = leechers this.unknown = unknown + this.negative = negative } } } diff --git a/tracker/src/main/groovy/com/muwire/tracker/SwarmManager.groovy b/tracker/src/main/groovy/com/muwire/tracker/SwarmManager.groovy index 3a925ed6..e56a45b7 100644 --- a/tracker/src/main/groovy/com/muwire/tracker/SwarmManager.groovy +++ b/tracker/src/main/groovy/com/muwire/tracker/SwarmManager.groovy @@ -68,7 +68,8 @@ class SwarmManager { private void trackSwarms() { final long now = System.currentTimeMillis() final long expiryCutoff = now - trackerProperties.getSwarmParameters().getExpiry() * 60 * 1000L - swarms.values().each { it.expire(expiryCutoff) } + final int maxFailures = trackerProperties.getSwarmParameters().getMaxFailures() + swarms.values().each { it.expire(expiryCutoff, maxFailures) } final long queryCutoff = now - trackerProperties.getSwarmParameters().getQueryInterval() * 60 * 60 * 1000L swarms.values().each { if (it.shouldQuery(queryCutoff, now)) @@ -136,6 +137,7 @@ class SwarmManager { } void fail(HostAndIH target) { + log.info("failing $target") swarms.get(target.infoHash)?.fail(target.host) } diff --git a/tracker/src/main/groovy/com/muwire/tracker/TrackerProperties.groovy b/tracker/src/main/groovy/com/muwire/tracker/TrackerProperties.groovy index 3fcda9ef..aa25229c 100644 --- a/tracker/src/main/groovy/com/muwire/tracker/TrackerProperties.groovy +++ b/tracker/src/main/groovy/com/muwire/tracker/TrackerProperties.groovy @@ -27,5 +27,7 @@ class TrackerProperties { int expiry = 60 /** how long to wait for a host to respond to a ping, in seconds */ int pingTimeout = 20 + /** Do not expire a host until it has failed this many times */ + int maxFailures = 3 } }