public PeerId[] NearestPeers(DhtId id, int count) { var cpl = DhtId.CommonPrefixLength(id, _local); lock (_tabLock) { if (cpl >= Buckets.Length) { cpl = Buckets.Length - 1; } var bucket = Buckets[cpl]; var peers = Util.CopyPeersFromList(id, bucket.Peers); if (peers.Count() < count) { if (cpl > 0) { var plist = Buckets[cpl - 1].Peers; peers = Util.CopyPeersFromList(id, plist); } if (cpl < Buckets.Length - 1) { var plist = Buckets[cpl + 1].Peers; peers = Util.CopyPeersFromList(id, plist); } } return(peers.OrderBy(p => p.Distance, new Util.DistanceComparer()) .Take(count) .Select(p => p.P).ToArray()); } }
public Bucket Split(int cpl, DhtId target) { _rwlock.EnterWriteLock(); try { var output = new List <PeerId>(); var newBuck = new Bucket(output); foreach (var e in _list) { var peerId = DhtId.ConvertPeerId(e); var peerCpl = DhtId.CommonPrefixLength(peerId, target); if (peerCpl > cpl) { output.Add(e); } } _list.RemoveAll(output.Contains); return(newBuck); } finally { _rwlock.ExitWriteLock(); } }
public RoutingTable(int bucketSize, DhtId localId, TimeSpan latency, IMetrics metrics) { Buckets = new[] { new Bucket() }; _bucketSize = bucketSize; _local = localId; _maxLatency = latency; _metrics = metrics; _tabLock = new object(); }
public PeerId NearestPeer(DhtId id) { var peers = NearestPeers(id, 1); if (peers.Length > 0) { return(peers[0]); } return(null); }
public PeerId Find(PeerId id) { var srch = NearestPeers(DhtId.ConvertPeerId(id), 1); if (srch.Length == 0 || srch[0] != id) { return(null); } return(srch[0]); }
public void Remove(PeerId p) { lock (_tabLock) { var peerId = DhtId.ConvertPeerId(p); var cpl = DhtId.CommonPrefixLength(peerId, _local); var bucketId = cpl; if (bucketId >= Buckets.Length) { bucketId = Buckets.Length - 1; } var bucket = Buckets[bucketId]; bucket.Remove(p); } }
public void Update(PeerId p) { var peerId = DhtId.ConvertPeerId(p); var cpl = DhtId.CommonPrefixLength(peerId, _local); lock (_tabLock) { var bucketId = cpl; if (bucketId >= Buckets.Length) { bucketId = Buckets.Length - 1; } var bucket = Buckets[bucketId]; if (bucket.Has(p)) { bucket.MoveToFront(p); return; } if (_metrics.LatencyEWMA(p) > _maxLatency) { return; } bucket.PushFront(p); if (bucket.Length > _bucketSize) { if (bucketId == Buckets.Length - 1) { NextBucket(); } else { bucket.PopBack(); } } } }
public static IEnumerable <PeerId> SortClosestPeers(IEnumerable <PeerId> peers, DhtId target) { return(CopyPeersFromList(target, peers) .OrderBy(p => p.Distance, new DistanceComparer()) .Select(p => p.P)); }
public static IEnumerable <PeerDistance> CopyPeersFromList(DhtId target, IEnumerable <PeerId> peers) { return(from peer in peers let pid = DhtId.ConvertPeerId(peer) select new PeerDistance { P = peer, Distance = ((byte[])target).XOR(pid) }); }