/// <inheritdoc/> internal override async Task <BlockStoreLoopStepResult> ExecuteAsync(ChainedBlock nextChainedBlock, CancellationToken token, bool disposeMode) { if (disposeMode) { return(BlockStoreLoopStepResult.Break()); } var result = BlockStoreLoopStepResult.Next(); var context = new BlockStoreInnerStepContext(token, this.BlockStoreLoop).Initialize(nextChainedBlock); this.BlockStoreLoop.BlockPuller.AskBlock(nextChainedBlock); while (!token.IsCancellationRequested) { foreach (var item in context.Routine.ToList()) { var executionResult = await item.ExecuteAsync(context); if (executionResult.ShouldBreak) { return(result); } } } return(result); }
/// <inheritdoc/> internal override async Task <BlockStoreLoopStepResult> ExecuteAsync(ChainedBlock nextChainedBlock, CancellationToken cancellationToken, bool disposeMode) { if (this.BlockStoreLoop.StoreTip.HashBlock != nextChainedBlock.Header.HashPrevBlock) { if (disposeMode) { return(BlockStoreLoopStepResult.Break()); } var blocksToDelete = new List <uint256>(); var blockToDelete = this.BlockStoreLoop.StoreTip; while (this.BlockStoreLoop.Chain.GetBlock(blockToDelete.HashBlock) == null) { blocksToDelete.Add(blockToDelete.HashBlock); blockToDelete = blockToDelete.Previous; } await this.BlockStoreLoop.BlockRepository.DeleteAsync(blockToDelete.HashBlock, blocksToDelete); this.BlockStoreLoop.SetStoreTip(blockToDelete); return(BlockStoreLoopStepResult.Break()); } return(BlockStoreLoopStepResult.Next()); }
/// <inheritdoc/> public override async Task <BlockStoreLoopStepResult> ExecuteAsync(BlockStoreInnerStepContext context) { context.GetNextBlock(); if (await ShouldStopFindingBlocks(context)) { if (!context.DownloadStack.Any()) { return(BlockStoreLoopStepResult.Break()); } context.StopFindingBlocks(); } else { context.BlockStoreLoop.BlockPuller.AskBlock(context.NextChainedBlock); context.DownloadStack.Enqueue(context.NextChainedBlock); if (context.DownloadStack.Count == context.BlockStoreLoop.BatchDownloadSize) { context.StopFindingBlocks(); } } return(BlockStoreLoopStepResult.Next()); }
/// <summary> /// Store missing blocks and remove them from pending blocks /// Set the Store's tip to <see cref=">lastFoundChainedBlock "/> /// </summary> private async Task <BlockStoreLoopStepResult> PushPendingBlocksToRepository(int pendingStorageBatchSize, List <BlockPair> pendingBlockPairsToStore, ChainedBlock lastFoundChainedBlock, CancellationToken cancellationToken, bool breakExecution) { await this.BlockStoreLoop.BlockRepository.PutAsync(lastFoundChainedBlock.HashBlock, pendingBlockPairsToStore.Select(b => b.Block).ToList()); this.BlockStoreLoop.SetStoreTip(lastFoundChainedBlock); if (breakExecution) { return(BlockStoreLoopStepResult.Break()); } return(BlockStoreLoopStepResult.Next()); }
/// <inheritdoc/> internal override async Task <BlockStoreLoopStepResult> ExecuteAsync(ChainedBlock nextChainedBlock, CancellationToken cancellationToken, bool disposeMode) { if (await this.BlockStoreLoop.BlockRepository.ExistAsync(nextChainedBlock.HashBlock)) { await this.BlockStoreLoop.BlockRepository.SetBlockHash(nextChainedBlock.HashBlock); this.BlockStoreLoop.SetStoreTip(nextChainedBlock); return(BlockStoreLoopStepResult.Continue()); } return(BlockStoreLoopStepResult.Next()); }
/// <inheritdoc/> public override async Task <BlockStoreLoopStepResult> ExecuteAsync(BlockStoreInnerStepContext context) { BlockPuller.DownloadedBlock downloadedBlock; if (context.BlockStoreLoop.BlockPuller.TryGetBlock(context.DownloadStack.Peek(), out downloadedBlock)) { var chainedBlockToDownload = context.DownloadStack.Dequeue(); context.Store.Add(new BlockPair(downloadedBlock.Block, chainedBlockToDownload)); context.InsertBlockSize += downloadedBlock.Length; context.StallCount = 0; if (context.InsertBlockSize > context.BlockStoreLoop.InsertBlockSizeThreshold || !context.DownloadStack.Any()) { var blocksToStore = context.Store.Select(bp => bp.Block).ToList(); await context.BlockStoreLoop.BlockRepository.PutAsync(chainedBlockToDownload.HashBlock, blocksToStore); context.BlockStoreLoop.SetStoreTip(chainedBlockToDownload); context.InsertBlockSize = 0; context.Store.Clear(); if (!context.DownloadStack.Any()) { return(BlockStoreLoopStepResult.Break()); } } } else { if (context.StallCount > 10000) { return(BlockStoreLoopStepResult.Break()); } await Task.Delay(100, context.CancellationToken); context.StallCount++; } return(BlockStoreLoopStepResult.Next()); }
/// <inheritdoc/> internal override async Task <BlockStoreLoopStepResult> ExecuteAsync(ChainedBlock nextChainedBlock, CancellationToken cancellationToken, bool disposeMode) { if (!this.BlockStoreLoop.PendingStorage.TryRemove(nextChainedBlock.HashBlock, out this.pendingBlockPairToStore)) { return(BlockStoreLoopStepResult.Next()); } if (this.BlockStoreLoop.ChainState.IsInitialBlockDownload && !disposeMode) { if (this.BlockStoreLoop.PendingStorage.Skip(0).Count() < this.BlockStoreLoop.PendingStorageBatchThreshold) { return(BlockStoreLoopStepResult.Break()); } } var pendingBlockPairsToStore = new List <BlockPair>(); pendingBlockPairsToStore.Add(this.pendingBlockPairToStore); var pendingStorageBatchSize = this.pendingBlockPairToStore.Block.GetSerializedSize(); var lastFoundChainedBlock = nextChainedBlock; while (!cancellationToken.IsCancellationRequested) { var inputChainedBlock = nextChainedBlock; nextChainedBlock = this.BlockStoreLoop.Chain.GetBlock(nextChainedBlock.Height + 1); var breakExecution = ShouldBreakExecution(inputChainedBlock, nextChainedBlock); if (!breakExecution && !this.BlockStoreLoop.PendingStorage.TryRemove(nextChainedBlock.HashBlock, out this.pendingBlockPairToStore)) { breakExecution = true; } if (breakExecution) { if (!pendingBlockPairsToStore.Any()) { break; } } else { pendingBlockPairsToStore.Add(this.pendingBlockPairToStore); pendingStorageBatchSize += this.pendingBlockPairToStore.Block.GetSerializedSize(); // TODO: add the size to the result coming from the signaler lastFoundChainedBlock = nextChainedBlock; } if (pendingStorageBatchSize > this.BlockStoreLoop.InsertBlockSizeThreshold || breakExecution) { var result = await PushPendingBlocksToRepository(pendingStorageBatchSize, pendingBlockPairsToStore, lastFoundChainedBlock, cancellationToken, breakExecution); if (result.ShouldBreak) { break; } pendingBlockPairsToStore.Clear(); pendingStorageBatchSize = 0; if (this.BlockStoreLoop.ChainState.IsInitialBlockDownload) // this can be tweaked if insert is effecting the consensus speed { await Task.Delay(this.BlockStoreLoop.PushIntervalIBD, cancellationToken); } } } pendingBlockPairsToStore.Clear(); pendingBlockPairsToStore = null; this.pendingBlockPairToStore = null; return(BlockStoreLoopStepResult.Continue()); }