예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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;
                }
            }
        }