Exemplo n.º 1
0
 /// <summary>
 ///     This is an important operation for long lasting allocations.
 ///     For example the full sync tends to allocate the same peer for many minutes and we use this method to ensure that
 ///     a newly arriving better peer can replace a currently selected one.
 ///     Consider that there are some external changes (e.g. node stats values change based on the sync transfer rates)
 ///     which may not be controlled from inside here, hence we decide to monitor the potential upgrades in a loop.
 /// </summary>
 /// <exception cref="InvalidOperationException">Thrown if an irreplaceable allocation is being replaced by this method (internal implementation error).</exception>
 private void UpgradeAllocations(string reason)
 {
     DropUselessPeers();
     WakeUpPeerThatSleptEnough();
     foreach ((SyncPeerAllocation allocation, _) in _replaceableAllocations)
     {
         lock (_isAllocatedChecks)
         {
             var unallocatedPeers = InitializedPeers.Where(p => p.CanBeAllocated(allocation.Contexts));
             allocation.AllocateBestPeer(unallocatedPeers, _stats, _blockTree);
         }
     }
 }
Exemplo n.º 2
0
        public async Task <SyncPeerAllocation> Allocate(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts allocationContexts = AllocationContexts.All, int timeoutMilliseconds = 0)
        {
            int      tryCount  = 1;
            DateTime startTime = DateTime.UtcNow;

            SyncPeerAllocation allocation = new SyncPeerAllocation(peerAllocationStrategy, allocationContexts);

            while (true)
            {
                lock (_isAllocatedChecks)
                {
                    allocation.AllocateBestPeer(InitializedPeers.Where(p => p.CanBeAllocated(allocationContexts)), _stats, _blockTree);
                    if (allocation.HasPeer)
                    {
                        if (peerAllocationStrategy.CanBeReplaced)
                        {
                            _replaceableAllocations.TryAdd(allocation, null);
                        }

                        return(allocation);
                    }
                }

                bool timeoutReached = timeoutMilliseconds == 0 ||
                                      (DateTime.UtcNow - startTime).TotalMilliseconds > timeoutMilliseconds;
                if (timeoutReached)
                {
                    return(SyncPeerAllocation.FailedAllocation);
                }

                int waitTime = 10 * tryCount++;

                if (!_signals.SafeWaitHandle.IsClosed)
                {
                    await _signals.WaitOneAsync(waitTime, _refreshLoopCancellation.Token);

                    if (!_signals.SafeWaitHandle.IsClosed)
                    {
                        _signals.Reset(); // without this we have no delay
                    }
                }
            }
        }