Changeset 7b758d89


Ignore:
Timestamp:
Jan 8, 2009 7:27:57 PM (12 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
ed34964
Parents:
1c7111e
Message:
Location:
router/java/src/net/i2p/router/networkdb/kademlia
Files:
6 edited

Legend:

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

    r1c7111e r7b758d89  
    88import java.util.Set;
    99
     10import net.i2p.data.DataFormatException;
    1011import net.i2p.data.DataStructure;
    1112import net.i2p.data.Hash;
     
    3334    private Map _activeFloodQueries;
    3435    private boolean _floodfillEnabled;
     36    /** for testing, see isFloodfill() below */
     37    private static String _alwaysQuery;
    3538   
    3639    public FloodfillNetworkDatabaseFacade(RouterContext context) {
     
    3841        _activeFloodQueries = new HashMap();
    3942         _floodfillEnabled = false;
     43        _alwaysQuery = _context.getProperty("netDb.alwaysQuery");
    4044
    4145        _context.statManager().createRateStat("netDb.successTime", "How long a successful search takes", "NetworkDatabase", new long[] { 60*60*1000l, 24*60*60*1000l });
     
    138142    public static boolean isFloodfill(RouterInfo peer) {
    139143        if (peer == null) return false;
     144        // For testing or local networks... we will
     145        // pretend that the specified router is floodfill.
     146        // Must be set at startup since it's static.
     147        // In that router, set netDb.floodfillOnly=false.
     148        // Warning - experts only!
     149        if (_alwaysQuery != null) {
     150            Hash aq = new Hash();
     151            try {
     152                aq.fromBase64(_alwaysQuery);
     153                if (aq.equals(peer.getIdentity().getHash()))
     154                    return true;
     155            } catch (DataFormatException dfe) {}
     156        }
    140157        String caps = peer.getCapabilities();
    141158        if ( (caps != null) && (caps.indexOf(FloodfillNetworkDatabaseFacade.CAPACITY_FLOODFILL) != -1) )
  • router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java

    r1c7111e r7b758d89  
    7979        }
    8080        public List getFloodfillParticipants() { return _floodfillMatches; }
     81        private static final int EXTRA_MATCHES = 100;
    8182        public void add(Hash entry) {
    8283            //if (_context.profileOrganizer().isFailing(entry))
     
    99100                _floodfillMatches.add(entry);
    100101            } else {
    101                 if ( (!SearchJob.onlyQueryFloodfillPeers(_context)) && (_wanted > _matches) && (_key != null) ) {
     102                // This didn't really work because we stopped filling up when _wanted == _matches,
     103                // thus we don't add and sort the whole db to find the closest.
     104                // So we keep going for a while. This, together with periodically shuffling the
     105                // KBucket (see KBucketImpl.add()) makes exploration work well.
     106                if ( (!SearchJob.onlyQueryFloodfillPeers(_context)) && (_wanted + EXTRA_MATCHES > _matches) && (_key != null) ) {
    102107                    BigInteger diff = getDistance(_key, entry);
    103108                    _sorted.put(diff, entry);
  • router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java

    r1c7111e r7b758d89  
    1111import java.math.BigInteger;
    1212import java.util.ArrayList;
     13import java.util.Collections;
    1314import java.util.HashSet;
    1415import java.util.Iterator;
     
    1920import net.i2p.data.DataHelper;
    2021import net.i2p.data.Hash;
     22import net.i2p.router.RouterContext;
    2123import net.i2p.util.Log;
    2224import net.i2p.util.RandomSource;
     
    3234    /** include if no bits higher than this bit (inclusive) are set */
    3335    private int _end;
     36    /** when did we last shake things up */
     37    private long _lastShuffle;
     38    private static final int SHUFFLE_DELAY = 10*60*1000;
    3439    private I2PAppContext _context;
    3540   
     
    3843        _log = context.logManager().getLog(KBucketImpl.class);
    3944        _entries = new ArrayList(64); //new HashSet();
     45        _lastShuffle = context.clock().now();
    4046        setLocal(local);
    4147    }
     
    233239            if (!_entries.contains(peer))
    234240                _entries.add(peer);
     241            // Randomize the bucket every once in a while if we are floodfill, so that
     242            // exploration will return better results. See FloodfillPeerSelector.add(Hash).
     243            if (_lastShuffle + SHUFFLE_DELAY < _context.clock().now() &&
     244                !SearchJob.onlyQueryFloodfillPeers((RouterContext)_context)) {
     245                Collections.shuffle(_entries, _context.random());
     246                _lastShuffle = _context.clock().now();
     247            }
    235248            return _entries.size();
    236249        }
     
    246259     * Generate a random key to go within this bucket
    247260     *
     261     * WARNING - Something is seriously broken here. testRand2() fails right away.
     262     * ExploreKeySelectorJob is now disabled, ExploreJob just searches for a random
     263     * key instead.
    248264     */
    249265    public Hash generateRandomKey() {
     
    337353     * Test harness to make sure its assigning keys to the right buckets
    338354     *
     355     * WARNING - Something is seriously broken here. testRand2() fails right away.
    339356     */
    340357    public static void main(String args[]) {
  • router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java

    r1c7111e r7b758d89  
    299299        if (!_quiet) {
    300300            // fill the passive queue periodically
     301            // Is this pointless too???
    301302            _context.jobQueue().addJob(new DataRepublishingSelectorJob(_context, this));
    302303            // fill the search queue with random keys in buckets that are too small
    303             _context.jobQueue().addJob(new ExploreKeySelectorJob(_context, this));
     304            // Disabled since KBucketImpl.generateRandomKey() is b0rked,
     305            // and anyway, we want to search for a completely random key,
     306            // not a random key for a particular kbucket.
     307            // _context.jobQueue().addJob(new ExploreKeySelectorJob(_context, this));
    304308            if (_exploreJob == null)
    305309                _exploreJob = new StartExplorersJob(_context, this);
  • router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java

    r1c7111e r7b758d89  
    1010
    1111import java.util.ArrayList;
     12import java.util.HashSet;
    1213import java.util.Iterator;
    1314import java.util.List;
     
    122123    private static final boolean DEFAULT_FLOODFILL_ONLY = true;
    123124   
     125    /** this is now misnamed, as it is only used to determine whether to return floodfill peers only */
    124126    static boolean onlyQueryFloodfillPeers(RouterContext ctx) {
    125         if (isCongested(ctx))
    126             return true;
     127        //if (isCongested(ctx))
     128        //    return true;
    127129        // If we are floodfill, we want the FloodfillPeerSelector (in add()) to include
    128130        // non-ff peers (if required) in DatabaseSearchReplyMessage responses
     
    131133        // The other two places this was called (one below and one in FNDF)
    132134        // have been commented out.
     135        // Returning false essentially enables kademlia as a backup to floodfill for search responses.
    133136        if (FloodfillNetworkDatabaseFacade.floodfillEnabled(ctx))
    134137            return false;
     
    136139    }
    137140   
     141/***
    138142    static boolean isCongested(RouterContext ctx) {
    139143        float availableSend = ctx.bandwidthLimiter().getOutboundKBytesPerSecond()*1024 - ctx.bandwidthLimiter().getSendBps();
     
    143147        return ( (availableSend < 6*1024) || (availableRecv < 6*1024) );
    144148    }
     149***/
    145150   
    146151    static final int PER_FLOODFILL_PEER_TIMEOUT = 10*1000;
     
    783788    boolean wasAttempted(Hash peer) { return _state.wasAttempted(peer); }
    784789    long timeoutMs() { return _timeoutMs; }
    785     boolean add(Hash peer) { return _facade.getKBuckets().add(peer); }
     790
     791    /** @return true if peer was new */
     792    boolean add(Hash peer) {
     793        boolean rv = _facade.getKBuckets().add(peer);
     794        if (rv) {
     795            if (_log.shouldLog(Log.DEBUG))
     796                _log.debug(getJobId() + ": Queueing up for next time: " + peer);
     797            Set s = new HashSet(1);
     798            s.add(peer);
     799            _facade.queueForExploration(s);
     800        }
     801        return rv;
     802    }
    786803    void decrementOutstandingFloodfillSearches() { _floodfillSearchesOutstanding--; }
    787804}
  • router/java/src/net/i2p/router/networkdb/kademlia/StartExplorersJob.java

    r1c7111e r7b758d89  
    2121 * Fire off search jobs for random keys from the explore pool, up to MAX_PER_RUN
    2222 * at a time.
     23 * If the explore pool is empty, just search for a random key.
    2324 *
    2425 */
     
    8384     * Run through the explore pool and pick out some values
    8485     *
     86     * Nope, ExploreKeySelectorJob is disabled, so the explore pool
     87     * may be empty. In that case, generate random keys.
    8588     */
    8689    private Set selectKeysToExplore() {
     
    8891        if (_log.shouldLog(Log.DEBUG))
    8992            _log.debug("Keys waiting for exploration: " + queued.size());
    90         if (queued.size() <= MAX_PER_RUN)
    91             return queued;
    9293        Set rv = new HashSet(MAX_PER_RUN);
    9394        for (Iterator iter = queued.iterator(); iter.hasNext(); ) {
     
    9596            rv.add(iter.next());
    9697        }
     98        for (int i = rv.size(); i < MAX_PER_RUN; i++) {
     99            byte hash[] = new byte[Hash.HASH_LENGTH];
     100            getContext().random().nextBytes(hash);
     101            Hash key = new Hash(hash);
     102            rv.add(key);
     103        }
    97104        return rv;
    98105    }
Note: See TracChangeset for help on using the changeset viewer.