Skip to content

Commit

Permalink
Merge pull request #92 from koculu/91-enhancement-provide-key-in-is-d…
Browse files Browse the repository at this point in the history
…eleted-marker-delegate-to-support-ttl-based-on-keys

Provide key in IsDeleted delegate to support TTL based on keys
  • Loading branch information
koculu authored Sep 6, 2024
2 parents 2b2183d + a5abf3b commit c4746e2
Show file tree
Hide file tree
Showing 24 changed files with 126 additions and 122 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ In this example, `-1` is used as the deletion marker for integer values:
using Tenray.ZoneTree;

using var zoneTree = new ZoneTreeFactory<int, int>()
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreate();

// Deleting a key by setting its value to -1
Expand All @@ -251,8 +251,8 @@ struct MyDeletableValueType
}

using var zoneTree = new ZoneTreeFactory<int, MyDeletableValueType>()
.SetIsValueDeletedDelegate((in MyDeletableValueType x) => x.IsDeleted)
.SetMarkValueDeletedDelegate((ref MyDeletableValueType x) => x.IsDeleted = true)
.SetIsDeletedDelegate((in int key, in MyDeletableValueType value) => value.IsDeleted)
.SetMarkValueDeletedDelegate((ref MyDeletableValueType value) => value.IsDeleted = true)
.OpenOrCreate();

