Example #1
0
        public Task Consumed(CommandMessage last)
        {
            if (last == null)
            {
                return(TplHelper.Empty);
            }

            using (_messagesLock.BeginUpgradeableReadLock())
            {
                var messages = _clientMessages[last.ClientId];
                var node     = messages.Last;
                while (node != null && node.Value != last)
                {
                    node = node.Previous;
                }

                using (_messagesLock.BeginWriteLock())
                {
                    while (node != null)
                    {
                        var previousNode = node.Previous;
                        while (previousNode != null && previousNode.Value.ClientId != node.Value.ClientId)
                        {
                            previousNode = previousNode.Previous;
                        }

                        node.List.Remove(node);
                        node = previousNode;
                    }
                }
            }

            return(TplHelper.Empty);
        }
Example #2
0
        public void Insert(IKProtocolEndpoint <TNodeId> endpoint)
        {
            var b = false;

            using (sync.BeginWriteLock())
                b = set.AddLast(endpoint);

            if (b)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, endpoint));
            }
        }
Example #3
0
        public IDisposable Subscribe(IObserver <T> observer)
        {
            using (_observersLock.BeginWriteLock())
            {
                _observers.Add(observer);
                if (_runningTask == null)
                {
                    _runningTask = _whenHasObserver(_observersProxy);
                }
            }

            return(Disposable.Create(delegate
            {
                using (_observersLock.BeginWriteLock())
                {
                    _observers.Remove(observer);
                    if (!_observers.Any() && _runningTask != null)
                    {
                        _runningTask.Dispose();
                        _runningTask = null;
                    }
                }
            }));
        }
Example #4
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();
            }
        }