Example #1
0
        public bool Remove(IKProtocolEndpoint <TNodeId> endpoint)
        {
            var b = false;

            using (sync.BeginUpgradableReadLock())
                if (set.Contains(endpoint))
                {
                    using (sync.BeginWriteLock())
                        b = set.Remove(endpoint);
                }

            if (b)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, endpoint));
            }

            return(b);
        }
Example #2
0
        /// <summary>
        /// Updates the position of the node in the bucket.
        /// </summary>
        /// <typeparam name="TKNetwork"></typeparam>
        /// <param name="nodeId"></param>
        /// <param name="nodeData"></param>
        /// <param name="nodeEvents"></param>
        /// <param name="protocol"></param>
        /// <param name="cancellationToken"></param>
        internal async ValueTask TouchAsync(TKNodeId nodeId, TKNodeData nodeData, IKNodeEvents nodeEvents, IKNodeProtocol <TKNodeId, TKNodeData> protocol, CancellationToken cancellationToken)
        {
            var lk = rw.BeginUpgradableReadLock();

            try
            {
                var i = GetNode(nodeId);
                if (i != null)
                {
                    using (rw.BeginWriteLock())
                    {
                        // item already exists, move to tail
                        l.Remove(i);
                        l.AddLast(i.Value);
                    }
                }
                else if (l.Count < k)
                {
                    using (rw.BeginWriteLock())
                    {
                        // item does not exist, but bucket has room, insert at tail
                        l.AddLast(new KBucketItem <TKNodeId, TKNodeData>(nodeId, nodeData, nodeEvents));
                    }
                }
                else
                {
                    // item does not exist, but bucket does not have room, ping first entry
                    var n = l.First;

                    // start ping, check for async completion
                    KNodePingResponse r;
                    var t = protocol.PingAsync(n.Value.Id, n.Value.Data, cancellationToken);

                    // completed synchronously (or immediately)
                    if (t.IsCompleted)
                    {
                        r = t.Result;
                    }
                    else
                    {
                        // temporarily release lock and wait for completion
                        lk.Dispose();
                        r  = await t;
                        lk = rw.BeginUpgradableReadLock();
                    }

                    // was able to successfully ping the node
                    if (r.Status == KNodeResponseStatus.OK)
                    {
                        // entry had response, move to tail, discard new entry
                        if (l.Count > 1)
                        {
                            using (rw.BeginWriteLock())
                            {
                                // remove from list if not already done (async operation could have overlapped)
                                if (n.List != null)
                                {
                                    l.Remove(n);
                                }

                                // node goes to end
                                l.AddLast(n.Value);
                            }
                        }
                    }
                    else
                    {
                        using (rw.BeginWriteLock())
                        {
                            // first entry had no response, remove, insert new at tail
                            l.Remove(n);
                            l.AddLast(new KBucketItem <TKNodeId, TKNodeData>(nodeId, nodeData, nodeEvents));
                        }
                    }
                }
            }
            finally
            {
                lk.Dispose();
            }
        }