package net.i2p.router.networkdb.kademlia;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.i2p.data.Hash;
import net.i2p.data.router.RouterInfo;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Go through all the routers once, after startup, and refetch their router infos.
* This should be run once after startup (and preferably after any reseed is complete,
* but we don't have any indication when that is).
* This will help routers that start after being shutdown for many days or weeks,
* as well as newly-reseeded routers, since
* validate() in KNDF doesn't start failing and refetching until the router has been
* up for an hour.
* To improve integration even more, we fetch the floodfills first.
* Ideally this should complete within the first half-hour of uptime.
*
* @since 0.8.8
*/
class RefreshRoutersJob extends JobImpl {
private final Log _log;
private final FloodfillNetworkDatabaseFacade _facade;
private List<Hash> _routers;
/** rerun fairly often. 1000 routers in 50 minutes
* Don't go faster as this overloads the expl. OBEP / IBGW
*/
private final static long RERUN_DELAY_MS = 3*1000;
private final static long EXPIRE = 2*60*60*1000;
public RefreshRoutersJob(RouterContext ctx, FloodfillNetworkDatabaseFacade facade) {
super(ctx);
_log = ctx.logManager().getLog(RefreshRoutersJob.class);
_facade = facade;
}
public String getName() { return "Refresh Routers Job"; }
public void runJob() {
if (_facade.isInitialized()) {
if (_routers == null) {
// make a list of all routers, floodfill first
_routers = _facade.getFloodfillPeers();
int ff = _routers.size();
Set<Hash> all = _facade.getAllRouters();
all.removeAll(_routers);
int non = all.size();
_routers.addAll(all);
if (_log.shouldLog(Log.INFO))
_log.info("To check: " + ff + " floodfills and " + non + " non-floodfills");
}
if (_routers.isEmpty()) {
if (_log.shouldLog(Log.INFO))
_log.info("Finished");
return;
}
long expire = getContext().clock().now() - EXPIRE;
for (Iterator<Hash> iter = _routers.iterator(); iter.hasNext(); ) {
Hash h = iter.next();
iter.remove();
if (h.equals(getContext().routerHash()))
continue;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Checking " + h);
RouterInfo ri = _facade.lookupRouterInfoLocally(h);
if (ri == null)
continue;
if (ri.getPublished() < expire) {
if (_log.shouldLog(Log.INFO))
_log.info("Refreshing " + h);
_facade.search(h, null, null, 15*1000, false);
break;
}
}
}
requeue(RERUN_DELAY_MS);
}
}