public void Remove() { var bucket = new KBucket <Contact>(); Assert.AreEqual(0, bucket.Count); bucket.Add(new Contact("a")); bucket.Add(new Contact("b")); bucket.Add(new Contact("c")); Assert.AreEqual(3, bucket.Count); bucket.Remove(new Contact("b")); Assert.AreEqual(2, bucket.Count); Assert.IsTrue(bucket.Contains(new Contact("a"))); Assert.IsFalse(bucket.Contains(new Contact("b"))); Assert.IsTrue(bucket.Contains(new Contact("c"))); }
public void Add() { var bucket = new KBucket <Contact>(); var x = new Contact("1"); bucket.Add(x); Assert.AreEqual(1, bucket.Count); Assert.IsTrue(bucket.Contains(x)); }
public void BucketTest() { var bucket = new KBucket(4, new System.Random(), Logger.None); var peer1 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), 0); var peer2 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), 0); var peer3 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), 0); var peer4 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), 0); var peer5 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), 0); Assert.Empty(bucket.Peers); Assert.True(bucket.IsEmpty()); Assert.Null(bucket.AddPeer(peer1)); Assert.True(bucket.Contains(peer1)); Assert.False(bucket.Contains(peer2)); Assert.False(bucket.IsEmpty()); Assert.False(bucket.IsFull()); Assert.Null(bucket.AddPeer(peer2)); Assert.Null(bucket.AddPeer(peer3)); Assert.Null(bucket.AddPeer(peer4)); Assert.True(bucket.IsFull()); Assert.Contains( bucket.GetRandomPeer(), new[] { peer1, peer2, peer3, peer4 }); Assert.Equal(peer1, bucket.AddPeer(peer5)); Assert.True(bucket.Contains(peer1)); Assert.False(bucket.Contains(peer5)); bucket.Clear(); Assert.True(bucket.IsEmpty()); }
protected void EvictContact(KBucket bucket, Contact toEvict) { evictionCount.TryRemove(toEvict.ID.Value, out _); Validate.IsTrue <BucketDoesNotContainContactToEvict>(bucket.Contains(toEvict.ID), "Bucket doesn't contain the contact to be evicted."); bucket.EvictContact(toEvict); ContactRemoved?.Invoke(this, new ContactEventArgs() { Contact = toEvict }); }
/// <summary> /// Add a contact if possible, based on the algorithm described /// in sections 2.2, 2.4 and 4.2 /// </summary> public void AddContact(Contact contact) { Validate.IsFalse<OurNodeCannotBeAContactException>(ourID == contact.ID, "Cannot add ourselves as a contact!"); contact.Touch(); // Update the LastSeen to now. lock (this) { KBucket kbucket = GetKBucket(contact.ID); if (kbucket.Contains(contact.ID)) { // Replace the existing contact, updating the network info and LastSeen timestamp. kbucket.UpdateContactInfo(contact); } else if (kbucket.IsBucketFull) { if (CanSplit(kbucket)) { // Split the bucket and try again. (KBucket k1, KBucket k2) = kbucket.Split(); int idx = GetKBucketIndex(contact.ID); buckets[idx] = k1; buckets.Insert(idx + 1, k2); buckets[idx].Touch(); buckets[idx + 1].Touch(); AddContact(contact); } else { Contact lastSeenContact = kbucket.Contacts.OrderBy(c => c.LastSeen).First(); RpcError error = lastSeenContact.Protocol.Ping(ourContact); if (error.HasError) { // Null continuation is used because unit tests may not initialize a DHT. dht?.DelayEviction(lastSeenContact, contact); } else { // Still can't add the contact, so put it into the pending list. dht?.AddToPending(contact); } } } else { // Bucket isn't full, so just add the contact. kbucket.AddContact(contact); dht?.ContactAddedToBucket(kbucket, contact); } } }
void AddValidNode(NodeInfo nodeInfo) { if (!nodeInfo.IsPublicEndPoint) { return; } if (nodeInfo.NodeId == LocalId) { return; } if (!_bucket.Contains(nodeInfo.NodeId)) { Log.Trace($"Adding new node {nodeInfo.PublicEndPoint}.", this); } var evictNode = _bucket.AddOrUpdate(nodeInfo); if (evictNode != null) { lock (_lock) { if (_evictionsCount > 8) { return; } _evictionsCount++; } TaskRunner.Run(async() => { var client = new NodeClient(evictNode.PublicEndPoint); var ni = await client.DownloadNodeInfo(); if (ni.ResultType == DownloadResultTypes.Ok) { _bucket.AddOrUpdate(evictNode); } else { _bucket.Remove(evictNode.NodeId); _bucket.AddOrUpdate(nodeInfo); } lock (_lock) { _evictionsCount--; } }); } }
public void BucketTest() { var bucket = new KBucket(4, new System.Random(), Logger.None); var peer1 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), AppProtocolVer); var peer2 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), AppProtocolVer); var peer3 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), AppProtocolVer); var peer4 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), AppProtocolVer); var peer5 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234), AppProtocolVer); Assert.Empty(bucket.Peers); Assert.True(bucket.IsEmpty()); bucket.AddPeer(peer1); Assert.True(bucket.Contains(peer1)); Assert.False(bucket.Contains(peer2)); Assert.False(bucket.IsEmpty()); Assert.False(bucket.IsFull()); // This sleep statement is used to distinguish updated time of followings. Thread.Sleep(100); bucket.AddPeer(peer2); Thread.Sleep(100); Assert.Contains( bucket.GetRandomPeer(null), new[] { peer1, peer2 } ); Assert.Contains( bucket.GetRandomPeer(peer1.Address), new[] { peer2 } ); bucket.AddPeer(peer3); Thread.Sleep(100); bucket.AddPeer(peer4); Assert.True(bucket.IsFull()); Assert.Equal( bucket.Peers.ToHashSet(), new HashSet <BoundPeer> { peer1, peer2, peer3, peer4 } ); Assert.Contains( bucket.GetRandomPeer(null), new[] { peer1, peer2, peer3, peer4 } ); Thread.Sleep(100); bucket.AddPeer(peer5); Assert.Equal( bucket.Peers.ToHashSet(), new HashSet <BoundPeer> { peer1, peer2, peer3, peer4 } ); Assert.False(bucket.Contains(peer5)); Assert.Equal(peer4, bucket.Head.Peer); Assert.Equal(peer1, bucket.Tail.Peer); Thread.Sleep(100); bucket.AddPeer(peer1); Assert.Equal(peer1, bucket.Head.Peer); Assert.Equal(peer2, bucket.Tail.Peer); Assert.False(bucket.RemovePeer(peer5)); Assert.True(bucket.RemovePeer(peer1)); Assert.DoesNotContain(peer1, bucket.Peers); Assert.Equal(3, bucket.Peers.Count()); bucket.Clear(); Assert.True(bucket.IsEmpty()); }
protected void EvictContact(KBucket bucket, Contact toEvict) { evictionCount.TryRemove(toEvict.ID.Value, out _); Validate.IsTrue <BucketDoesNotContainContactToEvict>(bucket.Contains(toEvict.ID), "Bucket doesn't contain the contact to be evicted."); bucket.EvictContact(toEvict); }
public void BucketTest() { var bucket = new KBucket(4, new System.Random(), Logger.None); var peer1 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234)); var peer2 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234)); var peer3 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234)); var peer4 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234)); var peer5 = new BoundPeer( new PrivateKey().PublicKey, new DnsEndPoint("0.0.0.0", 1234)); // Checks for an empty bucket. Assert.True(bucket.IsEmpty); Assert.False(bucket.IsFull); Assert.Empty(bucket.Peers); Assert.Empty(bucket.PeerStates); Assert.Null(bucket.GetRandomPeer()); Assert.Null(bucket.Head); Assert.Null(bucket.Tail); // Checks for a partially filled bucket. bucket.AddPeer(peer1, DateTimeOffset.UtcNow); Assert.False(bucket.IsEmpty); Assert.False(bucket.IsFull); Assert.True(bucket.Contains(peer1)); Assert.False(bucket.Contains(peer2)); Assert.NotNull(bucket.GetRandomPeer()); Assert.Null(bucket.GetRandomPeer(peer1.Address)); Assert.NotNull(bucket.GetRandomPeer(peer2.Address)); Assert.Equal(peer1, bucket.Head.Peer); Assert.Equal(peer1, bucket.Tail.Peer); // Sleep statement is used to distinguish updated times. Thread.Sleep(100); bucket.AddPeer(peer2, DateTimeOffset.UtcNow); Assert.Contains( bucket.GetRandomPeer(), new[] { peer1, peer2 } ); Assert.Contains( bucket.GetRandomPeer(peer1.Address), new[] { peer2 } ); // Checks for a full bucket. Thread.Sleep(100); bucket.AddPeer(peer3, DateTimeOffset.UtcNow); Thread.Sleep(100); bucket.AddPeer(peer4, DateTimeOffset.UtcNow); Assert.True(bucket.IsFull); Assert.Equal( bucket.Peers.ToHashSet(), new HashSet <BoundPeer> { peer1, peer2, peer3, peer4 } ); Assert.Contains( bucket.GetRandomPeer(), new[] { peer1, peer2, peer3, peer4 } ); Thread.Sleep(100); bucket.AddPeer(peer5, DateTimeOffset.UtcNow); Assert.Equal( bucket.Peers.ToHashSet(), new HashSet <BoundPeer> { peer1, peer2, peer3, peer4 } ); Assert.False(bucket.Contains(peer5)); Assert.Equal(peer4, bucket.Head.Peer); Assert.Equal(peer1, bucket.Tail.Peer); // Check order has changed. Thread.Sleep(100); bucket.AddPeer(peer1, DateTimeOffset.UtcNow); Assert.Equal(peer1, bucket.Head.Peer); Assert.Equal(peer2, bucket.Tail.Peer); Assert.False(bucket.RemovePeer(peer5)); Assert.True(bucket.RemovePeer(peer1)); Assert.DoesNotContain(peer1, bucket.Peers); Assert.Equal(3, bucket.Peers.Count()); // Clear the bucket. bucket.Clear(); Assert.True(bucket.IsEmpty); Assert.Empty(bucket.Peers); Assert.Null(bucket.Head); Assert.Null(bucket.Tail); Assert.Null(bucket.GetRandomPeer()); }
/// <summary> /// Determines in the peer exists in the routing table. /// </summary> public bool Contains(Peer peer) { return(_peers.Contains(new RoutingPeer(peer))); }