diff options
Diffstat (limited to '')
-rw-r--r-- | src/rocksdb/java/rocksjni/transaction.cc | 1646 |
1 files changed, 1646 insertions, 0 deletions
diff --git a/src/rocksdb/java/rocksjni/transaction.cc b/src/rocksdb/java/rocksjni/transaction.cc new file mode 100644 index 000000000..ae98b868c --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction.cc @@ -0,0 +1,1646 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). +// +// This file implements the "bridge" between Java and C++ +// for ROCKSDB_NAMESPACE::Transaction. + +#include <jni.h> +#include <functional> + +#include "include/org_rocksdb_Transaction.h" + +#include "rocksdb/utilities/transaction.h" +#include "rocksjni/portal.h" + +using namespace std::placeholders; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4503) // identifier' : decorated name length + // exceeded, name was truncated +#endif + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshot + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSnapshot(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->SetSnapshot(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshotOnNextOperation + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSnapshotOnNextOperation__J( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->SetSnapshotOnNextOperation(nullptr); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshotOnNextOperation + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setSnapshotOnNextOperation__JJ( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jtxn_notifier_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* txn_notifier = reinterpret_cast< + std::shared_ptr<ROCKSDB_NAMESPACE::TransactionNotifierJniCallback>*>( + jtxn_notifier_handle); + txn->SetSnapshotOnNextOperation(*txn_notifier); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getSnapshot + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getSnapshot(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + const ROCKSDB_NAMESPACE::Snapshot* snapshot = txn->GetSnapshot(); + return reinterpret_cast<jlong>(snapshot); +} + +/* + * Class: org_rocksdb_Transaction + * Method: clearSnapshot + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_clearSnapshot(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->ClearSnapshot(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: prepare + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_prepare(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::Status s = txn->Prepare(); + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: commit + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_commit(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::Status s = txn->Commit(); + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: rollback + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_rollback(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::Status s = txn->Rollback(); + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSavePoint(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->SetSavePoint(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: rollbackToSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_rollbackToSavePoint(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::Status s = txn->RollbackToSavePoint(); + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +typedef std::function<ROCKSDB_NAMESPACE::Status( + const ROCKSDB_NAMESPACE::ReadOptions&, const ROCKSDB_NAMESPACE::Slice&, + std::string*)> + FnGet; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +jbyteArray txn_get_helper(JNIEnv* env, const FnGet& fn_get, + const jlong& jread_options_handle, + const jbyteArray& jkey, const jint& jkey_part_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + + auto* read_options = + reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle); + std::string value; + ROCKSDB_NAMESPACE::Status s = fn_get(*read_options, 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); + + if (s.IsNotFound()) { + return nullptr; + } + + if (s.ok()) { + jbyteArray jret_value = env->NewByteArray(static_cast<jsize>(value.size())); + if (jret_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetByteArrayRegion(jret_value, 0, static_cast<jsize>(value.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value.c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return nullptr; + } + return jret_value; + } + + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; +} + +/* + * Class: org_rocksdb_Transaction + * Method: get + * Signature: (JJ[BIJ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_get__JJ_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnGet fn_get = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, std::string*)>( + &ROCKSDB_NAMESPACE::Transaction::Get, txn, _1, column_family_handle, + _2, _3); + return txn_get_helper(env, fn_get, jread_options_handle, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: get + * Signature: (JJ[BI)[B + */ +jbyteArray Java_org_rocksdb_Transaction_get__JJ_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnGet fn_get = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const ROCKSDB_NAMESPACE::Slice&, std::string*)>( + &ROCKSDB_NAMESPACE::Transaction::Get, txn, _1, _2, _3); + return txn_get_helper(env, fn_get, jread_options_handle, jkey, jkey_part_len); +} + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +// used by txn_multi_get_helper below +std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> txn_column_families_helper( + JNIEnv* env, jlongArray jcolumn_family_handles, bool* has_exception) { + std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles; + if (jcolumn_family_handles != nullptr) { + const jsize len_cols = env->GetArrayLength(jcolumn_family_handles); + if (len_cols > 0) { + if (env->EnsureLocalCapacity(len_cols) != 0) { + // out of memory + *has_exception = JNI_TRUE; + return std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(); + } + + jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr); + if (jcfh == nullptr) { + // exception thrown: OutOfMemoryError + *has_exception = JNI_TRUE; + return std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(); + } + for (int i = 0; i < len_cols; i++) { + auto* cf_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcfh[i]); + cf_handles.push_back(cf_handle); + } + env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT); + } + } + return cf_handles; +} + +typedef std::function<std::vector<ROCKSDB_NAMESPACE::Status>( + const ROCKSDB_NAMESPACE::ReadOptions&, + const std::vector<ROCKSDB_NAMESPACE::Slice>&, std::vector<std::string>*)> + FnMultiGet; + +void free_parts( + JNIEnv* env, + std::vector<std::tuple<jbyteArray, jbyte*, jobject>>& parts_to_free) { + for (auto& value : parts_to_free) { + jobject jk; + jbyteArray jk_ba; + jbyte* jk_val; + std::tie(jk_ba, jk_val, jk) = value; + env->ReleaseByteArrayElements(jk_ba, jk_val, JNI_ABORT); + env->DeleteLocalRef(jk); + } +} + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +// cf multi get +jobjectArray txn_multi_get_helper(JNIEnv* env, const FnMultiGet& fn_multi_get, + const jlong& jread_options_handle, + const jobjectArray& jkey_parts) { + const jsize len_key_parts = env->GetArrayLength(jkey_parts); + if (env->EnsureLocalCapacity(len_key_parts) != 0) { + // out of memory + return nullptr; + } + + std::vector<ROCKSDB_NAMESPACE::Slice> key_parts; + std::vector<std::tuple<jbyteArray, jbyte*, jobject>> key_parts_to_free; + for (int i = 0; i < len_key_parts; i++) { + const jobject jk = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, key_parts_to_free); + return nullptr; + } + jbyteArray jk_ba = reinterpret_cast<jbyteArray>(jk); + const jsize len_key = env->GetArrayLength(jk_ba); + if (env->EnsureLocalCapacity(len_key) != 0) { + // out of memory + env->DeleteLocalRef(jk); + free_parts(env, key_parts_to_free); + return nullptr; + } + jbyte* jk_val = env->GetByteArrayElements(jk_ba, nullptr); + if (jk_val == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jk); + free_parts(env, key_parts_to_free); + return nullptr; + } + + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(jk_val), + len_key); + key_parts.push_back(key_slice); + + key_parts_to_free.push_back(std::make_tuple(jk_ba, jk_val, jk)); + } + + auto* read_options = + reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle); + std::vector<std::string> value_parts; + std::vector<ROCKSDB_NAMESPACE::Status> s = + fn_multi_get(*read_options, key_parts, &value_parts); + + // free up allocated byte arrays + free_parts(env, key_parts_to_free); + + // prepare the results + const jclass jcls_ba = env->FindClass("[B"); + jobjectArray jresults = + env->NewObjectArray(static_cast<jsize>(s.size()), jcls_ba, nullptr); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + // add to the jresults + for (std::vector<ROCKSDB_NAMESPACE::Status>::size_type i = 0; i != s.size(); + i++) { + if (s[i].ok()) { + jbyteArray jentry_value = + env->NewByteArray(static_cast<jsize>(value_parts[i].size())); + if (jentry_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + jentry_value, 0, static_cast<jsize>(value_parts[i].size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value_parts[i].c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jentry_value); + return nullptr; + } + + env->SetObjectArrayElement(jresults, static_cast<jsize>(i), jentry_value); + env->DeleteLocalRef(jentry_value); + } + } + + return jresults; +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGet + * Signature: (JJ[[B[J)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGet__JJ_3_3B_3J( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts, jlongArray jcolumn_family_handles) { + bool has_exception = false; + const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> + column_family_handles = txn_column_families_helper( + env, jcolumn_family_handles, &has_exception); + if (has_exception) { + // exception thrown: OutOfMemoryError + return nullptr; + } + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnMultiGet fn_multi_get = std::bind<std::vector<ROCKSDB_NAMESPACE::Status> ( + ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>&, + const std::vector<ROCKSDB_NAMESPACE::Slice>&, std::vector<std::string>*)>( + &ROCKSDB_NAMESPACE::Transaction::MultiGet, txn, _1, column_family_handles, + _2, _3); + return txn_multi_get_helper(env, fn_multi_get, jread_options_handle, + jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGet + * Signature: (JJ[[B)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGet__JJ_3_3B( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnMultiGet fn_multi_get = std::bind<std::vector<ROCKSDB_NAMESPACE::Status> ( + ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const std::vector<ROCKSDB_NAMESPACE::Slice>&, std::vector<std::string>*)>( + &ROCKSDB_NAMESPACE::Transaction::MultiGet, txn, _1, _2, _3); + return txn_multi_get_helper(env, fn_multi_get, jread_options_handle, + jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getForUpdate + * Signature: (JJ[BIJZZ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_getForUpdate__JJ_3BIJZZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jlong jcolumn_family_handle, + jboolean jexclusive, jboolean jdo_validate) { + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnGet fn_get_for_update = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, std::string*, bool, bool)>( + &ROCKSDB_NAMESPACE::Transaction::GetForUpdate, txn, _1, + column_family_handle, _2, _3, jexclusive, jdo_validate); + return txn_get_helper(env, fn_get_for_update, jread_options_handle, jkey, + jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getForUpdate + * Signature: (JJ[BIZZ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_getForUpdate__JJ_3BIZZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jboolean jexclusive, + jboolean jdo_validate) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnGet fn_get_for_update = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const ROCKSDB_NAMESPACE::Slice&, std::string*, bool, bool)>( + &ROCKSDB_NAMESPACE::Transaction::GetForUpdate, txn, _1, _2, _3, + jexclusive, jdo_validate); + return txn_get_helper(env, fn_get_for_update, jread_options_handle, jkey, + jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGetForUpdate + * Signature: (JJ[[B[J)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGetForUpdate__JJ_3_3B_3J( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts, jlongArray jcolumn_family_handles) { + bool has_exception = false; + const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> + column_family_handles = txn_column_families_helper( + env, jcolumn_family_handles, &has_exception); + if (has_exception) { + // exception thrown: OutOfMemoryError + return nullptr; + } + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnMultiGet fn_multi_get_for_update = std::bind<std::vector< + ROCKSDB_NAMESPACE::Status> (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>&, + const std::vector<ROCKSDB_NAMESPACE::Slice>&, std::vector<std::string>*)>( + &ROCKSDB_NAMESPACE::Transaction::MultiGetForUpdate, txn, _1, + column_family_handles, _2, _3); + return txn_multi_get_helper(env, fn_multi_get_for_update, + jread_options_handle, jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGetForUpdate + * Signature: (JJ[[B)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGetForUpdate__JJ_3_3B( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnMultiGet fn_multi_get_for_update = std::bind<std::vector< + ROCKSDB_NAMESPACE::Status> (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::ReadOptions&, + const std::vector<ROCKSDB_NAMESPACE::Slice>&, std::vector<std::string>*)>( + &ROCKSDB_NAMESPACE::Transaction::MultiGetForUpdate, txn, _1, _2, _3); + return txn_multi_get_helper(env, fn_multi_get_for_update, + jread_options_handle, jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getIterator + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_Transaction_getIterator__JJ(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jread_options_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* read_options = + reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle); + return reinterpret_cast<jlong>(txn->GetIterator(*read_options)); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getIterator + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_Transaction_getIterator__JJJ( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jread_options_handle, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* read_options = + reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + return reinterpret_cast<jlong>( + txn->GetIterator(*read_options, column_family_handle)); +} + +typedef std::function<ROCKSDB_NAMESPACE::Status( + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)> + FnWriteKV; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_kv_helper(JNIEnv* env, const FnWriteKV& fn_write_kv, + const jbyteArray& jkey, const jint& jkey_part_len, + const jbyteArray& jval, const jint& jval_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + jbyte* value = env->GetByteArrayElements(jval, nullptr); + if (value == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + return; + } + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char*>(value), + jval_len); + + ROCKSDB_NAMESPACE::Status s = fn_write_kv(key_slice, value_slice); + + // 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(jval, value, JNI_ABORT); + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (s.ok()) { + return; + } + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[BI[BIJZ)V + */ +void Java_org_rocksdb_Transaction_put__J_3BI_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKV fn_put = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&, + bool)>(&ROCKSDB_NAMESPACE::Transaction::Put, txn, + column_family_handle, _1, _2, jassume_tracked); + txn_write_kv_helper(env, fn_put, jkey, jkey_part_len, jval, jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_put__J_3BI_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len, + jbyteArray jval, + jint jval_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKV fn_put = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::Put, txn, _1, _2); + txn_write_kv_helper(env, fn_put, jkey, jkey_part_len, jval, jval_len); +} + +typedef std::function<ROCKSDB_NAMESPACE::Status( + const ROCKSDB_NAMESPACE::SliceParts&, const ROCKSDB_NAMESPACE::SliceParts&)> + FnWriteKVParts; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_kv_parts_helper(JNIEnv* env, + const FnWriteKVParts& fn_write_kv_parts, + const jobjectArray& jkey_parts, + const jint& jkey_parts_len, + const jobjectArray& jvalue_parts, + const jint& jvalue_parts_len) { +#ifndef DEBUG + (void) jvalue_parts_len; +#else + assert(jkey_parts_len == jvalue_parts_len); +#endif + + auto key_parts = std::vector<ROCKSDB_NAMESPACE::Slice>(); + auto value_parts = std::vector<ROCKSDB_NAMESPACE::Slice>(); + auto jparts_to_free = std::vector<std::tuple<jbyteArray, jbyte*, jobject>>(); + + // convert java key_parts/value_parts byte[][] to Slice(s) + for (jsize i = 0; i < jkey_parts_len; ++i) { + const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, jparts_to_free); + return; + } + const jobject jobj_value_part = env->GetObjectArrayElement(jvalue_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + const jbyteArray jba_key_part = reinterpret_cast<jbyteArray>(jobj_key_part); + const jsize jkey_part_len = env->GetArrayLength(jba_key_part); + if (env->EnsureLocalCapacity(jkey_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); + if (jkey_part == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + const jbyteArray jba_value_part = + reinterpret_cast<jbyteArray>(jobj_value_part); + const jsize jvalue_part_len = env->GetArrayLength(jba_value_part); + if (env->EnsureLocalCapacity(jvalue_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + jbyte* jvalue_part = env->GetByteArrayElements(jba_value_part, nullptr); + if (jvalue_part == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jba_value_part, jvalue_part, JNI_ABORT); + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + jparts_to_free.push_back( + std::make_tuple(jba_key_part, jkey_part, jobj_key_part)); + jparts_to_free.push_back( + std::make_tuple(jba_value_part, jvalue_part, jobj_value_part)); + + key_parts.push_back(ROCKSDB_NAMESPACE::Slice( + reinterpret_cast<char*>(jkey_part), jkey_part_len)); + value_parts.push_back(ROCKSDB_NAMESPACE::Slice( + reinterpret_cast<char*>(jvalue_part), jvalue_part_len)); + } + + // call the write_multi function + ROCKSDB_NAMESPACE::Status s = fn_write_kv_parts( + ROCKSDB_NAMESPACE::SliceParts(key_parts.data(), (int)key_parts.size()), + ROCKSDB_NAMESPACE::SliceParts(value_parts.data(), + (int)value_parts.size())); + + // cleanup temporary memory + free_parts(env, jparts_to_free); + + // return + if (s.ok()) { + return; + } + + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[[BI[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_put__J_3_3BI_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKVParts fn_put_parts = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::SliceParts&, + const ROCKSDB_NAMESPACE::SliceParts&, bool)>( + &ROCKSDB_NAMESPACE::Transaction::Put, txn, column_family_handle, _1, + _2, jassume_tracked); + txn_write_kv_parts_helper(env, fn_put_parts, jkey_parts, jkey_parts_len, + jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[[BI[[BI)V + */ +void Java_org_rocksdb_Transaction_put__J_3_3BI_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKVParts fn_put_parts = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::SliceParts&, + const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::Put, txn, _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts, jkey_parts, jkey_parts_len, + jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: merge + * Signature: (J[BI[BIJZ)V + */ +void Java_org_rocksdb_Transaction_merge__J_3BI_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKV fn_merge = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&, + bool)>(&ROCKSDB_NAMESPACE::Transaction::Merge, txn, + column_family_handle, _1, _2, jassume_tracked); + txn_write_kv_helper(env, fn_merge, jkey, jkey_part_len, jval, jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: merge + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_merge__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKV fn_merge = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::Merge, txn, _1, _2); + txn_write_kv_helper(env, fn_merge, jkey, jkey_part_len, jval, jval_len); +} + +typedef std::function<ROCKSDB_NAMESPACE::Status( + const ROCKSDB_NAMESPACE::Slice&)> + FnWriteK; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_k_helper(JNIEnv* env, const FnWriteK& fn_write_k, + const jbyteArray& jkey, const jint& jkey_part_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + + ROCKSDB_NAMESPACE::Status s = fn_write_k(key_slice); + + // 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); + + if (s.ok()) { + return; + } + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[BIJZ)V + */ +void Java_org_rocksdb_Transaction_delete__J_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteK fn_delete = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, bool)>( + &ROCKSDB_NAMESPACE::Transaction::Delete, txn, column_family_handle, + _1, jassume_tracked); + txn_write_k_helper(env, fn_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_delete__J_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteK fn_delete = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::Delete, txn, _1); + txn_write_k_helper(env, fn_delete, jkey, jkey_part_len); +} + +typedef std::function<ROCKSDB_NAMESPACE::Status( + const ROCKSDB_NAMESPACE::SliceParts&)> + FnWriteKParts; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_k_parts_helper(JNIEnv* env, + const FnWriteKParts& fn_write_k_parts, + const jobjectArray& jkey_parts, + const jint& jkey_parts_len) { + std::vector<ROCKSDB_NAMESPACE::Slice> key_parts; + std::vector<std::tuple<jbyteArray, jbyte*, jobject>> jkey_parts_to_free; + + // convert java key_parts byte[][] to Slice(s) + for (jint i = 0; i < jkey_parts_len; ++i) { + const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, jkey_parts_to_free); + return; + } + + const jbyteArray jba_key_part = reinterpret_cast<jbyteArray>(jobj_key_part); + const jsize jkey_part_len = env->GetArrayLength(jba_key_part); + if (env->EnsureLocalCapacity(jkey_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jkey_parts_to_free); + return; + } + jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); + if (jkey_part == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jkey_parts_to_free); + return; + } + + jkey_parts_to_free.push_back(std::tuple<jbyteArray, jbyte*, jobject>( + jba_key_part, jkey_part, jobj_key_part)); + + key_parts.push_back(ROCKSDB_NAMESPACE::Slice( + reinterpret_cast<char*>(jkey_part), jkey_part_len)); + } + + // call the write_multi function + ROCKSDB_NAMESPACE::Status s = fn_write_k_parts( + ROCKSDB_NAMESPACE::SliceParts(key_parts.data(), (int)key_parts.size())); + + // cleanup temporary memory + free_parts(env, jkey_parts_to_free); + + // return + if (s.ok()) { + return; + } + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_delete__J_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle, + jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKParts fn_delete_parts = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::SliceParts&, bool)>( + &ROCKSDB_NAMESPACE::Transaction::Delete, txn, column_family_handle, + _1, jassume_tracked); + txn_write_k_parts_helper(env, fn_delete_parts, jkey_parts, jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_delete__J_3_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, + jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKParts fn_delete_parts = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::Delete, txn, _1); + txn_write_k_parts_helper(env, fn_delete_parts, jkey_parts, jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[BIJZ)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteK fn_single_delete = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, bool)>( + &ROCKSDB_NAMESPACE::Transaction::SingleDelete, txn, + column_family_handle, _1, jassume_tracked); + txn_write_k_helper(env, fn_single_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteK fn_single_delete = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::SingleDelete, txn, _1); + txn_write_k_helper(env, fn_single_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle, + jboolean jassume_tracked) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKParts fn_single_delete_parts = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::SliceParts&, bool)>( + &ROCKSDB_NAMESPACE::Transaction::SingleDelete, txn, + column_family_handle, _1, jassume_tracked); + txn_write_k_parts_helper(env, fn_single_delete_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKParts fn_single_delete_parts = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::SingleDelete, txn, _1); + txn_write_k_parts_helper(env, fn_single_delete_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3BI_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKV fn_put_untracked = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::PutUntracked, txn, + column_family_handle, _1, _2); + txn_write_kv_helper(env, fn_put_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKV fn_put_untracked = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::PutUntracked, txn, _1, _2); + txn_write_kv_helper(env, fn_put_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[[BI[[BIJ)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3_3BI_3_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKVParts fn_put_parts_untracked = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::SliceParts&, + const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::PutUntracked, txn, column_family_handle, + _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts_untracked, jkey_parts, + jkey_parts_len, jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[[BI[[BI)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3_3BI_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKVParts fn_put_parts_untracked = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::SliceParts&, + const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::PutUntracked, txn, _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts_untracked, jkey_parts, + jkey_parts_len, jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: mergeUntracked + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_Transaction_mergeUntracked__J_3BI_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKV fn_merge_untracked = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::MergeUntracked, txn, + column_family_handle, _1, _2); + txn_write_kv_helper(env, fn_merge_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: mergeUntracked + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_mergeUntracked__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKV fn_merge_untracked = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::Slice&, const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::MergeUntracked, txn, _1, _2); + txn_write_kv_helper(env, fn_merge_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteK fn_delete_untracked = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::DeleteUntracked, txn, + column_family_handle, _1); + txn_write_k_helper(env, fn_delete_untracked, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteK fn_delete_untracked = std::bind<ROCKSDB_NAMESPACE::Status ( + ROCKSDB_NAMESPACE::Transaction::*)(const ROCKSDB_NAMESPACE::Slice&)>( + &ROCKSDB_NAMESPACE::Transaction::DeleteUntracked, txn, _1); + txn_write_k_helper(env, fn_delete_untracked, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[[BIJ)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + FnWriteKParts fn_delete_untracked_parts = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + ROCKSDB_NAMESPACE::ColumnFamilyHandle*, + const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::DeleteUntracked, txn, + column_family_handle, _1); + txn_write_k_parts_helper(env, fn_delete_untracked_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + FnWriteKParts fn_delete_untracked_parts = + std::bind<ROCKSDB_NAMESPACE::Status (ROCKSDB_NAMESPACE::Transaction::*)( + const ROCKSDB_NAMESPACE::SliceParts&)>( + &ROCKSDB_NAMESPACE::Transaction::DeleteUntracked, txn, _1); + txn_write_k_parts_helper(env, fn_delete_untracked_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putLogData + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_putLogData(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + txn->PutLogData(key_slice); + + // 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); +} + +/* + * Class: org_rocksdb_Transaction + * Method: disableIndexing + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_disableIndexing(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->DisableIndexing(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: enableIndexing + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_enableIndexing(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->EnableIndexing(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumKeys + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumKeys(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetNumKeys(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumPuts + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumPuts(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetNumPuts(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumDeletes + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumDeletes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetNumDeletes(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumMerges + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumMerges(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetNumMerges(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getElapsedTime + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getElapsedTime(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetElapsedTime(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWriteBatch + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getWriteBatch(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetWriteBatch()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setLockTimeout + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setLockTimeout(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jlock_timeout) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->SetLockTimeout(jlock_timeout); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWriteOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getWriteOptions(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetWriteOptions()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setWriteOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setWriteOptions(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jwrite_options_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* write_options = + reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle); + txn->SetWriteOptions(*write_options); +} + +/* + * Class: org_rocksdb_Transaction + * Method: undo + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_Transaction_undoGetForUpdate__J_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>( + jcolumn_family_handle); + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + txn->UndoGetForUpdate(column_family_handle, key_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Transaction + * Method: undoGetForUpdate + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_undoGetForUpdate__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), + jkey_part_len); + txn->UndoGetForUpdate(key_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Transaction + * Method: rebuildFromWriteBatch + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_rebuildFromWriteBatch( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jwrite_batch_handle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + auto* write_batch = + reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwrite_batch_handle); + ROCKSDB_NAMESPACE::Status s = txn->RebuildFromWriteBatch(write_batch); + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: getCommitTimeWriteBatch + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getCommitTimeWriteBatch(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetCommitTimeWriteBatch()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setLogNumber + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setLogNumber(JNIEnv* /*env*/, + jobject /*jobj*/, jlong jhandle, + jlong jlog_number) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + txn->SetLogNumber(jlog_number); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getLogNumber + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getLogNumber(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return txn->GetLogNumber(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setName + * Signature: (JLjava/lang/String;)V + */ +void Java_org_rocksdb_Transaction_setName(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jstring jname) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + const char* name = env->GetStringUTFChars(jname, nullptr); + if (name == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + ROCKSDB_NAMESPACE::Status s = txn->SetName(name); + + env->ReleaseStringUTFChars(jname, name); + + if (!s.ok()) { + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: getName + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_Transaction_getName(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::TransactionName name = txn->GetName(); + return env->NewStringUTF(name.data()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getID + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getID(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::TransactionID id = txn->GetID(); + return static_cast<jlong>(id); +} + +/* + * Class: org_rocksdb_Transaction + * Method: isDeadlockDetect + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Transaction_isDeadlockDetect(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + return static_cast<jboolean>(txn->IsDeadlockDetect()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWaitingTxns + * Signature: (J)Lorg/rocksdb/Transaction/WaitingTransactions; + */ +jobject Java_org_rocksdb_Transaction_getWaitingTxns(JNIEnv* env, + jobject jtransaction_obj, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + uint32_t column_family_id; + std::string key; + std::vector<ROCKSDB_NAMESPACE::TransactionID> waiting_txns = + txn->GetWaitingTxns(&column_family_id, &key); + jobject jwaiting_txns = + ROCKSDB_NAMESPACE::TransactionJni::newWaitingTransactions( + env, jtransaction_obj, column_family_id, key, waiting_txns); + return jwaiting_txns; +} + +/* + * Class: org_rocksdb_Transaction + * Method: getState + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Transaction_getState(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + ROCKSDB_NAMESPACE::Transaction::TransactionState txn_status = txn->GetState(); + switch (txn_status) { + case ROCKSDB_NAMESPACE::Transaction::TransactionState::STARTED: + return 0x0; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::AWAITING_PREPARE: + return 0x1; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::PREPARED: + return 0x2; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::AWAITING_COMMIT: + return 0x3; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::COMMITED: + return 0x4; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::AWAITING_ROLLBACK: + return 0x5; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::ROLLEDBACK: + return 0x6; + + case ROCKSDB_NAMESPACE::Transaction::TransactionState::LOCKS_STOLEN: + return 0x7; + } + + assert(false); + return static_cast<jbyte>(-1); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getId + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getId(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); + uint64_t id = txn->GetId(); + return static_cast<jlong>(id); +} + +/* + * Class: org_rocksdb_Transaction + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + delete reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle); +} |