public async Task InitializeAsync(CancellationToken cancel = default) { using (BenchmarkLogger.Measure()) { using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) using (await MatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) using (await ImmatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) { await EnsureBackwardsCompatibilityAsync().ConfigureAwait(false); if (Network == Network.RegTest) { MatureIndexFileManager.DeleteMe(); // RegTest is not a global ledger, better to delete it. ImmatureIndexFileManager.DeleteMe(); } cancel.ThrowIfCancellationRequested(); if (!MatureIndexFileManager.Exists()) { await MatureIndexFileManager.WriteAllLinesAsync(new[] { StartingFilter.ToLine() }, CancellationToken.None).ConfigureAwait(false); } cancel.ThrowIfCancellationRequested(); await InitializeFiltersAsync(cancel).ConfigureAwait(false); } } }
/// <summary> /// It'll LogError the exceptions. /// If cancelled, it'll LogTrace the exception. /// </summary> private async Task TryCommitToFileAsync(TimeSpan throttle, CancellationToken cancel) { try { // If throttle is requested, then throttle. if (throttle != TimeSpan.Zero) { // Increment the throttle ID and remember the incremented value. int incremented = Interlocked.Increment(ref _throttleId); if (incremented < 21) { await Task.Delay(throttle, cancel).ConfigureAwait(false); } // If the _throttleId is still the incremented value, then I am the latest CommitToFileAsync request. // In this case I want to make the _throttledId 0 and go ahead and do the writeline. // If the _throttledId is not the incremented value anymore then I am not the latest request here, // So just return, the latest request will do the file write in its own time. if (Interlocked.CompareExchange(ref _throttleId, 0, incremented) != incremented) { return; } } else { Interlocked.Exchange(ref _throttleId, 0); // So to notify the currently throttled threads that they do not have to run. } using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) using (await MatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) using (await ImmatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) { // Do not feed the cancellationToken here I always want this to finish running for safety. var currentImmatureLines = ImmatureFilters.Select(x => x.ToLine()).ToArray(); // So we do not read on ImmatureFilters while removing them. var matureLinesToAppend = currentImmatureLines.SkipLast(100); var immatureLines = currentImmatureLines.TakeLast(100); var tasks = new Task[] { MatureIndexFileManager.AppendAllLinesAsync(matureLinesToAppend, CancellationToken.None), ImmatureIndexFileManager.WriteAllLinesAsync(immatureLines, CancellationToken.None) }; while (ImmatureFilters.Count > 100) { ImmatureFilters.RemoveFirst(); } await Task.WhenAll(tasks).ConfigureAwait(false); } } catch (Exception ex) when(ex is OperationCanceledException or TimeoutException) { Logger.LogTrace(ex); } catch (Exception ex) { Logger.LogError(ex); } }
public async Task ForeachFiltersAsync(Func <FilterModel, Task> todo, Height fromHeight, CancellationToken cancel = default) { using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) using (await MatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) { var firstImmatureHeight = ImmatureFilters.FirstOrDefault()?.Header?.Height; if (!firstImmatureHeight.HasValue || firstImmatureHeight.Value > fromHeight) { if (MatureIndexFileManager.Exists()) { uint height = StartingHeight; using var sr = MatureIndexFileManager.OpenText(); if (!sr.EndOfStream) { var lineTask = sr.ReadLineAsync(); Task tTask = Task.CompletedTask; string?line = null; while (lineTask is { })
public async Task <IEnumerable <FilterModel> > RemoveAllImmmatureFiltersAsync(CancellationToken cancel, bool deleteAndCrashIfMature = false) { var removed = new List <FilterModel>(); using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) { if (ImmatureFilters.Any()) { Logger.LogWarning($"Filters got corrupted. Reorging {ImmatureFilters.Count} immature filters in an attempt to fix them."); } else { Logger.LogCritical($"Filters got corrupted and have no more immature filters."); if (deleteAndCrashIfMature) { Logger.LogCritical($"Deleting all filters and crashing the software..."); using (await MatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) using (await ImmatureIndexAsyncLock.LockAsync(cancel).ConfigureAwait(false)) { ImmatureIndexFileManager.DeleteMe(); MatureIndexFileManager.DeleteMe(); } Environment.Exit(2); } } } while (ImmatureFilters.Any()) { removed.Add(await RemoveLastFilterAsync(cancel).ConfigureAwait(false)); } return(removed); }