// Deleting a key by setting the IsDeleted flag
Expand Down
2 changes: 1 addition & 1 deletion src/ZoneTree.UnitTests/CountTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void CountRecordsDuringAMerge(
Directory.Delete(dataPath, true);

using var zoneTree = new ZoneTreeFactory<string, int>()
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetIsDeletedDelegate((in string key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetMutableSegmentMaxItemCount(100)
.SetDataDirectory(dataPath)
Expand Down
4 changes: 2 additions & 2 deletions src/ZoneTree.UnitTests/FixedSizeKeyAndValueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ static void ReloadIntIntTreeTestHelper(string dataPath, bool destroy)
.SetWriteAheadLogDirectory(dataPath)
.ConfigureWriteAheadLogOptions(x =>
x.WriteAheadLogMode = WriteAheadLogMode.Sync)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreate();
var n = 2000;
var deleted = new HashSet<int>() { 11, 99, 273, 200, 333, 441, 203, 499, 666 };
Expand Down
12 changes: 6 additions & 6 deletions src/ZoneTree.UnitTests/IteratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public void IntIntIterator()
.SetMutableSegmentMaxItemCount(11)
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreate();
var a = 250;
var b = 500;
Expand Down Expand Up @@ -89,8 +89,8 @@ public void IntIntIteratorSeek()
.SetMutableSegmentMaxItemCount(11)
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreate();
var a = 250;
var b = 500;
Expand Down Expand Up @@ -180,8 +180,8 @@ public void IntIntIteratorReflectNewInserts()
.SetMutableSegmentMaxItemCount(250)
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreate();
var a = 251;
var b = 500;
Expand Down
12 changes: 6 additions & 6 deletions src/ZoneTree.UnitTests/MergeEmptySegmentsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public void MergeEmptySegments(
Directory.Delete(dataPath, true);

using var zoneTree = new ZoneTreeFactory<int, int>()
.SetIsValueDeletedDelegate((in int x) => true)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => true)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.SetMutableSegmentMaxItemCount(100)
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
Expand Down Expand Up @@ -64,8 +64,8 @@ public void MergeDeletedSegments(

var isRecordDeleted = false;
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetIsValueDeletedDelegate((in int x) => isRecordDeleted)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => isRecordDeleted)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.SetMutableSegmentMaxItemCount(100)
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
Expand Down Expand Up @@ -124,8 +124,8 @@ public void MergeDeletedBottomSegments(

var isRecordDeleted = false;
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetIsValueDeletedDelegate((in int x) => isRecordDeleted)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => isRecordDeleted)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.SetMutableSegmentMaxItemCount(100)
.SetDiskSegmentMaxItemCount(250)
.SetDataDirectory(dataPath)
Expand Down
16 changes: 8 additions & 8 deletions src/ZoneTree.UnitTests/OptimisticTransactionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ public void ReadCommittedTest(int compactionThreshold)
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreateTransactional();

zoneTree.Maintenance.TransactionLog.CompactionThreshold = compactionThreshold;
Expand Down Expand Up @@ -172,8 +172,8 @@ public void TransactionLogCompactionTest(int compactionThreshold)
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreateTransactional();

zoneTree.Maintenance.TransactionLog.CompactionThreshold = compactionThreshold;
Expand Down Expand Up @@ -219,8 +219,8 @@ public void TransactionLogCompactionWithSkipWriteRule(int compactionThreshold)
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreateTransactional();

zoneTree.Maintenance.TransactionLog.CompactionThreshold = compactionThreshold;
Expand Down Expand Up @@ -254,8 +254,8 @@ public void TransactionIsolationTest(int compactionThreshold)
using var zoneTree = new ZoneTreeFactory<int, int>()
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetIsValueDeletedDelegate((in int x) => x == -1)
.SetMarkValueDeletedDelegate((ref int x) => x = -1)
.SetIsDeletedDelegate((in int key, in int value) => value == -1)
.SetMarkValueDeletedDelegate((ref int value) => value = -1)
.OpenOrCreateTransactional();

zoneTree.Maintenance.TransactionLog.CompactionThreshold = compactionThreshold;
Expand Down
8 changes: 4 additions & 4 deletions src/ZoneTree.UnitTests/TTLTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public void TestTTL()
.SetDataDirectory(dataPath)
.SetWriteAheadLogDirectory(dataPath)
.SetValueSerializer(new StructSerializer<TTLValue<int>>())
.SetIsValueDeletedDelegate((in TTLValue<int> x) => x.IsExpired)
.SetMarkValueDeletedDelegate(void (ref TTLValue<int> x) => x.Expire())
.SetIsDeletedDelegate((in int key, in TTLValue<int> value) => value.IsExpired)
.SetMarkValueDeletedDelegate(void (ref TTLValue<int> value) => value.Expire())
.OpenOrCreate();

zoneTree.Upsert(5, new TTLValue<int>(99, DateTime.UtcNow.AddMilliseconds(300)));
Expand All @@ -33,8 +33,8 @@ public void TestTTL()
Thread.Sleep(150);
f1 = zoneTree.TryGetAndUpdate(
5,
out v1,
bool (ref TTLValue<int> v) =>
out v1,
bool (ref TTLValue<int> v) =>
v.SlideExpiration(TimeSpan.FromMilliseconds(300)));
Thread.Sleep(450); // initial expiration (300) + slided expiration (300) - Thread.Sleep(150)
f2 = zoneTree.TryGetAndUpdate(
Expand Down
8 changes: 4 additions & 4 deletions src/ZoneTree/Collections/DictionaryWithWal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public sealed class DictionaryWithWAL<TKey, TValue> : IDisposable

readonly IRefComparer<TKey> Comparer;

readonly IsValueDeletedDelegate<TValue> IsValueDeleted;
readonly IsDeletedDelegate<TKey, TValue> IsDeleted;

readonly MarkValueDeletedDelegate<TValue> MarkValueDeleted;

Expand All @@ -54,7 +54,7 @@ public DictionaryWithWAL(
ISerializer<TKey> keySerializer,
ISerializer<TValue> valueSerializer,
IRefComparer<TKey> comparer,
IsValueDeletedDelegate<TValue> isValueDeleted,
IsDeletedDelegate<TKey, TValue> isDeleted,
MarkValueDeletedDelegate<TValue> markValueDeleted)
{
WriteAheadLogProvider = writeAheadLogProvider;
Expand All @@ -63,7 +63,7 @@ public DictionaryWithWAL(
.GetOrCreateWAL(segmentId, category, options, keySerializer, valueSerializer);
SegmentId = segmentId;
Category = category;
IsValueDeleted = isValueDeleted;
IsDeleted = isDeleted;
MarkValueDeleted = markValueDeleted;
LoadFromWriteAheadLog();
}
Expand Down Expand Up @@ -91,7 +91,7 @@ void LoadFromWriteAheadLog()
result.Keys,
result.Values,
Comparer,
IsValueDeleted);
IsDeleted);
var len = newKeys.Count;
for (var i = 0; i < len; ++i)
{
Expand Down
2 changes: 1 addition & 1 deletion src/ZoneTree/Core/ZoneTree.BottomSegments.Merge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void skipElement()
minSegmentIndex = minEntry.SegmentIndex;

// ignore deleted entries if writeDeletedValues is false.
if (!writeDeletedValues && IsValueDeleted(minEntry.Value))
if (!writeDeletedValues && IsDeleted(minEntry.Key, minEntry.Value))
{
skipElement();
prevKey = minEntry.Key;
Expand Down
2 changes: 1 addition & 1 deletion src/ZoneTree/Core/ZoneTree.Merge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ void skipElement()
minSegmentIndex = minEntry.SegmentIndex;

// ignore deleted entries if bottom segments queue is empty.
if (!hasBottomSegments && IsValueDeleted(minEntry.Value))
if (!hasBottomSegments && IsDeleted(minEntry.Key, minEntry.Value))
{
skipElement();
prevKey = minEntry.Key;
Expand Down
14 changes: 7 additions & 7 deletions src/ZoneTree/Core/ZoneTree.ReadWrite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public bool ContainsKey(in TKey key)
if (MutableSegment.ContainsKey(key))
{
if (MutableSegment.TryGet(key, out TValue value))
return !IsValueDeleted(value);
return !IsDeleted(key, value);
}

return TryGetFromReadonlySegments(in key, out _);
Expand All @@ -23,7 +23,7 @@ bool TryGetFromReadonlySegments(in TKey key, out TValue value)
{
if (segment.TryGet(key, out value))
{
return !IsValueDeleted(value);
return !IsDeleted(key, value);
}
}

Expand All @@ -33,14 +33,14 @@ bool TryGetFromReadonlySegments(in TKey key, out TValue value)
{
if (DiskSegment.TryGet(key, out value))
{
return !IsValueDeleted(value);
return !IsDeleted(key, value);
}

foreach (var segment in BottomSegmentQueue)
{
if (segment.TryGet(key, out value))
{
return !IsValueDeleted(value);
return !IsDeleted(key, value);
}
}
return false;
Expand All @@ -56,7 +56,7 @@ public bool TryGet(in TKey key, out TValue value)
{
if (MutableSegment.TryGet(key, out value))
{
return !IsValueDeleted(value);
return !IsDeleted(key, value);
}
return TryGetFromReadonlySegments(in key, out value);
}
Expand All @@ -76,7 +76,7 @@ public bool TryGetAndUpdate(in TKey key, out TValue value, ValueUpdaterDelegate<

if (MutableSegment.TryGet(key, out value))
{
if (IsValueDeleted(value))
if (IsDeleted(key, value))
return false;
}
else if (!TryGetFromReadonlySegments(in key, out value))
Expand All @@ -101,7 +101,7 @@ public bool TryAtomicGetAndUpdate(in TKey key, out TValue value, ValueUpdaterDel
{
if (MutableSegment.TryGet(key, out value))
{
if (IsValueDeleted(value))
if (IsDeleted(key, value))
return false;
}
else if (!TryGetFromReadonlySegments(in key, out value))
Expand Down
15 changes: 8 additions & 7 deletions src/ZoneTree/Core/ZoneTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public sealed partial class ZoneTree<TKey, TValue> : IZoneTree<TKey, TValue>, IZ

readonly MaxHeapEntryRefComparer<TKey, TValue> MaxHeapEntryComparer;

readonly IsValueDeletedDelegate<TValue> IsValueDeleted;
readonly IsDeletedDelegate<TKey, TValue> IsDeleted;

readonly SingleProducerSingleConsumerQueue<IReadOnlySegment<TKey, TValue>> ReadOnlySegmentQueue = new();

Expand Down Expand Up @@ -142,7 +142,7 @@ public ZoneTree(ZoneTreeOptions<TKey, TValue> options)
MaxHeapEntryComparer = new MaxHeapEntryRefComparer<TKey, TValue>(options.Comparer);
MutableSegment = new MutableSegment<TKey, TValue>(
options, IncrementalIdProvider.NextId(), new IncrementalIdProvider());
IsValueDeleted = options.IsValueDeleted;
IsDeleted = options.IsDeleted;
FillZoneTreeMeta();
MetaWal.SaveMetaData(
ZoneTreeMeta,
Expand Down Expand Up @@ -178,7 +178,7 @@ long maximumSegmentId
ReadOnlySegmentQueue.Enqueue(ros);
foreach (var bs in bottomSegments.Reverse())
BottomSegmentQueue.Enqueue(bs);
IsValueDeleted = options.IsValueDeleted;
IsDeleted = options.IsDeleted;
}

void FillZoneTreeMeta()
Expand Down Expand Up @@ -304,16 +304,17 @@ public long Count()
var count = diskSegment.Length;
while (iterator.Next())
{
var hasKey = diskSegment.ContainsKey(iterator.CurrentKey);
var isValueDeleted = IsValueDeleted(iterator.CurrentValue);
var key = iterator.CurrentKey;
var hasKey = diskSegment.ContainsKey(key);
var isDeleted = IsDeleted(key, iterator.CurrentValue);
if (hasKey)
{
if (isValueDeleted)
if (isDeleted)
--count;
}
else
{
if (!isValueDeleted)
if (!isDeleted)
++count;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/ZoneTree/Core/ZoneTreeIterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public sealed class ZoneTreeIterator<TKey, TValue> : IZoneTreeIterator<TKey, TVa

IReadOnlyList<ISeekableIterator<TKey, TValue>> SeekableIterators;

readonly IsValueDeletedDelegate<TValue> IsValueDeleted;
readonly IsDeletedDelegate<TKey, TValue> IsDeleted;

readonly IRefComparer<TKey> Comparer;

Expand Down Expand Up @@ -85,7 +85,7 @@ public ZoneTreeIterator(
bool includeDiskSegment,
bool includeBottomSegments)
{
IsValueDeleted = options.IsValueDeleted;
IsDeleted = options.IsDeleted;
Comparer = options.Comparer;
ZoneTree = zoneTree;
HeapEntryComparer = heapEntryComparer;
Expand Down Expand Up @@ -280,7 +280,7 @@ void skipElement()
minSegmentIndex = minEntry.SegmentIndex;

// ignore deleted entries.
if (!IncludeDeletedRecords && IsValueDeleted(minEntry.Value))
if (!IncludeDeletedRecords && IsDeleted(minEntry.Key, minEntry.Value))
{
skipElement();
PrevKey = minEntry.Key;
Expand Down Expand Up @@ -330,7 +330,7 @@ void skipElement()
minSegmentIndex = minEntry.SegmentIndex;

// ignore deleted entries.
if (!IncludeDeletedRecords && IsValueDeleted(minEntry.Value))
if (!IncludeDeletedRecords && IsDeleted(minEntry.Key, minEntry.Value))
{
skipElement();
PrevKey = minEntry.Key;
Expand Down
4 changes: 2 additions & 2 deletions src/ZoneTree/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<Authors>Ahmed Yasin Koculu</Authors>
<PackageId>ZoneTree</PackageId>
<Title>ZoneTree</Title>
<ProductVersion>1.8.0.0</ProductVersion>
<Version>1.8.0.0</Version>
<ProductVersion>1.8.1.0</ProductVersion>
<Version>1.8.1.0</Version>
<Authors>Ahmed Yasin Koculu</Authors>
<AssemblyTitle>ZoneTree</AssemblyTitle>
<Description>ZoneTree is a persistent, high-performance, transactional, ACID-compliant ordered key-value database for NET. It can operate in memory or on local/cloud storage.</Description>
Expand Down
Loading

0 comments on commit c4746e2

Please sign in to comment.