From 22d88e24db012639eeafcaa7fa26ab01eb56f952 Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Mon, 12 Sep 2016 19:51:08 +0100 Subject: [PATCH] Allow an offset as well as a length to be specified for byte[] operations in RocksJava JNI (#1264) Test Plan: Execute the Java test suite Reviewers: yhchiang Subscribers: andrewkr, dhruba Differential Revision: https://reviews.facebook.net/D61971 --- java/rocksjni/rocksjni.cc | 405 ++++++++++---------- java/src/main/java/org/rocksdb/RocksDB.java | 267 +++++++------ 2 files changed, 359 insertions(+), 313 deletions(-) diff --git a/java/rocksjni/rocksjni.cc b/java/rocksjni/rocksjni.cc index e77452e61..4561f6801 100644 --- a/java/rocksjni/rocksjni.cc +++ b/java/rocksjni/rocksjni.cc @@ -206,14 +206,18 @@ jobjectArray Java_org_rocksdb_RocksDB_listColumnFamilies( void rocksdb_put_helper( JNIEnv* env, rocksdb::DB* db, const rocksdb::WriteOptions& write_options, - rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len, jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { + + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + + jbyte* value = new jbyte[jvalue_len]; + env->GetByteArrayRegion(jvalue, jvalue_off, jvalue_len, value); - jbyte* key = env->GetByteArrayElements(jkey, 0); - jbyte* value = env->GetByteArrayElements(jentry_value, 0); rocksdb::Slice key_slice(reinterpret_cast(key), jkey_len); rocksdb::Slice value_slice(reinterpret_cast(value), - jentry_value_len); + jvalue_len); rocksdb::Status s; if (cf_handle != nullptr) { @@ -223,11 +227,9 @@ void rocksdb_put_helper( s = db->Put(write_options, key_slice, value_slice); } - // trigger java unref on key and value. - // by passing JNI_ABORT, it will simply release the reference without - // copying the result back to the java byte array. - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); - env->ReleaseByteArrayElements(jentry_value, value, JNI_ABORT); + // cleanup + delete [] value; + delete [] key; if (s.ok()) { return; @@ -238,36 +240,37 @@ void rocksdb_put_helper( /* * Class: org_rocksdb_RocksDB * Method: put - * Signature: (J[BI[BI)V + * Signature: (J[BII[BII)V */ -void Java_org_rocksdb_RocksDB_put__J_3BI_3BI( +void Java_org_rocksdb_RocksDB_put__J_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); rocksdb_put_helper(env, db, default_write_options, nullptr, - jkey, jkey_len, - jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, + jvalue, jvalue_off, jvalue_len); } + /* * Class: org_rocksdb_RocksDB * Method: put - * Signature: (J[BI[BIJ)V + * Signature: (J[BII[BIIJ)V */ -void Java_org_rocksdb_RocksDB_put__J_3BI_3BIJ( +void Java_org_rocksdb_RocksDB_put__J_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { rocksdb_put_helper(env, db, default_write_options, cf_handle, - jkey, jkey_len, jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -277,39 +280,39 @@ void Java_org_rocksdb_RocksDB_put__J_3BI_3BIJ( /* * Class: org_rocksdb_RocksDB * Method: put - * Signature: (JJ[BI[BI)V + * Signature: (JJ[BII[BII)V */ -void Java_org_rocksdb_RocksDB_put__JJ_3BI_3BI( +void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast( jwrite_options_handle); rocksdb_put_helper(env, db, *write_options, nullptr, - jkey, jkey_len, - jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, + jvalue, jvalue_off, jvalue_len); } /* * Class: org_rocksdb_RocksDB * Method: put - * Signature: (JJ[BI[BIJ)V + * Signature: (JJ[BII[BIIJ)V */ -void Java_org_rocksdb_RocksDB_put__JJ_3BI_3BIJ( +void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast( jwrite_options_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { rocksdb_put_helper(env, db, *write_options, cf_handle, - jkey, jkey_len, jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -363,12 +366,12 @@ void Java_org_rocksdb_RocksDB_write1( // rocksdb::DB::KeyMayExist jboolean key_may_exist_helper(JNIEnv* env, rocksdb::DB* db, const rocksdb::ReadOptions& read_opt, - rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_len, - jobject jstring_buffer) { + rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len, jobject jstring_buffer) { std::string value; bool value_found = false; - jboolean isCopy; - jbyte* key = env->GetByteArrayElements(jkey, &isCopy); + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); rocksdb::Slice key_slice(reinterpret_cast(key), jkey_len); bool keyMayExist; if (cf_handle != nullptr) { @@ -379,6 +382,10 @@ jboolean key_may_exist_helper(JNIEnv* env, rocksdb::DB* db, &value, &value_found); } + // cleanup + delete [] key; + + // extract the value if (value_found && !value.empty()) { jclass clazz = env->GetObjectClass(jstring_buffer); jmethodID mid = env->GetMethodID(clazz, "append", @@ -386,37 +393,36 @@ jboolean key_may_exist_helper(JNIEnv* env, rocksdb::DB* db, jstring new_value_str = env->NewStringUTF(value.c_str()); env->CallObjectMethod(jstring_buffer, mid, new_value_str); } - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); return static_cast(keyMayExist); } /* * Class: org_rocksdb_RocksDB * Method: keyMayExist - * Signature: (J[BILjava/lang/StringBuffer;)Z + * Signature: (J[BIILjava/lang/StringBuffer;)Z */ -jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BILjava_lang_StringBuffer_2( - JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jkey, jint jkey_len, - jobject jstring_buffer) { +jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BIILjava_lang_StringBuffer_2( + JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len, jobject jstring_buffer) { auto* db = reinterpret_cast(jdb_handle); return key_may_exist_helper(env, db, rocksdb::ReadOptions(), - nullptr, jkey, jkey_len, jstring_buffer); + nullptr, jkey, jkey_off, jkey_len, jstring_buffer); } /* * Class: org_rocksdb_RocksDB * Method: keyMayExist - * Signature: (J[BIJLjava/lang/StringBuffer;)Z + * Signature: (J[BIIJLjava/lang/StringBuffer;)Z */ -jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BIJLjava_lang_StringBuffer_2( - JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jkey, jint jkey_len, - jlong jcf_handle, jobject jstring_buffer) { +jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BIIJLjava_lang_StringBuffer_2( + JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len, jlong jcf_handle, jobject jstring_buffer) { auto* db = reinterpret_cast(jdb_handle); auto* cf_handle = reinterpret_cast( jcf_handle); if (cf_handle != nullptr) { return key_may_exist_helper(env, db, rocksdb::ReadOptions(), - cf_handle, jkey, jkey_len, jstring_buffer); + cf_handle, jkey, jkey_off, jkey_len, jstring_buffer); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -427,26 +433,27 @@ jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BIJLjava_lang_StringBuffer_2( /* * Class: org_rocksdb_RocksDB * Method: keyMayExist - * Signature: (JJ[BILjava/lang/StringBuffer;)Z + * Signature: (JJ[BIILjava/lang/StringBuffer;)Z */ -jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BILjava_lang_StringBuffer_2( +jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIILjava_lang_StringBuffer_2( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jread_options_handle, - jbyteArray jkey, jint jkey_len, jobject jstring_buffer) { + jbyteArray jkey, jint jkey_off, jint jkey_len, jobject jstring_buffer) { auto* db = reinterpret_cast(jdb_handle); auto& read_options = *reinterpret_cast( jread_options_handle); return key_may_exist_helper(env, db, read_options, - nullptr, jkey, jkey_len, jstring_buffer); + nullptr, jkey, jkey_off, jkey_len, jstring_buffer); } /* * Class: org_rocksdb_RocksDB * Method: keyMayExist - * Signature: (JJ[BIJLjava/lang/StringBuffer;)Z + * Signature: (JJ[BIIJLjava/lang/StringBuffer;)Z */ -jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIJLjava_lang_StringBuffer_2( +jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIIJLjava_lang_StringBuffer_2( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jread_options_handle, - jbyteArray jkey, jint jkey_len, jlong jcf_handle, jobject jstring_buffer) { + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle, + jobject jstring_buffer) { auto* db = reinterpret_cast(jdb_handle); auto& read_options = *reinterpret_cast( jread_options_handle); @@ -454,7 +461,7 @@ jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIJLjava_lang_StringBuffer_2( jcf_handle); if (cf_handle != nullptr) { return key_may_exist_helper(env, db, read_options, cf_handle, - jkey, jkey_len, jstring_buffer); + jkey, jkey_off, jkey_len, jstring_buffer); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -468,9 +475,10 @@ jboolean Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIJLjava_lang_StringBuffer_2( jbyteArray rocksdb_get_helper( JNIEnv* env, rocksdb::DB* db, const rocksdb::ReadOptions& read_opt, rocksdb::ColumnFamilyHandle* column_family_handle, jbyteArray jkey, - jint jkey_len) { - jboolean isCopy; - jbyte* key = env->GetByteArrayElements(jkey, &isCopy); + jint jkey_off, jint jkey_len) { + + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); rocksdb::Slice key_slice( reinterpret_cast(key), jkey_len); @@ -483,10 +491,8 @@ jbyteArray rocksdb_get_helper( s = db->Get(read_opt, key_slice, &value); } - // trigger java unref on key. - // by passing JNI_ABORT, it will simply release the reference without - // copying the result back to the java byte array. - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + // cleanup + delete [] key; if (s.IsNotFound()) { return nullptr; @@ -506,30 +512,30 @@ jbyteArray rocksdb_get_helper( /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (J[BI)[B + * Signature: (J[BII)[B */ -jbyteArray Java_org_rocksdb_RocksDB_get__J_3BI( +jbyteArray Java_org_rocksdb_RocksDB_get__J_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len) { return rocksdb_get_helper(env, reinterpret_cast(jdb_handle), rocksdb::ReadOptions(), nullptr, - jkey, jkey_len); + jkey, jkey_off, jkey_len); } /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (J[BIJ)[B + * Signature: (J[BIIJ)[B */ -jbyteArray Java_org_rocksdb_RocksDB_get__J_3BIJ( +jbyteArray Java_org_rocksdb_RocksDB_get__J_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { auto db_handle = reinterpret_cast(jdb_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { return rocksdb_get_helper(env, db_handle, rocksdb::ReadOptions(), - cf_handle, jkey, jkey_len); + cf_handle, jkey, jkey_off, jkey_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -541,31 +547,31 @@ jbyteArray Java_org_rocksdb_RocksDB_get__J_3BIJ( /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (JJ[BI)[B + * Signature: (JJ[BII)[B */ -jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BI( +jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jbyteArray jkey, jint jkey_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len) { return rocksdb_get_helper(env, reinterpret_cast(jdb_handle), *reinterpret_cast(jropt_handle), nullptr, - jkey, jkey_len); + jkey, jkey_off, jkey_len); } /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (JJ[BIJ)[B + * Signature: (JJ[BIIJ)[B */ -jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BIJ( +jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { auto db_handle = reinterpret_cast(jdb_handle); auto& ro_opt = *reinterpret_cast(jropt_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { return rocksdb_get_helper(env, db_handle, ro_opt, cf_handle, - jkey, jkey_len); + jkey, jkey_off, jkey_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -577,11 +583,13 @@ jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BIJ( jint rocksdb_get_helper( JNIEnv* env, rocksdb::DB* db, const rocksdb::ReadOptions& read_options, rocksdb::ColumnFamilyHandle* column_family_handle, jbyteArray jkey, - jint jkey_len, jbyteArray jentry_value, jint jentry_value_len) { + jint jkey_off, jint jkey_len, jbyteArray jvalue, jint jvalue_off, + jint jvalue_len) { static const int kNotFound = -1; static const int kStatusError = -2; - jbyte* key = env->GetByteArrayElements(jkey, 0); + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); rocksdb::Slice key_slice( reinterpret_cast(key), jkey_len); @@ -596,10 +604,8 @@ jint rocksdb_get_helper( s = db->Get(read_options, key_slice, &cvalue); } - // trigger java unref on key. - // by passing JNI_ABORT, it will simply release the reference without - // copying the result back to the java byte array. - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + // cleanup + delete [] key; if (s.IsNotFound()) { return kNotFound; @@ -617,10 +623,10 @@ jint rocksdb_get_helper( } jint cvalue_len = static_cast(cvalue.size()); - jint length = std::min(jentry_value_len, cvalue_len); + jint length = std::min(jvalue_len, cvalue_len); env->SetByteArrayRegion( - jentry_value, 0, length, + jvalue, jvalue_off, length, reinterpret_cast(cvalue.c_str())); return cvalue_len; } @@ -628,6 +634,7 @@ jint rocksdb_get_helper( // cf multi get jobjectArray multi_get_helper(JNIEnv* env, jobject jdb, rocksdb::DB* db, const rocksdb::ReadOptions& rOpt, jobjectArray jkeys, + jintArray jkey_offs, jintArray jkey_lens, jlongArray jcolumn_family_handles) { std::vector cf_handles; if (jcolumn_family_handles != nullptr) { @@ -642,24 +649,35 @@ jobjectArray multi_get_helper(JNIEnv* env, jobject jdb, rocksdb::DB* db, } std::vector keys; - std::vector> keys_to_free; + std::vector> keys_to_free; jsize len_keys = env->GetArrayLength(jkeys); - if(env->EnsureLocalCapacity(len_keys) != 0) { + if (env->EnsureLocalCapacity(len_keys) != 0) { // out of memory return NULL; } + + jint* jkey_off = env->GetIntArrayElements(jkey_offs, NULL); + jint* jkey_len = env->GetIntArrayElements(jkey_lens, NULL); + for (int i = 0; i < len_keys; i++) { - jobject jk = env->GetObjectArrayElement(jkeys, i); - jbyteArray jk_ba = reinterpret_cast(jk); - jsize len_key = env->GetArrayLength(jk_ba); - jbyte* jk_val = env->GetByteArrayElements(jk_ba, NULL); + jobject jkey = env->GetObjectArrayElement(jkeys, i); + + jbyteArray jkey_ba = reinterpret_cast(jkey); - rocksdb::Slice key_slice(reinterpret_cast(jk_val), len_key); + jint len_key = jkey_len[i]; + jbyte* key = new jbyte[len_key]; + env->GetByteArrayRegion(jkey_ba, jkey_off[i], len_key, key); + + rocksdb::Slice key_slice(reinterpret_cast(key), len_key); keys.push_back(key_slice); - keys_to_free.push_back(std::make_tuple(jk_ba, jk_val, jk)); + keys_to_free.push_back(std::pair(key, jkey)); } + // cleanup jkey_off and jken_len + env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT); + env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT); + std::vector values; std::vector s; if (cf_handles.size() == 0) { @@ -669,15 +687,11 @@ jobjectArray multi_get_helper(JNIEnv* env, jobject jdb, rocksdb::DB* db, } // free up allocated byte arrays - for (std::vector>::size_type i = 0; - i < keys_to_free.size(); i++) { - jobject jk; - jbyteArray jk_ba; - jbyte* jk_val; - std::tie(jk_ba, jk_val, jk) = keys_to_free[i]; - env->ReleaseByteArrayElements(jk_ba, jk_val, JNI_ABORT); - env->DeleteLocalRef(jk); + for (auto it = keys_to_free.begin(); it != keys_to_free.end(); ++it) { + delete [] it->first; + env->DeleteLocalRef(it->second); } + keys_to_free.clear(); // prepare the results jclass jcls_ba = env->FindClass("[B"); @@ -703,80 +717,85 @@ jobjectArray multi_get_helper(JNIEnv* env, jobject jdb, rocksdb::DB* db, /* * Class: org_rocksdb_RocksDB * Method: multiGet - * Signature: (J[[B)[[B + * Signature: (J[[B[I[I)[[B */ -jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B( - JNIEnv* env, jobject jdb, jlong jdb_handle, jobjectArray jkeys) { +jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I( + JNIEnv* env, jobject jdb, jlong jdb_handle, jobjectArray jkeys, + jintArray jkey_offs, jintArray jkey_lens) { return multi_get_helper(env, jdb, reinterpret_cast(jdb_handle), - rocksdb::ReadOptions(), jkeys, nullptr); + rocksdb::ReadOptions(), jkeys, jkey_offs, jkey_lens, nullptr); } /* * Class: org_rocksdb_RocksDB * Method: multiGet - * Signature: (J[[B[J)[[B + * Signature: (J[[B[I[I[J)[[B */ -jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3J( +jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I_3J( JNIEnv* env, jobject jdb, jlong jdb_handle, jobjectArray jkeys, + jintArray jkey_offs, jintArray jkey_lens, jlongArray jcolumn_family_handles) { return multi_get_helper(env, jdb, reinterpret_cast(jdb_handle), - rocksdb::ReadOptions(), jkeys, jcolumn_family_handles); + rocksdb::ReadOptions(), jkeys, jkey_offs, jkey_lens, + jcolumn_family_handles); } /* * Class: org_rocksdb_RocksDB * Method: multiGet - * Signature: (JJ[[B)[[B + * Signature: (JJ[[B[I[I)[[B */ -jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B( +jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jobjectArray jkeys) { + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens) { return multi_get_helper(env, jdb, reinterpret_cast(jdb_handle), - *reinterpret_cast(jropt_handle), jkeys, nullptr); + *reinterpret_cast(jropt_handle), jkeys, jkey_offs, + jkey_lens, nullptr); } /* * Class: org_rocksdb_RocksDB * Method: multiGet - * Signature: (JJ[[B[J)[[B + * Signature: (JJ[[B[I[I[J)[[B */ -jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3J( +jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I_3J( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jobjectArray jkeys, jlongArray jcolumn_family_handles) { + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens, + jlongArray jcolumn_family_handles) { return multi_get_helper(env, jdb, reinterpret_cast(jdb_handle), - *reinterpret_cast(jropt_handle), jkeys, - jcolumn_family_handles); + *reinterpret_cast(jropt_handle), jkeys, jkey_offs, + jkey_lens, jcolumn_family_handles); } /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (J[BI[BI)I + * Signature: (J[BII[BII)I */ -jint Java_org_rocksdb_RocksDB_get__J_3BI_3BI( +jint Java_org_rocksdb_RocksDB_get__J_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { return rocksdb_get_helper(env, reinterpret_cast(jdb_handle), rocksdb::ReadOptions(), nullptr, - jkey, jkey_len, jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (J[BI[BIJ)I + * Signature: (J[BII[BIIJ)I */ -jint Java_org_rocksdb_RocksDB_get__J_3BI_3BIJ( +jint Java_org_rocksdb_RocksDB_get__J_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db_handle = reinterpret_cast(jdb_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { return rocksdb_get_helper(env, db_handle, rocksdb::ReadOptions(), cf_handle, - jkey, jkey_len, jentry_value, jentry_value_len); + jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -788,33 +807,33 @@ jint Java_org_rocksdb_RocksDB_get__J_3BI_3BIJ( /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (JJ[BI[BI)I + * Signature: (JJ[BII[BII)I */ -jint Java_org_rocksdb_RocksDB_get__JJ_3BI_3BI( +jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { return rocksdb_get_helper(env, reinterpret_cast(jdb_handle), *reinterpret_cast(jropt_handle), - nullptr, jkey, jkey_len, jentry_value, jentry_value_len); + nullptr, jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } /* * Class: org_rocksdb_RocksDB * Method: get - * Signature: (JJ[BI[BIJ)I + * Signature: (JJ[BII[BIIJ)I */ -jint Java_org_rocksdb_RocksDB_get__JJ_3BI_3BIJ( +jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db_handle = reinterpret_cast(jdb_handle); auto& ro_opt = *reinterpret_cast(jropt_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { return rocksdb_get_helper(env, db_handle, ro_opt, cf_handle, jkey, - jkey_len, jentry_value, jentry_value_len); + jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -826,8 +845,10 @@ jint Java_org_rocksdb_RocksDB_get__JJ_3BI_3BIJ( // rocksdb::DB::Delete() void rocksdb_delete_helper( JNIEnv* env, rocksdb::DB* db, const rocksdb::WriteOptions& write_options, - rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_len) { - jbyte* key = env->GetByteArrayElements(jkey, 0); + rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); rocksdb::Slice key_slice(reinterpret_cast(key), jkey_len); rocksdb::Status s; @@ -837,10 +858,9 @@ void rocksdb_delete_helper( // backwards compatibility s = db->Delete(write_options, key_slice); } - // trigger java unref on key and value. - // by passing JNI_ABORT, it will simply release the reference without - // copying the result back to the java byte array. - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + // cleanup + delete [] key; if (!s.ok()) { rocksdb::RocksDBExceptionJni::ThrowNew(env, s); @@ -851,33 +871,33 @@ void rocksdb_delete_helper( /* * Class: org_rocksdb_RocksDB * Method: delete - * Signature: (J[BI)V + * Signature: (J[BII)V */ -void Java_org_rocksdb_RocksDB_delete__J_3BI( +void Java_org_rocksdb_RocksDB_delete__J_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); rocksdb_delete_helper(env, db, default_write_options, nullptr, - jkey, jkey_len); + jkey, jkey_off, jkey_len); } /* * Class: org_rocksdb_RocksDB * Method: delete - * Signature: (J[BIJ)V + * Signature: (J[BIIJ)V */ -void Java_org_rocksdb_RocksDB_delete__J_3BIJ( +void Java_org_rocksdb_RocksDB_delete__J_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { rocksdb_delete_helper(env, db, default_write_options, cf_handle, - jkey, jkey_len); + jkey, jkey_off, jkey_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -887,30 +907,32 @@ void Java_org_rocksdb_RocksDB_delete__J_3BIJ( /* * Class: org_rocksdb_RocksDB * Method: delete - * Signature: (JJ[BIJ)V + * Signature: (JJ[BII)V */ -void Java_org_rocksdb_RocksDB_delete__JJ_3BI( +void Java_org_rocksdb_RocksDB_delete__JJ_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jlong jwrite_options, jbyteArray jkey, jint jkey_len) { + jlong jwrite_options, jbyteArray jkey, jint jkey_off, jint jkey_len) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast(jwrite_options); - rocksdb_delete_helper(env, db, *write_options, nullptr, jkey, jkey_len); + rocksdb_delete_helper(env, db, *write_options, nullptr, jkey, jkey_off, + jkey_len); } /* * Class: org_rocksdb_RocksDB * Method: delete - * Signature: (JJ[BIJ)V + * Signature: (JJ[BIIJ)V */ -void Java_org_rocksdb_RocksDB_delete__JJ_3BIJ( +void Java_org_rocksdb_RocksDB_delete__JJ_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jlong jwrite_options, jbyteArray jkey, jint jkey_len, + jlong jwrite_options, jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast(jwrite_options); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { - rocksdb_delete_helper(env, db, *write_options, cf_handle, jkey, jkey_len); + rocksdb_delete_helper(env, db, *write_options, cf_handle, jkey, jkey_off, + jkey_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -1018,14 +1040,15 @@ void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BIJ( void rocksdb_merge_helper( JNIEnv* env, rocksdb::DB* db, const rocksdb::WriteOptions& write_options, - rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { - - jbyte* key = env->GetByteArrayElements(jkey, 0); - jbyte* value = env->GetByteArrayElements(jentry_value, 0); + rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, jint jkey_off, + jint jkey_len, jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + jbyte* value = new jbyte[jkey_len]; + env->GetByteArrayRegion(jvalue, jvalue_off, jvalue_len, value); rocksdb::Slice key_slice(reinterpret_cast(key), jkey_len); rocksdb::Slice value_slice(reinterpret_cast(value), - jentry_value_len); + jvalue_len); rocksdb::Status s; if (cf_handle != nullptr) { @@ -1034,11 +1057,9 @@ void rocksdb_merge_helper( s = db->Merge(write_options, key_slice, value_slice); } - // trigger java unref on key and value. - // by passing JNI_ABORT, it will simply release the reference without - // copying the result back to the java byte array. - env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); - env->ReleaseByteArrayElements(jentry_value, value, JNI_ABORT); + // cleanup + delete [] value; + delete [] key; if (s.ok()) { return; @@ -1049,36 +1070,36 @@ void rocksdb_merge_helper( /* * Class: org_rocksdb_RocksDB * Method: merge - * Signature: (J[BI[BI)V + * Signature: (J[BII[BII)V */ -void Java_org_rocksdb_RocksDB_merge__J_3BI_3BI( +void Java_org_rocksdb_RocksDB_merge__J_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); rocksdb_merge_helper(env, db, default_write_options, - nullptr, jkey, jkey_len, jentry_value, jentry_value_len); + nullptr, jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } /* * Class: org_rocksdb_RocksDB * Method: merge - * Signature: (J[BI[BIJ)V + * Signature: (J[BII[BIIJ)V */ -void Java_org_rocksdb_RocksDB_merge__J_3BI_3BIJ( +void Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); static const rocksdb::WriteOptions default_write_options = rocksdb::WriteOptions(); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { rocksdb_merge_helper(env, db, default_write_options, - cf_handle, jkey, jkey_len, jentry_value, jentry_value_len); + cf_handle, jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -1088,38 +1109,38 @@ void Java_org_rocksdb_RocksDB_merge__J_3BI_3BIJ( /* * Class: org_rocksdb_RocksDB * Method: merge - * Signature: (JJ[BI[BI)V + * Signature: (JJ[BII[BII)V */ -void Java_org_rocksdb_RocksDB_merge__JJ_3BI_3BI( +void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast( jwrite_options_handle); rocksdb_merge_helper(env, db, *write_options, - nullptr, jkey, jkey_len, jentry_value, jentry_value_len); + nullptr, jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } /* * Class: org_rocksdb_RocksDB * Method: merge - * Signature: (JJ[BI[BIJ)V + * Signature: (JJ[BII[BIIJ)V */ -void Java_org_rocksdb_RocksDB_merge__JJ_3BI_3BIJ( +void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ( JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options_handle, - jbyteArray jkey, jint jkey_len, - jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jvalue, jint jvalue_off, jint jvalue_len, jlong jcf_handle) { auto db = reinterpret_cast(jdb_handle); auto write_options = reinterpret_cast( jwrite_options_handle); auto cf_handle = reinterpret_cast(jcf_handle); if (cf_handle != nullptr) { rocksdb_merge_helper(env, db, *write_options, - cf_handle, jkey, jkey_len, jentry_value, jentry_value_len); + cf_handle, jkey, jkey_off, jkey_len, jvalue, jvalue_off, jvalue_len); } else { rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); @@ -1696,7 +1717,7 @@ void Java_org_rocksdb_RocksDB_setOptions(JNIEnv* env, jobject jdb, std::unordered_map options_map; const jsize len = env->GetArrayLength(jkeys); assert(len == env->GetArrayLength(jvalues)); - for(int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { jobject jobj_key = env->GetObjectArrayElement(jkeys, i); jobject jobj_value = env->GetObjectArrayElement(jvalues, i); jstring jkey = reinterpret_cast(jobj_key); diff --git a/java/src/main/java/org/rocksdb/RocksDB.java b/java/src/main/java/org/rocksdb/RocksDB.java index 2781043d4..b27c1c4fc 100644 --- a/java/src/main/java/org/rocksdb/RocksDB.java +++ b/java/src/main/java/org/rocksdb/RocksDB.java @@ -403,7 +403,7 @@ public class RocksDB extends RocksObject { */ public void put(final byte[] key, final byte[] value) throws RocksDBException { - put(nativeHandle_, key, key.length, value, value.length); + put(nativeHandle_, key, 0, key.length, value, 0, value.length); } /** @@ -422,7 +422,7 @@ public class RocksDB extends RocksObject { */ public void put(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value) throws RocksDBException { - put(nativeHandle_, key, key.length, value, value.length, + put(nativeHandle_, key, 0, key.length, value, 0, value.length, columnFamilyHandle.nativeHandle_); } @@ -439,7 +439,7 @@ public class RocksDB extends RocksObject { public void put(final WriteOptions writeOpts, final byte[] key, final byte[] value) throws RocksDBException { put(nativeHandle_, writeOpts.nativeHandle_, - key, key.length, value, value.length); + key, 0, key.length, value, 0, value.length); } /** @@ -461,8 +461,8 @@ public class RocksDB extends RocksObject { public void put(final ColumnFamilyHandle columnFamilyHandle, final WriteOptions writeOpts, final byte[] key, final byte[] value) throws RocksDBException { - put(nativeHandle_, writeOpts.nativeHandle_, key, key.length, value, - value.length, columnFamilyHandle.nativeHandle_); + put(nativeHandle_, writeOpts.nativeHandle_, key, 0, key.length, value, + 0, value.length, columnFamilyHandle.nativeHandle_); } /** @@ -477,8 +477,8 @@ public class RocksDB extends RocksObject { * found in block-cache. * @return boolean value indicating if key does not exist or might exist. */ - public boolean keyMayExist(final byte[] key, final StringBuffer value){ - return keyMayExist(nativeHandle_, key, key.length, value); + public boolean keyMayExist(final byte[] key, final StringBuffer value) { + return keyMayExist(nativeHandle_, key, 0, key.length, value); } /** @@ -495,8 +495,8 @@ public class RocksDB extends RocksObject { * @return boolean value indicating if key does not exist or might exist. */ public boolean keyMayExist(final ColumnFamilyHandle columnFamilyHandle, - final byte[] key, final StringBuffer value){ - return keyMayExist(nativeHandle_, key, key.length, + final byte[] key, final StringBuffer value) { + return keyMayExist(nativeHandle_, key, 0, key.length, columnFamilyHandle.nativeHandle_, value); } @@ -514,9 +514,9 @@ public class RocksDB extends RocksObject { * @return boolean value indicating if key does not exist or might exist. */ public boolean keyMayExist(final ReadOptions readOptions, - final byte[] key, final StringBuffer value){ + final byte[] key, final StringBuffer value) { return keyMayExist(nativeHandle_, readOptions.nativeHandle_, - key, key.length, value); + key, 0, key.length, value); } /** @@ -535,9 +535,9 @@ public class RocksDB extends RocksObject { */ public boolean keyMayExist(final ReadOptions readOptions, final ColumnFamilyHandle columnFamilyHandle, final byte[] key, - final StringBuffer value){ + final StringBuffer value) { return keyMayExist(nativeHandle_, readOptions.nativeHandle_, - key, key.length, columnFamilyHandle.nativeHandle_, + key, 0, key.length, columnFamilyHandle.nativeHandle_, value); } @@ -581,7 +581,7 @@ public class RocksDB extends RocksObject { */ public void merge(final byte[] key, final byte[] value) throws RocksDBException { - merge(nativeHandle_, key, key.length, value, value.length); + merge(nativeHandle_, key, 0, key.length, value, 0, value.length); } /** @@ -597,7 +597,7 @@ public class RocksDB extends RocksObject { */ public void merge(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value) throws RocksDBException { - merge(nativeHandle_, key, key.length, value, value.length, + merge(nativeHandle_, key, 0, key.length, value, 0, value.length, columnFamilyHandle.nativeHandle_); } @@ -615,7 +615,7 @@ public class RocksDB extends RocksObject { public void merge(final WriteOptions writeOpts, final byte[] key, final byte[] value) throws RocksDBException { merge(nativeHandle_, writeOpts.nativeHandle_, - key, key.length, value, value.length); + key, 0, key.length, value, 0, value.length); } /** @@ -634,7 +634,7 @@ public class RocksDB extends RocksObject { final WriteOptions writeOpts, final byte[] key, final byte[] value) throws RocksDBException { merge(nativeHandle_, writeOpts.nativeHandle_, - key, key.length, value, value.length, + key, 0, key.length, value, 0, value.length, columnFamilyHandle.nativeHandle_); } @@ -653,7 +653,7 @@ public class RocksDB extends RocksObject { * native library. */ public int get(final byte[] key, final byte[] value) throws RocksDBException { - return get(nativeHandle_, key, key.length, value, value.length); + return get(nativeHandle_, key, 0, key.length, value, 0, value.length); } /** @@ -675,7 +675,7 @@ public class RocksDB extends RocksObject { */ public int get(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value) throws RocksDBException, IllegalArgumentException { - return get(nativeHandle_, key, key.length, value, value.length, + return get(nativeHandle_, key, 0, key.length, value, 0, value.length, columnFamilyHandle.nativeHandle_); } @@ -698,7 +698,7 @@ public class RocksDB extends RocksObject { public int get(final ReadOptions opt, final byte[] key, final byte[] value) throws RocksDBException { return get(nativeHandle_, opt.nativeHandle_, - key, key.length, value, value.length); + key, 0, key.length, value, 0, value.length); } /** * Get the value associated with the specified key within column family. @@ -721,8 +721,8 @@ public class RocksDB extends RocksObject { public int get(final ColumnFamilyHandle columnFamilyHandle, final ReadOptions opt, final byte[] key, final byte[] value) throws RocksDBException { - return get(nativeHandle_, opt.nativeHandle_, key, key.length, value, - value.length, columnFamilyHandle.nativeHandle_); + return get(nativeHandle_, opt.nativeHandle_, key, 0, key.length, value, + 0, value.length, columnFamilyHandle.nativeHandle_); } /** @@ -738,7 +738,7 @@ public class RocksDB extends RocksObject { * native library. */ public byte[] get(final byte[] key) throws RocksDBException { - return get(nativeHandle_, key, key.length); + return get(nativeHandle_, key, 0, key.length); } /** @@ -757,7 +757,7 @@ public class RocksDB extends RocksObject { */ public byte[] get(final ColumnFamilyHandle columnFamilyHandle, final byte[] key) throws RocksDBException { - return get(nativeHandle_, key, key.length, + return get(nativeHandle_, key, 0, key.length, columnFamilyHandle.nativeHandle_); } @@ -776,7 +776,7 @@ public class RocksDB extends RocksObject { */ public byte[] get(final ReadOptions opt, final byte[] key) throws RocksDBException { - return get(nativeHandle_, opt.nativeHandle_, key, key.length); + return get(nativeHandle_, opt.nativeHandle_, key, 0, key.length); } /** @@ -796,7 +796,7 @@ public class RocksDB extends RocksObject { */ public byte[] get(final ColumnFamilyHandle columnFamilyHandle, final ReadOptions opt, final byte[] key) throws RocksDBException { - return get(nativeHandle_, opt.nativeHandle_, key, key.length, + return get(nativeHandle_, opt.nativeHandle_, key, 0, key.length, columnFamilyHandle.nativeHandle_); } @@ -814,10 +814,17 @@ public class RocksDB extends RocksObject { throws RocksDBException { assert(keys.size() != 0); - final byte[][] values = multiGet(nativeHandle_, - keys.toArray(new byte[keys.size()][])); + final byte[][] keysArray = keys.toArray(new byte[keys.size()][]); + final int keyOffsets[] = new int[keysArray.length]; + final int keyLengths[] = new int[keysArray.length]; + for(int i = 0; i < keyLengths.length; i++) { + keyLengths[i] = keysArray[i].length; + } + + final byte[][] values = multiGet(nativeHandle_, keysArray, keyOffsets, + keyLengths); - Map keyValueMap = new HashMap<>(); + final Map keyValueMap = new HashMap<>(); for(int i = 0; i < values.length; i++) { if(values[i] == null) { continue; @@ -862,10 +869,18 @@ public class RocksDB extends RocksObject { for (int i = 0; i < columnFamilyHandleList.size(); i++) { cfHandles[i] = columnFamilyHandleList.get(i).nativeHandle_; } - final byte[][] values = multiGet(nativeHandle_, - keys.toArray(new byte[keys.size()][]), cfHandles); - Map keyValueMap = new HashMap<>(); + final byte[][] keysArray = keys.toArray(new byte[keys.size()][]); + final int keyOffsets[] = new int[keysArray.length]; + final int keyLengths[] = new int[keysArray.length]; + for(int i = 0; i < keyLengths.length; i++) { + keyLengths[i] = keysArray[i].length; + } + + final byte[][] values = multiGet(nativeHandle_, keysArray, keyOffsets, + keyLengths, cfHandles); + + final Map keyValueMap = new HashMap<>(); for(int i = 0; i < values.length; i++) { if (values[i] == null) { continue; @@ -890,10 +905,17 @@ public class RocksDB extends RocksObject { final List keys) throws RocksDBException { assert(keys.size() != 0); + final byte[][] keysArray = keys.toArray(new byte[keys.size()][]); + final int keyOffsets[] = new int[keysArray.length]; + final int keyLengths[] = new int[keysArray.length]; + for(int i = 0; i < keyLengths.length; i++) { + keyLengths[i] = keysArray[i].length; + } + final byte[][] values = multiGet(nativeHandle_, opt.nativeHandle_, - keys.toArray(new byte[keys.size()][])); + keysArray, keyOffsets, keyLengths); - Map keyValueMap = new HashMap<>(); + final Map keyValueMap = new HashMap<>(); for(int i = 0; i < values.length; i++) { if(values[i] == null) { continue; @@ -938,10 +960,18 @@ public class RocksDB extends RocksObject { for (int i = 0; i < columnFamilyHandleList.size(); i++) { cfHandles[i] = columnFamilyHandleList.get(i).nativeHandle_; } + + final byte[][] keysArray = keys.toArray(new byte[keys.size()][]); + final int keyOffsets[] = new int[keysArray.length]; + final int keyLengths[] = new int[keysArray.length]; + for(int i = 0; i < keyLengths.length; i++) { + keyLengths[i] = keysArray[i].length; + } + final byte[][] values = multiGet(nativeHandle_, opt.nativeHandle_, - keys.toArray(new byte[keys.size()][]), cfHandles); + keysArray, keyOffsets, keyLengths, cfHandles); - Map keyValueMap = new HashMap<>(); + final Map keyValueMap = new HashMap<>(); for(int i = 0; i < values.length; i++) { if(values[i] == null) { continue; @@ -980,7 +1010,7 @@ public class RocksDB extends RocksObject { * native library. */ public void delete(final byte[] key) throws RocksDBException { - delete(nativeHandle_, key, key.length); + delete(nativeHandle_, key, 0, key.length); } /** @@ -1017,7 +1047,7 @@ public class RocksDB extends RocksObject { */ public void delete(final ColumnFamilyHandle columnFamilyHandle, final byte[] key) throws RocksDBException { - delete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_); + delete(nativeHandle_, key, 0, key.length, columnFamilyHandle.nativeHandle_); } /** @@ -1052,7 +1082,7 @@ public class RocksDB extends RocksObject { */ public void delete(final WriteOptions writeOpt, final byte[] key) throws RocksDBException { - delete(nativeHandle_, writeOpt.nativeHandle_, key, key.length); + delete(nativeHandle_, writeOpt.nativeHandle_, key, 0, key.length); } /** @@ -1093,7 +1123,7 @@ public class RocksDB extends RocksObject { public void delete(final ColumnFamilyHandle columnFamilyHandle, final WriteOptions writeOpt, final byte[] key) throws RocksDBException { - delete(nativeHandle_, writeOpt.nativeHandle_, key, key.length, + delete(nativeHandle_, writeOpt.nativeHandle_, key, 0, key.length, columnFamilyHandle.nativeHandle_); } @@ -1970,91 +2000,87 @@ public class RocksDB extends RocksObject { final long[] columnFamilyOptions ) throws RocksDBException; - protected native static byte[][] listColumnFamilies( - long optionsHandle, String path) throws RocksDBException; - protected native void put( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native void put( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; - protected native void put( - long handle, long writeOptHandle, - byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native void put( - long handle, long writeOptHandle, - byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; + protected native static byte[][] listColumnFamilies(long optionsHandle, + String path) throws RocksDBException; + protected native void put(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength) + throws RocksDBException; + protected native void put(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength, + long cfHandle) throws RocksDBException; + protected native void put(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength) throws RocksDBException; + protected native void put(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength, long cfHandle) throws RocksDBException; protected native void write0(final long handle, long writeOptHandle, long wbHandle) throws RocksDBException; protected native void write1(final long handle, long writeOptHandle, long wbwiHandle) throws RocksDBException; protected native boolean keyMayExist(final long handle, final byte[] key, - final int keyLen, final StringBuffer stringBuffer); + final int keyOffset, final int keyLength, + final StringBuffer stringBuffer); protected native boolean keyMayExist(final long handle, final byte[] key, - final int keyLen, final long cfHandle, final StringBuffer stringBuffer); - protected native boolean keyMayExist(final long handle, - final long optionsHandle, final byte[] key, final int keyLen, + final int keyOffset, final int keyLength, final long cfHandle, final StringBuffer stringBuffer); protected native boolean keyMayExist(final long handle, - final long optionsHandle, final byte[] key, final int keyLen, - final long cfHandle, final StringBuffer stringBuffer); - protected native void merge( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native void merge( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; - protected native void merge( - long handle, long writeOptHandle, - byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native void merge( - long handle, long writeOptHandle, - byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; - protected native int get( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native int get( - long handle, byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; - protected native int get( - long handle, long readOptHandle, byte[] key, int keyLen, - byte[] value, int valueLen) throws RocksDBException; - protected native int get( - long handle, long readOptHandle, byte[] key, int keyLen, - byte[] value, int valueLen, long cfHandle) throws RocksDBException; - protected native byte[][] multiGet(final long dbHandle, final byte[][] keys); + final long optionsHandle, final byte[] key, final int keyOffset, + final int keyLength, final StringBuffer stringBuffer); + protected native boolean keyMayExist(final long handle, + final long optionsHandle, final byte[] key, final int keyOffset, + final int keyLength, final long cfHandle, + final StringBuffer stringBuffer); + protected native void merge(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength) + throws RocksDBException; + protected native void merge(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength, + long cfHandle) throws RocksDBException; + protected native void merge(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength) throws RocksDBException; + protected native void merge(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength, long cfHandle) throws RocksDBException; + protected native int get(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength) + throws RocksDBException; + protected native int get(long handle, byte[] key, int keyOffset, + int keyLength, byte[] value, int valueOffset, int valueLength, + long cfHandle) throws RocksDBException; + protected native int get(long handle, long readOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength) throws RocksDBException; + protected native int get(long handle, long readOptHandle, byte[] key, + int keyOffset, int keyLength, byte[] value, int valueOffset, + int valueLength, long cfHandle) throws RocksDBException; protected native byte[][] multiGet(final long dbHandle, final byte[][] keys, + final int[] keyOffsets, final int[] keyLengths); + protected native byte[][] multiGet(final long dbHandle, final byte[][] keys, + final int[] keyOffsets, final int[] keyLengths, final long[] columnFamilyHandles); protected native byte[][] multiGet(final long dbHandle, final long rOptHandle, - final byte[][] keys); + final byte[][] keys, final int[] keyOffsets, final int[] keyLengths); protected native byte[][] multiGet(final long dbHandle, final long rOptHandle, - final byte[][] keys, final long[] columnFamilyHandles); - protected native byte[] get( - long handle, byte[] key, int keyLen) throws RocksDBException; - protected native byte[] get( - long handle, byte[] key, int keyLen, long cfHandle) - throws RocksDBException; - protected native byte[] get( - long handle, long readOptHandle, - byte[] key, int keyLen) throws RocksDBException; - protected native byte[] get( - long handle, long readOptHandle, - byte[] key, int keyLen, long cfHandle) throws RocksDBException; - protected native void delete( - long handle, byte[] key, int keyLen) throws RocksDBException; - protected native void delete( - long handle, byte[] key, int keyLen, long cfHandle) - throws RocksDBException; - protected native void delete( - long handle, long writeOptHandle, - byte[] key, int keyLen) throws RocksDBException; - protected native void delete( - long handle, long writeOptHandle, - byte[] key, int keyLen, long cfHandle) throws RocksDBException; + final byte[][] keys, final int[] keyOffsets, final int[] keyLengths, + final long[] columnFamilyHandles); + protected native byte[] get(long handle, byte[] key, int keyOffset, + int keyLength) throws RocksDBException; + protected native byte[] get(long handle, byte[] key, int keyOffset, + int keyLength, long cfHandle) throws RocksDBException; + protected native byte[] get(long handle, long readOptHandle, + byte[] key, int keyOffset, int keyLength) throws RocksDBException; + protected native byte[] get(long handle, long readOptHandle, byte[] key, + int keyOffset, int keyLength, long cfHandle) throws RocksDBException; + protected native void delete(long handle, byte[] key, int keyOffset, + int keyLength) throws RocksDBException; + protected native void delete(long handle, byte[] key, int keyOffset, + int keyLength, long cfHandle) throws RocksDBException; + protected native void delete(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength) throws RocksDBException; + protected native void delete(long handle, long writeOptHandle, byte[] key, + int keyOffset, int keyLength, long cfHandle) throws RocksDBException; protected native void singleDelete( long handle, byte[] key, int keyLen) throws RocksDBException; protected native void singleDelete( @@ -2070,8 +2096,8 @@ public class RocksDB extends RocksObject { String property, int propertyLength) throws RocksDBException; protected native String getProperty0(long nativeHandle, long cfHandle, String property, int propertyLength) throws RocksDBException; - protected native long getLongProperty(long nativeHandle, - String property, int propertyLength) throws RocksDBException; + protected native long getLongProperty(long nativeHandle, String property, + int propertyLength) throws RocksDBException; protected native long getLongProperty(long nativeHandle, long cfHandle, String property, int propertyLength) throws RocksDBException; protected native long iterator(long handle); @@ -2083,8 +2109,7 @@ public class RocksDB extends RocksObject { final long[] columnFamilyHandles, final long readOptHandle) throws RocksDBException; protected native long getSnapshot(long nativeHandle); - protected native void releaseSnapshot( - long nativeHandle, long snapshotHandle); + protected native void releaseSnapshot(long nativeHandle, long snapshotHandle); @Override protected final native void disposeInternal(final long handle); private native long getDefaultColumnFamily(long handle); private native long createColumnFamily(final long handle, @@ -2094,8 +2119,8 @@ public class RocksDB extends RocksObject { throws RocksDBException; private native void flush(long handle, long flushOptHandle) throws RocksDBException; - private native void flush(long handle, long flushOptHandle, - long cfHandle) throws RocksDBException; + private native void flush(long handle, long flushOptHandle, long cfHandle) + throws RocksDBException; private native void compactRange0(long handle, boolean reduce_level, int target_level, int target_path_id) throws RocksDBException; private native void compactRange0(long handle, byte[] begin, int beginLen, @@ -2111,8 +2136,8 @@ public class RocksDB extends RocksObject { private native void continueBackgroundWork(long handle) throws RocksDBException; private native long getLatestSequenceNumber(long handle); private native void disableFileDeletions(long handle) throws RocksDBException; - private native void enableFileDeletions(long handle, - boolean force) throws RocksDBException; + private native void enableFileDeletions(long handle, boolean force) + throws RocksDBException; private native long getUpdatesSince(long handle, long sequenceNumber) throws RocksDBException; private native void setOptions(long handle, long cfHandle, String[] keys,