/// <summary>
 /// Updates the reference to the node within the table.
 /// </summary>
 /// <param name="nodeId"></param>
 /// <param name="nodeData"></param>
 /// <param name="nodeEvents"></param>
 /// <param name="cancellationToken"></param>
 /// <returns></returns>
 public ValueTask TouchAsync(TKNodeId nodeId, TKNodeData nodeData = default, IKNodeEvents nodeEvents = null, CancellationToken cancellationToken = default)
 {
     return(GetBucket(nodeId).TouchAsync(nodeId, nodeData, nodeEvents, protocol, cancellationToken));
 }
Example #2
0
 /// <summary>
 /// Initializes a new instance.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="data"></param>
 /// <param name="events"></param>
 public KBucketItem(TKNodeId id, TKNodeData data, IKNodeEvents events)
 {
     this.id     = id;
     this.data   = data;
     this.events = events;
 }
Example #3
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();
            }
        }