public byte[] this[byte[] key] { get { lock (_diffLock) { RequiredPeerDifficulty = UInt256.Max(RequiredPeerDifficulty, BeamSyncContext.MinimumDifficulty.Value); } // it is not possible for the item to be requested from the DB and missing in the DB unless the DB is corrupted // if it is missing in the MemDb then it must exist somewhere on the web (unless the block is corrupted / invalid) // we grab the node from the web through requests // if the block is invalid then we will be timing out for a long time // in such case it would be good to have some gossip about corrupted blocks // but such gossip would be cheap // if we keep timing out then we would finally reject the block (but only shelve it instead of marking invalid) bool wasInDb = true; while (true) { if (BeamSyncContext.Cancelled.Value.IsCancellationRequested) { throw new TaskCanceledException("Beam Sync task cancelled by a new block."); } if (_isDisposed) { throw new ObjectDisposedException("Beam Sync DB disposed"); } // shall I leave test logic forever? if (BeamSyncContext.LoopIterationsToFailInTest.Value != null) { int?currentValue = BeamSyncContext.LoopIterationsToFailInTest.Value--; if (currentValue == 0) { throw new Exception(); } } var fromMem = _db[key]; if (fromMem == null) { if (Bytes.AreEqual(key, Keccak.Zero.Bytes)) { // we store sync progress data at Keccak.Zero; return(null); } TimeSpan expiry = _contextExpiryTimeSpan; if (BeamSyncContext.Description.Value?.Contains("preProcess") ?? false) { expiry = _preProcessExpiryTimeSpan; } if (DateTime.UtcNow - (BeamSyncContext.LastFetchUtc.Value ?? DateTime.UtcNow) > expiry) { string message = $"Beam sync request {BeamSyncContext.Description.Value} with last update on {BeamSyncContext.LastFetchUtc.Value:hh:mm:ss.fff} has expired"; if (_logger.IsDebug) { _logger.Debug(message); } throw new BeamSyncException(message); } wasInDb = false; // _logger.Info($"BEAM SYNC Asking for {key.ToHexString()} - resolved keys so far {_resolvedKeysCount}"); int count; lock (_requestedNodes) { _requestedNodes.Add(new Keccak(key)); count = _requestedNodes.Count; } // _logger.Error($"Requested {key.ToHexString()}"); NeedMoreData?.Invoke(this, EventArgs.Empty); _autoReset.WaitOne(50); } else { if (!wasInDb) { BeamSyncContext.ResolvedInContext.Value++; Interlocked.Increment(ref _resolvedKeysCount); // if (_logger.IsInfo) _logger.Info($"{_description} Resolved key {key.ToHexString()} of context {BeamSyncContext.Description.Value} - resolved ctx {BeamSyncContext.ResolvedInContext.Value} | total {_resolvedKeysCount}"); } BeamSyncContext.LastFetchUtc.Value = DateTime.UtcNow; return(fromMem); } } } set => _db[key] = value;
private void DataConsumerOnNeedMoreData(object sender, EventArgs e) { NeedMoreData?.Invoke(this, EventArgs.Empty); }