add a max failuires parameter when deciding whether to expire a host. Report the number of negative hosts in the info rpc

This commit is contained in:
Zlatin Balevsky
2020-04-29 12:20:23 +01:00
parent 028a8d5044
commit 9167c9edf7
4 changed files with 22 additions and 14 deletions

View File

@@ -10,18 +10,19 @@ class Host {
final Persona persona final Persona persona
long lastPinged long lastPinged
long lastResponded long lastResponded
int failures
volatile String xHave volatile String xHave
Host(Persona persona) { Host(Persona persona) {
this.persona = persona this.persona = persona
} }
boolean isExpired(long cutoff) { boolean isExpired(long cutoff, int maxFailures) {
lastPinged > lastResponded && lastResponded <= cutoff lastPinged > lastResponded && lastResponded <= cutoff && failures >= maxFailures
} }
@Override @Override
public String toString() { public String toString() {
"Host:[${persona.getHumanReadableName()} lastPinged:$lastPinged lastResponded:$lastResponded xHave:$xHave]" "Host:[${persona.getHumanReadableName()} lastPinged:$lastPinged lastResponded:$lastResponded failures:$failures xHave:$xHave]"
} }
} }

View File

@@ -46,17 +46,17 @@ class Swarm {
/** /**
* @param cutoff expire hosts older than this * @param cutoff expire hosts older than this
*/ */
synchronized void expire(long cutoff) { synchronized void expire(long cutoff, int maxFailures) {
doExpire(cutoff, seeds) doExpire(cutoff, maxFailures, seeds)
doExpire(cutoff, leeches) doExpire(cutoff, maxFailures, leeches)
doExpire(cutoff, unknown) doExpire(cutoff, maxFailures, unknown)
} }
private static void doExpire(long cutoff, Map<Persona,Host> map) { private static void doExpire(long cutoff, int maxFailures, Map<Persona,Host> map) {
for (Iterator<Persona> iter = map.keySet().iterator(); iter.hasNext();) { for (Iterator<Persona> iter = map.keySet().iterator(); iter.hasNext();) {
Persona p = iter.next() Persona p = iter.next()
Host h = map.get(p) Host h = map.get(p)
if (h.isExpired(cutoff)) if (h.isExpired(cutoff, maxFailures))
iter.remove() iter.remove()
} }
} }
@@ -90,7 +90,8 @@ class Swarm {
if (responder != h) if (responder != h)
log.warning("received a response mismatch from host $responder vs $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) { switch(code) {
case 200: addSeed(responder); break case 200: addSeed(responder); break
case 206 : addLeech(responder); break; case 206 : addLeech(responder); break;
@@ -103,6 +104,7 @@ class Swarm {
Host h = inFlight.remove(failed.persona) Host h = inFlight.remove(failed.persona)
if (h != failed) if (h != failed)
log.warning("failed a host that wasn't in flight $failed vs $h") log.warning("failed a host that wasn't in flight $failed vs $h")
h.failures++
} }
private void addSeed(Host h) { private void addSeed(Host h) {
@@ -163,17 +165,18 @@ class Swarm {
public Info info() { public Info info() {
List<String> seeders = seeds.keySet().collect { it.getHumanReadableName() } List<String> seeders = seeds.keySet().collect { it.getHumanReadableName() }
List<String> leechers = leeches.keySet().collect { it.getHumanReadableName() } List<String> 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 { public static class Info {
final List<String> seeders, leechers final List<String> seeders, leechers
final int unknown final int unknown, negative
Info(List<String> seeders, List<String> leechers, int unknown) { Info(List<String> seeders, List<String> leechers, int unknown, int negative) {
this.seeders = seeders this.seeders = seeders
this.leechers = leechers this.leechers = leechers
this.unknown = unknown this.unknown = unknown
this.negative = negative
} }
} }
} }

View File

@@ -68,7 +68,8 @@ class SwarmManager {
private void trackSwarms() { private void trackSwarms() {
final long now = System.currentTimeMillis() final long now = System.currentTimeMillis()
final long expiryCutoff = now - trackerProperties.getSwarmParameters().getExpiry() * 60 * 1000L 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 final long queryCutoff = now - trackerProperties.getSwarmParameters().getQueryInterval() * 60 * 60 * 1000L
swarms.values().each { swarms.values().each {
if (it.shouldQuery(queryCutoff, now)) if (it.shouldQuery(queryCutoff, now))
@@ -136,6 +137,7 @@ class SwarmManager {
} }
void fail(HostAndIH target) { void fail(HostAndIH target) {
log.info("failing $target")
swarms.get(target.infoHash)?.fail(target.host) swarms.get(target.infoHash)?.fail(target.host)
} }

View File

@@ -27,5 +27,7 @@ class TrackerProperties {
int expiry = 60 int expiry = 60
/** how long to wait for a host to respond to a ping, in seconds */ /** how long to wait for a host to respond to a ping, in seconds */
int pingTimeout = 20 int pingTimeout = 20
/** Do not expire a host until it has failed this many times */
int maxFailures = 3
} }
} }