Beispiel #1
0
        /// <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());
        }
Beispiel #4
0
        /// <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());
        }
Beispiel #5
0
        /// <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());
        }
Beispiel #7
0
        /// <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());
        }