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.NoSuchElementException; import java.util.Set; import net.i2p.data.DatabaseEntry; import net.i2p.data.Hash; import net.i2p.router.Job; import net.i2p.router.RouterContext; import net.i2p.util.Log; /** * This extends StoreJob to fire off a FloodfillVerifyStoreJob after success. * * Stores through this class always request a reply. * */ class FloodfillStoreJob extends StoreJob { private final FloodfillNetworkDatabaseFacade _facade; private static final String PROP_RI_VERIFY = "router.verifyRouterInfoStore"; /** * Send a data structure to the floodfills * */ public FloodfillStoreJob(RouterContext context, FloodfillNetworkDatabaseFacade facade, Hash key, DatabaseEntry data, Job onSuccess, Job onFailure, long timeoutMs) { this(context, facade, key, data, onSuccess, onFailure, timeoutMs, null); } /** * @param toSkip set of peer hashes of people we dont want to send the data to (e.g. we * already know they have it). This can be null. */ public FloodfillStoreJob(RouterContext context, FloodfillNetworkDatabaseFacade facade, Hash key, DatabaseEntry data, Job onSuccess, Job onFailure, long timeoutMs, Set<Hash> toSkip) { super(context, facade, key, data, onSuccess, onFailure, timeoutMs, toSkip); _facade = facade; } @Override protected int getParallelization() { return 1; } @Override protected int getRedundancy() { return 1; } /** * Send was totally successful */ @Override protected void succeed() { super.succeed(); if (_facade.isVerifyInProgress(_state.getTarget())) { if (_log.shouldLog(Log.INFO)) _log.info("Skipping verify, one already in progress for: " + _state.getTarget()); return; } if (getContext().router().gracefulShutdownInProgress()) { if (_log.shouldLog(Log.INFO)) _log.info("Skipping verify, shutdown in progress for: " + _state.getTarget()); return; } // Get the time stamp from the data we sent, so the Verify job can meke sure that // it finds something stamped with that time or newer. DatabaseEntry data = _state.getData(); boolean isRouterInfo = data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO; // default false since 0.9.7.1 if (isRouterInfo && !getContext().getBooleanProperty(PROP_RI_VERIFY)) { _facade.routerInfoPublishSuccessful(); return; } long published = data.getDate(); // we should always have exactly one successful entry Hash sentTo = null; try { sentTo = _state.getSuccessful().iterator().next(); } catch (NoSuchElementException nsee) {} getContext().jobQueue().addJob(new FloodfillVerifyStoreJob(getContext(), _state.getTarget(), published, isRouterInfo, sentTo, _facade)); } @Override public String getName() { return "Floodfill netDb store"; } }