Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions src/Neo/Persistence/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,20 @@ public class Trackable(StorageItem item, TrackState state)
public TrackState State { get; set; } = state;
}

/// <summary>
/// Delegate for storage entries
/// </summary>
/// <param name="sender">DataCache</param>
/// <param name="key">Key</param>
/// <param name="item">Item</param>
public delegate void OnEntryDelegate(DataCache sender, StorageKey key, StorageItem item);

private readonly Dictionary<StorageKey, Trackable> _dictionary = [];
private readonly HashSet<StorageKey>? _changeSet;

public event OnEntryDelegate? OnRead;
public event OnEntryDelegate? OnUpdate;

/// <summary>
/// True if DataCache is readOnly
/// </summary>
Expand Down Expand Up @@ -145,7 +156,7 @@ public virtual void Commit()
trackable.State = TrackState.None;
break;
case TrackState.Changed:
UpdateInternal(key, trackable.Item);
UpdateInternalWrapper(key, trackable.Item);
trackable.State = TrackState.None;
break;
case TrackState.Deleted:
Expand Down Expand Up @@ -218,7 +229,7 @@ public void Delete(StorageKey key)
}
else
{
var item = TryGetInternal(key);
var item = TryGetInternalWrapper(key);
if (item == null) return;
_dictionary.Add(key, new Trackable(item, TrackState.Deleted));
_changeSet?.Add(key);
Expand Down Expand Up @@ -390,7 +401,7 @@ public bool Contains(StorageKey key)
}
else
{
var item = TryGetInternal(key);
var item = TryGetInternalWrapper(key);
if (item == null)
{
if (factory == null) return null;
Expand All @@ -407,6 +418,21 @@ public bool Contains(StorageKey key)
}
}

private StorageItem? TryGetInternalWrapper(StorageKey key)
{
var item = TryGetInternal(key);
if (item == null) return null;

OnRead?.Invoke(this, key, item);
return item;
}

private void UpdateInternalWrapper(StorageKey key, StorageItem value)
{
UpdateInternal(key, value);
OnUpdate?.Invoke(this, key, value);
}

/// <summary>
/// Reads a specified entry from the cache.
/// If the entry is not in the cache, it will be automatically loaded from the underlying storage.
Expand Down Expand Up @@ -440,7 +466,7 @@ public StorageItem GetOrAdd(StorageKey key, Func<StorageItem> factory)
}
else
{
var item = TryGetInternal(key);
var item = TryGetInternalWrapper(key);
if (item == null)
{
trackable = new Trackable(factory(), TrackState.Added);
Expand Down Expand Up @@ -538,7 +564,7 @@ public StorageItem GetOrAdd(StorageKey key, Func<StorageItem> factory)
return null;
return trackable.Item;
}
var value = TryGetInternal(key);
var value = TryGetInternalWrapper(key);
if (value == null) return null;
_dictionary.Add(key, new Trackable(value, TrackState.None));
return value;
Expand Down
12 changes: 12 additions & 0 deletions src/Neo/Persistence/IStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ public interface IStore :
IWriteStore<byte[], byte[]>,
IDisposable
{
/// <summary>
/// Delegate for OnNewSnapshot
/// </summary>
/// <param name="sender">Store</param>
/// <param name="snapshot">Snapshot</param>
public delegate void OnNewSnapshotDelegate(IStore sender, IStoreSnapshot snapshot);

/// <summary>
/// Event raised when a new snapshot is created
/// </summary>
public event OnNewSnapshotDelegate? OnNewSnapshot;

/// <summary>
/// Creates a snapshot of the database.
/// </summary>
Expand Down
7 changes: 6 additions & 1 deletion src/Neo/Persistence/Providers/MemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class MemoryStore : IStore
{
private readonly ConcurrentDictionary<byte[], byte[]> _innerData = new(ByteArrayEqualityComparer.Default);

/// <inheritdoc/>
public event IStore.OnNewSnapshotDelegate? OnNewSnapshot;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Delete(byte[] key)
{
Expand All @@ -38,7 +41,9 @@ public void Dispose() { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IStoreSnapshot GetSnapshot()
{
return new MemorySnapshot(this, _innerData);
var snapshot = new MemorySnapshot(this, _innerData);
OnNewSnapshot?.Invoke(this, snapshot);
return snapshot;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
11 changes: 9 additions & 2 deletions src/Plugins/LevelDBStore/Plugins/Storage/Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ internal class Store : IStore, IEnumerable<KeyValuePair<byte[], byte[]>>
private readonly DB _db;
private readonly Options _options;

/// <inheritdoc/>
public event IStore.OnNewSnapshotDelegate? OnNewSnapshot;

public Store(string path)
{
_options = new Options
Expand All @@ -47,8 +50,12 @@ public void Dispose()
_options.Dispose();
}

public IStoreSnapshot GetSnapshot() =>
new Snapshot(this, _db);
public IStoreSnapshot GetSnapshot()
{
var snapshot = new Snapshot(this, _db);
OnNewSnapshot?.Invoke(this, snapshot);
return snapshot;
}

public void Put(byte[] key, byte[] value) =>
_db.Put(WriteOptions.Default, key, value);
Expand Down
7 changes: 6 additions & 1 deletion src/Plugins/RocksDBStore/Plugins/Storage/Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ internal class Store : IStore
{
private readonly RocksDb _db;

/// <inheritdoc/>
public event IStore.OnNewSnapshotDelegate? OnNewSnapshot;

public Store(string path)
{
_db = RocksDb.Open(Options.Default, Path.GetFullPath(path));
Expand All @@ -34,7 +37,9 @@ public void Dispose()

public IStoreSnapshot GetSnapshot()
{
return new Snapshot(this, _db);
var snapshot = new Snapshot(this, _db);
OnNewSnapshot?.Invoke(this, snapshot);
return snapshot;
}

/// <inheritdoc/>
Expand Down
Loading