/** * Creates the bag for the peers. This peer knows a lot about close peers and the further away the * peers are, the less known they are. Distance is measured with XOR of the peer ID. The distance * of peer with ID 0x12 and peer with Id 0x28 is 0x3a. * * @param self The peer ID of this peer * @param configuration Configuration settings for this map */ public PeerMap( final Number160 self, int bagSize, int cacheTimeoutMillis, int maxNrBeforeExclude, int[] waitingTimeBetweenNodeMaintenenceSeconds, int cachSize, MapAcceptHandler mapHandler) { if (self == null || self.isZero()) throw new IllegalArgumentException("Zero or null are not a valid IDs"); this.self = self; this.peerMapStat = new PeerMapStat(); // The original Kademlia suggests 20, butwe can go much lower, as we // dont have a fixed limit for a bag. The bagSize is a suggestion and if // maxpeers has not been reached, the peer is added even though it // exceeds the bag limit. this.bagSize = bagSize; this.maxPeers = bagSize * Number160.BITS; // The time that a removed peer will be in the cache in milliseconds. this.cacheTimeout = cacheTimeoutMillis; this.maxFail = maxNrBeforeExclude; this.maintenanceTimeoutsSeconds = waitingTimeBetweenNodeMaintenenceSeconds; // The size of the cache of removed peers this.peerOfflineLogs = new CacheMap<PeerAddress, Log>(cachSize, false); this.mapHandler = mapHandler; List<Map<Number160, PeerAddress>> tmp = new ArrayList<Map<Number160, PeerAddress>>(); for (int i = 0; i < Number160.BITS; i++) { // I made some experiments here and concurrent sets are not // necessary, as we divide similar to segments aNonBlockingHashSets // in a // concurrent map. In a full network, we have 160 segments, for // smaller we see around 3-4 segments, growing with the number of // peers. bags closer to 0 will see more read than write, and bags // closer to 160 will see more writes than reads. tmp.add( Collections.<Number160, PeerAddress>synchronizedMap( new HashMap<Number160, PeerAddress>())); } this.peerMap = Collections.unmodifiableList(tmp); this.statistics = new Statistics(peerMap, self, maxPeers, bagSize); }
/** * The distance metric is the XOR metric. * * @param id1 The first id * @param id2 The second id * @return The distance */ static Number160 distance(Number160 id1, Number160 id2) { return id1.xor(id2); }