public void Sync() { var retrieveBlocksTasks = new SyncBlocksTask[_peers.Length]; for (var peerIndex = 0; peerIndex < _peers.Length; peerIndex++) { retrieveBlocksTasks[peerIndex] = StartPeerSync(peerIndex); } do { var tasks = retrieveBlocksTasks.Select(rbt => rbt.Task).ToArray(); // ReSharper disable once CoVariantArrayConversion Task.WaitAny(tasks); foreach (var peerTask in retrieveBlocksTasks) { ProcessPeerBlocks(peerTask); } ProcessPendingBlocks(); } while (SyncBlocks(retrieveBlocksTasks)); //Continue only if block is full, otherwise peer do not have more blocks /*if (retrieveBlocksTask.Task.Result.Length >= _syncBlockPageSize) * { * retrieveBlocksTasks[completeTaskIndex] = StartPeerSync(completeTaskIndex); * return true; * }*/ }
private SyncBlocksTask StartPeerSync(int peerIndex, int syncBlockIndex, int syncBlockPageSize) { _feedback.SyncChainRetrieveBlocks(syncBlockIndex, syncBlockPageSize, _peers[peerIndex].Client.Host.AbsoluteUri); var result = new SyncBlocksTask( syncBlockIndex, syncBlockPageSize, _peers[peerIndex].Client.GetBlocksAsync(syncBlockIndex, syncBlockPageSize)); return(result); }
/// <summary> /// Try add retrieved peer blocks to block chain or add them as failed to be retried from another peer /// </summary> /// <param name="peerBlocksTask"></param> /// <returns>True if peer are processed successfully</returns> private void ProcessPeerBlocks(SyncBlocksTask peerBlocksTask) { if (peerBlocksTask.Ready) { if (peerBlocksTask.AwaitProcessing) { if (!TryAddBlocks(peerBlocksTask)) { FailPeerBlocks(peerBlocksTask); } } peerBlocksTask.Processed = true; } }
private bool TryAddBlocks(SyncBlocksTask peerBlocksTask) { var peerResult = peerBlocksTask.Task.Result; if (peerBlocksTask.StartIndex != peerResult[0].Signed.Data.Index) { return(false); } var peerBlockNextIndex = CalculatePeerBlockNextIndex(peerBlocksTask.StartIndex); if (peerBlockNextIndex >= 0) { return(AddNewChainBlocks(peerBlockNextIndex, peerResult)); } //Add as pending blocks, as previous blocks are still not synced _feedback.SyncChainPendingBlocks(peerBlocksTask.StartIndex, peerBlocksTask.Task.Result.Length); _pendingBlocks.Add(peerBlocksTask.StartIndex, peerBlocksTask); return(true); }
private void FailPeerBlocks(SyncBlocksTask peerBlocksTask) { _feedback.SyncChainInvalidBlocks(peerBlocksTask.StartIndex, _syncBlockPageSize); peerBlocksTask.Failed = true; _missingBlocks.Add(peerBlocksTask.StartIndex, peerBlocksTask); }