diff --git a/src/ZoneTree/Collections/BplusTree/BTree.Write.cs b/src/ZoneTree/Collections/BplusTree/BTree.Write.cs index dfe4d81..b81284c 100644 --- a/src/ZoneTree/Collections/BplusTree/BTree.Write.cs +++ b/src/ZoneTree/Collections/BplusTree/BTree.Write.cs @@ -135,11 +135,28 @@ public partial class BTree (var left, var right) = childLeaf .SplitLeaf(pivotPosition, LeafSize, GetNodeLocker(), GetNodeLocker()); - left.Previous = childLeaf.Previous; - right.Next = childLeaf.Next; - var pre = childLeaf.Previous; + pre?.WriteLock(); + // prevent neighbour split at the same time. + while (childLeaf.Previous != pre) + { + pre.WriteUnlock(); + pre = childLeaf.Previous; + pre.WriteLock(); + } + var next = childLeaf.Next; + next?.WriteLock(); + // prevent neighbour split at the same time. + while (childLeaf.Next != next) + { + next.WriteUnlock(); + next = childLeaf.Next; + next.WriteLock(); + } + + left.Previous = pre; + right.Next = next; if (pre == null) FirstLeafNode = left; @@ -151,6 +168,9 @@ public partial class BTree else next.Previous = right; + next?.WriteUnlock(); + pre?.WriteUnlock(); + parent.InsertKeyAndChild(parentInsertPosition, in pivotKey, left, right); } else @@ -176,8 +196,8 @@ public partial class BTree return false; } leaf.Insert(position, in key, in value); - node.WriteUnlock(); Interlocked.Increment(ref _length); + node.WriteUnlock(); return true; } @@ -215,8 +235,8 @@ public partial class BTree opIndex = IncrementalIdProvider.NextId(); leaf.Insert(position, in key, in value); - node.WriteUnlock(); Interlocked.Increment(ref _length); + node.WriteUnlock(); return true; } @@ -257,8 +277,8 @@ public partial class BTree TValue value = default; adder(ref value); leaf.Insert(position, in key, in value); - node.WriteUnlock(); Interlocked.Increment(ref _length); + node.WriteUnlock(); return AddOrUpdateResult.ADDED; } diff --git a/src/ZoneTree/Core/ZoneTree.cs b/src/ZoneTree/Core/ZoneTree.cs index 91c352a..87e2eca 100644 --- a/src/ZoneTree/Core/ZoneTree.cs +++ b/src/ZoneTree/Core/ZoneTree.cs @@ -51,6 +51,8 @@ public sealed class ZoneTree : IZoneTree, IZoneTreeM public int ReadOnlySegmentsRecordCount => ReadOnlySegmentQueue.Sum(x => x.Length); + public int MutableSegmentRecordCount => SegmentZero.Length; + public int InMemoryRecordCount => SegmentZero.Length + ReadOnlySegmentsRecordCount; diff --git a/src/ZoneTree/IZoneTreeMaintenance.cs b/src/ZoneTree/IZoneTreeMaintenance.cs index 90bba7c..8b76683 100644 --- a/src/ZoneTree/IZoneTreeMaintenance.cs +++ b/src/ZoneTree/IZoneTreeMaintenance.cs @@ -34,6 +34,11 @@ public interface IZoneTreeMaintenance /// int ReadOnlySegmentsRecordCount { get; } + /// + /// Retrieves the number of records in mutable segment (SegmentZero). + /// + int MutableSegmentRecordCount { get; } + /// /// Retrieves the total number of records that lies in memory /// excluding the sparse array records of DiskSegment.