Skip to content

Commit 11e8525

Browse files
committed
Merge pull request XRPLF#124 from ankgup87/master
[Java] Add iterator JNI bindings
2 parents 0f2d768 + bbdd550 commit 11e8525

9 files changed

+391
-6
lines changed

java/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB org.rocksdb.Options org.rocksdb.WriteBatch org.rocksdb.WriteBatchInternal org.rocksdb.WriteBatchTest org.rocksdb.WriteOptions org.rocksdb.BackupableDB org.rocksdb.BackupableDBOptions org.rocksdb.Statistics
1+
NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB org.rocksdb.Options org.rocksdb.WriteBatch org.rocksdb.WriteBatchInternal org.rocksdb.WriteBatchTest org.rocksdb.WriteOptions org.rocksdb.BackupableDB org.rocksdb.BackupableDBOptions org.rocksdb.Statistics org.rocksdb.Iterator
22
NATIVE_INCLUDE = ./include
33
ROCKSDB_JAR = rocksdbjni.jar
44

java/RocksDBSample.java

+36-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
// LICENSE file in the root directory of this source tree. An additional grant
44
// of patent rights can be found in the PATENTS file in the same directory.
55

6-
import java.util.*;
7-
import java.lang.*;
6+
import java.util.Arrays;
87
import org.rocksdb.*;
98
import org.rocksdb.util.SizeUnit;
109
import java.io.IOException;
@@ -142,6 +141,41 @@ public static void main(String[] args) {
142141
System.out.println("Failed in call to geHistogramData()");
143142
assert(false); //Should never reach here.
144143
}
144+
145+
Iterator iterator = db.newIterator();
146+
147+
boolean seekToFirstPassed = false;
148+
for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
149+
iterator.status();
150+
assert(iterator.key() != null);
151+
assert(iterator.value() != null);
152+
seekToFirstPassed = true;
153+
}
154+
if(seekToFirstPassed) {
155+
System.out.println("iterator seekToFirst tests passed.");
156+
}
157+
158+
boolean seekToLastPassed = false;
159+
for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) {
160+
iterator.status();
161+
assert(iterator.key() != null);
162+
assert(iterator.value() != null);
163+
seekToLastPassed = true;
164+
}
165+
166+
if(seekToLastPassed) {
167+
System.out.println("iterator seekToLastPassed tests passed.");
168+
}
169+
170+
iterator.seekToFirst();
171+
iterator.seek(iterator.key());
172+
assert(iterator.key() != null);
173+
assert(iterator.value() != null);
174+
175+
System.out.println("iterator seek test passed.");
176+
177+
iterator.close();
178+
System.out.println("iterator tests passed.");
145179
} catch (RocksDBException e) {
146180
System.err.println(e);
147181
}

