From 417cdf209575e1fd5abd228839fd285c8207cd8f Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 11:39:58 +0100 Subject: [PATCH 01/16] Nullable --- src/Neo/Persistence/ClonedCache.cs | 22 +++--- src/Neo/Persistence/DataCache.cs | 107 ++++++++++++++++------------- 2 files changed, 70 insertions(+), 59 deletions(-) diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index d89491e2b9..29adbbb77b 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -9,6 +9,8 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +#nullable enable + using Neo.SmartContract; using System.Collections.Generic; @@ -16,48 +18,48 @@ namespace Neo.Persistence { class ClonedCache : DataCache { - private readonly DataCache innerCache; + private readonly DataCache _innerCache; public ClonedCache(DataCache innerCache) { - this.innerCache = innerCache; + _innerCache = innerCache; } protected override void AddInternal(StorageKey key, StorageItem value) { - innerCache.Add(key, value.Clone()); + _innerCache.Add(key, value.Clone()); } protected override void DeleteInternal(StorageKey key) { - innerCache.Delete(key); + _innerCache.Delete(key); } protected override bool ContainsInternal(StorageKey key) { - return innerCache.Contains(key); + return _innerCache.Contains(key); } /// protected override StorageItem GetInternal(StorageKey key) { - return innerCache[key].Clone(); + return _innerCache[key].Clone(); } protected override IEnumerable<(StorageKey, StorageItem)> SeekInternal(byte[] keyOrPreifx, SeekDirection direction) { - foreach (var (key, value) in innerCache.Seek(keyOrPreifx, direction)) + foreach (var (key, value) in _innerCache.Seek(keyOrPreifx, direction)) yield return (key, value.Clone()); } - protected override StorageItem TryGetInternal(StorageKey key) + protected override StorageItem? TryGetInternal(StorageKey key) { - return innerCache.TryGet(key)?.Clone(); + return _innerCache.TryGet(key)?.Clone(); } protected override void UpdateInternal(StorageKey key, StorageItem value) { - innerCache.GetAndChange(key).FromReplica(value); + _innerCache.GetAndChange(key)?.FromReplica(value); } } } diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index eedab96152..3b03d5af74 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -9,10 +9,13 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +#nullable enable + using Neo.Extensions; using Neo.SmartContract; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; @@ -44,8 +47,8 @@ public class Trackable public TrackState State; } - private readonly Dictionary dictionary = new(); - private readonly HashSet changeSet = new(); + private readonly Dictionary _dictionary = new(); + private readonly HashSet _changeSet = new(); /// /// Reads a specified entry from the cache. If the entry is not in the cache, it will be automatically loaded from the underlying storage. @@ -57,9 +60,9 @@ public StorageItem this[StorageKey key] { get { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) throw new KeyNotFoundException(); @@ -72,7 +75,7 @@ public StorageItem this[StorageKey key] Item = GetInternal(key), State = TrackState.None }; - dictionary.Add(key, trackable); + _dictionary.Add(key, trackable); } return trackable.Item; } @@ -88,9 +91,9 @@ public StorageItem this[StorageKey key] /// Note: This method does not read the internal storage to check whether the record already exists. public void Add(StorageKey key, StorageItem value) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { trackable.Item = value; trackable.State = trackable.State switch @@ -102,14 +105,14 @@ public void Add(StorageKey key, StorageItem value) } else { - dictionary[key] = new Trackable + _dictionary[key] = new Trackable { Key = key, Item = value, State = TrackState.Added }; } - changeSet.Add(key); + _changeSet.Add(key); } } @@ -126,7 +129,7 @@ public void Add(StorageKey key, StorageItem value) public virtual void Commit() { LinkedList deletedItem = new(); - foreach (Trackable trackable in GetChangeSet()) + foreach (var trackable in GetChangeSet()) switch (trackable.State) { case TrackState.Added: @@ -144,9 +147,9 @@ public virtual void Commit() } foreach (StorageKey key in deletedItem) { - dictionary.Remove(key); + _dictionary.Remove(key); } - changeSet.Clear(); + _changeSet.Clear(); } /// @@ -174,32 +177,32 @@ public DataCache CloneCache() /// The key of the entry. public void Delete(StorageKey key) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { if (trackable.State == TrackState.Added) { trackable.State = TrackState.NotFound; - changeSet.Remove(key); + _changeSet.Remove(key); } else if (trackable.State != TrackState.NotFound) { trackable.State = TrackState.Deleted; - changeSet.Add(key); + _changeSet.Add(key); } } else { - StorageItem item = TryGetInternal(key); + var item = TryGetInternal(key); if (item == null) return; - dictionary.Add(key, new Trackable + _dictionary.Add(key, new Trackable { Key = key, Item = item, State = TrackState.Deleted }); - changeSet.Add(key); + _changeSet.Add(key); } } } @@ -216,12 +219,18 @@ public void Delete(StorageKey key) /// The prefix of the key. /// The search direction. /// The entries found with the desired prefix. - public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[] key_prefix = null, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[]? key_prefix = null, SeekDirection direction = SeekDirection.Forward) { + if (key_prefix == null) + { + // Backwards seek for zero prefix is not supported for now. + throw new ArgumentNullException(nameof(key_prefix)); + } + var seek_prefix = key_prefix; if (direction == SeekDirection.Backward) { - if (key_prefix == null || key_prefix.Length == 0) + if (key_prefix.Length == 0) { // Backwards seek for zero prefix is not supported for now. throw new ArgumentException(); } @@ -278,10 +287,10 @@ public void Delete(StorageKey key) /// The change set. public IEnumerable GetChangeSet() { - lock (dictionary) + lock (_dictionary) { - foreach (StorageKey key in changeSet) - yield return dictionary[key]; + foreach (StorageKey key in _changeSet) + yield return _dictionary[key]; } } @@ -292,9 +301,9 @@ public IEnumerable GetChangeSet() /// if the cache contains an entry with the specified key; otherwise, . public bool Contains(StorageKey key) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) return trackable.State != TrackState.Deleted && trackable.State != TrackState.NotFound; return ContainsInternal(key); } @@ -321,11 +330,11 @@ public bool Contains(StorageKey key) /// The key of the entry. /// A delegate used to create the entry if it doesn't exist. If the entry already exists, the factory will not be used. /// The cached data. Or if it doesn't exist and the is not provided. - public StorageItem GetAndChange(StorageKey key, Func factory = null) + public StorageItem? GetAndChange(StorageKey key, Func? factory = null) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) { @@ -338,13 +347,13 @@ public StorageItem GetAndChange(StorageKey key, Func factory = null else { trackable.State = TrackState.Added; - changeSet.Add(key); + _changeSet.Add(key); } } else if (trackable.State == TrackState.None) { trackable.State = TrackState.Changed; - changeSet.Add(key); + _changeSet.Add(key); } } else @@ -364,8 +373,8 @@ public StorageItem GetAndChange(StorageKey key, Func factory = null { trackable.State = TrackState.Changed; } - dictionary.Add(key, trackable); - changeSet.Add(key); + _dictionary.Add(key, trackable); + _changeSet.Add(key); } return trackable.Item; } @@ -379,9 +388,9 @@ public StorageItem GetAndChange(StorageKey key, Func factory = null /// The cached data. public StorageItem GetOrAdd(StorageKey key, Func factory) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) { @@ -393,7 +402,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) else { trackable.State = TrackState.Added; - changeSet.Add(key); + _changeSet.Add(key); } } } @@ -408,13 +417,13 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) { trackable.Item = factory(); trackable.State = TrackState.Added; - changeSet.Add(key); + _changeSet.Add(key); } else { trackable.State = TrackState.None; } - dictionary.Add(key, trackable); + _dictionary.Add(key, trackable); } return trackable.Item; } @@ -426,14 +435,14 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) /// The key to be sought. /// The direction of seek. /// An enumerator containing all the entries after seeking. - public IEnumerable<(StorageKey Key, StorageItem Value)> Seek(byte[] keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> Seek(byte[]? keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) { IEnumerable<(byte[], StorageKey, StorageItem)> cached; HashSet cachedKeySet; ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; - lock (dictionary) + lock (_dictionary) { - cached = dictionary + cached = _dictionary .Where(p => p.Value.State != TrackState.Deleted && p.Value.State != TrackState.NotFound && (keyOrPrefix == null || comparer.Compare(p.Key.ToArray(), keyOrPrefix) >= 0)) .Select(p => ( @@ -443,7 +452,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) )) .OrderBy(p => p.KeyBytes, comparer) .ToArray(); - cachedKeySet = new HashSet(dictionary.Keys); + cachedKeySet = new HashSet(_dictionary.Keys); } var uncached = SeekInternal(keyOrPrefix ?? Array.Empty(), direction) .Where(p => !cachedKeySet.Contains(p.Key)) @@ -490,19 +499,19 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) /// /// The key of the entry. /// The cached data. Or if it is neither in the cache nor in the underlying storage. - public StorageItem TryGet(StorageKey key) + public StorageItem? TryGet(StorageKey key) { - lock (dictionary) + lock (_dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (_dictionary.TryGetValue(key, out var trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) return null; return trackable.Item; } - StorageItem value = TryGetInternal(key); + var value = TryGetInternal(key); if (value == null) return null; - dictionary.Add(key, new Trackable + _dictionary.Add(key, new Trackable { Key = key, Item = value, @@ -514,7 +523,7 @@ public StorageItem TryGet(StorageKey key) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGet(StorageKey key, out StorageItem item) + public bool TryGet(StorageKey key, [NotNullWhen(true)] out StorageItem? item) { item = TryGet(key); return item != null; @@ -525,7 +534,7 @@ public bool TryGet(StorageKey key, out StorageItem item) /// /// The key of the entry. /// The data of the entry. Or if it doesn't exist. - protected abstract StorageItem TryGetInternal(StorageKey key); + protected abstract StorageItem? TryGetInternal(StorageKey key); /// /// Updates an entry in the underlying storage. From 354f44fb70d08cabff5c147bb85b9e670ad3a625 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 11:47:37 +0100 Subject: [PATCH 02/16] Optimize --- src/Neo/Persistence/DataCache.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 3b03d5af74..9ef02a0f66 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -358,20 +358,25 @@ public bool Contains(StorageKey key) } else { - trackable = new Trackable - { - Key = key, - Item = TryGetInternal(key) - }; - if (trackable.Item == null) + var item = TryGetInternal(key); + if (item == null) { if (factory == null) return null; - trackable.Item = factory(); - trackable.State = TrackState.Added; + trackable = new Trackable + { + Key = key, + Item = factory(), + State = TrackState.Added + }; } else { - trackable.State = TrackState.Changed; + trackable = new Trackable + { + Key = key, + Item = item, + State = TrackState.Changed + }; } _dictionary.Add(key, trackable); _changeSet.Add(key); From 114c38c829752576ef98d4fbc35f674ada7e4743 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 11:50:07 +0100 Subject: [PATCH 03/16] Fix nullables --- src/Neo/Persistence/DataCache.cs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 9ef02a0f66..3d104e4320 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -31,6 +31,7 @@ public abstract class DataCache : IReadOnlyStoreView /// public class Trackable { +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. /// /// The key of the entry. /// @@ -40,6 +41,7 @@ public class Trackable /// The data of the entry. /// public StorageItem Item; +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. /// /// The state of the entry. @@ -413,20 +415,25 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) } else { - trackable = new Trackable - { - Key = key, - Item = TryGetInternal(key) - }; - if (trackable.Item == null) + var item = TryGetInternal(key); + if (item == null) { - trackable.Item = factory(); - trackable.State = TrackState.Added; + trackable = new Trackable + { + Key = key, + Item = factory(), + State = TrackState.Added + }; _changeSet.Add(key); } else { - trackable.State = TrackState.None; + trackable = new Trackable + { + Key = key, + Item = item, + State = TrackState.None + }; } _dictionary.Add(key, trackable); } From 9a0b4dd8b0030140d6e1349caeccda4702213024 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 12:20:39 +0100 Subject: [PATCH 04/16] Fix ut --- src/Neo/Persistence/DataCache.cs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 3d104e4320..e19fdf7bc2 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -223,21 +223,20 @@ public void Delete(StorageKey key) /// The entries found with the desired prefix. public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[]? key_prefix = null, SeekDirection direction = SeekDirection.Forward) { - if (key_prefix == null) - { - // Backwards seek for zero prefix is not supported for now. - throw new ArgumentNullException(nameof(key_prefix)); - } - var seek_prefix = key_prefix; if (direction == SeekDirection.Backward) { + if (key_prefix == null) + { + // Backwards seek for zero prefix is not supported for now. + throw new ArgumentNullException(nameof(key_prefix)); + } if (key_prefix.Length == 0) { // Backwards seek for zero prefix is not supported for now. throw new ArgumentException(); } seek_prefix = null; - for (int i = key_prefix.Length - 1; i >= 0; i--) + for (var i = key_prefix.Length - 1; i >= 0; i--) { if (key_prefix[i] < 0xff) { @@ -249,18 +248,18 @@ public void Delete(StorageKey key) } if (seek_prefix == null) { - throw new ArgumentException(); + throw new ArgumentNullException(nameof(seek_prefix)); } } - return FindInternal(key_prefix, seek_prefix, direction); + return FindInternal(key_prefix, seek_prefix!, direction); } - private IEnumerable<(StorageKey Key, StorageItem Value)> FindInternal(byte[] key_prefix, byte[] seek_prefix, SeekDirection direction) + private IEnumerable<(StorageKey Key, StorageItem Value)> FindInternal(byte[]? key_prefix, byte[]? seek_prefix, SeekDirection direction) { foreach (var (key, value) in Seek(seek_prefix, direction)) - if (key.ToArray().AsSpan().StartsWith(key_prefix)) + if (key_prefix == null || key.ToArray().AsSpan().StartsWith(key_prefix)) yield return (key, value); - else if (direction == SeekDirection.Forward || !key.ToArray().SequenceEqual(seek_prefix)) + else if (direction == SeekDirection.Forward || (seek_prefix == null || !key.ToArray().SequenceEqual(seek_prefix))) yield break; } From 281f92a91059b8766e737ba4acb6f7195cb10bb9 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 12:25:57 +0100 Subject: [PATCH 05/16] More --- src/Neo/Persistence/DataCache.cs | 2 +- src/Neo/Persistence/MemorySnapshot.cs | 42 ++++++++++++++------------- src/Neo/Persistence/MemoryStore.cs | 10 ++++--- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index e19fdf7bc2..92f1f22ddb 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -251,7 +251,7 @@ public void Delete(StorageKey key) throw new ArgumentNullException(nameof(seek_prefix)); } } - return FindInternal(key_prefix, seek_prefix!, direction); + return FindInternal(key_prefix, seek_prefix, direction); } private IEnumerable<(StorageKey Key, StorageItem Value)> FindInternal(byte[]? key_prefix, byte[]? seek_prefix, SeekDirection direction) diff --git a/src/Neo/Persistence/MemorySnapshot.cs b/src/Neo/Persistence/MemorySnapshot.cs index ca772d9127..7b2a748a21 100644 --- a/src/Neo/Persistence/MemorySnapshot.cs +++ b/src/Neo/Persistence/MemorySnapshot.cs @@ -9,40 +9,42 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +#nullable enable + using Neo.Extensions; -using Neo.IO; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Neo.Persistence { internal class MemorySnapshot : ISnapshot { - private readonly ConcurrentDictionary innerData; - private readonly ImmutableDictionary immutableData; - private readonly ConcurrentDictionary writeBatch; + private readonly ConcurrentDictionary _innerData; + private readonly ImmutableDictionary _immutableData; + private readonly ConcurrentDictionary _writeBatch; public MemorySnapshot(ConcurrentDictionary innerData) { - this.innerData = innerData; - immutableData = innerData.ToImmutableDictionary(ByteArrayEqualityComparer.Default); - writeBatch = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); + _innerData = innerData; + _immutableData = innerData.ToImmutableDictionary(ByteArrayEqualityComparer.Default); + _writeBatch = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); } public void Commit() { - foreach (var pair in writeBatch) + foreach (var pair in _writeBatch) if (pair.Value is null) - innerData.TryRemove(pair.Key, out _); + _innerData.TryRemove(pair.Key, out _); else - innerData[pair.Key] = pair.Value; + _innerData[pair.Key] = pair.Value; } public void Delete(byte[] key) { - writeBatch[key] = null; + _writeBatch[key] = null; } public void Dispose() @@ -51,34 +53,34 @@ public void Dispose() public void Put(byte[] key, byte[] value) { - writeBatch[key[..]] = value[..]; + _writeBatch[key[..]] = value[..]; } /// - public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[]? keyOrPrefix, SeekDirection direction = SeekDirection.Forward) { - ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; - IEnumerable> records = immutableData; + var comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; + IEnumerable> records = _immutableData; if (keyOrPrefix?.Length > 0) records = records.Where(p => comparer.Compare(p.Key, keyOrPrefix) >= 0); records = records.OrderBy(p => p.Key, comparer); return records.Select(p => (p.Key[..], p.Value[..])); } - public byte[] TryGet(byte[] key) + public byte[]? TryGet(byte[] key) { - immutableData.TryGetValue(key, out byte[] value); + _immutableData.TryGetValue(key, out var value); return value?[..]; } - public bool TryGet(byte[] key, out byte[] value) + public bool TryGet(byte[] key, [MaybeNullWhen(false)] out byte[]? value) { - return immutableData.TryGetValue(key, out value); + return _immutableData.TryGetValue(key, out value); } public bool Contains(byte[] key) { - return immutableData.ContainsKey(key); + return _immutableData.ContainsKey(key); } } } diff --git a/src/Neo/Persistence/MemoryStore.cs b/src/Neo/Persistence/MemoryStore.cs index cb57210c7d..0419f45259 100644 --- a/src/Neo/Persistence/MemoryStore.cs +++ b/src/Neo/Persistence/MemoryStore.cs @@ -9,10 +9,12 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +#nullable enable + using Neo.Extensions; -using Neo.IO; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; @@ -62,14 +64,14 @@ public void Put(byte[] key, byte[] value) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte[] TryGet(byte[] key) + public byte[]? TryGet(byte[] key) { - if (!_innerData.TryGetValue(key, out byte[] value)) return null; + if (!_innerData.TryGetValue(key, out var value)) return null; return value[..]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGet(byte[] key, out byte[] value) + public bool TryGet(byte[] key, [MaybeNullWhen(false)] out byte[] value) { return _innerData.TryGetValue(key, out value); } From ace1edca4900c1a51e897c43a2e1ba78df80c0f0 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 13 Jan 2025 13:15:35 +0100 Subject: [PATCH 06/16] Update src/Neo/Persistence/DataCache.cs Co-authored-by: Christopher Schuchardt --- src/Neo/Persistence/DataCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 92f1f22ddb..5196652034 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -233,7 +233,7 @@ public void Delete(StorageKey key) } if (key_prefix.Length == 0) { // Backwards seek for zero prefix is not supported for now. - throw new ArgumentException(); + throw new ArgumentOutOfRangeException(); } seek_prefix = null; for (var i = key_prefix.Length - 1; i >= 0; i--) From ead1cdfabba16234b6cecfadd1d2464fefc0e59c Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 13 Jan 2025 13:15:46 +0100 Subject: [PATCH 07/16] Update src/Neo/Persistence/MemorySnapshot.cs Co-authored-by: Christopher Schuchardt --- src/Neo/Persistence/MemorySnapshot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/MemorySnapshot.cs b/src/Neo/Persistence/MemorySnapshot.cs index 7b2a748a21..595a8783aa 100644 --- a/src/Neo/Persistence/MemorySnapshot.cs +++ b/src/Neo/Persistence/MemorySnapshot.cs @@ -73,7 +73,7 @@ public void Put(byte[] key, byte[] value) return value?[..]; } - public bool TryGet(byte[] key, [MaybeNullWhen(false)] out byte[]? value) + public bool TryGet(byte[] key, [NotNullWhen(true)] out byte[]? value) { return _immutableData.TryGetValue(key, out value); } From 00cec144a34a50747e5887473587ae403c8330fd Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 13 Jan 2025 13:15:54 +0100 Subject: [PATCH 08/16] Update src/Neo/Persistence/MemoryStore.cs Co-authored-by: Christopher Schuchardt --- src/Neo/Persistence/MemoryStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/MemoryStore.cs b/src/Neo/Persistence/MemoryStore.cs index 0419f45259..cf43938ecb 100644 --- a/src/Neo/Persistence/MemoryStore.cs +++ b/src/Neo/Persistence/MemoryStore.cs @@ -71,7 +71,7 @@ public void Put(byte[] key, byte[] value) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGet(byte[] key, [MaybeNullWhen(false)] out byte[] value) + public bool TryGet(byte[] key, [NotNullWhen(true)] out byte[] value) { return _innerData.TryGetValue(key, out value); } From ef37d0cc18ccc351319496ff5e71803df10f9f89 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 15:16:18 +0100 Subject: [PATCH 09/16] Remove pragma --- src/Neo/Persistence/DataCache.cs | 66 ++++++-------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 92f1f22ddb..e7c9bd4f92 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -29,24 +29,22 @@ public abstract class DataCache : IReadOnlyStoreView /// /// Represents an entry in the cache. /// - public class Trackable + public class Trackable(StorageKey key, StorageItem item, TrackState state) { -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. /// /// The key of the entry. /// - public StorageKey Key; + public StorageKey Key { get; } = key; /// /// The data of the entry. /// - public StorageItem Item; -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + public StorageItem Item { get; set; } = item; /// /// The state of the entry. /// - public TrackState State; + public TrackState State { get; set; } = state; } private readonly Dictionary _dictionary = new(); @@ -71,12 +69,7 @@ public StorageItem this[StorageKey key] } else { - trackable = new Trackable - { - Key = key, - Item = GetInternal(key), - State = TrackState.None - }; + trackable = new Trackable(key, GetInternal(key), TrackState.None); _dictionary.Add(key, trackable); } return trackable.Item; @@ -107,12 +100,7 @@ public void Add(StorageKey key, StorageItem value) } else { - _dictionary[key] = new Trackable - { - Key = key, - Item = value, - State = TrackState.Added - }; + _dictionary[key] = new Trackable(key, value, TrackState.Added); } _changeSet.Add(key); } @@ -198,12 +186,7 @@ public void Delete(StorageKey key) { var item = TryGetInternal(key); if (item == null) return; - _dictionary.Add(key, new Trackable - { - Key = key, - Item = item, - State = TrackState.Deleted - }); + _dictionary.Add(key, new Trackable(key, item, TrackState.Deleted)); _changeSet.Add(key); } } @@ -363,21 +346,11 @@ public bool Contains(StorageKey key) if (item == null) { if (factory == null) return null; - trackable = new Trackable - { - Key = key, - Item = factory(), - State = TrackState.Added - }; + trackable = new Trackable(key, factory(), TrackState.Added); } else { - trackable = new Trackable - { - Key = key, - Item = item, - State = TrackState.Changed - }; + trackable = new Trackable(key, item, TrackState.Changed); } _dictionary.Add(key, trackable); _changeSet.Add(key); @@ -417,22 +390,12 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) var item = TryGetInternal(key); if (item == null) { - trackable = new Trackable - { - Key = key, - Item = factory(), - State = TrackState.Added - }; + trackable = new Trackable(key, factory(), TrackState.Added); _changeSet.Add(key); } else { - trackable = new Trackable - { - Key = key, - Item = item, - State = TrackState.None - }; + trackable = new Trackable(key, item, TrackState.None); } _dictionary.Add(key, trackable); } @@ -522,12 +485,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) } var value = TryGetInternal(key); if (value == null) return null; - _dictionary.Add(key, new Trackable - { - Key = key, - Item = value, - State = TrackState.None - }); + _dictionary.Add(key, new Trackable(key, value, TrackState.None)); return value; } } From 033448970b115ed24cba03da6f27a5f14b50d475 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 15:18:22 +0100 Subject: [PATCH 10/16] Clean --- src/Neo/Persistence/DataCache.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 65e9c83fe9..460ea672f5 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -211,12 +211,13 @@ public void Delete(StorageKey key) { if (key_prefix == null) { - // Backwards seek for zero prefix is not supported for now. + // Backwards seek for null prefix is not supported for now. throw new ArgumentNullException(nameof(key_prefix)); } if (key_prefix.Length == 0) - { // Backwards seek for zero prefix is not supported for now. - throw new ArgumentOutOfRangeException(); + { + // Backwards seek for zero prefix is not supported for now. + throw new ArgumentOutOfRangeException(nameof(key_prefix)); } seek_prefix = null; for (var i = key_prefix.Length - 1; i >= 0; i--) From 5cd1c535c9a00887f6d69b0d7a6ab395f91aaabc Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 15:23:55 +0100 Subject: [PATCH 11/16] SnapshotCache --- src/Neo/Persistence/SnapshotCache.cs | 30 +++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Neo/Persistence/SnapshotCache.cs b/src/Neo/Persistence/SnapshotCache.cs index 777e9b5802..34740c7b75 100644 --- a/src/Neo/Persistence/SnapshotCache.cs +++ b/src/Neo/Persistence/SnapshotCache.cs @@ -9,6 +9,8 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +#nullable enable + using Neo.Extensions; using Neo.SmartContract; using System; @@ -22,8 +24,8 @@ namespace Neo.Persistence /// public class SnapshotCache : DataCache, IDisposable { - private readonly IReadOnlyStore store; - private readonly ISnapshot snapshot; + private readonly IReadOnlyStore _store; + private readonly ISnapshot? _snapshot; /// /// Initializes a new instance of the class. @@ -31,58 +33,58 @@ public class SnapshotCache : DataCache, IDisposable /// An to create a readonly cache; or an to create a snapshot cache. public SnapshotCache(IReadOnlyStore store) { - this.store = store; - snapshot = store as ISnapshot; + _store = store; + _snapshot = store as ISnapshot; } protected override void AddInternal(StorageKey key, StorageItem value) { - snapshot?.Put(key.ToArray(), value.ToArray()); + _snapshot?.Put(key.ToArray(), value.ToArray()); } protected override void DeleteInternal(StorageKey key) { - snapshot?.Delete(key.ToArray()); + _snapshot?.Delete(key.ToArray()); } public override void Commit() { base.Commit(); - snapshot?.Commit(); + _snapshot?.Commit(); } protected override bool ContainsInternal(StorageKey key) { - return store.Contains(key.ToArray()); + return _store.Contains(key.ToArray()); } public void Dispose() { - snapshot?.Dispose(); + _snapshot?.Dispose(); } /// protected override StorageItem GetInternal(StorageKey key) { - if (store.TryGet(key.ToArray(), out var value)) + if (_store.TryGet(key.ToArray(), out var value)) return new(value); throw new KeyNotFoundException(); } protected override IEnumerable<(StorageKey, StorageItem)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction) { - return store.Seek(keyOrPrefix, direction).Select(p => (new StorageKey(p.Key), new StorageItem(p.Value))); + return _store.Seek(keyOrPrefix, direction).Select(p => (new StorageKey(p.Key), new StorageItem(p.Value))); } /// - protected override StorageItem TryGetInternal(StorageKey key) + protected override StorageItem? TryGetInternal(StorageKey key) { - return store.TryGet(key.ToArray(), out var value) ? new(value) : null; + return _store.TryGet(key.ToArray(), out var value) ? new(value) : null; } protected override void UpdateInternal(StorageKey key, StorageItem value) { - snapshot?.Put(key.ToArray(), value.ToArray()); + _snapshot?.Put(key.ToArray(), value.ToArray()); } } } From d0f034cd256e3fc73b1ba08eef249f4cfff00c35 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Mon, 13 Jan 2025 15:38:56 +0100 Subject: [PATCH 12/16] Change exception --- src/Neo/Persistence/DataCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 460ea672f5..09715e7902 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -232,7 +232,7 @@ public void Delete(StorageKey key) } if (seek_prefix == null) { - throw new ArgumentNullException(nameof(seek_prefix)); + throw new NullReferenceException($"{nameof(seek_prefix)} can't be null"); } } return FindInternal(key_prefix, seek_prefix, direction); From 2ef6457736518e1c238423e0945112e5b5a73821 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 14 Jan 2025 12:22:43 +0100 Subject: [PATCH 13/16] Fix conflicts --- src/Neo/Persistence/DataCache.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 507527fb40..a1eb24adb3 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -118,11 +118,11 @@ public void Add(StorageKey key, StorageItem value) /// public virtual void Commit() { - lock (dictionary) + lock (_dictionary) { - foreach (var key in changeSet) + foreach (var key in _changeSet) { - var trackable = dictionary[key]; + var trackable = _dictionary[key]; switch (trackable.State) { case TrackState.Added: @@ -135,11 +135,11 @@ public virtual void Commit() break; case TrackState.Deleted: DeleteInternal(key); - dictionary.Remove(key); + _dictionary.Remove(key); break; } } - changeSet.Clear(); + _changeSet.Clear(); } } From b5b09a4a58bd33bc51fb1013e371d927af31a4a3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 15 Jan 2025 11:46:59 +0100 Subject: [PATCH 14/16] Update src/Neo/Persistence/DataCache.cs Co-authored-by: Christopher Schuchardt --- src/Neo/Persistence/DataCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index a1eb24adb3..b79e48fb9e 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -233,7 +233,7 @@ public void Delete(StorageKey key) } if (seek_prefix == null) { - throw new NullReferenceException($"{nameof(seek_prefix)} can't be null"); + throw new ArgumentException($"{nameof(key_prefix)} can't be empty."); } } return FindInternal(key_prefix, seek_prefix, direction); From fe56246f46bfe7d4fa0e5e7419a6ba5b887b59ed Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 16 Jan 2025 00:37:59 -0800 Subject: [PATCH 15/16] Update src/Neo/Persistence/DataCache.cs Co-authored-by: nan01ab --- src/Neo/Persistence/DataCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index b79e48fb9e..3f10896f2f 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -233,7 +233,7 @@ public void Delete(StorageKey key) } if (seek_prefix == null) { - throw new ArgumentException($"{nameof(key_prefix)} can't be empty."); + throw new ArgumentException($"{nameof(key_prefix)} with all bytes being 0xff is not supported now"); } } return FindInternal(key_prefix, seek_prefix, direction); From 5af9001658df4a351be7f172c7a9078512ab29d5 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Fri, 17 Jan 2025 10:28:36 +0100 Subject: [PATCH 16/16] Avoid logic change --- src/Neo/Persistence/ClonedCache.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index 29adbbb77b..f593b62bc1 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -59,7 +59,10 @@ protected override StorageItem GetInternal(StorageKey key) protected override void UpdateInternal(StorageKey key, StorageItem value) { - _innerCache.GetAndChange(key)?.FromReplica(value); + var entry = _innerCache.GetAndChange(key) + ?? throw new KeyNotFoundException(); + + entry.FromReplica(value); } } }