2323import static java .util .Objects .requireNonNull ;
2424import jnr .ffi .Pointer ;
2525import jnr .ffi .byref .NativeLongByReference ;
26+ import jnr .ffi .provider .MemoryManager ;
27+ import static org .lmdbjava .BufferProxy .MDB_VAL_STRUCT_SIZE ;
2628import static org .lmdbjava .Dbi .KeyNotFoundException .MDB_NOTFOUND ;
2729import static org .lmdbjava .Env .SHOULD_CHECK ;
2830import static org .lmdbjava .Library .LIB ;
31+ import static org .lmdbjava .Library .RUNTIME ;
2932import static org .lmdbjava .MaskedFlag .mask ;
3033import static org .lmdbjava .PutFlags .MDB_RESERVE ;
3134import static org .lmdbjava .ResultCodeMapper .checkRc ;
4144 */
4245public final class Cursor <T > implements AutoCloseable {
4346
47+ private static final MemoryManager MEM_MGR = RUNTIME .getMemoryManager ();
4448 private boolean closed ;
4549 private final Pointer ptrCursor ;
4650 private Txn <T > txn ;
4751
52+ private T k ;
53+ private final BufferProxy <T > proxy ;
54+ private final Pointer ptrKey ;
55+ private final long ptrKeyAddr ;
56+ private final Pointer ptrVal ;
57+ private final long ptrValAddr ;
58+ private T v ;
59+
4860 Cursor (final Pointer ptr , final Txn <T > txn ) {
4961 requireNonNull (ptr );
5062 requireNonNull (txn );
5163 this .ptrCursor = ptr ;
5264 this .txn = txn ;
65+
66+ this .proxy = txn .proxy ;
67+ this .k = proxy .allocate ();
68+ this .v = proxy .allocate ();
69+ ptrKey = MEM_MGR .allocateTemporary (MDB_VAL_STRUCT_SIZE , false );
70+ ptrKeyAddr = ptrKey .address ();
71+ ptrVal = MEM_MGR .allocateTemporary (MDB_VAL_STRUCT_SIZE , false );
72+ ptrValAddr = ptrVal .address ();
73+ }
74+
75+ void keyIn (final T key ) {
76+ proxy .in (key , ptrKey , ptrKeyAddr );
77+ }
78+
79+ T keyOut () {
80+ k = proxy .out (k , ptrKey , ptrKeyAddr );
81+ return k ;
82+ }
83+
84+ Pointer pointerKey () {
85+ return ptrKey ;
86+ }
87+
88+ Pointer pointerVal () {
89+ return ptrVal ;
90+ }
91+
92+ void valIn (final T val ) {
93+ proxy .in (val , ptrVal , ptrValAddr );
94+ }
95+
96+ void valIn (final int size ) {
97+ proxy .in (v , size , ptrVal , ptrValAddr );
98+ }
99+
100+ T valOut () {
101+ v = proxy .out (v , ptrVal , ptrValAddr );
102+ return v ;
53103 }
54104
55105 /**
@@ -68,6 +118,8 @@ public void close() {
68118 txn .checkReady ();
69119 }
70120 LIB .mdb_cursor_close (ptrCursor );
121+ proxy .deallocate (k );
122+ proxy .deallocate (v );
71123 closed = true ;
72124 }
73125
@@ -131,26 +183,25 @@ public boolean get(final T key, final GetOp op) {
131183 checkNotClosed ();
132184 txn .checkReady ();
133185 }
134- txn . keyIn (key );
186+ keyIn (key );
135187
136- final int rc = LIB .mdb_cursor_get (ptrCursor , txn .pointerKey (), txn .
137- pointerVal (), op .getCode ());
188+ final int rc = LIB .mdb_cursor_get (ptrCursor , pointerKey (), pointerVal (), op .getCode ());
138189
139190 if (rc == MDB_NOTFOUND ) {
140191 return false ;
141192 }
142193
143194 checkRc (rc );
144- txn . keyOut ();
145- txn . valOut ();
195+ keyOut ();
196+ valOut ();
146197 return true ;
147198 }
148199
149200 /**
150201 * @return the key that the cursor is located at.
151202 */
152203 public T key () {
153- return txn . key () ;
204+ return k ;
154205 }
155206
156207 /**
@@ -199,13 +250,12 @@ public void put(final T key, final T val, final PutFlags... op) {
199250 txn .checkReady ();
200251 txn .checkWritesAllowed ();
201252 }
202- txn . keyIn (key );
203- txn . valIn (val );
253+ keyIn (key );
254+ valIn (val );
204255 final int flags = mask (op );
205- checkRc (LIB .mdb_cursor_put (ptrCursor , txn .pointerKey (), txn .pointerVal (),
206- flags ));
207- txn .keyOut ();
208- txn .valOut ();
256+ checkRc (LIB .mdb_cursor_put (ptrCursor , pointerKey (), pointerVal (), flags ));
257+ keyOut ();
258+ valOut ();
209259 }
210260
211261 /**
@@ -256,13 +306,12 @@ public T reserve(final T key, final int size, final PutFlags... op) {
256306 txn .checkReady ();
257307 txn .checkWritesAllowed ();
258308 }
259- txn . keyIn (key );
260- txn . valIn (size );
309+ keyIn (key );
310+ valIn (size );
261311 final int flags = mask (op ) | MDB_RESERVE .getMask ();
262- checkRc (LIB .mdb_cursor_put (ptrCursor , txn .pointerKey (), txn .pointerVal (),
263- flags ));
264- txn .valOut ();
265- return txn .val ();
312+ checkRc (LIB .mdb_cursor_put (ptrCursor , pointerKey (), pointerVal (), flags ));
313+ valOut ();
314+ return val ();
266315 }
267316
268317 /**
@@ -278,25 +327,23 @@ public boolean seek(final SeekOp op) {
278327 txn .checkReady ();
279328 }
280329
281- final int rc = LIB .mdb_cursor_get (ptrCursor , txn .pointerKey (), txn .
282- pointerVal (),
283- op .getCode ());
330+ final int rc = LIB .mdb_cursor_get (ptrCursor , pointerKey (), pointerVal (), op .getCode ());
284331
285332 if (rc == MDB_NOTFOUND ) {
286333 return false ;
287334 }
288335
289336 checkRc (rc );
290- txn . keyOut ();
291- txn . valOut ();
337+ keyOut ();
338+ valOut ();
292339 return true ;
293340 }
294341
295342 /**
296343 * @return the value that the cursor is located at.
297344 */
298345 public T val () {
299- return txn . val () ;
346+ return v ;
300347 }
301348
302349 private void checkNotClosed () throws ClosedException {
0 commit comments