Skip to content

Commit e9f98b7

Browse files
committed
Added more helpful comments to txn and cursor, removed dead and incorrect code
1 parent 86c8769 commit e9f98b7

File tree

3 files changed

+128
-122
lines changed

3 files changed

+128
-122
lines changed

src/LightningDB/LightningCursor.cs

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ namespace LightningDB;
99
/// <summary>
1010
/// Represents a cursor used to navigate and manipulate records within a database in the context of a transaction.
1111
/// </summary>
12+
/// <remarks>
13+
/// A cursor is associated with a specific transaction and database and cannot be used when its database handle
14+
/// is closed or when its transaction has ended (except with <see cref="LightningTransaction.Renew"/>).
15+
///
16+
/// Cursor lifecycle management:
17+
/// - A cursor in a write-transaction can be closed before its transaction ends, and will otherwise be closed when its transaction ends.
18+
/// - A cursor in a read-only transaction must be closed explicitly, before or after its transaction ends.
19+
/// - It can be reused with <see cref="LightningTransaction.Renew"/> before finally closing it.
20+
///
21+
/// Cursors cannot span threads - a cursor handle may only be used by a single thread.
22+
///
23+
/// A cursor maintains a position in the database and can be used for navigation and
24+
/// for operations like insertion, deletion, or retrieval of database records.
25+
/// </remarks>
1226
public class LightningCursor : IDisposable
1327
{
1428
private nint _handle;
@@ -51,7 +65,7 @@ public MDBResultCode Set(byte[] key)
5165
{
5266
return Get(CursorOperation.Set, key).resultCode;
5367
}
54-
68+
5569
/// <summary>
5670
/// Position at specified key, if key is not found index will be positioned to closest match.
5771
/// </summary>
@@ -71,7 +85,7 @@ public MDBResultCode Set(ReadOnlySpan<byte> key)
7185
{
7286
return Get(CursorOperation.SetKey, key);
7387
}
74-
88+
7589
/// <summary>
7690
/// Moves to the key and populates Current with the values stored.
7791
/// </summary>
@@ -92,7 +106,7 @@ public MDBResultCode GetBoth(byte[] key, byte[] value)
92106
{
93107
return Get(CursorOperation.GetBoth, key, value).resultCode;
94108
}
95-
109+
96110
/// <summary>
97111
/// Position at key/data pair. Only for MDB_DUPSORT
98112
/// </summary>
@@ -114,7 +128,7 @@ public MDBResultCode GetBothRange(byte[] key, byte[] value)
114128
{
115129
return Get(CursorOperation.GetBothRange, key, value).resultCode;
116130
}
117-
131+
118132
/// <summary>
119133
/// position at key, nearest data. Only for MDB_DUPSORT
120134
/// </summary>
@@ -135,7 +149,7 @@ public MDBResultCode SetRange(byte[] key)
135149
{
136150
return Get(CursorOperation.SetRange, key).resultCode;
137151
}
138-
152+
139153
/// <summary>
140154
/// Position at first key greater than or equal to specified key.
141155
/// </summary>
@@ -254,7 +268,7 @@ public MDBResultCode SetRange(ReadOnlySpan<byte> key)
254268
{
255269
return Get(CursorOperation.PreviousNoDuplicate);
256270
}
257-
271+
258272
private (MDBResultCode resultCode, MDBValue key, MDBValue value) Get(CursorOperation operation)
259273
{
260274
var mdbKey = new MDBValue();
@@ -300,7 +314,7 @@ private unsafe (MDBResultCode resultCode, MDBValue key, MDBValue value) Get(Curs
300314
/// Store by cursor.
301315
/// This function stores key/data pairs into the database. The cursor is positioned at the new item, or on failure usually near it.
302316
/// Note: Earlier documentation incorrectly said errors would leave the state of the cursor unchanged.
303-
/// If the function fails for any reason, the state of the cursor will be unchanged.
317+
/// If the function fails for any reason, the state of the cursor will be unchanged.
304318
/// If the function succeeds and an item is inserted into the database, the cursor is always positioned to refer to the newly inserted item.
305319
/// </summary>
306320
/// <param name="key">The key operated on.</param>
@@ -325,7 +339,7 @@ public MDBResultCode Put(byte[] key, byte[] value, CursorPutOptions options)
325339
/// Store by cursor.
326340
/// This function stores key/data pairs into the database. The cursor is positioned at the new item, or on failure usually near it.
327341
/// Note: Earlier documentation incorrectly said errors would leave the state of the cursor unchanged.
328-
/// If the function fails for any reason, the state of the cursor will be unchanged.
342+
/// If the function fails for any reason, the state of the cursor will be unchanged.
329343
/// If the function succeeds and an item is inserted into the database, the cursor is always positioned to refer to the newly inserted item.
330344
/// </summary>
331345
/// <param name="key">The key operated on.</param>
@@ -354,8 +368,8 @@ public unsafe MDBResultCode Put(ReadOnlySpan<byte> key, ReadOnlySpan<byte> value
354368

355369
/// <summary>
356370
/// Store by cursor.
357-
/// This function stores key/data pairs into the database.
358-
/// If the function fails for any reason, the state of the cursor will be unchanged.
371+
/// This function stores key/data pairs into the database.
372+
/// If the function fails for any reason, the state of the cursor will be unchanged.
359373
/// If the function succeeds and an item is inserted into the database, the cursor is always positioned to refer to the newly inserted item.
360374
/// </summary>
361375
/// <param name="key">The key operated on.</param>
@@ -368,7 +382,7 @@ public unsafe MDBResultCode Put(byte[] key, byte[][] values)
368382
var overallLength = values.Sum(arr => arr.Length);//probably allocates but boy is it handy...
369383

370384

371-
//the idea here is to gain some perf by stackallocating the buffer to
385+
//the idea here is to gain some perf by stackallocating the buffer to
372386
//hold the contiguous keys
373387
if (overallLength < StackAllocateLimit)
374388
{
@@ -384,7 +398,7 @@ public unsafe MDBResultCode Put(byte[] key, byte[][] values)
384398
}
385399

386400
//these local methods could be made static, but the compiler will emit these closures
387-
//as structs with very little overhead. Also static local functions isn't available
401+
//as structs with very little overhead. Also static local functions isn't available
388402
//until C# 8 so I can't use it anyway...
389403
MDBResultCode InnerPutMultiple(Span<byte> contiguousValuesBuffer)
390404
{
@@ -415,7 +429,7 @@ void FlattenInfo(Span<byte> targetBuffer)
415429
}
416430
}
417431

418-
int GetSize()
432+
int GetSize()
419433
{
420434
if (values.Length == 0 || values[0] == null || values[0].Length == 0)
421435
return 0;
@@ -465,8 +479,8 @@ public MDBResultCode Delete()
465479

466480
/// <summary>
467481
/// Renew a cursor handle.
468-
/// Cursors are associated with a specific transaction and database and may not span threads.
469-
/// Cursors that are only used in read-only transactions may be re-used, to avoid unnecessary malloc/free overhead.
482+
/// Cursors are associated with a specific transaction and database and may not span threads.
483+
/// Cursors that are only used in read-only transactions may be re-used, to avoid unnecessary malloc/free overhead.
470484
/// The cursor may be associated with a new read-only transaction, and referencing the same database handle as it was created with.
471485
/// </summary>
472486
/// <returns>Returns <see cref="MDBResultCode"/></returns>
@@ -477,8 +491,8 @@ public MDBResultCode Renew()
477491

478492
/// <summary>
479493
/// Renew a cursor handle.
480-
/// Cursors are associated with a specific transaction and database and may not span threads.
481-
/// Cursors that are only used in read-only transactions may be re-used, to avoid unnecessary malloc/free overhead.
494+
/// Cursors are associated with a specific transaction and database and may not span threads.
495+
/// Cursors that are only used in read-only transactions may be re-used, to avoid unnecessary malloc/free overhead.
482496
/// The cursor may be associated with a new read-only transaction, and referencing the same database handle as it was created with.
483497
/// </summary>
484498
/// <param name="txn">Transaction to renew in.</param>
@@ -493,11 +507,11 @@ public MDBResultCode Renew(LightningTransaction txn)
493507

494508
return mdb_cursor_renew(txn._handle, _handle);
495509
}
496-
510+
497511
/// <summary>
498512
/// Return count of duplicates for current key.
499-
///
500-
/// This call is only valid on databases that support sorted duplicate data items DatabaseOpenFlags.DuplicatesFixed.
513+
///
514+
/// This call is only valid on databases that support sorted duplicate data items DatabaseOpenFlags.DuplicatesFixed.
501515
/// </summary>
502516
/// <param name="value">Output parameter where the duplicate count will be stored.</param>
503517
/// <returns>Returns <see cref="MDBResultCode"/></returns>
@@ -534,7 +548,7 @@ private void Dispose(bool disposing)
534548
{
535549
throw new InvalidOperationException("The LightningCursor in a read-only transaction must be disposed explicitly.");
536550
}
537-
551+
538552
if (ShouldCloseCursor())
539553
{
540554
mdb_cursor_close(_handle);
@@ -559,4 +573,4 @@ public void Dispose()
559573
{
560574
Dispose(false);
561575
}
562-
}
576+
}

src/LightningDB/LightningTransaction.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ namespace LightningDB;
99
/// Provides methods for managing database operations within the scope of a transaction, including
1010
/// database access, key-value storage, and transaction control (commit, abort, etc.).
1111
/// </summary>
12+
/// <remarks>
13+
/// A transaction and its cursors must only be used by a single thread, and a thread may only
14+
/// have a single transaction at a time (except for read-only transactions when MDB_NOTLS is in use).
15+
///
16+
/// Transactions can be nested to any level. When a parent transaction has active child transactions,
17+
/// it and its cursors may not issue any operations other than Commit and Abort.
18+
///
19+
/// Possible errors when creating transactions include:
20+
/// - MDB_PANIC: A fatal error occurred earlier and the environment must be shut down
21+
/// - MDB_MAP_RESIZED: Another process wrote data beyond this environment's mapsize and the map must be resized
22+
/// - MDB_READERS_FULL: A read-only transaction was requested but the reader lock table is full
23+
/// - ENOMEM: Out of memory
24+
///
25+
/// Cursors created within a transaction cannot span across transactions.
26+
/// </remarks>
1227
public sealed class LightningTransaction : IDisposable
1328
{
1429
/// <summary>
@@ -465,4 +480,4 @@ public override bool Equals(object obj)
465480
var tran = obj as LightningTransaction;
466481
return tran != null && _handle.Equals(tran._handle);
467482
}
468-
}
483+
}

0 commit comments

Comments
 (0)