Skip to content

Commit 49c9294

Browse files
committed
Implemented mdb_set_dupsort
1 parent 1f5e9e9 commit 49c9294

File tree

6 files changed

+111
-12
lines changed

6 files changed

+111
-12
lines changed

src/LightningDB.Tests/TransactionTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,5 +218,38 @@ public void TransactionShouldSupportCustomComparer()
218218
Assert.AreEqual(keysSorted[order++], pair.Key);
219219
}
220220
}
221+
222+
[Test]
223+
public void TransactionShouldSupportCustomDupSorter()
224+
{
225+
//arrange
226+
Func<int, int, int> comparison = (l, r) => -Math.Sign(l - r);
227+
228+
_txn = _env.BeginTransaction();
229+
var db = _txn.OpenDatabase(
230+
options: new DatabaseOptions
231+
{
232+
Flags = DatabaseOpenFlags.DuplicatesFixed,
233+
DuplicatesSort = b => b.FromFunc(comparison)
234+
});
235+
236+
var valuesUnsorted = new int[] { 2, 10, 5, 0 };
237+
var valuesSorted = valuesUnsorted.ToArray();
238+
Array.Sort(valuesSorted, new Comparison<int>(comparison));
239+
240+
//act
241+
using (var c = _txn.CreateCursor(db))
242+
c.PutMultiple(123, valuesUnsorted);
243+
244+
//assert
245+
using (var c = _txn.CreateCursor(db))
246+
{
247+
int order = 0;
248+
249+
KeyValuePair<int, int> pair;
250+
while (c.MoveNextDuplicate(out pair))
251+
Assert.AreEqual(valuesSorted[order++], pair.Value);
252+
}
253+
}
221254
}
222255
}

src/LightningDB/DatabaseOptions.cs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public DatabaseOptions()
1818

1919
public Func<CompareFunctionBuilder, LightningCompareDelegate> Compare { get; set; }
2020

21+
public Func<CompareFunctionBuilder, LightningCompareDelegate> DuplicatesSort { get; set; }
22+
2123
public Encoding Encoding { get; set; }
2224

2325
public DatabaseOpenFlags Flags { get; set; }
@@ -31,28 +33,44 @@ private static CompareFunction CreateNativeCompareFunction(
3133
compare.Invoke(db, NativeMethods.ValueByteArrayFromPtr(left), NativeMethods.ValueByteArrayFromPtr(right));
3234
}
3335

34-
private static CompareFunction SetNativeCompareFunction(
35-
LightningTransaction tran, LightningDatabase db, LightningCompareDelegate compare)
36+
private static void SetNativeCompareFunction(
37+
LightningTransaction tran,
38+
LightningDatabase db,
39+
Func<CompareFunctionBuilder, LightningCompareDelegate> delegateFactory,
40+
Func<INativeLibraryFacade, CompareFunction, int> setter)
3641
{
37-
var compareFunction = CreateNativeCompareFunction(db, compare);
42+
if (delegateFactory == null)
43+
return;
44+
45+
var comparer = delegateFactory.Invoke(new CompareFunctionBuilder());
46+
if (comparer == null)
47+
return;
3848

39-
NativeMethods.Execute(lib =>
40-
lib.mdb_set_compare(tran._handle, db._handle, compareFunction));
49+
var compareFunction = CreateNativeCompareFunction(db, comparer);
4150

42-
return compareFunction;
51+
NativeMethods.Execute(lib => setter.Invoke(lib, compareFunction));
52+
tran.SubTransactionsManager.StoreComparer(comparer);
4353
}
4454

4555
internal void SetComparer(LightningTransaction tran, LightningDatabase db)
4656
{
47-
if (Compare == null)
48-
return;
57+
SetNativeCompareFunction(
58+
tran,
59+
db,
60+
Compare,
61+
(lib, func) => lib.mdb_set_compare(tran._handle, db._handle, func));
62+
}
4963

50-
var comparer = Compare.Invoke(new CompareFunctionBuilder());
51-
if (comparer == null)
64+
internal void SetDuplicatesSort(LightningTransaction tran, LightningDatabase db)
65+
{
66+
if (!db.OpenFlags.HasFlag(DatabaseOpenFlags.DuplicatesSort))
5267
return;
5368

54-
var nativeComparer = SetNativeCompareFunction(tran, db, comparer);
55-
tran.SubTransactionsManager.StoreComparer(comparer);
69+
SetNativeCompareFunction(
70+
tran,
71+
db,
72+
DuplicatesSort,
73+
(lib, func) => lib.mdb_set_dupsort(tran._handle, db._handle, func));
5674
}
5775
}
5876
}

src/LightningDB/LightningTransaction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public LightningDatabase OpenDatabase(string name = null, DatabaseOptions option
8383
var db = this.Environment.OpenDatabase(name, this, options.Flags, options.Encoding);
8484

8585
options.SetComparer(this, db);
86+
options.SetDuplicatesSort(this, db);
8687

8788
return db;
8889
}

