Example #1
0
        private async Task RunSyncLoop()
        {
            while (true)
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace("Sync loop - WAIT.");
                }
                _syncRequested.Wait(_syncLoopCancellation.Token);
                _syncRequested.Reset();

                if (_logger.IsTrace)
                {
                    _logger.Trace("Sync loop - IN.");
                }
                if (_syncLoopCancellation.IsCancellationRequested)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace("Sync loop cancellation requested - leaving the main sync loop.");
                    }
                    break;
                }

                if (!_blockTree.CanAcceptNewBlocks)
                {
                    continue;
                }

                _syncMode.Update();
                _syncReport.CurrentSyncMode = _syncMode.Current;

                if (_blocksSyncAllocation == null)
                {
                    AllocateBlocksSync();
                    if (_syncMode.Current == SyncMode.Headers)
                    {
                        _blocksSyncAllocation.MinBlocksAhead = SyncModeSelector.FullSyncThreshold;
                    }
                    else
                    {
                        _blocksSyncAllocation.MinBlocksAhead = null;
                    }
                }
                else if (_syncMode.IsParallel)
                {
                    FreeBlocksSyncAllocation();
                }

                PeerInfo bestPeer = null;
                if (_blocksSyncAllocation != null)
                {
                    UInt256 ourTotalDifficulty = _blockTree.BestSuggestedHeader?.TotalDifficulty ?? 0;
                    _syncPeerPool.EnsureBest(); // can we remove it yet?
                    bestPeer = _blocksSyncAllocation?.Current;
                    if (bestPeer == null || bestPeer.TotalDifficulty <= ourTotalDifficulty)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace("Skipping sync - no peer with better chain.");
                        }
                        continue;
                    }

                    SyncEvent?.Invoke(this, new SyncEventArgs(bestPeer.SyncPeer, Synchronization.SyncEvent.Started));
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Starting {_syncMode.Current} sync with {bestPeer} - theirs {bestPeer?.HeadNumber} {bestPeer?.TotalDifficulty} | ours {_blockTree.BestSuggestedHeader?.Number ?? 0} {_blockTree.BestSuggestedHeader?.TotalDifficulty ?? 0}");
                    }
                }

                _peerSyncCancellation = new CancellationTokenSource();
                var         linkedCancellation = CancellationTokenSource.CreateLinkedTokenSource(_peerSyncCancellation.Token, _syncLoopCancellation.Token);
                Task <long> syncProgressTask;
                switch (_syncMode.Current)
                {
                case SyncMode.FastBlocks:
                    syncProgressTask = _fastBlockDownloader.Sync(linkedCancellation.Token);
                    break;

                case SyncMode.Headers:
                    syncProgressTask = _syncConfig.DownloadBodiesInFastSync
                            ? _blockDownloader.DownloadBlocks(bestPeer, SyncModeSelector.FullSyncThreshold, linkedCancellation.Token, _syncConfig.DownloadReceiptsInFastSync ? BlockDownloader.DownloadOptions.DownloadWithReceipts : BlockDownloader.DownloadOptions.Download)
                            : _blockDownloader.DownloadHeaders(bestPeer, SyncModeSelector.FullSyncThreshold, linkedCancellation.Token);
                    break;

                case SyncMode.StateNodes:
                    syncProgressTask = DownloadStateNodes(_syncLoopCancellation.Token);
                    break;

                case SyncMode.WaitForProcessor:
                    syncProgressTask = Task.Delay(5000).ContinueWith(_ => 0L);
                    break;

                case SyncMode.Full:
                    syncProgressTask = _blockDownloader.DownloadBlocks(bestPeer, 0, linkedCancellation.Token);
                    break;

                case SyncMode.NotStarted:
                    syncProgressTask = Task.Delay(1000).ContinueWith(_ => 0L);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                switch (_syncMode.Current)
                {
                case SyncMode.WaitForProcessor:
                    if (_logger.IsInfo)
                    {
                        _logger.Info("Waiting for the block processor to catch up before the next sync round...");
                    }
                    await syncProgressTask;
                    break;

                case SyncMode.NotStarted:
                    if (_logger.IsInfo)
                    {
                        _logger.Info("Waiting for peers to connect before selecting the sync mode...");
                    }
                    await syncProgressTask;
                    break;

                default:
                    await syncProgressTask.ContinueWith(t => HandleSyncRequestResult(t, bestPeer));

                    break;
                }

                if (syncProgressTask.IsCompletedSuccessfully)
                {
                    long progress = syncProgressTask.Result;
                    if (progress == 0 && _blocksSyncAllocation != null)
                    {
                        _syncPeerPool.ReportNoSyncProgress(_blocksSyncAllocation); // not very fair here - allocation may have changed
                    }
                }

                _blocksSyncAllocation?.FinishSync();
                linkedCancellation.Dispose();
                var source = _peerSyncCancellation;
                _peerSyncCancellation = null;
                source?.Dispose();
            }
        }
