package net.i2p.router.networkdb.kademlia;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.util.Set;
import net.i2p.data.DatabaseEntry;
import net.i2p.data.Hash;
import net.i2p.data.router.RouterInfo;
import net.i2p.router.CommSystemFacade.Status;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Go through the routing table pick routers that are
* is out of date, but don't expire routers we're actively connected to.
*
* We could in the future use profile data, netdb total size, a Kademlia XOR distance,
* or other criteria to minimize netdb size, but for now we just use _facade's
* validate(), which is a sliding expriation based on netdb size.
*
*/
class ExpireRoutersJob extends JobImpl {
private final Log _log;
private final KademliaNetworkDatabaseFacade _facade;
/** rerun fairly often, so the fails don't queue up too many netdb searches at once */
private final static long RERUN_DELAY_MS = 5*60*1000;
public ExpireRoutersJob(RouterContext ctx, KademliaNetworkDatabaseFacade facade) {
super(ctx);
_log = ctx.logManager().getLog(ExpireRoutersJob.class);
_facade = facade;
}
public String getName() { return "Expire Routers Job"; }
public void runJob() {
if (getContext().commSystem().getStatus() != Status.DISCONNECTED) {
int removed = expireKeys();
if (_log.shouldLog(Log.INFO))
_log.info("Routers expired: " + removed);
}
requeue(RERUN_DELAY_MS);
}
/**
* Run through all of the known peers and pick ones that have really old
* routerInfo publish dates, excluding ones that we are connected to,
* so that they can be failed
*
* @return number removed
*/
private int expireKeys() {
Set<Hash> keys = _facade.getAllRouters();
keys.remove(getContext().routerHash());
if (keys.size() < 150)
return 0;
int removed = 0;
for (Hash key : keys) {
// Don't expire anybody we are connected to
if (!getContext().commSystem().isEstablished(key)) {
DatabaseEntry e = _facade.lookupLocallyWithoutValidation(key);
if (e != null &&
e.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
try {
if (_facade.validate((RouterInfo) e) != null) {
_facade.dropAfterLookupFailed(key);
removed++;
}
} catch (IllegalArgumentException iae) {
_facade.dropAfterLookupFailed(key);
removed++;
}
}
}
}
return removed;
}
}