java/org/rocksdb/Iterator.java

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
2+
// This source code is licensed under the BSD-style license found in the
3+
// LICENSE file in the root directory of this source tree. An additional grant
4+
// of patent rights can be found in the PATENTS file in the same directory.
5+
6+
package org.rocksdb;
7+
8+
/**
9+
* An iterator yields a sequence of key/value pairs from a source.
10+
* The following class defines the interface. Multiple implementations
11+
* are provided by this library. In particular, iterators are provided
12+
* to access the contents of a Table or a DB.
13+
*
14+
* Multiple threads can invoke const methods on an Iterator without
15+
* external synchronization, but if any of the threads may call a
16+
* non-const method, all threads accessing the same Iterator must use
17+
* external synchronization.
18+
*/
19+
public class Iterator {
20+
private long nativeHandle_;
21+
22+
public Iterator(long nativeHandle) {
23+
nativeHandle_ = nativeHandle;
24+
}
25+
26+
/**
27+
* An iterator is either positioned at a key/value pair, or
28+
* not valid. This method returns true iff the iterator is valid.
29+
* @return true if iterator is valid.
30+
*/
31+
public boolean isValid() {
32+
assert(isInitialized());
33+
return isValid0(nativeHandle_);
34+
}
35+
36+
/**
37+
* Position at the first key in the source. The iterator is Valid()
38+
* after this call iff the source is not empty.
39+
*/
40+
public void seekToFirst() {
41+
assert(isInitialized());
42+
seekToFirst0(nativeHandle_);
43+
}
44+
45+
/**
46+
* Position at the last key in the source. The iterator is
47+
* Valid() after this call iff the source is not empty.
48+
*/
49+
public void seekToLast() {
50+
assert(isInitialized());
51+
seekToLast0(nativeHandle_);
52+
}
53+
54+
/**
55+
* Moves to the next entry in the source. After this call, Valid() is
56+
* true iff the iterator was not positioned at the last entry in the source.
57+
* REQUIRES: Valid()
58+
*/
59+
public void next() {
60+
assert(isInitialized());
61+
next0(nativeHandle_);
62+
}
63+
64+
/**
65+
* Moves to the previous entry in the source. After this call, Valid() is
66+
* true iff the iterator was not positioned at the first entry in source.
67+
* REQUIRES: Valid()
68+
*/
69+
public void prev() {
70+
assert(isInitialized());
71+
prev0(nativeHandle_);
72+
}
73+
74+
/**
75+
* Return the key for the current entry. The underlying storage for
76+
* the returned slice is valid only until the next modification of
77+
* the iterator.
78+
* REQUIRES: Valid()
79+
* @return key for the current entry.
80+
*/
81+
public byte[] key() {
82+
assert(isInitialized());
83+
return key0(nativeHandle_);
84+
}
85+
86+
/**
87+
* Return the value for the current entry. The underlying storage for
88+
* the returned slice is valid only until the next modification of
89+
* the iterator.
90+
* REQUIRES: !AtEnd() && !AtStart()
91+
* @return value for the current entry.
92+
*/
93+
public byte[] value() {
94+
assert(isInitialized());
95+
return value0(nativeHandle_);
96+
}
97+
98+
/**
99+
* Position at the first key in the source that at or past target
100+
* The iterator is Valid() after this call iff the source contains
101+
* an entry that comes at or past target.
102+
*/
103+
public void seek(byte[] target) {
104+
assert(isInitialized());
105+
seek0(nativeHandle_, target, target.length);
106+
}
107+
108+
/**
109+
* If an error has occurred, return it. Else return an ok status.
110+
* If non-blocking IO is requested and this operation cannot be
111+
* satisfied without doing some IO, then this returns Status::Incomplete().
112+
*
113+
*/
114+
public void status() throws RocksDBException {
115+
assert(isInitialized());
116+
status0(nativeHandle_);
117+
}
118+
119+
/**
120+
* Deletes underlying C++ iterator pointer.
121+
*/
122+
public synchronized void close() {
123+
if(nativeHandle_ != 0) {
124+
close0(nativeHandle_);
125+
}
126+
}
127+
128+
@Override protected void finalize() {
129+
close();
130+
}
131+
132+
private boolean isInitialized() {
133+
return (nativeHandle_ != 0);
134+
}
135+
136+
private native boolean isValid0(long handle);
137+
private native void close0(long handle);
138+
private native void seekToFirst0(long handle);
139+
private native void seekToLast0(long handle);
140+
private native void next0(long handle);
141+
private native void prev0(long handle);
142+
private native byte[] key0(long handle);
143+
private native byte[] value0(long handle);
144+
private native void seek0(long handle, byte[] target, int targetLen);
145+
private native void status0(long handle);
146+
}

java/org/rocksdb/Options.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ public int maxBackgroundCompactions() {
508508
return maxBackgroundCompactions(nativeHandle_);
509509
}
510510