src/LightningDB/Native/INativeLibraryFacade.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,5 +569,20 @@ interface INativeLibraryFacade
569569
///EINVAL - an invalid parameter was specified.
570570
/// </returns>
571571
int mdb_set_compare(IntPtr txn, uint dbi, CompareFunction cmp);
572+
573+
/// <summary>
574+
/// Set a custom data comparison function for a MDB_DUPSORT database.
575+
/// This comparison function is called whenever it is necessary to compare a data item specified by the application with a data item currently stored in the database. This function only takes effect if the database was opened with the MDB_DUPSORT flag. If no comparison function is specified, and no special key flags were specified with mdb_dbi_open(), the data items are compared lexically, with shorter items collating before longer items.
576+
/// Warning:
577+
/// This function must be called before any data access functions are used, otherwise data corruption may occur. The same comparison function must be used by every program accessing the database, every time the database is used.
578+
/// </summary>
579+
/// <param name="txn">A transaction handle returned by mdb_txn_begin()</param>
580+
/// <param name="dbi">A database handle returned by mdb_dbi_open()</param>
581+
/// <param name="cmp">A MDB_cmp_func function</param>
582+
/// <returns>
583+
/// A non-zero error value on failure and 0 on success. Some possible errors are:
584+
/// EINVAL - an invalid parameter was specified.
585+
/// </returns>
586+
int mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp);
572587
}
573588
}

src/LightningDB/Native/NativeLibraryFacades.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ class Native32BitLibraryFacade : INativeLibraryFacade
121121
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
122122
private static extern int mdb_set_compare(IntPtr txn, uint dbi, CompareFunction cmp);
123123

124+
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
125+
private static extern int mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp);
126+
124127
#endregion
125128

126129
int INativeLibraryFacade.mdb_env_create(out IntPtr env)
@@ -314,6 +317,11 @@ int INativeLibraryFacade.mdb_set_compare(IntPtr txn, uint dbi, CompareFunction c
314317
{
315318
return Native32BitLibraryFacade.mdb_set_compare(txn, dbi, cmp);
316319
}
320+
321+
int INativeLibraryFacade.mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp)
322+
{
323+
return Native32BitLibraryFacade.mdb_set_dupsort(txn, dbi, cmp);
324+
}
317325
}
318326

319327
class Native64BitLibraryFacade : INativeLibraryFacade
@@ -430,6 +438,9 @@ class Native64BitLibraryFacade : INativeLibraryFacade
430438
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
431439
private static extern int mdb_set_compare(IntPtr txn, uint dbi, CompareFunction cmp);
432440

441+
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
442+
private static extern int mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp);
443+
433444
#endregion
434445

435446
int INativeLibraryFacade.mdb_env_create(out IntPtr env)
@@ -611,6 +622,11 @@ int INativeLibraryFacade.mdb_set_compare(IntPtr txn, uint dbi, CompareFunction c
611622
{
612623
return Native64BitLibraryFacade.mdb_set_compare(txn, dbi, cmp);
613624
}
625+
626+
int INativeLibraryFacade.mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp)
627+
{
628+
return Native64BitLibraryFacade.mdb_set_dupsort(txn, dbi, cmp);
629+
}
614630
}
615631

616632
class FallbackLibraryFacade : INativeLibraryFacade
@@ -727,6 +743,9 @@ class FallbackLibraryFacade : INativeLibraryFacade
727743
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
728744
private static extern int mdb_set_compare(IntPtr txn, uint dbi, CompareFunction cmp);
729745

746+
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
747+
private static extern int mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp);
748+
730749
#endregion
731750

732751
int INativeLibraryFacade.mdb_env_create(out IntPtr env)
@@ -920,6 +939,11 @@ int INativeLibraryFacade.mdb_set_compare(IntPtr txn, uint dbi, CompareFunction c
920939
{
921940
return FallbackLibraryFacade.mdb_set_compare(txn, dbi, cmp);
922941
}
942+
943+
int INativeLibraryFacade.mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp)
944+
{
945+
return FallbackLibraryFacade.mdb_set_dupsort(txn, dbi, cmp);
946+
}
923947
}
924948

925949
}

src/LightningDB/Native/NativeLibraryFacades.tt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ namespace LightningDB.Native
136136
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
137137
private static extern int mdb_set_compare(IntPtr txn, uint dbi, CompareFunction cmp);
138138

139+
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
140+
private static extern int mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp);
141+
139142
#endregion
140143

141144
int INativeLibraryFacade.mdb_env_create(out IntPtr env)
@@ -333,6 +336,11 @@ namespace LightningDB.Native
333336
{
334337
return <#= pair.Value #>LibraryFacade.mdb_set_compare(txn, dbi, cmp);
335338
}
339+
340+
int INativeLibraryFacade.mdb_set_dupsort(IntPtr txn, uint dbi, CompareFunction cmp)
341+
{
342+
return <#= pair.Value #>LibraryFacade.mdb_set_dupsort(txn, dbi, cmp);
343+
}
336344
}
337345
<#
338346
}

0 commit comments

Comments
 (0)