public void WaitForOperatorEmitsElementsThrowsExceptionDespiteRestart()
        {
            var facade = new TestFacade();

            var synced = new Synced <Exception>();

            facade.Schedule(() =>
            {
                var workflow = new WaitForWorkflow(1000);
                Sync.AfterNext(workflow.EmitEventsToSource, true);
                Sync.AfterNext(workflow.SetFieldVariableAfterWaitedFor, true);
            });

            Thread.Sleep(100);

            facade.PersistAndCloseDown();

            Thread.Sleep(100);

            facade.LoadAgain();

            Thread.Sleep(3000);

            synced.Value.ShouldBeNull();

            var thrownException = facade.Resolve <WaitForWorkflow>().ThrownException;

            (thrownException is TimeoutException).ShouldBeTrue();

            facade.Dispose();
        }
        public void WaitForOperatorEmitsElementsBeforeTimeOutDespiteRestart()
        {
            var facade = new TestFacade();

            var synced = new Synced <WaitForWorkflow>();

            facade.Schedule(() =>
            {
                var workflow = new WaitForWorkflow(5000);

                Sync.AfterNext(workflow.EmitEventsToSource, true);
                Sync.AfterNext(workflow.SetFieldVariableAfterWaitedFor, true);
            });

            Thread.Sleep(100);

            facade.PersistAndCloseDown();

            Thread.Sleep(100);

            facade.LoadAgain();

            Thread.Sleep(3000);

            synced.Value.ShouldBeNull();

            var w = facade.Resolve <WaitForWorkflow>();

            w.Emits.ToArray().Length.ShouldBe(5);

            facade.Dispose();
        }
コード例 #3
0
        public void EnqueuedWorkIsExecuted()
        {
            var value = new Synced <int>();

            var queueWorker = new QueueWorker();

            queueWorker.Do(() => value.Value = 10);

            value.WaitFor(i => i == 10);
        }
コード例 #4
0
        public XmlDocument Serialize()
        {
            XmlDocument doc  = new XmlDocument();
            var         root = doc.CreateElement("t_audits");

            doc.AppendChild(root);

            var child = doc.CreateElement("timestamp");
            var cdata = doc.CreateCDataSection(Timestamp.Ticks.ToString());

            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("location");
            cdata = doc.CreateCDataSection(Location);
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("latitude");
            cdata = doc.CreateCDataSection(Latitude.ToString());
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("longitude");
            cdata = doc.CreateCDataSection(Longitude.ToString());
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("information");
            cdata = doc.CreateCDataSection(Information);
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("picture");
            cdata = doc.CreateCDataSection(Convert.ToBase64String((byte[])Picture, 0, ((byte[])Picture).Length));
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("synced");
            cdata = doc.CreateCDataSection(Synced.ToString());
            child.AppendChild(cdata);
            root.AppendChild(child);

            child = doc.CreateElement("login");
            cdata = doc.CreateCDataSection(Login);
            child.AppendChild(cdata);
            root.AppendChild(child);

            return(doc);
        }
コード例 #5
0
        public void DelegatesAndSchedulerAreSetAfterStartingTheScheduler()
        {
            var objectStore = ObjectStore.New(new InMemoryStorageEngine());
            var syncs       = new SynchronizationQueue();
            var scheduler   = new InternalScheduler(objectStore, new ReadyToSchedules(), syncs, new Engine(), false);

            scheduler.Start();

            var synced = new Synced <bool>();

            scheduler.Schedule(() => synced.Value = Roots.Instance.Value == objectStore.Roots, false);

            synced.WaitFor(d => synced.Value);

            scheduler.Dispose();
        }
コード例 #6
0
        public void WorkQueueIsSwappedCorrectlyOnLongRunningWork()
        {
            var value1 = new Synced <bool>();
            var value2 = new Synced <bool>();

            var queueWorker = new QueueWorker();

            queueWorker.Do(() =>
            {
                Thread.Sleep(200);
                value1.Value = true;
            });

            Thread.Sleep(100);

            queueWorker.Do(() =>
            {
                Thread.Sleep(200);
                value2.Value = true;
            });

            value2.WaitFor(b => b);
            value1.Value.ShouldBe(true);
        }
コード例 #7
0
 private static void OnSynced() => Synced?.Invoke(null, EventArgs.Empty);
コード例 #8
0
 internal virtual void OnSynced() => Synced?.Invoke(this, EventArgs.Empty);
