Changeset 50f10e8


Ignore:
Timestamp:
Sep 15, 2008 4:22:09 PM (12 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
7c083ed
Parents:
69d9c054
Message:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java

    r69d9c054 r50f10e8  
    2424 * a match from one of those peers, with no fallback to the kademlia search
    2525 *
     26 * Exception (a semi-exception, since we still fail completely without fallback):
     27 * If we don't know any floodfill peers, we ask a couple of peers at random,
     28 * who will hopefully reply with some floodfill keys.
     29 * We still fail without fallback, but we then spin off a job to
     30 * ask that same random peer for the RouterInfos for those keys.
     31 * If that job succeeds, the next search should work better.
     32 *
     33 * In addition, we follow the floodfill keys in the DSRM
     34 * (DatabaseSearchReplyMessage) if we know less than 4 floodfills.
     35 *
     36 * These enhancements allow the router to bootstrap back into the network
     37 * after it loses (or never had) floodfill references, as long as it
     38 * knows one peer that is up.
     39 *
    2640 */
    2741class FloodOnlySearchJob extends FloodSearchJob {
    28     private Log _log;
     42    protected Log _log;
    2943    private FloodfillNetworkDatabaseFacade _facade;
    30     private Hash _key;
     44    protected Hash _key;
    3145    private List _onFind;
    3246    private List _onFailed;
    3347    private long _expiration;
    34     private int _timeoutMs;
     48    protected int _timeoutMs;
    3549    private long _origExpiration;
    3650    private boolean _isLease;
    37     private volatile int _lookupsRemaining;
     51    protected volatile int _lookupsRemaining;
    3852    private volatile boolean _dead;
    3953    private long _created;
     54    private boolean _shouldProcessDSRM;
    4055   
    41     private List _out;
    42     private MessageSelector _replySelector;
    43     private ReplyJob _onReply;
    44     private Job _onTimeout;
     56    protected List _out;
     57    protected MessageSelector _replySelector;
     58    protected ReplyJob _onReply;
     59    protected Job _onTimeout;
    4560    public FloodOnlySearchJob(RouterContext ctx, FloodfillNetworkDatabaseFacade facade, Hash key, Job onFind, Job onFailed, int timeoutMs, boolean isLease) {
    4661        super(ctx, facade, key, onFind, onFailed, timeoutMs, isLease);
     
    6378        _onTimeout = new FloodOnlyLookupTimeoutJob(getContext(), this);
    6479        _created = System.currentTimeMillis();
     80        _shouldProcessDSRM = false;
    6581    }
    6682    void addDeferred(Job onFind, Job onFailed, long timeoutMs, boolean isLease) {
     
    7389    }
    7490    public long getExpiration() { return _expiration; }
     91    public boolean shouldProcessDSRM() { return _shouldProcessDSRM; }
    7592    private static final int CONCURRENT_SEARCHES = 2;
    7693    public void runJob() {
    7794        // pick some floodfill peers and send out the searches
    7895        List floodfillPeers = _facade.getFloodfillPeers();
    79         if (floodfillPeers == null) {
     96        if (floodfillPeers.size() <= 3)
     97            _shouldProcessDSRM = true;
     98        if (floodfillPeers.size() <= 0) {
    8099            if (_log.shouldLog(Log.ERROR))
    81100                _log.error("Running netDb searches against the floodfill peers, but we don't know any");
    82             failed();
    83             return;
     101            floodfillPeers = new ArrayList(_facade.getAllRouters());
     102            if (floodfillPeers.size() <= 0) {
     103                if (_log.shouldLog(Log.ERROR))
     104                    _log.error("We don't know any peers at all");
     105                failed();
     106                return;
     107            }
    84108        }
    85109        OutNetMessage out = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout, _timeoutMs);
     
    211235    private Log _log;
    212236    private FloodOnlySearchJob _search;
     237    private DatabaseSearchReplyMessage _dsrm;
    213238    public FloodOnlyLookupMatchJob(RouterContext ctx, FloodOnlySearchJob job) {
    214239        super(ctx);
    215240        _log = ctx.logManager().getLog(getClass());
    216241        _search = job;
     242        _dsrm = null;
    217243    }
    218244    public void runJob() {
     
    225251            int remaining = _search.getLookupsRemaining();
    226252            if (_log.shouldLog(Log.INFO))
    227                 _log.info(_search.getJobId() + ": got a DatabasSearchReply when we were looking for "
     253                _log.info(_search.getJobId() + ": got a DatabaseSearchReply when we were looking for "
    228254                          + _search.getKey().toBase64() + ", with " + remaining + " outstanding searches");
    229255            // netDb reply pointing us at other people
     256            // Only process if we don't know enough floodfills
     257            if (_search.shouldProcessDSRM() && _dsrm != null) {
     258                if (_log.shouldLog(Log.INFO))
     259                    _log.info(_search.getJobId() + ": Processing DatabaseSearchReply");
     260                // Chase the hashes from the reply
     261                getContext().jobQueue().addJob(new SingleLookupJob(getContext(), _dsrm));
     262            }
    230263            _search.failed();
    231264        }
     
    235268        if (message instanceof DatabaseSearchReplyMessage) {
    236269            // a dsrm is only passed in when there are no more lookups remaining
     270            // If more than one peer sent one, we only process the last one
     271            _dsrm = (DatabaseSearchReplyMessage) message;
    237272            _search.failed();
    238273            return;
     
    289324    }   
    290325}
     326
     327/** Below here, only used to lookup the DSRM reply hashes when we are short of floodfills **/
     328
     329/**
     330 * Ask the peer who sent us the DSRM for the RouterInfos.
     331 * A simple version of SearchReplyJob in SearchJob.java.
     332 * Skip the profile updates - this should be rare.
     333 *
     334 */
     335class SingleLookupJob extends JobImpl {
     336    private Log _log;
     337    private DatabaseSearchReplyMessage _dsrm;
     338    public SingleLookupJob(RouterContext ctx, DatabaseSearchReplyMessage dsrm) {
     339        super(ctx);
     340        _log = ctx.logManager().getLog(getClass());
     341        _dsrm = dsrm;
     342    }
     343    public void runJob() {
     344        Hash from = _dsrm.getFromHash();
     345        for (int i = 0; i < _dsrm.getNumReplies(); i++) {
     346            Hash peer = _dsrm.getReply(i);
     347            if (peer.equals(getContext().routerHash())) // us
     348                continue;
     349            if (getContext().netDb().lookupRouterInfoLocally(peer) == null)
     350                getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, from));
     351        }
     352    }
     353    public String getName() { return "NetDb process DSRM"; }
     354}
     355
     356/**
     357 * Ask a single peer for a single key.
     358 * This isn't really a flood-only search job at all, but we extend
     359 * FloodOnlySearchJob so we can use the same selectors, etc.
     360 *
     361 */
     362class SingleSearchJob extends FloodOnlySearchJob {
     363    Hash _to;
     364    OutNetMessage _onm;
     365    public SingleSearchJob(RouterContext ctx, Hash key, Hash to) {
     366        // warning, null FloodfillNetworkDatabaseFacade ...
     367        // define our own failed() and success() below so _facade isn't used.
     368        super(ctx, null, key, null, null, 5*1000, false);
     369        _to = to;
     370    }
     371    public String getName() { return "NetDb search key from DSRM"; }
     372    public boolean shouldProcessDSRM() { return false; } // don't loop
     373    public void runJob() {
     374        _onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout, _timeoutMs);
     375        DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true);
     376        TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundTunnel();
     377        TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundTunnel();
     378        if ( (replyTunnel == null) || (outTunnel == null) ) {
     379            failed();
     380            return;
     381        }
     382        dlm.setFrom(replyTunnel.getPeer(0));
     383        dlm.setMessageExpiration(getContext().clock().now()+5*1000);
     384        dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0));
     385        dlm.setSearchKey(_key);
     386       
     387        if (_log.shouldLog(Log.INFO))
     388            _log.info(getJobId() + ": Single search for " + _key.toBase64() + " to " + _to.toBase64());
     389        getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to);
     390        _lookupsRemaining = 1;
     391    }
     392    void failed() {
     393        getContext().messageRegistry().unregisterPending(_onm);
     394    }
     395    void success() {}
     396}
Note: See TracChangeset for help on using the changeset viewer.