Пример #1
0
        private async Task DownloadNextBlocksAsync(Node node, CancellationToken ctsToken, int maxBlocksToDownload = 1)
        {
            var heights = new List <Height>();

            using (await _asyncLock.LockAsync())
            {
                if (_blocksToDownload.Count == 0)
                {
                    await Task.Delay(100, ctsToken).ContinueWith(tsk => { });

                    return;
                }

                if (_blocksToDownload.Count < maxBlocksToDownload * 2)
                {
                    maxBlocksToDownload = 1;
                }

                for (int i = 0; i < maxBlocksToDownload; i++)
                {
                    // todo check if we have that much block
                    var height = _blocksToDownload.Min();
                    _blocksToDownload.TryRemove(height);
                    heights.Add(height);
                }
            }
            try
            {
                var headers = new HashSet <ChainedBlock>();
                foreach (var height in heights)
                {
                    var neededHeader = await _walletJob.TryGetHeaderAsync(height);

                    headers.Add(neededHeader);
                }

                var delayMinutes = heights.Count;
                using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(delayMinutes)))
                {
                    var timeoutToken     = cancellationTokenSource.Token;
                    var downloadCtsToken = CancellationTokenSource.CreateLinkedTokenSource(timeoutToken, ctsToken).Token;

                    HashSet <Block> blocks = null;
                    try
                    {
                        blocks = new HashSet <Block>(await Task.Run(() => node.GetBlocks(headers.ToArray(), downloadCtsToken)));
                    }
                    catch (Exception)
                    {
                        if (timeoutToken.IsCancellationRequested)
                        {
                            node.DisconnectAsync($"Block download time > {delayMinutes}min");
                        }
                        else
                        {
                            node.DisconnectAsync("Block download failed");
                        }
                        blocks = null;
                    }
                    if (blocks == null)
                    {
                        foreach (var height in heights)
                        {
                            _blocksToDownload.Add(height);
                        }
                    }
                    else
                    {
                        int i = 0;
                        foreach (var block in blocks)
                        {
                            _downloadedBlocks.AddOrReplace(heights[i], block);
                            i++;
                        }
                    }
                }
            }
            catch (Exception)
            {
                using (_asyncLock.Lock())
                {
                    foreach (var height in heights)
                    {
                        _blocksToDownload.Add(height);
                    }
                }
            }
        }
Пример #2
0
        private async Task DownloadNextBlocks(Node node, CancellationToken ctsToken, int maxBlocksToDownload = 1)
        {
            var heights = new List <Height>();

            try
            {
                await _sem.WaitAsync(ctsToken).ConfigureAwait(false);

                if (BlocksToDownload.Count == 0)
                {
                    await Task.Delay(100, ctsToken).ContinueWith(tsk => { }).ConfigureAwait(false);

                    return;
                }

                if (BlocksToDownload.Count < maxBlocksToDownload * 2)
                {
                    maxBlocksToDownload = 1;
                }

                for (int i = 0; i < maxBlocksToDownload; i++)
                {
                    // todo check if we have that much block
                    var height = BlocksToDownload.Min();
                    BlocksToDownload.TryRemove(height);
                    heights.Add(height);
                }
            }
            finally
            {
                _sem.Release();
            }
            try
            {
                var headers = new HashSet <ChainedBlock>();
                foreach (var height in heights)
                {
                    WalletJob.TryGetHeader(height, out ChainedBlock neededHeader);
                    headers.Add(neededHeader);
                }

                var delayMinutes     = heights.Count;
                var timeoutToken     = new CancellationTokenSource(TimeSpan.FromMinutes(delayMinutes)).Token;
                var downloadCtsToken = CancellationTokenSource.CreateLinkedTokenSource(timeoutToken, ctsToken).Token;

                HashSet <Block> blocks = null;
                try
                {
                    blocks = new HashSet <Block>(await Task.Run(() => node.GetBlocks(headers.ToArray(), downloadCtsToken)).ConfigureAwait(false));
                }
                catch
                {
                    if (timeoutToken.IsCancellationRequested)
                    {
                        node.DisconnectAsync($"Block download time > {delayMinutes}min");
                    }
                    else
                    {
                        node.DisconnectAsync("Block download failed");
                    }
                    blocks = null;
                }
                if (blocks == null)
                {
                    foreach (var height in heights)
                    {
                        BlocksToDownload.Add(height);
                    }
                }
                else
                {
                    int i = 0;
                    foreach (var block in blocks)
                    {
                        DownloadedBlocks.AddOrReplace(heights[i], block);
                        i++;
                    }
                }
            }
            catch
            {
                try
                {
                    await _sem.WaitAsync(ctsToken).ConfigureAwait(false);

                    foreach (var height in heights)
                    {
                        BlocksToDownload.Add(height);
                    }
                }
                finally
                {
                    _sem.Release();
                }
            }
        }