Skip to content

Commit 5861127

Browse files
committed
refactor Comparator
1 parent 7b239f1 commit 5861127

File tree

2 files changed

+72
-54
lines changed

2 files changed

+72
-54
lines changed

RocksDbSharp/ColumnFamilyOptions.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
using System.Collections.Generic;
33
using System.Dynamic;
44
using System.Linq;
5+
using System.Runtime.InteropServices;
56
using System.Text;
67
using System.Threading.Tasks;
78

89
namespace RocksDbSharp
910
{
1011
public class ColumnFamilyOptions : OptionsHandle
1112
{
13+
Comparator Comparator { get; set; }
14+
IntPtr ComparatorStatePtr { get; set; }
1215

1316
public ColumnFamilyOptions SetBlockBasedTableFactory(BlockBasedTableOptions table_options)
1417
{
@@ -156,8 +159,63 @@ public ColumnFamilyOptions SetComparator(IntPtr comparator)
156159
return this;
157160
}
158161

162+
/// <summary>
163+
/// Comparator used to define the order of keys in the table.
164+
/// Default: a comparator that uses lexicographic byte-wise ordering
165+
///
166+
/// REQUIRES: The client must ensure that the comparator supplied
167+
/// here has the same name and orders keys *exactly* the same as the
168+
/// comparator provided to previous open calls on the same DB.
169+
/// </summary>
159170
public ColumnFamilyOptions SetComparator(Comparator comparator)
160-
=> SetComparator(comparator.Handle);
171+
{
172+
// Hold onto the reference to the comparator
173+
Comparator = comparator;
174+
175+
// Allocate some memory for the name bytes
176+
var name = comparator.Name ?? comparator.GetType().FullName;
177+
var nameBytes = Encoding.UTF8.GetBytes(name + "\0");
178+
var namePtr = Marshal.AllocHGlobal(nameBytes.Length);
179+
Marshal.Copy(nameBytes, 0, namePtr, nameBytes.Length);
180+
181+
// Allocate the state
182+
var state = new ComparatorState
183+
{
184+
NamePtr = namePtr,
185+
};
186+
var statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(state));
187+
Marshal.StructureToPtr(state, statePtr, false);
188+
189+
// Create the comparator
190+
IntPtr handle = Native.Instance.rocksdb_comparator_create(
191+
state: statePtr,
192+
destructor: Comparator_Destroy,
193+
compare: Comparator_Compare,
194+
name: Comparator_GetNamePtr
195+
);
196+
197+
ComparatorStatePtr = statePtr;
198+
199+
return SetComparator(handle);
200+
}
201+
202+
private unsafe int Comparator_Compare(IntPtr state, IntPtr a, UIntPtr alen, IntPtr b, UIntPtr blen)
203+
=> Comparator.Compare(a, alen, b, blen);
204+
205+
private unsafe void Comparator_Destroy(IntPtr state)
206+
{
207+
var namePtr = (*((ComparatorState*)state)).NamePtr;
208+
Marshal.FreeHGlobal(namePtr);
209+
Marshal.FreeHGlobal(state);
210+
}
211+
private unsafe IntPtr Comparator_GetNamePtr(IntPtr state)
212+
=> (*((ComparatorState*)state)).NamePtr;
213+
214+
[StructLayout(LayoutKind.Sequential)]
215+
private struct ComparatorState
216+
{
217+
public IntPtr NamePtr { get; set; }
218+
}
161219

162220
/// <summary>
163221
/// REQUIRES: The client must provide a merge operator if Merge operation

RocksDbSharp/Comparator.cs

Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,72 +6,32 @@
66

77
namespace RocksDbSharp
88
{
9-
public unsafe delegate int CompareFunc(IntPtr state, byte* a, ulong alen, byte* b, ulong blen);
10-
public delegate void DestroyFunc(IntPtr state);
11-
public delegate string GetNameFunc(IntPtr state);
12-
139
public interface Comparator
1410
{
15-
IntPtr Handle { get; }
11+
string Name { get; }
12+
int Compare(IntPtr a, UIntPtr alen, IntPtr b, UIntPtr blen);
1613
}
1714

18-
public abstract class ComparatorBase : Comparator
19-
{
20-
public IntPtr Handle { get; protected set; }
21-
public virtual string Name { get; }
22-
23-
private DestroyFunc _destroy;
24-
25-
public unsafe ComparatorBase(string name = null, IntPtr state = default(IntPtr))
26-
{
27-
Name = name ?? GetType().FullName;
28-
_destroy = s => this.Destroy(s);
29-
Handle = Native.Instance.rocksdb_comparator_create(
30-
state: IntPtr.Zero,
31-
destructor: CurrentFramework.GetFunctionPointerForDelegate(_destroy),
32-
compare: CurrentFramework.GetFunctionPointerForDelegate<CompareFunc>(Compare),
33-
getName: CurrentFramework.GetFunctionPointerForDelegate<GetNameFunc>(GetName)
34-
);
35-
}
36-
37-
~ComparatorBase()
38-
{
39-
if (Handle != IntPtr.Zero)
40-
{
41-
#if !NODESTROY
42-
Native.Instance.rocksdb_comparator_destroy(Handle);
43-
#endif
44-
Handle = IntPtr.Zero;
45-
}
46-
}
47-
48-
public abstract unsafe int Compare(IntPtr state, byte* a, ulong alen, byte* b, ulong blen);
49-
50-
public virtual void Destroy(IntPtr state)
51-
{
52-
}
53-
54-
protected virtual string GetName(IntPtr state) => Name;
55-
}
56-
57-
public abstract class StringComparatorBase : ComparatorBase
15+
public abstract class StringComparatorBase : Comparator
5816
{
5917
public Encoding Encoding { get; }
6018

19+
public string Name { get; }
20+
6121
public StringComparatorBase(Encoding encoding = null, string name = null, IntPtr state = default(IntPtr))
62-
: base(name, state)
6322
{
23+
Name = name ?? typeof(StringComparatorBase).Name;
6424
Encoding = encoding ?? Encoding.UTF8;
6525
}
6626

67-
public override unsafe int Compare(IntPtr state, byte* a, ulong alen, byte* b, ulong blen)
27+
public abstract int Compare(string a, string b);
28+
29+
public unsafe int Compare(IntPtr a, UIntPtr alen, IntPtr b, UIntPtr blen)
6830
{
69-
var astr = Encoding.GetString(a, (int)alen);
70-
var bstr = Encoding.GetString(b, (int)blen);
71-
return Compare(state, astr, bstr);
31+
var astr = Encoding.GetString((byte*)a, (int)alen);
32+
var bstr = Encoding.GetString((byte*)b, (int)blen);
33+
return Compare(astr, bstr);
7234
}
73-
74-
public abstract int Compare(IntPtr state, string a, string b);
7535
}
7636

7737
public class StringComparator : StringComparatorBase
@@ -91,6 +51,6 @@ public StringComparator(bool ignoreCase, Encoding encoding = null, string name =
9151
{
9252
}
9353

94-
public override int Compare(IntPtr state, string a, string b) => CompareFunc(a, b);
54+
public override int Compare(string a, string b) => CompareFunc(a, b);
9555
}
9656
}

0 commit comments

Comments
 (0)