511-
/**
511+
/**
512512
* Creates statistics object which collects metrics about database operations.
513513
Statistics objects should not be shared between DB instances as
514514
it does not use any locks to prevent concurrent updates.

java/org/rocksdb/RocksDB.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package org.rocksdb;
77

8-
import java.util.*;
98
import java.io.Closeable;
109
import java.io.IOException;
1110

@@ -137,6 +136,20 @@ public void remove(WriteOptions writeOpt, byte[] key)
137136
remove(nativeHandle_, writeOpt.nativeHandle_, key, key.length);
138137
}
139138

139+
/**
140+
* Return a heap-allocated iterator over the contents of the database.
141+
* The result of newIterator() is initially invalid (caller must
142+
* call one of the Seek methods on the iterator before using it).
143+
*
144+
* Caller should close the iterator when it is no longer needed.
145+
* The returned iterator should be closed before this db is closed.
146+
*
147+
* @return instance of iterator object.
148+
*/
149+
public Iterator newIterator() {
150+
return new Iterator(iterator0(nativeHandle_));
151+
}
152+
140153
@Override protected void finalize() {
141154
close();
142155
}
@@ -170,6 +183,7 @@ protected native void remove(
170183
protected native void remove(
171184
long handle, long writeOptHandle,
172185
byte[] key, int keyLen) throws RocksDBException;
186+
protected native long iterator0(long optHandle);
173187
protected native void close0();
174188

175189
protected long nativeHandle_;

java/rocksjni/iterator.cc

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
2+
// This source code is licensed under the BSD-style license found in the
3+
// LICENSE file in the root directory of this source tree. An additional grant
4+
// of patent rights can be found in the PATENTS file in the same directory.
5+
//
6+
// This file implements the "bridge" between Java and C++ and enables
7+
// calling c++ rocksdb::Iterator methods from Java side.
8+
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <jni.h>
12+
13+
#include "include/org_rocksdb_Iterator.h"
14+
#include "rocksjni/portal.h"
15+
#include "rocksdb/iterator.h"
16+
17+
/*
18+
* Class: org_rocksdb_Iterator
19+
* Method: isValid0
20+
* Signature: (J)Z
21+
*/
22+
jboolean Java_org_rocksdb_Iterator_isValid0(
23+
JNIEnv* env, jobject jobj, jlong handle) {
24+
return reinterpret_cast<rocksdb::Iterator*>(handle)->Valid();
25+
}
26+
27+
/*
28+
* Class: org_rocksdb_Iterator
29+
* Method: close0
30+
* Signature: (J)V
31+
*/
32+
void Java_org_rocksdb_Iterator_seekToFirst0(
33+
JNIEnv* env, jobject jobj, jlong handle) {
34+
reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToFirst();
35+
}
36+
37+
/*
38+
* Class: org_rocksdb_Iterator
39+
* Method: seekToFirst0
40+
* Signature: (J)V
41+
*/
42+
void Java_org_rocksdb_Iterator_seekToLast0(
43+
JNIEnv* env, jobject jobj, jlong handle) {
44+
reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToLast();
45+
}
46+
47+
/*
48+
* Class: org_rocksdb_Iterator
49+
* Method: seekToLast0
50+
* Signature: (J)V
51+
*/
52+
void Java_org_rocksdb_Iterator_next0(
53+
JNIEnv* env, jobject jobj, jlong handle) {
54+
reinterpret_cast<rocksdb::Iterator*>(handle)->Next();
55+
}
56+
57+
/*
58+
* Class: org_rocksdb_Iterator
59+
* Method: next0
60+
* Signature: (J)V
61+
*/
62+
void Java_org_rocksdb_Iterator_prev0(
63+
JNIEnv* env, jobject jobj, jlong handle) {
64+
reinterpret_cast<rocksdb::Iterator*>(handle)->Prev();
65+
}
66+
67+
/*
68+
* Class: org_rocksdb_Iterator
69+
* Method: prev0
70+
* Signature: (J)V
71+
*/
72+
jbyteArray Java_org_rocksdb_Iterator_key0(
73+
JNIEnv* env, jobject jobj, jlong handle) {
74+
auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
75+
rocksdb::Slice key_slice = it->key();
76+
77+
jbyteArray jkey = env->NewByteArray(key_slice.size());
78+
env->SetByteArrayRegion(
79+
jkey, 0, key_slice.size(),
80+
reinterpret_cast<const jbyte*>(key_slice.data()));
81+
return jkey;
82+
}
83+
84+
/*
85+
* Class: org_rocksdb_Iterator
86+
* Method: key0
87+
* Signature: (J)[B
88+
*/
89+
jbyteArray Java_org_rocksdb_Iterator_value0(
90+
JNIEnv* env, jobject jobj, jlong handle) {
91+
auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
92+
rocksdb::Slice value_slice = it->value();
93+
94+
jbyteArray jvalue = env->NewByteArray(value_slice.size());
95+
env->SetByteArrayRegion(
96+
jvalue, 0, value_slice.size(),
97+
reinterpret_cast<const jbyte*>(value_slice.data()));
98+
return jvalue;
99+
}
100+
101+
/*
102+
* Class: org_rocksdb_Iterator
103+
* Method: value0
104+
* Signature: (J)[B
105+
*/
106+
void Java_org_rocksdb_Iterator_seek0(
107+
JNIEnv* env, jobject jobj, jlong handle,
108+
jbyteArray jtarget, jint jtarget_len) {
109+
auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
110+
jbyte* target = env->GetByteArrayElements(jtarget, 0);
111+
rocksdb::Slice target_slice(
112+
reinterpret_cast<char*>(target), jtarget_len);
113+
114+
it->Seek(target_slice);
115+
116+
env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT);
117+
}
118+
119+
/*
120+
* Class: org_rocksdb_Iterator
121+
* Method: seek0
122+
* Signature: (J[BI)V
123+
*/
124+
void Java_org_rocksdb_Iterator_status0(
125+
JNIEnv* env, jobject jobj, jlong handle) {
126+
auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
127+
rocksdb::Status s = it->status();
128+
129+
if (s.ok()) {
130+
return;
131+
}
132+
133+
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
134+
}
135+
136+
/*
137+
* Class: org_rocksdb_Iterator
138+
* Method: status0
139+
* Signature: (J)V
140+
*/
141+
void Java_org_rocksdb_Iterator_close0(
142+
JNIEnv* env, jobject jobj, jlong handle) {
143+
auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
144+
delete it;
145+
146+
rocksdb::IteratorJni::setHandle(env, jobj, nullptr);
147+
}

0 commit comments

Comments
 (0)