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(); } }
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(); } }