Changeset ea07471


Ignore:
Timestamp:
Nov 27, 2009 2:39:53 PM (11 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
8682e7d
Parents:
1334977
Message:
  • NetDb?:
    • Switch from ArrayList? to ConcurrentHashSet? in KBucketImpl to reduce chance of deadlock; remove periodic shuffling of the bucket, needs to be addressed elsewhere
Location:
router/java/src/net/i2p/router/networkdb/kademlia
Files:
4 edited

Legend:

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

    r1334977 rea07471  
    5757     * @return set of Hash structures
    5858     */
    59     public Set getEntries();
     59    public Set<Hash> getEntries();
    6060    /**
    6161     * Retrieve hashes stored in the bucket, excluding the ones specified
    6262     * @return set of Hash structures
    6363     */
    64     public Set getEntries(Set toIgnoreHashes);
     64    public Set<Hash> getEntries(Set<Hash> toIgnoreHashes);
    6565    public void getEntries(SelectionCollector collector);
    6666   
     
    6969     * @param entries set of Hash structures
    7070     */
    71     public void setEntries(Set entries);
     71    public void setEntries(Set<Hash> entries);
    7272
    7373    /**
  • router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java

    r1334977 rea07471  
    1010
    1111import java.math.BigInteger;
    12 import java.util.ArrayList;
    1312import java.util.Collections;
    1413import java.util.HashSet;
    1514import java.util.Iterator;
    16 import java.util.List;
    1715import java.util.Set;
    1816
     
    2119import net.i2p.data.Hash;
    2220import net.i2p.router.RouterContext;
     21import net.i2p.util.ConcurrentHashSet;
    2322import net.i2p.util.Log;
    2423import net.i2p.util.RandomSource;
     
    2625class KBucketImpl implements KBucket {
    2726    private Log _log;
    28     /** set of Hash objects for the peers in the kbucket */
    29     private final List _entries;
     27    /**
     28     *  set of Hash objects for the peers in the kbucketx
     29     *
     30     *  jrandom switched from a HashSet to an ArrayList with this change:
     31     *  2005-08-27  jrandom
     32     *    * Minor logging and optimization tweaks in the router and SDK
     33     *
     34     *  Now we switch back to a ConcurrentHashSet and remove all the
     35     *  synchronization, which may or may not be faster than
     36     *  a synchronized ArrayList, with checks for existence before
     37     *  adding a Hash. But the other benefit is it removes one
     38     *  cause of profileMangager/netDb deadlock.
     39     */
     40    private final Set<Hash> _entries;
    3041    /** we center the kbucket set on the given hash, and derive distances from this */
    3142    private Hash _local;
     
    4253        _context = context;
    4354        _log = context.logManager().getLog(KBucketImpl.class);
    44         _entries = new ArrayList(0); //all but the last 1 or 2 buckets will be empty
     55        _entries = new ConcurrentHashSet(2); //all but the last 1 or 2 buckets will be empty
    4556        _lastShuffle = context.clock().now();
    4657        setLocal(local);
     
    5465    }
    5566    public int getKeyCount() {
    56         synchronized (_entries) {
    57             return _entries.size();
    58         }
     67        return _entries.size();
    5968    }
    6069   
     
    199208    }
    200209   
    201     public Set getEntries() {
    202         Set entries = new HashSet(64);
    203         synchronized (_entries) {
    204             for (int i = 0; i < _entries.size(); i++)
    205                 entries.add((Hash)_entries.get(i));
    206         }
     210    public Set<Hash> getEntries() {
     211        Set<Hash> entries = new HashSet(_entries);
    207212        return entries;
    208213    }
    209     public Set getEntries(Set toIgnoreHashes) {
    210         Set entries = new HashSet(64);
    211         synchronized (_entries) {
    212             for (int i = 0; i < _entries.size(); i++)
    213                 entries.add((Hash)_entries.get(i));
    214             entries.removeAll(toIgnoreHashes);
    215         }
     214    public Set<Hash> getEntries(Set toIgnoreHashes) {
     215        Set<Hash> entries = new HashSet(_entries);
     216        entries.removeAll(toIgnoreHashes);
    216217        return entries;
    217218    }
    218219   
    219220    public void getEntries(SelectionCollector collector) {
    220         synchronized (_entries) {
    221             for (int i = 0; i < _entries.size(); i++)
    222                 collector.add((Hash)_entries.get(i));
    223         }
    224     }
    225    
    226     public void setEntries(Set entries) {
    227         synchronized (_entries) {
    228             _entries.clear();
    229             for (Iterator iter = entries.iterator(); iter.hasNext(); ) {
    230                 Hash entry = (Hash)iter.next();
    231                 if (!_entries.contains(entry))
    232                     _entries.add(entry);
    233             }
    234         }
    235     }
    236    
     221        Set<Hash> entries = new HashSet(_entries);
     222        for (Hash h : entries) {
     223                collector.add(h);
     224        }
     225    }
     226   
     227    public void setEntries(Set<Hash> entries) {
     228        _entries.clear();
     229        _entries.addAll(entries);
     230    }
     231   
     232    /**
     233     *  Todo: shuffling here is a hack and doesn't work since
     234     *  wwe witched back to a HashSet implementation
     235     */
    237236    public int add(Hash peer) {
    238         synchronized (_entries) {
    239             if (!_entries.contains(peer))
    240                 _entries.add(peer);
     237            _entries.add(peer);
     238/**********
    241239            // Randomize the bucket every once in a while if we are floodfill, so that
    242240            // exploration will return better results. See FloodfillPeerSelector.add(Hash).
     
    246244                _lastShuffle = _context.clock().now();
    247245            }
    248             return _entries.size();
    249         }
     246***********/
     247        return _entries.size();
    250248    }
    251249   
    252250    public boolean remove(Hash peer) {
    253         synchronized (_entries) {
    254             return _entries.remove(peer);
    255         }
     251        return _entries.remove(peer);
    256252    }
    257253   
     
    333329        StringBuilder buf = new StringBuilder(1024);
    334330        buf.append("KBucketImpl: ");
    335         synchronized (_entries) {
    336             buf.append(_entries.toString()).append("\n");
    337         }
     331        buf.append(_entries.toString()).append("\n");
    338332        buf.append("Low bit: ").append(_begin).append(" high bit: ").append(_end).append('\n');
    339333        buf.append("Local key: \n");
  • router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java

    r1334977 rea07471  
    1010
    1111import java.math.BigInteger;
     12import java.util.Collections;
    1213import java.util.HashSet;
    1314import java.util.Set;
     
    8990    }
    9091   
    91     public Set getAll() { return getAll(new HashSet()); }
    92     public Set getAll(Set toIgnore) {
    93         HashSet all = new HashSet(1024);
     92    public Set<Hash> getAll() { return getAll(Collections.EMPTY_SET); };
     93    public Set<Hash> getAll(Set<Hash> toIgnore) {
     94        Set<Hash> all = new HashSet(1024);
    9495        for (int i = 0; i < _buckets.length; i++) {
    9596            all.addAll(_buckets[i].getEntries(toIgnore));
  • router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java

    r1334977 rea07471  
    122122        }
    123123        public void add(Hash entry) {
    124             if (_context.profileOrganizer().isFailing(entry))
    125                 return;
     124            // deadlock seen here, and we don't mark profiles failing anymore
     125            //if (_context.profileOrganizer().isFailing(entry))
     126            //    return;
    126127            if (_toIgnore.contains(entry))
    127128                return;
Note: See TracChangeset for help on using the changeset viewer.