コード例 #9
0
        private async Task PeerSyncAsync(CancellationToken token, PeerInfo peerInfo)
        {
            bool wasCancelled = false;

            ISynchronizationPeer peer       = peerInfo.Peer;
            BigInteger           bestNumber = BlockTree.BestSuggested.Number;

            const int maxLookup             = 64;
            int       ancestorLookupLevel   = 0;
            bool      isCommonAncestorKnown = false;

            while (peerInfo.NumberAvailable > bestNumber && peerInfo.NumberReceived <= peerInfo.NumberAvailable)
            {
                if (ancestorLookupLevel > maxLookup)
                {
                    throw new InvalidOperationException("Cannot find ancestor"); // TODO: remodel this after full sync test is added
                }

                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }

                if (!isCommonAncestorKnown)
                {
                    // TODO: cases when many peers used for sync and one peer finished sync and then we need resync - we should start from common point and not NumberReceived that may be far in the past
                    _logger.Info($"Finding common ancestor for {peerInfo.Peer.NodeId}");
                    isCommonAncestorKnown = true;
                }

                BigInteger blocksLeft = peerInfo.NumberAvailable - peerInfo.NumberReceived;
                // TODO: fault handling on tasks

                int blocksToRequest = (int)BigInteger.Min(blocksLeft + 1, BatchSize);
                if (_logger.IsDebugEnabled)
                {
                    _logger.Debug($"Sync request to peer with {peerInfo.NumberAvailable} blocks. Got {peerInfo.NumberReceived} and asking for {blocksToRequest} more.");
                }
                Task <BlockHeader[]> headersTask = peer.GetBlockHeaders(peerInfo.NumberReceived, blocksToRequest, 0, token);
                _currentSyncTask = headersTask;
                BlockHeader[] headers = await headersTask;
                if (_currentSyncTask.IsCanceled)
                {
                    wasCancelled = true;
                    break;
                }

                if (_currentSyncTask.IsFaulted)
                {
                    _logger.Error("Failed to retrieve headers when synchronizing", _currentSyncTask.Exception);
                    throw _currentSyncTask.Exception;
                }

                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }

                List <Keccak> hashes = new List <Keccak>();
                Dictionary <Keccak, BlockHeader> headersByHash = new Dictionary <Keccak, BlockHeader>();
                for (int i = 1; i < headers.Length; i++)
                {
                    hashes.Add(headers[i].Hash);
                    headersByHash[headers[i].Hash] = headers[i];
                }

                Task <Block[]> bodiesTask = peer.GetBlocks(hashes.ToArray(), token);
                _currentSyncTask = bodiesTask;
                Block[] blocks = await bodiesTask;
                if (_currentSyncTask.IsCanceled)
                {
                    wasCancelled = true;
                    break;
                }

                if (_currentSyncTask.IsFaulted)
                {
                    _logger.Error("Failed to retrieve bodies when synchronizing", _currentSyncTask.Exception);
                    throw _currentSyncTask.Exception;
                }

                ancestorLookupLevel = 0;

                for (int i = 0; i < blocks.Length; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        token.ThrowIfCancellationRequested();
                    }

                    blocks[i].Header = headersByHash[hashes[i]];
                }

                if (blocks.Length > 0)
                {
                    Block parent = BlockTree.FindParent(blocks[0]);
                    if (parent == null)
                    {
                        ancestorLookupLevel     += BatchSize;
                        peerInfo.NumberReceived -= BatchSize;
                        continue;
                    }
                }

                // Parity 1.11 non canonical blocks when testing on 27/06
                for (int i = 0; i < blocks.Length; i++)
                {
                    if (i != 0 && blocks[i].ParentHash != blocks[i - 1].Hash)
                    {
                        throw new EthSynchronizationException("Peer send an inconsistent block list");
                    }
                }

                for (int i = 0; i < blocks.Length; i++)
                {
                    if (_logger.IsInfoEnabled)
                    {
                        _logger.Info($"Received {blocks[i]} from {peer.NodeId}");
                    }

                    if (_blockValidator.ValidateSuggestedBlock(blocks[i]))
                    {
                        AddBlockResult addResult = BlockTree.SuggestBlock(blocks[i]);
                        if (addResult == AddBlockResult.UnknownParent)
                        {
                            if (_logger.IsInfoEnabled)
                            {
                                _logger.Info($"Block {blocks[i].Number} ignored (unknown parent)");
                            }
                            if (i == 0)
                            {
                                if (_logger.IsWarnEnabled)
                                {
                                    _logger.Warn("Resyncing split");
                                }
                                peerInfo.NumberReceived -= 1;
                                var   syncTask = Task.Run(() => PeerSyncAsync(_syncCancellationTokenSource.Token, peerInfo), _syncCancellationTokenSource.Token);
                                await syncTask;
                            }
                            else
                            {
                                const string message = "Peer sent an inconsistent batch of block headers";
                                _logger.Error(message);
                                throw new EthSynchronizationException(message);
                            }
                        }

                        if (_logger.IsDebugEnabled)
                        {
                            _logger.Debug($"Block {blocks[i].Number} suggested for processing");
                        }
                    }
                    else
                    {
                        if (_logger.IsWarnEnabled)
                        {
                            _logger.Warn($"Block {blocks[i].Number} skipped (validation failed)");
                        }
                    }
                }

                peerInfo.NumberReceived = blocks[blocks.Length - 1].Number;

                bestNumber = BlockTree.BestSuggested.Number;
            }

            if (_logger.IsInfoEnabled)
            {
                _logger.Info($"Stopping sync processes with Node: {peerInfo.Peer.NodeId}, wasCancelled: {wasCancelled}");
            }

            if (!wasCancelled)
            {
                peerInfo.IsSynced = true;
                Synced?.Invoke(this, new SyncEventArgs(peerInfo.Peer));
            }
        }