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
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]"
}
}

View File

@ -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<Persona,Host> map) {
private static void doExpire(long cutoff, int maxFailures, Map<Persona,Host> map) {
for (Iterator<Persona> 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<String> seeders = seeds.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 {
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.leechers = leechers
this.unknown = unknown
this.negative = negative
}
}
}

View File

@ -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)
}

View File

@ -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
}
}