/// <summary> /// Raised the <see cref="OnChanged"/> event. /// </summary> /// <param name="contact"></param> /// <param name="operation"></param> private void RaiseOnChanged(IContact contact, BucketOperation operation) { if (OnChanged != null) { OnChanged(contact, operation); } }
/// <summary> /// Raised the <see cref="OnChanged"/> event. /// </summary> /// <param name="contact"></param> /// <param name="operation"></param> private void RaiseOnChanged(IContact contact, BucketOperation operation) { if (contact == null) { throw new ArgumentNullException("contact"); } if (OnChanged != null) { OnChanged(contact, operation); } }
/// <summary> /// Adds an <see cref="IContact" /> to the <see cref="Bucket" /> and maintains the sorting. /// </summary> /// <param name="contact"></param> public void Add(IContact contact) { if (contact == null) { throw new ArgumentNullException("contact"); } // Prevent a Kademlia from registering himself as a contact if (contact.Equals(_owner.Contact)) { return; } BucketOperation operation = BucketOperation.Add; IContact firstContact = null; BucketOperation operationFirstContact = BucketOperation.Update; try { // Obtain lock _contactsReaderWriterLock.EnterWriteLock(); // 2 cases: // 1. contact is in list // 2. contact is not in list if (_contacts.Remove(contact)) { operation = BucketOperation.Update; } // Check if there is space in the bucket // If we just successfully removed the bucket we know it is an update operation, // else it will be an add operation if (_contacts.Count < Constants.K) { // There is space _contacts.Add(contact); } else { // There is not space, try to contact the least recently seen contact (located at the head) firstContact = _contacts.First(); bool replyReceived = false; try { using (NodeProxy nodeProxy = new NodeProxy(_owner, firstContact, false)) { replyReceived = nodeProxy.Context.Ping(); } } catch (Exception) { { } } // Remove the least recently seen contact from head _contacts.Remove(firstContact); if (replyReceived) { // It responded, so move it to the tail of the list, and issue an update event operationFirstContact = BucketOperation.Update; _contacts.Add(firstContact); // This means that we discard the new contact operation = BucketOperation.Discard; } else { // The least recently seen contact did not respond, so issue a remove event // and add the new contact to the tail, as it is the most recently seen operationFirstContact = BucketOperation.Remove; _contacts.Add(contact); // This means that we add the new contact operation = BucketOperation.Add; } } } catch (Exception ex) { Log.Error(ex); } finally { // Release lock _contactsReaderWriterLock.ExitWriteLock(); } if (firstContact != null) { RaiseOnChanged(firstContact, operationFirstContact); } RaiseOnChanged(contact, operation); }