Exemple #1
0
        private void EnqueueJobs(NodeBlocksRepository repo, ChainBase chain, CloudBlockBlob blobLock, string lease)
        {
            int          cumul      = 0;
            ChainedBlock from       = chain.Genesis;
            int          blockCount = 0;

            foreach (var block in repo.GetBlocks(new[] { chain.Genesis }.Concat(chain.EnumerateAfter(chain.Genesis)).Where(c => c.Height % BlockGranularity == 0).Select(c => c.HashBlock), default(CancellationToken)))
            {
                cumul      += block.Transactions.Count * BlockGranularity;
                blockCount += BlockGranularity;
                if (cumul > TransactionsPerWork)
                {
                    var nextFrom = chain.GetBlock(chain.GetBlock(block.GetHash()).Height + BlockGranularity);
                    if (nextFrom == null)
                    {
                        break;
                    }
                    EnqueueRange(chain, from, blockCount);
                    from       = nextFrom;
                    blockCount = 0;
                    cumul      = 0;
                }
            }

            blockCount = (chain.Tip.Height - from.Height) + 1;
            EnqueueRange(chain, from, blockCount);

            var bytes = chain.Tip.GetLocator().ToBytes();

            blobLock.UploadText(Encoders.Hex.EncodeData(bytes), null, new AccessCondition()
            {
                LeaseId = lease
            });
        }
Exemple #2
0
        public int Run(ChainBase chain = null)
        {
            ListenerTrace.Info("Start initial indexing");
            int totalProcessed = 0;

            using (var node = _Conf.Indexer.ConnectToNode(false))
            {
                ListenerTrace.Info("Handshaking...");
                node.VersionHandshake();
                ListenerTrace.Info("Handshaked");
                chain = chain ?? node.GetChain();
                ListenerTrace.Info("Current chain at height " + chain.Height);
                var blockRepository = new NodeBlocksRepository(node);

                var    blobLock = GetInitBlob();
                string lease    = null;
                try
                {
                    blobLock.UploadText("Enqueuing");
                    lease = blobLock.AcquireLease(null, null);
                }
                catch (StorageException)
                {
                }
                if (lease != null)
                {
                    ListenerTrace.Info("Queueing index jobs");
                    EnqueueJobs(blockRepository, chain, blobLock, lease);
                }
                ListenerTrace.Info("Dequeuing index jobs");

                while (true)
                {
                    var msg = _Conf.Topics
                              .InitialIndexing
                              .ReceiveAsync(TimeSpan.FromMilliseconds(1000))
                              .Result;

                    var ns          = _Conf.Topics.InitialIndexing.GetNamespace();
                    var description = ns.GetQueue(_Conf.Topics.InitialIndexing.Queue);

                    Console.WriteLine("Work remaining in the queue : " + description.MessageCountDetails.ActiveMessageCount);
                    if (msg == null)
                    {
                        var state = blobLock.DownloadText();
                        if (state == "Enqueuing" || description.MessageCountDetails.ActiveMessageCount != 0)
                        {
                            ListenerTrace.Info("Additional work will be enqueued...");
                            continue;
                        }
                        else
                        {
                            var locator = new BlockLocator();
                            locator.FromBytes(Encoders.Hex.DecodeData(state));
                            UpdateCheckpoints(locator);
                            break;
                        }
                    }

                    using (msg.Message)
                    {
                        var range = msg.Body;
                        using (var sched = new CustomThreadPoolTaskScheduler(50, 100, range.ToString()))
                        {
                            ListenerTrace.Info("Processing " + range.ToString());
                            totalProcessed++;
                            var          task    = _IndexTasks[range.Target];
                            BlockFetcher fetcher = new BlockFetcher(task.Item1, blockRepository, chain)
                            {
                                FromHeight = range.From,
                                ToHeight   = range.From + range.Count - 1
                            };
                            try
                            {
                                task.Item2.SaveProgression = false;
                                task.Item2.EnsureIsSetup   = totalProcessed == 0;
                                var index = Task.Factory.StartNew(() =>
                                {
                                    task.Item2.Index(fetcher, sched);
                                }, TaskCreationOptions.LongRunning);
                                while (!index.Wait(TimeSpan.FromMinutes(4)))
                                {
                                    msg.Message.RenewLock();
                                    ListenerTrace.Info("Lock renewed");
                                }
                            }
                            catch (AggregateException aex)
                            {
                                ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
                                throw;
                            }

                            range.Processed = true;
                            msg.Message.Complete();
                        }
                    }
                }
            }
            ListenerTrace.Info("Initial indexing terminated");
            return(totalProcessed);
        }