示例#1
0
 private void ProcessFilter(FilterModel filter, bool enqueue)
 {
     if (enqueue)
     {
         ImmatureFilters.Add(filter);
     }
     HashChain.AddOrReplace(filter.BlockHeight.Value, filter.BlockHash);
 }
示例#2
0
        /// <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);
                    }

                    // 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 notified the currently throttled threads that they don't have to run.
                }

                using (await MatureIndexFileManager.Mutex.LockAsync(cancel))
                    using (await ImmatureIndexFileManager.Mutex.LockAsync(cancel))
                        using (await IndexLock.LockAsync(cancel))
                        {
                            // Don't feed the cancellationToken here I always want this to finish running for safety.
                            var currentImmatureLines = ImmatureFilters.Select(x => x.ToHeightlessLine());
                            var matureLinesToAppend  = currentImmatureLines.SkipLast(100);
                            var immatureLines        = currentImmatureLines.TakeLast(100);
                            await MatureIndexFileManager.AppendAllLinesAsync(matureLinesToAppend);

                            await ImmatureIndexFileManager.WriteAllLinesAsync(immatureLines);

                            while (ImmatureFilters.Count > 100)
                            {
                                ImmatureFilters.RemoveFirst();
                            }
                        }
            }
            catch (Exception ex) when(ex is OperationCanceledException ||
                                      ex is TaskCanceledException ||
                                      ex is TimeoutException)
            {
                Logger.LogTrace <IndexStore>(ex);
            }
            catch (Exception ex)
            {
                Logger.LogError <IndexStore>(ex);
            }
        }
示例#3
0
 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 { })
示例#4
0
        private bool TryProcessFilter(FilterModel filter, bool enqueue)
        {
            try
            {
                SmartHeaderChain.AddOrReplace(filter.Header);
                if (enqueue)
                {
                    ImmatureFilters.Add(filter);
                }

                return(true);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                return(false);
            }
        }
示例#5
0
        public async Task ForeachFiltersAsync(Func <FilterModel, Task> todo, Height fromHeight)
        {
            using (await MatureIndexFileManager.Mutex.LockAsync())
                using (await IndexLock.LockAsync())
                {
                    var firstImmatureHeight = ImmatureFilters.FirstOrDefault()?.BlockHeight;
                    if (!firstImmatureHeight.HasValue || firstImmatureHeight.Value > fromHeight)
                    {
                        if (MatureIndexFileManager.Exists())
                        {
                            Height height = StartingHeight;
                            using (var sr = MatureIndexFileManager.OpenText(16384))
                            {
                                while (!sr.EndOfStream)
                                {
                                    var line = await sr.ReadLineAsync();

                                    if (firstImmatureHeight == height)
                                    {
                                        break;                                 // Let's use our the immature filters from here on. The content is the same, just someone else modified the file.
                                    }

                                    if (height < fromHeight.Value)
                                    {
                                        height++;
                                        continue;
                                    }

                                    var filter = FilterModel.FromHeightlessLine(line, height);

                                    await todo(filter);

                                    height++;
                                }
                            }
                        }
                    }

                    foreach (FilterModel filter in ImmatureFilters)
                    {
                        await todo(filter);
                    }
                }
        }
示例#6
0
    public async Task <FilterModel> RemoveLastFilterAsync(CancellationToken cancel)
    {
        FilterModel?filter = null;

        using (await IndexLock.LockAsync(cancel).ConfigureAwait(false))
        {
            filter = ImmatureFilters.Last();
            ImmatureFilters.RemoveLast();
            if (SmartHeaderChain.TipHeight != filter.Header.Height)
            {
                throw new InvalidOperationException($"{nameof(SmartHeaderChain)} and {nameof(ImmatureFilters)} are not in sync.");
            }
            SmartHeaderChain.RemoveTip();
        }

        Reorged?.Invoke(this, filter);

        AbandonedTasks.AddAndClearCompleted(TryCommitToFileAsync(TimeSpan.FromSeconds(3), cancel));

        return(filter);
    }
示例#7
0
        public async Task <FilterModel> RemoveLastFilterAsync(CancellationToken cancel)
        {
            FilterModel filter = null;

            using (await IndexLock.LockAsync())
            {
                filter = ImmatureFilters.Last();
                ImmatureFilters.RemoveLast();
                if (HashChain.TipHeight != filter.BlockHeight.Value)
                {
                    throw new InvalidOperationException("HashChain and ImmatureFilters are not in sync.");
                }
                HashChain.RemoveLast();
            }

            Reorged?.Invoke(this, filter);

            _ = TryCommitToFileAsync(TimeSpan.FromSeconds(3), cancel);

            return(filter);
        }
示例#8
0
    private bool TryProcessFilter(FilterModel filter, bool enqueue)
    {
        try
        {
            if (IsWrongFilter(filter))
            {
                return(false);
            }

            SmartHeaderChain.AppendTip(filter.Header);
            if (enqueue)
            {
                ImmatureFilters.Add(filter);
            }

            return(true);
        }
        catch (Exception ex)
        {
            Logger.LogError(ex);
            return(false);
        }
    }
示例#9
0
    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);
    }
示例#10
0
        public async Task ForeachFiltersAsync(Func <FilterModel, Task> todo, Height fromHeight, CancellationToken cancel = default)
        {
            using (await MatureIndexFileManager.Mutex.LockAsync(cancel).ConfigureAwait(false))
                using (await IndexLock.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 != null)
                                {
                                    if (firstImmatureHeight == height)
                                    {
                                        break;                                 // Let's use our the immature filters from here on. The content is the same, just someone else modified the file.
                                    }

                                    if (line is null)
                                    {
                                        line = await lineTask.ConfigureAwait(false);
                                    }

                                    lineTask = sr.EndOfStream ? null : sr.ReadLineAsync();

                                    if (height < fromHeight.Value)
                                    {
                                        height++;
                                        line = null;
                                        continue;
                                    }

                                    var filter = FilterModel.FromLine(line);

                                    await tTask.ConfigureAwait(false);

                                    tTask = todo(filter);

                                    height++;

                                    line = null;
                                }
                                await tTask.ConfigureAwait(false);
                            }

                            while (!sr.EndOfStream)
                            {
                                var line = await sr.ReadLineAsync().ConfigureAwait(false);

                                if (firstImmatureHeight == height)
                                {
                                    break;                             // Let's use our the immature filters from here on. The content is the same, just someone else modified the file.
                                }

                                if (height < fromHeight.Value)
                                {
                                    height++;
                                    continue;
                                }

                                var filter = FilterModel.FromLine(line);

                                await todo(filter).ConfigureAwait(false);

                                height++;
                            }
                        }
                    }

                    foreach (FilterModel filter in ImmatureFilters)
                    {
                        await todo(filter).ConfigureAwait(false);
                    }
                }
        }