public void NonRespondingContactDelayedEvictionTest() { // Create a DHT so we have an eviction handler. Dht dht = new Dht(ID.Zero, new VirtualProtocol(), () => null, new Router()); //Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero); //((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); IBucketList bucketList = SetupSplitFailure(dht.Node.BucketList); Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred."); Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0."); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // The bucket is now full. Pick the first contact, as it is last seen (they are added in chronological order.) Contact nonRespondingContact = bucketList.Buckets[1].Contacts[0]; // Since the protocols are shared, we need to assign a unique protocol for this node for testing. VirtualProtocol vpUnresponding = new VirtualProtocol(((VirtualProtocol)nonRespondingContact.Protocol).Node, false); nonRespondingContact.Protocol = vpUnresponding; // Setup the next new contact (it can respond.) Contact nextNewContact = new Contact(dht.Contact.Protocol, ID.Zero.SetBit(159)); bucketList.AddContact(nextNewContact); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // Verify CanSplit -> Evict happened. Assert.IsTrue(dht.PendingContacts.Count == 1, "Expected one pending contact."); Assert.IsTrue(dht.PendingContacts.Contains(nextNewContact), "Expected pending contact to be the 21st contact."); Assert.IsTrue(dht.EvictionCount.Count == 1, "Expected one contact to be pending eviction."); }
public void ForceFailedAddTest() { Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero); ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); IBucketList bucketList = SetupSplitFailure(); Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred."); Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0."); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // This next contact should not split the bucket as depth == 5 and therefore adding the contact will fail. // Any unique ID >= 2^159 will do. byte[] id = new byte[20]; id[19] = 0x80; Contact newContact = new Contact(dummyContact.Protocol, new ID(id)); bucketList.AddContact(newContact); Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should not have occurred."); Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0."); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // Verify CanSplit -> Evict did not happen. Assert.IsFalse(bucketList.Buckets[1].Contacts.Contains(newContact), "Expected new contact NOT to replace an older contact."); }
/// <summary> /// Make a node on a specific port, with a specified ID /// </summary> /// <param name="port"></param> public KademliaClient(IBucketList cache, IStorage dataStore, Func<Uri, IKadmeliaServer> serverFactory) { this.routingTable = cache; this.dataStore = dataStore; this.serverFactory = serverFactory; myself = cache.OurContact; }
public KademliaServer(IBucketList cache, IStorage storage, Func<Uri, IKadmeliaServer> serverFactory) { this.serverFactory = this.serverFactory; this.routingTable = cache; this._storage = storage; this.myself = cache.OurContact; }
/// <summary> /// If cache storage is not explicity provided, we use an in-memory virtual storage. /// </summary> public Node(Contact contact, IStorage storage, IStorage cacheStorage = null) { ourContact = contact; bucketList = new BucketList(contact); this.storage = storage; this.cacheStorage = cacheStorage; if (cacheStorage == null) { this.cacheStorage = new VirtualStorage(); } }
protected IBucketList SetupSplitFailure(IBucketList bucketList = null) { // force host node ID to < 2^159 so the node ID is not in the 2^159 ... 2^160 range byte[] bhostID = new byte[20]; bhostID[19] = 0x7F; ID hostID = new ID(bhostID); Contact dummyContact = new Contact(new VirtualProtocol(), hostID); ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); bucketList = bucketList ?? new BucketList(hostID, dummyContact); // Also add a contact in this 0 - 2^159 range, arbitrarily something not our host ID. // This ensures that only one bucket split will occur after 20 nodes with ID >= 2^159 are added, // otherwise, buckets will in the 2^159 ... 2^160 space. dummyContact = new Contact(new VirtualProtocol(), ID.One); ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); bucketList.AddContact(new Contact(dummyContact.Protocol, ID.One)); Assert.IsTrue(bucketList.Buckets.Count == 1, "Bucket split should not have occurred."); Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0."); // make sure contact ID's all have the same 5 bit prefix and are in the 2^159 ... 2^160 - 1 space byte[] bcontactID = new byte[20]; bcontactID[19] = 0x80; // 1000 xxxx prefix, xxxx starts at 1000 (8) // this ensures that all the contacts in a bucket match only the prefix as only the first 5 bits are shared. // |----| shared range // 1000 1000 ... // 1000 1100 ... // 1000 1110 ... byte shifter = 0x08; int pos = 19; Constants.K.ForEach(() => { bcontactID[pos] |= shifter; ID contactID = new ID(bcontactID); dummyContact = new Contact(new VirtualProtocol(), ID.One); ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); bucketList.AddContact(new Contact(dummyContact.Protocol, contactID)); shifter >>= 1; if (shifter == 0) { shifter = 0x80; --pos; } }); return(bucketList); }
// not perfect, but it's something public static long TestBucketList( IBucketList <int> list, int addOperations, int insertOperations, int modifyIndexOperations, int removeOperations) { var stopWatch = new Stopwatch(); stopWatch.Start(); var rnd = new Random(); while (addOperations > 0 || insertOperations > 0) { var op = rnd.Next() % 4; if ((op == 0 || (addOperations <= 0 && insertOperations <= 0)) && removeOperations > 0 && list.Size > 0) { var index = rnd.Next() % list.Size; list.Remove(index); --removeOperations; } else if (op == 1 && modifyIndexOperations > 0 && list.Size > 0) { var index = rnd.Next() % list.Size; var value = rnd.Next(); list[index] = list[index] + value; --modifyIndexOperations; } else if (op == 2 && insertOperations > 0) { var index = rnd.Next() % (list.Size + 1); var value = rnd.Next(); list.Insert(index, value); --insertOperations; } else { var value = rnd.Next(); list.Add(value); --addOperations; } } stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); }
public void NonRespondingContactEvictedTest() { // Create a DHT so we have an eviction handler. Dht dht = new Dht(ID.Zero, new VirtualProtocol(), () => null, new Router()); //Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero); //((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage()); IBucketList bucketList = SetupSplitFailure(dht.Node.BucketList); Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred."); Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0."); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // The bucket is now full. Pick the first contact, as it is last seen (they are added in chronological order.) Contact nonRespondingContact = bucketList.Buckets[1].Contacts[0]; // Since the protocols are shared, we need to assign a unique protocol for this node for testing. VirtualProtocol vpUnresponding = new VirtualProtocol(((VirtualProtocol)nonRespondingContact.Protocol).Node, false); nonRespondingContact.Protocol = vpUnresponding; // Setup the next new contact (it can respond.) Contact nextNewContact = new Contact(dht.Contact.Protocol, ID.Zero.SetBit(159)); // Hit the non-responding contact EVICTION_LIMIT times, which will trigger the eviction algorithm. Constants.EVICTION_LIMIT.ForEach(() => bucketList.AddContact(nextNewContact)); Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1."); // Verify CanSplit -> Pending eviction happened. Assert.IsTrue(dht.PendingContacts.Count == 0, "Pending contact list should now be empty."); Assert.IsFalse(bucketList.Buckets.SelectMany(b => b.Contacts).Contains(nonRespondingContact), "Expected bucket to NOT contain non-responding contact."); Assert.IsTrue(bucketList.Buckets.SelectMany(b => b.Contacts).Contains(nextNewContact), "Expected bucket to contain new contact."); Assert.IsTrue(dht.EvictionCount.Count == 0, "Expected no contacts to be pending eviction."); }
public BucketListController(IBucketList bucketListService) { _bucketListService = bucketListService; }