From 5bbeefaa490c0c509983ef6c5515da4fdc4c935d Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 03:26:22 -0700 Subject: [PATCH 1/7] Adding iterator JNI binding --- java/RocksDBSample.java | 8 +++++-- java/org/rocksdb/Iterator.java | 42 ++++++++++++++++++++++++++++++++++ java/org/rocksdb/RocksDB.java | 6 ++++- java/rocksjni/iterator.cc | 41 +++++++++++++++++++++++++++++++++ java/rocksjni/portal.h | 33 ++++++++++++++++++++++++++ java/rocksjni/rocksjni.cc | 7 ++++++ java/rocksjni/statistics.cc | 1 - 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 java/org/rocksdb/Iterator.java create mode 100644 java/rocksjni/iterator.cc diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index 406102426..f4afe79cf 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -3,8 +3,7 @@ // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. -import java.util.*; -import java.lang.*; +import java.util.Arrays; import org.rocksdb.*; import org.rocksdb.util.SizeUnit; import java.io.IOException; @@ -142,6 +141,11 @@ public class RocksDBSample { System.out.println("Failed in call to geHistogramData()"); assert(false); //Should never reach here. } + + Iterator iterator = db.iterator(); + iterator.seekToFirst(); + assert(iterator.isValid()); + iterator.close(); } catch (RocksDBException e) { System.err.println(e); } diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java new file mode 100644 index 000000000..945514230 --- /dev/null +++ b/java/org/rocksdb/Iterator.java @@ -0,0 +1,42 @@ +// Copyright (c) 2014, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. + +package org.rocksdb; + +public class Iterator { + private long nativeHandle_; + + public Iterator(long nativeHandle) { + nativeHandle_ = nativeHandle; + } + + public boolean isValid() { + assert(isInitialized()); + return isValid0(nativeHandle_); + } + + public void seekToFirst() { + assert(isInitialized()); + seekToFirst0(nativeHandle_); + } + + public synchronized void close() { + if(nativeHandle_ != 0) { + close0(nativeHandle_); + } + } + + @Override protected void finalize() { + close(); + } + + private boolean isInitialized() { + return (nativeHandle_ != 0); + } + + private native boolean isValid0(long handle); + private native void close0(long handle); + private native void seekToFirst0(long handle); +} \ No newline at end of file diff --git a/java/org/rocksdb/RocksDB.java b/java/org/rocksdb/RocksDB.java index 9f93f9986..586331e04 100644 --- a/java/org/rocksdb/RocksDB.java +++ b/java/org/rocksdb/RocksDB.java @@ -5,7 +5,6 @@ package org.rocksdb; -import java.util.*; import java.io.Closeable; import java.io.IOException; @@ -136,6 +135,10 @@ public class RocksDB { throws RocksDBException { remove(nativeHandle_, writeOpt.nativeHandle_, key, key.length); } + + public Iterator iterator() { + return new Iterator(iterator0(nativeHandle_)); + } @Override protected void finalize() { close(); @@ -170,6 +173,7 @@ public class RocksDB { protected native void remove( long handle, long writeOptHandle, byte[] key, int keyLen) throws RocksDBException; + protected native long iterator0(long optHandle); protected native void close0(); protected long nativeHandle_; diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc new file mode 100644 index 000000000..9f6edd0ee --- /dev/null +++ b/java/rocksjni/iterator.cc @@ -0,0 +1,41 @@ +// Copyright (c) 2014, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// This file implements the "bridge" between Java and C++ and enables +// calling c++ rocksdb::Iterator methods from Java side. + +#include +#include +#include + +#include "include/org_rocksdb_Iterator.h" +#include "rocksjni/portal.h" +#include "rocksdb/iterator.h" + +jboolean Java_org_rocksdb_Iterator_isValid0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + return st->Valid(); +} + +void Java_org_rocksdb_Iterator_seekToFirst0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + st->SeekToFirst(); +} + +void Java_org_rocksdb_Iterator_close0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + delete st; + + rocksdb::IteratorJni::setHandle(env, jobj, nullptr); +} \ No newline at end of file diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index 024062c0b..32e033aaf 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -213,5 +213,38 @@ class BackupableDBOptionsJni { reinterpret_cast(op)); } }; + +class IteratorJni { + public: + // Get the java class id of org.rocksdb.Iteartor. + static jclass getJClass(JNIEnv* env) { + static jclass jclazz = env->FindClass("org/rocksdb/Iterator"); + assert(jclazz != nullptr); + return jclazz; + } + + // Get the field id of the member variable of org.rocksdb.Iterator + // that stores the pointer to rocksdb::Iterator + static jfieldID getHandleFieldID(JNIEnv* env) { + static jfieldID fid = env->GetFieldID( + getJClass(env), "nativeHandle_", "J"); + assert(fid != nullptr); + return fid; + } + + // Get the pointer to rocksdb::Iterator + static rocksdb::Iterator* getHandle(JNIEnv* env, jobject jobj) { + return reinterpret_cast( + env->GetLongField(jobj, getHandleFieldID(env))); + } + + // Pass the rocksdb::Iterator pointer to the java side. + static void setHandle( + JNIEnv* env, jobject jobj, rocksdb::Iterator* op) { + env->SetLongField( + jobj, getHandleFieldID(env), + reinterpret_cast(op)); + } +}; } // namespace rocksdb #endif // JAVA_ROCKSJNI_PORTAL_H_ diff --git a/java/rocksjni/rocksjni.cc b/java/rocksjni/rocksjni.cc index 6602f0cc7..4e4093294 100644 --- a/java/rocksjni/rocksjni.cc +++ b/java/rocksjni/rocksjni.cc @@ -296,3 +296,10 @@ void Java_org_rocksdb_RocksDB_close0( rocksdb::RocksDBJni::setHandle(env, java_db, nullptr); } + +jlong Java_org_rocksdb_RocksDB_iterator0( + JNIEnv* env, jobject jdb, jlong db_handle) { + auto db = reinterpret_cast(db_handle); + rocksdb::Iterator* iterator = db->NewIterator(rocksdb::ReadOptions()); + return reinterpret_cast(iterator); +} \ No newline at end of file diff --git a/java/rocksjni/statistics.cc b/java/rocksjni/statistics.cc index 546b5fec7..bf170c6de 100644 --- a/java/rocksjni/statistics.cc +++ b/java/rocksjni/statistics.cc @@ -13,7 +13,6 @@ #include "include/org_rocksdb_Statistics.h" #include "rocksjni/portal.h" #include "rocksdb/statistics.h" -#include /* * Class: org_rocksdb_Statistics From eda398491a19ae02ffb304e2686514c171a603c5 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 03:35:01 -0700 Subject: [PATCH 2/7] Add more iterator functions --- java/RocksDBSample.java | 3 +++ java/org/rocksdb/Iterator.java | 18 ++++++++++++++++++ java/rocksjni/iterator.cc | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index f4afe79cf..018d86815 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -145,6 +145,9 @@ public class RocksDBSample { Iterator iterator = db.iterator(); iterator.seekToFirst(); assert(iterator.isValid()); + iterator.next(); + iterator.seekToLast(); + iterator.prev(); iterator.close(); } catch (RocksDBException e) { System.err.println(e); diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java index 945514230..dbd11015b 100644 --- a/java/org/rocksdb/Iterator.java +++ b/java/org/rocksdb/Iterator.java @@ -22,6 +22,21 @@ public class Iterator { seekToFirst0(nativeHandle_); } + public void seekToLast() { + assert(isInitialized()); + seekToLast0(nativeHandle_); + } + + public void next() { + assert(isInitialized()); + next0(nativeHandle_); + } + + public void prev() { + assert(isInitialized()); + prev0(nativeHandle_); + } + public synchronized void close() { if(nativeHandle_ != 0) { close0(nativeHandle_); @@ -39,4 +54,7 @@ public class Iterator { private native boolean isValid0(long handle); private native void close0(long handle); private native void seekToFirst0(long handle); + private native void seekToLast0(long handle); + private native void next0(long handle); + private native void prev0(long handle); } \ No newline at end of file diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc index 9f6edd0ee..2f6d0a6b3 100644 --- a/java/rocksjni/iterator.cc +++ b/java/rocksjni/iterator.cc @@ -30,6 +30,30 @@ void Java_org_rocksdb_Iterator_seekToFirst0( st->SeekToFirst(); } +void Java_org_rocksdb_Iterator_seekToLast0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + st->SeekToLast(); +} + +void Java_org_rocksdb_Iterator_next0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + st->Next(); +} + +void Java_org_rocksdb_Iterator_prev0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + st->Prev(); +} + void Java_org_rocksdb_Iterator_close0( JNIEnv* env, jobject jobj, jlong handle) { auto st = reinterpret_cast(handle); From 1d6c1e018fe5e7048af92433094716bd00b8c61a Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 12:55:28 -0700 Subject: [PATCH 3/7] Add more iterator JNI bindings --- java/Makefile | 2 +- java/RocksDBSample.java | 37 +++++++++++++++++++--- java/org/rocksdb/Iterator.java | 24 ++++++++++++++ java/rocksjni/iterator.cc | 57 ++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 6 deletions(-) diff --git a/java/Makefile b/java/Makefile index c9e65808a..81b5afc79 100644 --- a/java/Makefile +++ b/java/Makefile @@ -1,4 +1,4 @@ -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 +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 NATIVE_INCLUDE = ./include ROCKSDB_JAR = rocksdbjni.jar diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index 018d86815..7a5eb7093 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -143,12 +143,39 @@ public class RocksDBSample { } Iterator iterator = db.iterator(); + + boolean seekToFirstPassed = false; + for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) { + iterator.status(); + assert(iterator.key() != null); + assert(iterator.value() != null); + seekToFirstPassed = true; + } + if(seekToFirstPassed) { + System.out.println("iterator seekToFirst tests passed."); + } + + boolean seekToLastPassed = false; + for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) { + iterator.status(); + assert(iterator.key() != null); + assert(iterator.value() != null); + seekToLastPassed = true; + } + + if(seekToLastPassed) { + System.out.println("iterator seekToLastPassed tests passed."); + } + iterator.seekToFirst(); - assert(iterator.isValid()); - iterator.next(); - iterator.seekToLast(); - iterator.prev(); - iterator.close(); + iterator.seek(iterator.key()); + assert(iterator.key() != null); + assert(iterator.value() != null); + + System.out.println("iterator seek test passed."); + + iterator.close(); + System.out.println("iterator tests passed."); } catch (RocksDBException e) { System.err.println(e); } diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java index dbd11015b..099c5f7df 100644 --- a/java/org/rocksdb/Iterator.java +++ b/java/org/rocksdb/Iterator.java @@ -37,6 +37,26 @@ public class Iterator { prev0(nativeHandle_); } + public byte[] key() { + assert(isInitialized()); + return key0(nativeHandle_); + } + + public byte[] value() { + assert(isInitialized()); + return value0(nativeHandle_); + } + + public void seek(byte[] target) { + assert(isInitialized()); + seek0(nativeHandle_, target, target.length); + } + + public void status(){ + assert(isInitialized()); + status0(nativeHandle_); + } + public synchronized void close() { if(nativeHandle_ != 0) { close0(nativeHandle_); @@ -57,4 +77,8 @@ public class Iterator { private native void seekToLast0(long handle); private native void next0(long handle); private native void prev0(long handle); + private native byte[] key0(long handle); + private native byte[] value0(long handle); + private native void seek0(long handle, byte[] target, int targetLen); + private native void status0(long handle); } \ No newline at end of file diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc index 2f6d0a6b3..be8bb10d5 100644 --- a/java/rocksjni/iterator.cc +++ b/java/rocksjni/iterator.cc @@ -54,6 +54,63 @@ void Java_org_rocksdb_Iterator_prev0( st->Prev(); } +jbyteArray Java_org_rocksdb_Iterator_key0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + rocksdb::Slice key_slice = st->key(); + + jbyteArray jkey = env->NewByteArray(key_slice.size()); + env->SetByteArrayRegion( + jkey, 0, key_slice.size(), + reinterpret_cast(key_slice.data())); + return jkey; +} + +jbyteArray Java_org_rocksdb_Iterator_value0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + rocksdb::Slice value_slice = st->value(); + + jbyteArray jvalue = env->NewByteArray(value_slice.size()); + env->SetByteArrayRegion( + jvalue, 0, value_slice.size(), + reinterpret_cast(value_slice.data())); + return jvalue; +} + +void Java_org_rocksdb_Iterator_seek0( + JNIEnv* env, jobject jobj, jlong handle, + jbyteArray jtarget, jint jtarget_len) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + jbyte* target = env->GetByteArrayElements(jtarget, 0); + rocksdb::Slice target_slice( + reinterpret_cast(target), jtarget_len); + + st->Seek(target_slice); + + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); +} + +void Java_org_rocksdb_Iterator_status0( + JNIEnv* env, jobject jobj, jlong handle) { + auto st = reinterpret_cast(handle); + assert(st != nullptr); + + rocksdb::Status s = st->status(); + + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + void Java_org_rocksdb_Iterator_close0( JNIEnv* env, jobject jobj, jlong handle) { auto st = reinterpret_cast(handle); From dc28a726c19552f4155bd85e26e159b54d473c44 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 13:05:21 -0700 Subject: [PATCH 4/7] Add doc + refactor + fix formatting --- java/RocksDBSample.java | 14 ++-- java/org/rocksdb/Iterator.java | 30 ++++---- java/org/rocksdb/Options.java | 2 +- java/org/rocksdb/RocksDB.java | 2 +- java/rocksjni/iterator.cc | 126 ++++++++++++++++++++------------- java/rocksjni/portal.h | 8 +++ java/rocksjni/rocksjni.cc | 2 +- 7 files changed, 111 insertions(+), 73 deletions(-) diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index 7a5eb7093..aa05b7887 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -141,9 +141,9 @@ public class RocksDBSample { System.out.println("Failed in call to geHistogramData()"); assert(false); //Should never reach here. } - + Iterator iterator = db.iterator(); - + boolean seekToFirstPassed = false; for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) { iterator.status(); @@ -154,7 +154,7 @@ public class RocksDBSample { if(seekToFirstPassed) { System.out.println("iterator seekToFirst tests passed."); } - + boolean seekToLastPassed = false; for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) { iterator.status(); @@ -162,18 +162,18 @@ public class RocksDBSample { assert(iterator.value() != null); seekToLastPassed = true; } - + if(seekToLastPassed) { System.out.println("iterator seekToLastPassed tests passed."); } - + iterator.seekToFirst(); iterator.seek(iterator.key()); assert(iterator.key() != null); assert(iterator.value() != null); - + System.out.println("iterator seek test passed."); - + iterator.close(); System.out.println("iterator tests passed."); } catch (RocksDBException e) { diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java index 099c5f7df..6069f27b0 100644 --- a/java/org/rocksdb/Iterator.java +++ b/java/org/rocksdb/Iterator.java @@ -7,70 +7,70 @@ package org.rocksdb; public class Iterator { private long nativeHandle_; - + public Iterator(long nativeHandle) { nativeHandle_ = nativeHandle; } - + public boolean isValid() { assert(isInitialized()); return isValid0(nativeHandle_); } - + public void seekToFirst() { assert(isInitialized()); seekToFirst0(nativeHandle_); } - + public void seekToLast() { assert(isInitialized()); seekToLast0(nativeHandle_); } - + public void next() { assert(isInitialized()); next0(nativeHandle_); } - + public void prev() { assert(isInitialized()); prev0(nativeHandle_); } - + public byte[] key() { assert(isInitialized()); return key0(nativeHandle_); } - + public byte[] value() { assert(isInitialized()); return value0(nativeHandle_); } - + public void seek(byte[] target) { assert(isInitialized()); seek0(nativeHandle_, target, target.length); } - + public void status(){ assert(isInitialized()); status0(nativeHandle_); } - + public synchronized void close() { if(nativeHandle_ != 0) { close0(nativeHandle_); } } - + @Override protected void finalize() { close(); } - + private boolean isInitialized() { return (nativeHandle_ != 0); } - + private native boolean isValid0(long handle); private native void close0(long handle); private native void seekToFirst0(long handle); @@ -81,4 +81,4 @@ public class Iterator { private native byte[] value0(long handle); private native void seek0(long handle, byte[] target, int targetLen); private native void status0(long handle); -} \ No newline at end of file +} diff --git a/java/org/rocksdb/Options.java b/java/org/rocksdb/Options.java index 64b56b87c..13b35e434 100644 --- a/java/org/rocksdb/Options.java +++ b/java/org/rocksdb/Options.java @@ -508,7 +508,7 @@ public class Options { return maxBackgroundCompactions(nativeHandle_); } - /** + /** * Creates statistics object which collects metrics about database operations. Statistics objects should not be shared between DB instances as it does not use any locks to prevent concurrent updates. diff --git a/java/org/rocksdb/RocksDB.java b/java/org/rocksdb/RocksDB.java index 586331e04..bbfc18f4c 100644 --- a/java/org/rocksdb/RocksDB.java +++ b/java/org/rocksdb/RocksDB.java @@ -135,7 +135,7 @@ public class RocksDB { throws RocksDBException { remove(nativeHandle_, writeOpt.nativeHandle_, key, key.length); } - + public Iterator iterator() { return new Iterator(iterator0(nativeHandle_)); } diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc index be8bb10d5..378e013e0 100644 --- a/java/rocksjni/iterator.cc +++ b/java/rocksjni/iterator.cc @@ -14,53 +14,71 @@ #include "rocksjni/portal.h" #include "rocksdb/iterator.h" +/* + * Class: org_rocksdb_Iterator + * Method: isValid0 + * Signature: (J)Z + */ jboolean Java_org_rocksdb_Iterator_isValid0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - return st->Valid(); + auto it = rocksdb::IteratorJni::getIterator(handle); + return it->Valid(); } +/* + * Class: org_rocksdb_Iterator + * Method: close0 + * Signature: (J)V + */ void Java_org_rocksdb_Iterator_seekToFirst0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - st->SeekToFirst(); + auto it = rocksdb::IteratorJni::getIterator(handle); + it->SeekToFirst(); } +/* + * Class: org_rocksdb_Iterator + * Method: seekToFirst0 + * Signature: (J)V + */ void Java_org_rocksdb_Iterator_seekToLast0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - st->SeekToLast(); + auto it = rocksdb::IteratorJni::getIterator(handle); + it->SeekToLast(); } +/* + * Class: org_rocksdb_Iterator + * Method: seekToLast0 + * Signature: (J)V + */ void Java_org_rocksdb_Iterator_next0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - st->Next(); + auto it = rocksdb::IteratorJni::getIterator(handle); + it->Next(); } +/* + * Class: org_rocksdb_Iterator + * Method: next0 + * Signature: (J)V + */ void Java_org_rocksdb_Iterator_prev0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - st->Prev(); + auto it = rocksdb::IteratorJni::getIterator(handle); + it->Prev(); } +/* + * Class: org_rocksdb_Iterator + * Method: prev0 + * Signature: (J)V + */ jbyteArray Java_org_rocksdb_Iterator_key0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - rocksdb::Slice key_slice = st->key(); - + auto it = rocksdb::IteratorJni::getIterator(handle); + rocksdb::Slice key_slice = it->key(); + jbyteArray jkey = env->NewByteArray(key_slice.size()); env->SetByteArrayRegion( jkey, 0, key_slice.size(), @@ -68,13 +86,16 @@ jbyteArray Java_org_rocksdb_Iterator_key0( return jkey; } +/* + * Class: org_rocksdb_Iterator + * Method: key0 + * Signature: (J)[B + */ jbyteArray Java_org_rocksdb_Iterator_value0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - rocksdb::Slice value_slice = st->value(); - + auto it = rocksdb::IteratorJni::getIterator(handle); + rocksdb::Slice value_slice = it->value(); + jbyteArray jvalue = env->NewByteArray(value_slice.size()); env->SetByteArrayRegion( jvalue, 0, value_slice.size(), @@ -82,41 +103,50 @@ jbyteArray Java_org_rocksdb_Iterator_value0( return jvalue; } +/* + * Class: org_rocksdb_Iterator + * Method: value0 + * Signature: (J)[B + */ void Java_org_rocksdb_Iterator_seek0( JNIEnv* env, jobject jobj, jlong handle, jbyteArray jtarget, jint jtarget_len) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - + auto it = rocksdb::IteratorJni::getIterator(handle); jbyte* target = env->GetByteArrayElements(jtarget, 0); rocksdb::Slice target_slice( reinterpret_cast(target), jtarget_len); - - st->Seek(target_slice); - + + it->Seek(target_slice); + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); } +/* + * Class: org_rocksdb_Iterator + * Method: seek0 + * Signature: (J[BI)V + */ void Java_org_rocksdb_Iterator_status0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - rocksdb::Status s = st->status(); - + auto it = rocksdb::IteratorJni::getIterator(handle); + rocksdb::Status s = it->status(); + if (s.ok()) { return; } - + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); } +/* + * Class: org_rocksdb_Iterator + * Method: status0 + * Signature: (J)V + */ void Java_org_rocksdb_Iterator_close0( JNIEnv* env, jobject jobj, jlong handle) { - auto st = reinterpret_cast(handle); - assert(st != nullptr); - - delete st; - + auto it = rocksdb::IteratorJni::getIterator(handle); + delete it; + rocksdb::IteratorJni::setHandle(env, jobj, nullptr); -} \ No newline at end of file +} diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index 32e033aaf..f6eabe2f1 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -245,6 +245,14 @@ class IteratorJni { jobj, getHandleFieldID(env), reinterpret_cast(op)); } + + // Cast long to rocksdb::Iterator pointer. + static rocksdb::Iterator* getIterator(jlong handle) { + auto it = reinterpret_cast(handle); + assert(it != nullptr); + + return it; + } }; } // namespace rocksdb #endif // JAVA_ROCKSJNI_PORTAL_H_ diff --git a/java/rocksjni/rocksjni.cc b/java/rocksjni/rocksjni.cc index 4e4093294..877ba063b 100644 --- a/java/rocksjni/rocksjni.cc +++ b/java/rocksjni/rocksjni.cc @@ -302,4 +302,4 @@ jlong Java_org_rocksdb_RocksDB_iterator0( auto db = reinterpret_cast(db_handle); rocksdb::Iterator* iterator = db->NewIterator(rocksdb::ReadOptions()); return reinterpret_cast(iterator); -} \ No newline at end of file +} From 06b590dd7c9befb8172144c7fab884c6639deda5 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 13:13:01 -0700 Subject: [PATCH 5/7] Add doc --- java/RocksDBSample.java | 2 +- java/org/rocksdb/Iterator.java | 65 ++++++++++++++++++++++++++++++++-- java/org/rocksdb/RocksDB.java | 10 +++++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index aa05b7887..d33428a50 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -142,7 +142,7 @@ public class RocksDBSample { assert(false); //Should never reach here. } - Iterator iterator = db.iterator(); + Iterator iterator = db.newIterator(); boolean seekToFirstPassed = false; for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) { diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java index 6069f27b0..eddf8cc49 100644 --- a/java/org/rocksdb/Iterator.java +++ b/java/org/rocksdb/Iterator.java @@ -5,6 +5,17 @@ package org.rocksdb; +/** + * An iterator yields a sequence of key/value pairs from a source. + * The following class defines the interface. Multiple implementations + * are provided by this library. In particular, iterators are provided + * to access the contents of a Table or a DB. + * + * Multiple threads can invoke const methods on an Iterator without + * external synchronization, but if any of the threads may call a + * non-const method, all threads accessing the same Iterator must use + * external synchronization. + */ public class Iterator { private long nativeHandle_; @@ -12,51 +23,101 @@ public class Iterator { nativeHandle_ = nativeHandle; } + /** + * An iterator is either positioned at a key/value pair, or + * not valid. This method returns true iff the iterator is valid. + * @return true if iterator is valid. + */ public boolean isValid() { assert(isInitialized()); return isValid0(nativeHandle_); } + /** + * Position at the first key in the source. The iterator is Valid() + * after this call iff the source is not empty. + */ public void seekToFirst() { assert(isInitialized()); seekToFirst0(nativeHandle_); } + /** + * Position at the last key in the source. The iterator is + * Valid() after this call iff the source is not empty. + */ public void seekToLast() { assert(isInitialized()); seekToLast0(nativeHandle_); } - + + /** + * Moves to the next entry in the source. After this call, Valid() is + * true iff the iterator was not positioned at the last entry in the source. + * REQUIRES: Valid() + */ public void next() { assert(isInitialized()); next0(nativeHandle_); } - + + /** + * Moves to the previous entry in the source. After this call, Valid() is + * true iff the iterator was not positioned at the first entry in source. + * REQUIRES: Valid() + */ public void prev() { assert(isInitialized()); prev0(nativeHandle_); } + /** + * Return the key for the current entry. The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * REQUIRES: Valid() + * @return key for the current entry. + */ public byte[] key() { assert(isInitialized()); return key0(nativeHandle_); } + /** + * Return the value for the current entry. The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * REQUIRES: !AtEnd() && !AtStart() + * @return value for the current entry. + */ public byte[] value() { assert(isInitialized()); return value0(nativeHandle_); } + /** + * Position at the first key in the source that at or past target + * The iterator is Valid() after this call iff the source contains + * an entry that comes at or past target. + */ public void seek(byte[] target) { assert(isInitialized()); seek0(nativeHandle_, target, target.length); } + /** + * If an error has occurred, return it. Else return an ok status. + * If non-blocking IO is requested and this operation cannot be + * satisfied without doing some IO, then this returns Status::Incomplete(). + */ public void status(){ assert(isInitialized()); status0(nativeHandle_); } + /** + * Deletes underlying C++ iterator pointer. + */ public synchronized void close() { if(nativeHandle_ != 0) { close0(nativeHandle_); diff --git a/java/org/rocksdb/RocksDB.java b/java/org/rocksdb/RocksDB.java index bbfc18f4c..b43764f8f 100644 --- a/java/org/rocksdb/RocksDB.java +++ b/java/org/rocksdb/RocksDB.java @@ -136,7 +136,15 @@ public class RocksDB { remove(nativeHandle_, writeOpt.nativeHandle_, key, key.length); } - public Iterator iterator() { + /** + * Return a heap-allocated iterator over the contents of the database. + * The result of newIterator() is initially invalid (caller must + * call one of the Seek methods on the iterator before using it). + * + * Caller should close the iterator when it is no longer needed. + * The returned iterator should be closed before this db is closed. + */ + public Iterator newIterator() { return new Iterator(iterator0(nativeHandle_)); } From 1574e0c41accaf854395a5c3a910b490beb2a417 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 13:21:06 -0700 Subject: [PATCH 6/7] Add doc --- java/org/rocksdb/Iterator.java | 27 ++++++++++++++------------- java/org/rocksdb/RocksDB.java | 4 +++- java/rocksjni/iterator.cc | 12 ++++++------ java/rocksjni/portal.h | 4 ++-- java/rocksjni/rocksjni.cc | 5 +++++ 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/java/org/rocksdb/Iterator.java b/java/org/rocksdb/Iterator.java index eddf8cc49..c34deab35 100644 --- a/java/org/rocksdb/Iterator.java +++ b/java/org/rocksdb/Iterator.java @@ -8,12 +8,12 @@ package org.rocksdb; /** * An iterator yields a sequence of key/value pairs from a source. * The following class defines the interface. Multiple implementations - * are provided by this library. In particular, iterators are provided + * are provided by this library. In particular, iterators are provided * to access the contents of a Table or a DB. - * - * Multiple threads can invoke const methods on an Iterator without + * + * Multiple threads can invoke const methods on an Iterator without * external synchronization, but if any of the threads may call a - * non-const method, all threads accessing the same Iterator must use + * non-const method, all threads accessing the same Iterator must use * external synchronization. */ public class Iterator { @@ -50,7 +50,7 @@ public class Iterator { assert(isInitialized()); seekToLast0(nativeHandle_); } - + /** * Moves to the next entry in the source. After this call, Valid() is * true iff the iterator was not positioned at the last entry in the source. @@ -60,7 +60,7 @@ public class Iterator { assert(isInitialized()); next0(nativeHandle_); } - + /** * Moves to the previous entry in the source. After this call, Valid() is * true iff the iterator was not positioned at the first entry in source. @@ -73,7 +73,7 @@ public class Iterator { /** * Return the key for the current entry. The underlying storage for - * the returned slice is valid only until the next modification of + * the returned slice is valid only until the next modification of * the iterator. * REQUIRES: Valid() * @return key for the current entry. @@ -84,9 +84,9 @@ public class Iterator { } /** - * Return the value for the current entry. The underlying storage for - * the returned slice is valid only until the next modification of - * the iterator. + * Return the value for the current entry. The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. * REQUIRES: !AtEnd() && !AtStart() * @return value for the current entry. */ @@ -106,11 +106,12 @@ public class Iterator { } /** - * If an error has occurred, return it. Else return an ok status. - * If non-blocking IO is requested and this operation cannot be + * If an error has occurred, return it. Else return an ok status. + * If non-blocking IO is requested and this operation cannot be * satisfied without doing some IO, then this returns Status::Incomplete(). + * */ - public void status(){ + public void status() throws RocksDBException { assert(isInitialized()); status0(nativeHandle_); } diff --git a/java/org/rocksdb/RocksDB.java b/java/org/rocksdb/RocksDB.java index b43764f8f..38426d50c 100644 --- a/java/org/rocksdb/RocksDB.java +++ b/java/org/rocksdb/RocksDB.java @@ -140,9 +140,11 @@ public class RocksDB { * Return a heap-allocated iterator over the contents of the database. * The result of newIterator() is initially invalid (caller must * call one of the Seek methods on the iterator before using it). - * + * * Caller should close the iterator when it is no longer needed. * The returned iterator should be closed before this db is closed. + * + * @return instance of iterator object. */ public Iterator newIterator() { return new Iterator(iterator0(nativeHandle_)); diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc index 378e013e0..7b83991c7 100644 --- a/java/rocksjni/iterator.cc +++ b/java/rocksjni/iterator.cc @@ -80,9 +80,9 @@ jbyteArray Java_org_rocksdb_Iterator_key0( rocksdb::Slice key_slice = it->key(); jbyteArray jkey = env->NewByteArray(key_slice.size()); - env->SetByteArrayRegion( - jkey, 0, key_slice.size(), - reinterpret_cast(key_slice.data())); + env->SetByteArrayRegion( + jkey, 0, key_slice.size(), + reinterpret_cast(key_slice.data())); return jkey; } @@ -97,9 +97,9 @@ jbyteArray Java_org_rocksdb_Iterator_value0( rocksdb::Slice value_slice = it->value(); jbyteArray jvalue = env->NewByteArray(value_slice.size()); - env->SetByteArrayRegion( - jvalue, 0, value_slice.size(), - reinterpret_cast(value_slice.data())); + env->SetByteArrayRegion( + jvalue, 0, value_slice.size(), + reinterpret_cast(value_slice.data())); return jvalue; } diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index f6eabe2f1..fea01bcc5 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -224,7 +224,7 @@ class IteratorJni { } // Get the field id of the member variable of org.rocksdb.Iterator - // that stores the pointer to rocksdb::Iterator + // that stores the pointer to rocksdb::Iterator. static jfieldID getHandleFieldID(JNIEnv* env) { static jfieldID fid = env->GetFieldID( getJClass(env), "nativeHandle_", "J"); @@ -232,7 +232,7 @@ class IteratorJni { return fid; } - // Get the pointer to rocksdb::Iterator + // Get the pointer to rocksdb::Iterator. static rocksdb::Iterator* getHandle(JNIEnv* env, jobject jobj) { return reinterpret_cast( env->GetLongField(jobj, getHandleFieldID(env))); diff --git a/java/rocksjni/rocksjni.cc b/java/rocksjni/rocksjni.cc index 877ba063b..f3f9c831b 100644 --- a/java/rocksjni/rocksjni.cc +++ b/java/rocksjni/rocksjni.cc @@ -297,6 +297,11 @@ void Java_org_rocksdb_RocksDB_close0( rocksdb::RocksDBJni::setHandle(env, java_db, nullptr); } +/* + * Class: org_rocksdb_RocksDB + * Method: iterator0 + * Signature: (J)J + */ jlong Java_org_rocksdb_RocksDB_iterator0( JNIEnv* env, jobject jdb, jlong db_handle) { auto db = reinterpret_cast(db_handle); From bbdd550b662b408cf3c4360d0b17a437150a074f Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Sat, 19 Apr 2014 23:17:42 -0700 Subject: [PATCH 7/7] Remove getIterator function from portal --- java/rocksjni/iterator.cc | 25 ++++++++++--------------- java/rocksjni/portal.h | 8 -------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/java/rocksjni/iterator.cc b/java/rocksjni/iterator.cc index 7b83991c7..f23ca1d87 100644 --- a/java/rocksjni/iterator.cc +++ b/java/rocksjni/iterator.cc @@ -21,8 +21,7 @@ */ jboolean Java_org_rocksdb_Iterator_isValid0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); - return it->Valid(); + return reinterpret_cast(handle)->Valid(); } /* @@ -32,8 +31,7 @@ jboolean Java_org_rocksdb_Iterator_isValid0( */ void Java_org_rocksdb_Iterator_seekToFirst0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); - it->SeekToFirst(); + reinterpret_cast(handle)->SeekToFirst(); } /* @@ -43,8 +41,7 @@ void Java_org_rocksdb_Iterator_seekToFirst0( */ void Java_org_rocksdb_Iterator_seekToLast0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); - it->SeekToLast(); + reinterpret_cast(handle)->SeekToLast(); } /* @@ -54,8 +51,7 @@ void Java_org_rocksdb_Iterator_seekToLast0( */ void Java_org_rocksdb_Iterator_next0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); - it->Next(); + reinterpret_cast(handle)->Next(); } /* @@ -65,8 +61,7 @@ void Java_org_rocksdb_Iterator_next0( */ void Java_org_rocksdb_Iterator_prev0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); - it->Prev(); + reinterpret_cast(handle)->Prev(); } /* @@ -76,7 +71,7 @@ void Java_org_rocksdb_Iterator_prev0( */ jbyteArray Java_org_rocksdb_Iterator_key0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); + auto it = reinterpret_cast(handle); rocksdb::Slice key_slice = it->key(); jbyteArray jkey = env->NewByteArray(key_slice.size()); @@ -93,7 +88,7 @@ jbyteArray Java_org_rocksdb_Iterator_key0( */ jbyteArray Java_org_rocksdb_Iterator_value0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); + auto it = reinterpret_cast(handle); rocksdb::Slice value_slice = it->value(); jbyteArray jvalue = env->NewByteArray(value_slice.size()); @@ -111,7 +106,7 @@ jbyteArray Java_org_rocksdb_Iterator_value0( void Java_org_rocksdb_Iterator_seek0( JNIEnv* env, jobject jobj, jlong handle, jbyteArray jtarget, jint jtarget_len) { - auto it = rocksdb::IteratorJni::getIterator(handle); + auto it = reinterpret_cast(handle); jbyte* target = env->GetByteArrayElements(jtarget, 0); rocksdb::Slice target_slice( reinterpret_cast(target), jtarget_len); @@ -128,7 +123,7 @@ void Java_org_rocksdb_Iterator_seek0( */ void Java_org_rocksdb_Iterator_status0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); + auto it = reinterpret_cast(handle); rocksdb::Status s = it->status(); if (s.ok()) { @@ -145,7 +140,7 @@ void Java_org_rocksdb_Iterator_status0( */ void Java_org_rocksdb_Iterator_close0( JNIEnv* env, jobject jobj, jlong handle) { - auto it = rocksdb::IteratorJni::getIterator(handle); + auto it = reinterpret_cast(handle); delete it; rocksdb::IteratorJni::setHandle(env, jobj, nullptr); diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index fea01bcc5..a4e2dc21a 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -245,14 +245,6 @@ class IteratorJni { jobj, getHandleFieldID(env), reinterpret_cast(op)); } - - // Cast long to rocksdb::Iterator pointer. - static rocksdb::Iterator* getIterator(jlong handle) { - auto it = reinterpret_cast(handle); - assert(it != nullptr); - - return it; - } }; } // namespace rocksdb #endif // JAVA_ROCKSJNI_PORTAL_H_