public bool RemoveStaleContact(NodeContact contact) { KBucket currentBucket = this; while (true) { NodeContact[] contacts; KBucket leftBucket; KBucket rightBucket; lock (currentBucket) { contacts = currentBucket._contacts; leftBucket = currentBucket._leftBucket; rightBucket = currentBucket._rightBucket; if (contacts != null) { #region remove contact from this bucket if (currentBucket._contactCount <= DhtNode.KADEMLIA_K) { return(false); //k-bucket is not full and replacement cache is empty } //check if there is more deserving contact to be removed than the current one foreach (NodeContact testContact in contacts) { if ((testContact != null) && testContact.IsStale() && (contact.SuccessfulRpcCount > testContact.SuccessfulRpcCount)) { //set test contact for removal contact = testContact; break; } } for (int i = 0; i < contacts.Length; i++) { if (contact.Equals(contacts[i])) { if (contacts[i].IsStale()) { //remove stale contact contacts[i] = null; currentBucket._lastChanged = DateTime.UtcNow; KBucket bucket = currentBucket; do { Interlocked.Decrement(ref bucket._contactCount); bucket = bucket._parentBucket; }while (bucket != null); return(true); } break; } } return(false); //contact was not found or was not stale #endregion } } if ((leftBucket._bucketID & contact.NodeId) == leftBucket._bucketID) { currentBucket = leftBucket; } else { currentBucket = rightBucket; } } }
public bool AddContact(NodeContact contact) { KBucket currentBucket = this; while (true) { NodeContact[] contacts; KBucket leftBucket; KBucket rightBucket; lock (currentBucket) { contacts = currentBucket._contacts; leftBucket = currentBucket._leftBucket; rightBucket = currentBucket._rightBucket; if (contacts != null) { #region add contact in this bucket //search if contact already exists for (int i = 0; i < contacts.Length; i++) { if (contact.Equals(contacts[i])) { return(false); //contact already exists } } //try add contact for (int i = 0; i < contacts.Length; i++) { if (contacts[i] == null) { contacts[i] = contact; currentBucket._lastChanged = DateTime.UtcNow; KBucket bucket = currentBucket; do { Interlocked.Increment(ref bucket._contactCount); bucket = bucket._parentBucket; }while (bucket != null); return(true); } } //k-bucket is full so contact was not added //if current contact is not stale then find and replace with any existing stale contact if (!contact.IsStale()) { for (int i = 0; i < contacts.Length; i++) { if (contacts[i].IsStale()) { contacts[i] = contact; currentBucket._lastChanged = DateTime.UtcNow; KBucket bucket = currentBucket; do { Interlocked.Increment(ref bucket._contactCount); bucket = bucket._parentBucket; }while (bucket != null); return(true); } } } //no stale contact in this k-bucket to replace! if (contacts[0].IsCurrentNode || (currentBucket._bucketDepth < (DhtNode.KADEMLIA_B - 1))) { //split current bucket and add contact! SplitBucket(currentBucket, contact); KBucket bucket = currentBucket; do { Interlocked.Increment(ref bucket._contactCount); bucket = bucket._parentBucket; }while (bucket != null); return(true); } //k-bucket is full! return(false); #endregion } } if ((leftBucket._bucketID & contact.NodeId) == leftBucket._bucketID) { currentBucket = leftBucket; } else { currentBucket = rightBucket; } } }