Skip to content

Commit 4d949e1

Browse files
committed
Dbi<byte[]> suggestion
1 parent 66a2632 commit 4d949e1

File tree

9 files changed

+139
-20
lines changed

9 files changed

+139
-20
lines changed

src/main/java/org/lmdbjava/BufferProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,6 @@ public abstract class BufferProxy<T> { // NOPMD
9797
* @param ptr the pointer to the <code>MDB_val</code>
9898
* @param ptrAddr the address of the <code>MDB_val</code> pointer
9999
*/
100-
protected abstract void out(T buffer, Pointer ptr, long ptrAddr);
100+
protected abstract T out(T buffer, Pointer ptr, long ptrAddr);
101101

102102
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.lmdbjava;
2+
3+
import jnr.ffi.Pointer;
4+
import jnr.ffi.provider.MemoryManager;
5+
6+
import static org.lmdbjava.Library.RUNTIME;
7+
8+
public class ByteArrayProxy extends BufferProxy<byte[]> {
9+
private static final MemoryManager MEM_MGR = RUNTIME.getMemoryManager();
10+
11+
@Override
12+
protected byte[] allocate() {
13+
return new byte[0];
14+
}
15+
16+
@Override
17+
protected void deallocate(byte[] buff) {
18+
}
19+
20+
@Override
21+
protected void in(byte[] buffer, Pointer ptr, long ptrAddr) {
22+
Pointer pointer = MEM_MGR.allocateDirect(buffer.length);
23+
pointer.put(0, buffer, 0, buffer.length);
24+
ptr.putLong(STRUCT_FIELD_OFFSET_SIZE, buffer.length);
25+
ptr.putLong(STRUCT_FIELD_OFFSET_DATA, pointer.address());
26+
}
27+
28+
@Override
29+
protected void in(byte[] buffer, int size, Pointer ptr, long ptrAddr) {
30+
31+
}
32+
33+
@Override
34+
protected byte[] out(byte[] buffer, Pointer ptr, long ptrAddr) {
35+
final long addr = ptr.getLong(STRUCT_FIELD_OFFSET_DATA);
36+
final int size = (int) ptr.getLong(STRUCT_FIELD_OFFSET_SIZE);
37+
Pointer pointer = MEM_MGR.newPointer(addr, size);
38+
byte[] bytes = new byte[size];
39+
pointer.get(0, bytes, 0, size);
40+
return bytes;
41+
}
42+
}

src/main/java/org/lmdbjava/ByteBufferProxy.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ protected void in(final ByteBuffer buffer, final int size, final Pointer ptr,
178178
}
179179

180180
@Override
181-
protected void out(final ByteBuffer buffer, final Pointer ptr,
181+
protected ByteBuffer out(final ByteBuffer buffer, final Pointer ptr,
182182
final long ptrAddr) {
183183
final long addr = ptr.getLong(STRUCT_FIELD_OFFSET_DATA);
184184
final long size = ptr.getLong(STRUCT_FIELD_OFFSET_SIZE);
@@ -189,6 +189,7 @@ protected void out(final ByteBuffer buffer, final Pointer ptr,
189189
throw new LmdbException("Cannot modify buffer", e);
190190
}
191191
buffer.clear();
192+
return buffer;
192193
}
193194

194195
}
@@ -228,13 +229,14 @@ protected void in(final ByteBuffer buffer, final int size, final Pointer ptr,
228229
}
229230

230231
@Override
231-
protected void out(final ByteBuffer buffer, final Pointer ptr,
232+
protected ByteBuffer out(final ByteBuffer buffer, final Pointer ptr,
232233
final long ptrAddr) {
233234
final long addr = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_DATA);
234235
final long size = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_SIZE);
235236
UNSAFE.putLong(buffer, ADDRESS_OFFSET, addr);
236237
UNSAFE.putInt(buffer, CAPACITY_OFFSET, (int) size);
237238
buffer.clear();
239+
return buffer;
238240
}
239241
}
240242

src/main/java/org/lmdbjava/Dbi.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,7 @@ public T get(final Txn<T> txn, final T key) {
180180
return null;
181181
}
182182
checkRc(rc);
183-
txn.valOut(); // marked as out in LMDB C docs
184-
return txn.val();
183+
return txn.valOut(); // marked as out in LMDB C docs
185184
}
186185