Example #2
0
        private async Task RunSyncLoop()
        {
            while (true)
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace("Sync loop - WAIT.");
                }
                _syncRequested.Wait(_syncLoopCancellation.Token);
                if (_syncLoopCancellation.IsCancellationRequested)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace("Sync loop cancellation requested - leaving the main sync loop.");
                    }
                    break;
                }

                _syncRequested.Reset();
                if (_logger.IsTrace)
                {
                    _logger.Trace("Sync loop - IN.");
                }

                if (!_blockTree.CanAcceptNewBlocks)
                {
                    continue;
                }

                PeerInfo bestPeer = null;
                if (_blocksSyncAllocation != null)
                {
                    UInt256 ourTotalDifficulty = _blockTree.BestSuggested?.TotalDifficulty ?? 0;
                    _syncPeerPool.EnsureBest();
                    bestPeer = _blocksSyncAllocation?.Current;
                    if (bestPeer == null || bestPeer.TotalDifficulty <= ourTotalDifficulty)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace("Skipping sync - no peer with better chain.");
                        }
                        continue;
                    }

                    SyncEvent?.Invoke(this, new SyncEventArgs(bestPeer.SyncPeer, Synchronization.SyncEvent.Started));
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Starting {_syncMode.Current} sync with {bestPeer} - theirs {bestPeer?.HeadNumber} {bestPeer?.TotalDifficulty} | ours {_bestSuggestedNumber} {_blockTree.BestSuggested?.TotalDifficulty ?? 0}");
                    }
                }

                _peerSyncCancellation = new CancellationTokenSource();
                var         linkedCancellation = CancellationTokenSource.CreateLinkedTokenSource(_peerSyncCancellation.Token, _syncLoopCancellation.Token);
                Task <long> syncProgressTask;
                switch (_syncMode.Current)
                {
                case SyncMode.Headers:
                    syncProgressTask = _blockDownloader.DownloadHeaders(bestPeer, SyncModeSelector.FullSyncThreshold, linkedCancellation.Token);
                    break;

                case SyncMode.StateNodes:
                    syncProgressTask = DownloadStateNodes(_syncLoopCancellation.Token);
                    break;

                case SyncMode.WaitForProcessor:
                    syncProgressTask = Task.Delay(1000).ContinueWith(_ => 0L);
                    break;

                case SyncMode.Full:
                    syncProgressTask = _blockDownloader.DownloadBlocks(bestPeer, linkedCancellation.Token);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                SyncMode beforeUpdate  = _syncMode.Current;
                long     bestFullState = FindBestFullState();
                _syncMode.Update(_bestSuggestedNumber, _blockTree.BestSuggestedFullBlock?.Number ?? 0, bestFullState);
                if (beforeUpdate != SyncMode.WaitForProcessor)
                {
                    await syncProgressTask.ContinueWith(t => HandleSyncRequestResult(t, bestPeer));

                    if (_syncMode.Current == SyncMode.Headers)
                    {
                        _blocksSyncAllocation.MinBlocksAhead = SyncModeSelector.FullSyncThreshold;
                    }
                    else if (_blocksSyncAllocation != null)
                    {
                        _blocksSyncAllocation.MinBlocksAhead = null;
                    }

                    if (syncProgressTask.IsCompletedSuccessfully)
                    {
                        long progress = syncProgressTask.Result;
                        if (_syncMode.Current == beforeUpdate && progress == 0 && _blocksSyncAllocation != null)
                        {
                            _syncPeerPool.ReportNoSyncProgress(_blocksSyncAllocation); // not very fair here - allocation may have changed
                        }
                    }
                }

                _blocksSyncAllocation?.FinishSync();

                linkedCancellation.Dispose();
                var source = _peerSyncCancellation;
                _peerSyncCancellation = null;
                source?.Dispose();
            }
        }