diff --git a/src/Paprika/Store/DataPage.cs b/src/Paprika/Store/DataPage.cs index e73128eb..5ee0f6b0 100644 --- a/src/Paprika/Store/DataPage.cs +++ b/src/Paprika/Store/DataPage.cs @@ -74,6 +74,11 @@ public Page DeleteByPrefix(in NibblePath prefix, IBatchContext batch) buckets[prefix.Nibble0] = batch.GetAddress(child); } } + else + { + batch.RegisterForFutureReuse(page); + return batch.NullPage; + } } else { diff --git a/src/Paprika/Store/IBatchContext.cs b/src/Paprika/Store/IBatchContext.cs index 0ad72127..e13d05d5 100644 --- a/src/Paprika/Store/IBatchContext.cs +++ b/src/Paprika/Store/IBatchContext.cs @@ -72,6 +72,8 @@ Page EnsureWritableCopy(ref DbAddress addr) Page TryGetPageAlloc(ref DbAddress addr, PageType pageType); BatchStats? Stats { get; } + + public unsafe Page NullPage => new Page((byte*)0); } public class BatchStats : IBatchStats diff --git a/src/Paprika/Store/LeafOverflowPage.cs b/src/Paprika/Store/LeafOverflowPage.cs index 5ec5ae1a..a9c5d0e8 100644 --- a/src/Paprika/Store/LeafOverflowPage.cs +++ b/src/Paprika/Store/LeafOverflowPage.cs @@ -47,6 +47,11 @@ public Page DeleteByPrefix(in NibblePath prefix, IBatchContext batch) var writable = batch.GetWritableCopy(page); return new LeafOverflowPage(writable).DeleteByPrefix(prefix, batch); } + if (prefix.IsEmpty) + { + batch.RegisterForFutureReuse(page); + return batch.NullPage; + } Map.DeleteByPrefix(prefix); diff --git a/src/Paprika/Store/PagedDb.cs b/src/Paprika/Store/PagedDb.cs index aa17306e..e79195c8 100644 --- a/src/Paprika/Store/PagedDb.cs +++ b/src/Paprika/Store/PagedDb.cs @@ -519,8 +519,8 @@ class Batch : BatchContextBase, IBatch private readonly RootPage _root; private readonly uint _reusePagesOlderThanBatchId; private bool _verify = false; - private bool _disposed; - + private bool _disposed; + private readonly Context _ctx; /// diff --git a/src/Paprika/Store/StateRootPage.cs b/src/Paprika/Store/StateRootPage.cs index 86681d90..236b24d8 100644 --- a/src/Paprika/Store/StateRootPage.cs +++ b/src/Paprika/Store/StateRootPage.cs @@ -75,6 +75,12 @@ public Page DeleteByPrefix(in NibblePath prefix, IBatchContext batch) return new StateRootPage(writable).DeleteByPrefix(prefix, batch); } + if (prefix.IsEmpty) + { + batch.RegisterForFutureReuse(page); + return batch.NullPage; + } + Debug.Assert(prefix.Length > ConsumedNibbles, "Removing prefix at the root? Something went wrong."); var index = GetIndex(prefix); diff --git a/src/Paprika/Store/StorageFanOut.cs b/src/Paprika/Store/StorageFanOut.cs index aed117f7..2f23adc5 100644 --- a/src/Paprika/Store/StorageFanOut.cs +++ b/src/Paprika/Store/StorageFanOut.cs @@ -188,6 +188,12 @@ public Page DeleteByPrefix(in NibblePath prefix, IBatchContext batch) var writable = batch.GetWritableCopy(page); return new Level1Page(writable).DeleteByPrefix(prefix, batch); } + if (prefix.IsEmpty) + { + batch.RegisterForFutureReuse(page); + return batch.NullPage; + } + var index = GetIndex(prefix, Type.Storage, out var sliced);