187186
/**
@@ -332,8 +331,7 @@ public T reserve(final Txn<T> txn, final T key, final int size) {
332331
final int mask = mask(MDB_RESERVE);
333332
checkRc(LIB.mdb_put(txn.pointer(), ptr, txn.pointerKey(), txn.pointerVal(),
334333
mask));
335-
txn.valOut(); // marked as in,out in LMDB C docs
336-
return txn.val();
334+
return txn.valOut(); // marked as in,out in LMDB C docs
337335
}
338336

339337
/**

src/main/java/org/lmdbjava/DirectBufferProxy.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ protected void in(final DirectBuffer buffer, final int size, final Pointer ptr,
9292
}
9393

9494
@Override
95-
protected void out(final DirectBuffer buffer, final Pointer ptr,
95+
protected DirectBuffer out(final DirectBuffer buffer, final Pointer ptr,
9696
final long ptrAddr) {
9797
final long addr = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_DATA);
9898
final long size = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_SIZE);
9999
buffer.wrap(addr, (int) size);
100+
return buffer;
100101
}
101102

102103
}

src/main/java/org/lmdbjava/Txn.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
public final class Txn<T> implements AutoCloseable {
4545

4646
private static final MemoryManager MEM_MGR = RUNTIME.getMemoryManager();
47-
private final T k;
47+
private T k;
48+
private T v;
4849
private final Txn<T> parent;
4950
private final BufferProxy<T> proxy;
5051
private final Pointer ptr;
@@ -54,7 +55,6 @@ public final class Txn<T> implements AutoCloseable {
5455
private final long ptrValAddr;
5556
private final boolean readOnly;
5657
private State state;
57-
private final T v;
5858

5959
Txn(final Env<T> env, final Txn<T> parent, final BufferProxy<T> proxy,
6060
final TxnFlags... flags) {
@@ -229,8 +229,9 @@ void keyIn(final T key) {
229229
proxy.in(key, ptrKey, ptrKeyAddr);
230230
}
231231

232-
void keyOut() {
233-
proxy.out(k, ptrKey, ptrKeyAddr);
232+
T keyOut() {
233+
k = proxy.out(k, ptrKey, ptrKeyAddr);
234+
return k;
234235
}
235236

236237
Pointer pointer() {
@@ -253,8 +254,9 @@ void valIn(final int size) {
253254
proxy.in(v, size, ptrVal, ptrValAddr);
254255
}
255256

256-
void valOut() {
257-
proxy.out(v, ptrVal, ptrValAddr);
257+
T valOut() {
258+
v = proxy.out(v, ptrVal, ptrValAddr);
259+
return v;
258260
}
259261

260262
/**

src/test/java/org/lmdbjava/ByteBufProxy.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ protected void in(final ByteBuf buffer, final int size, final Pointer ptr,
123123
}
124124

125125
@Override
126-
protected void out(final ByteBuf buffer, final Pointer ptr, final long ptrAddr) {
126+
protected ByteBuf out(final ByteBuf buffer, final Pointer ptr, final long ptrAddr) {
127127
final long addr = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_DATA);
128128
final long size = UNSAFE.getLong(ptrAddr + STRUCT_FIELD_OFFSET_SIZE);
129129
UNSAFE.putLong(buffer, ADDRESS_OFFSET, addr);
130130
UNSAFE.putLong(buffer, LENGTH_OFFSET, (int) size);
131131
buffer.readerIndex(0).writerIndex((int) size);
132+
return buffer;
132133
}
133134
}

src/test/java/org/lmdbjava/CursorTest.java

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,8 @@
5353
import static org.lmdbjava.SeekOp.MDB_LAST;
5454
import static org.lmdbjava.SeekOp.MDB_NEXT;
5555
import static org.lmdbjava.SeekOp.MDB_PREV;
56-
import static org.lmdbjava.TestUtils.DB_1;
57-
import static org.lmdbjava.TestUtils.POSIX_MODE;
58-
import static org.lmdbjava.TestUtils.bb;
59-
import static org.lmdbjava.TestUtils.mdb;
60-
import static org.lmdbjava.TestUtils.nb;
56+
import static org.lmdbjava.TestUtils.*;
57+
6158
import org.lmdbjava.Txn.NotReadyException;
6259
import org.lmdbjava.Txn.ReadOnlyRequiredException;
6360

@@ -248,6 +245,76 @@ public void cursorMutableDirectBuffer() {
248245
}
249246
}
250247

248+
@Test
249+
@SuppressWarnings("checkstyle:executablestatementcount")
250+
public void cursorByteArray() {
251+
final Env<byte[]> env = makeEnv(new ByteArrayProxy());
252+
final Dbi<byte[]> db = env.openDbi(DB_1, MDB_CREATE, MDB_DUPSORT);
253+
try (final Txn<byte[]> txn = env.txnWrite()) {
254+
// populate data
255+
final Cursor<byte[]> c = db.openCursor(txn);
256+
c.put(ba(1), ba(2), MDB_NOOVERWRITE);
257+
c.put(ba(3), ba(4));
258+
c.put(ba(5), ba(6));
259+
260+
// check MDB_SET operations
261+
final byte[] key3 = ba(3);
262+
assertThat(c.get(key3, MDB_SET_KEY), is(true));
263+
assertThat(new UnsafeBuffer(txn.key()).getInt(0), is(3));
264+
assertThat(new UnsafeBuffer(txn.val()).getInt(0), is(4));
265+
final byte[] key6 = ba(5);
266+
assertThat(c.get(key6, MDB_SET_RANGE), is(true));
267+
assertThat(new UnsafeBuffer(txn.key()).getInt(0), is(5));
268+
assertThat(new UnsafeBuffer(txn.val()).getInt(0), is(6));
269+
final byte[] key999 = ba(999);
270+
assertThat(c.get(key999, MDB_SET_KEY), is(false));
271+
272+
// check MDB navigation operations
273+
assertThat(c.seek(MDB_LAST), is(true));
274+
final MutableDirectBuffer mdb1 = mdb(0);
275+
final MutableDirectBuffer mdb2 = mdb(0);
276+
mdb1.wrap(txn.key());
277+
mdb2.wrap(txn.val());
278+
279+
assertThat(c.seek(MDB_PREV), is(true));
280+
final MutableDirectBuffer mdb3 = mdb(0);
281+
final MutableDirectBuffer mdb4 = mdb(0);
282+
mdb3.wrap(txn.key());
283+
mdb4.wrap(txn.val());
284+
285+
assertThat(c.seek(MDB_NEXT), is(true));
286+
final MutableDirectBuffer mdb5 = mdb(0);
287+
final MutableDirectBuffer mdb6 = mdb(0);
288+
mdb5.wrap(txn.key());
289+
mdb6.wrap(txn.val());
290+
291+
assertThat(c.seek(MDB_FIRST), is(true));
292+
final MutableDirectBuffer mdb7 = mdb(0);
293+
final MutableDirectBuffer mdb8 = mdb(0);
294+
mdb7.wrap(txn.key());
295+
mdb8.wrap(txn.val());
296+
297+
// assert afterwards to ensure memory address from LMDB
298+
// are valid within same txn and across cursor movement
299+
// MDB_LAST
300+
assertThat(mdb1.getInt(0), is(5));
301+
assertThat(mdb2.getInt(0), is(6));
302+
303+
// MDB_PREV
304+
assertThat(mdb3.getInt(0), is(3));
305+
assertThat(mdb4.getInt(0), is(4));
306+
307+
// MDB_NEXT
308+
assertThat(mdb5.getInt(0), is(5));
309+
assertThat(mdb6.getInt(0), is(6));
310+
311+
// MDB_FIRST
312+
assertThat(mdb7.getInt(0), is(1));
313+
assertThat(mdb8.getInt(0), is(2));
314+
}
315+
}
316+
317+
251318
@Test
252319
public void delete() {
253320
final Env<ByteBuffer> env = makeEnv(PROXY_OPTIMAL);

src/test/java/org/lmdbjava/TestUtils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,10 @@ static ByteBuf nb(final int value) {
7272
return b;
7373
}
7474

75+
static byte[] ba(final int value) {
76+
final MutableDirectBuffer b = new UnsafeBuffer(new byte[4]);
77+
b.putInt(0, value);
78+
return b.byteArray();
79+
}
80+
7581
}

0 commit comments

Comments
 (0)