@@ -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>
1226public 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+ }
0 commit comments