| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- // 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::TransactionDB.
- #include <jni.h>
- #include <functional>
- #include <memory>
- #include <utility>
- #include "include/org_rocksdb_TransactionDB.h"
- #include "rocksdb/options.h"
- #include "rocksdb/utilities/transaction.h"
- #include "rocksdb/utilities/transaction_db.h"
- #include "rocksjni/portal.h"
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: open
- * Signature: (JJLjava/lang/String;)J
- */
- jlong Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2(
- JNIEnv* env, jclass, jlong joptions_handle,
- jlong jtxn_db_options_handle, jstring jdb_path) {
- auto* options =
- reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions_handle);
- auto* txn_db_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDBOptions*>(
- jtxn_db_options_handle);
- ROCKSDB_NAMESPACE::TransactionDB* tdb = nullptr;
- const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
- if (db_path == nullptr) {
- // exception thrown: OutOfMemoryError
- return 0;
- }
- ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::TransactionDB::Open(
- *options, *txn_db_options, db_path, &tdb);
- env->ReleaseStringUTFChars(jdb_path, db_path);
- if (s.ok()) {
- return reinterpret_cast<jlong>(tdb);
- } else {
- ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
- return 0;
- }
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: open
- * Signature: (JJLjava/lang/String;[[B[J)[J
- */
- jlongArray Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2_3_3B_3J(
- JNIEnv* env, jclass, jlong jdb_options_handle,
- jlong jtxn_db_options_handle, jstring jdb_path, jobjectArray jcolumn_names,
- jlongArray jcolumn_options_handles) {
- const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
- if (db_path == nullptr) {
- // exception thrown: OutOfMemoryError
- return nullptr;
- }
- const jsize len_cols = env->GetArrayLength(jcolumn_names);
- if (env->EnsureLocalCapacity(len_cols) != 0) {
- // out of memory
- env->ReleaseStringUTFChars(jdb_path, db_path);
- return nullptr;
- }
- jlong* jco = env->GetLongArrayElements(jcolumn_options_handles, nullptr);
- if (jco == nullptr) {
- // exception thrown: OutOfMemoryError
- env->ReleaseStringUTFChars(jdb_path, db_path);
- return nullptr;
- }
- std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> column_families;
- for (int i = 0; i < len_cols; i++) {
- const jobject jcn = env->GetObjectArrayElement(jcolumn_names, i);
- if (env->ExceptionCheck()) {
- // exception thrown: ArrayIndexOutOfBoundsException
- env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
- env->ReleaseStringUTFChars(jdb_path, db_path);
- return nullptr;
- }
- const jbyteArray jcn_ba = reinterpret_cast<jbyteArray>(jcn);
- jbyte* jcf_name = env->GetByteArrayElements(jcn_ba, nullptr);
- if (jcf_name == nullptr) {
- // exception thrown: OutOfMemoryError
- env->DeleteLocalRef(jcn);
- env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
- env->ReleaseStringUTFChars(jdb_path, db_path);
- return nullptr;
- }
- const int jcf_name_len = env->GetArrayLength(jcn_ba);
- if (env->EnsureLocalCapacity(jcf_name_len) != 0) {
- // out of memory
- env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT);
- env->DeleteLocalRef(jcn);
- env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
- env->ReleaseStringUTFChars(jdb_path, db_path);
- return nullptr;
- }
- const std::string cf_name(reinterpret_cast<char*>(jcf_name), jcf_name_len);
- const ROCKSDB_NAMESPACE::ColumnFamilyOptions* cf_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(jco[i]);
- column_families.push_back(
- ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));
- env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT);
- env->DeleteLocalRef(jcn);
- }
- env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
- auto* db_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_options_handle);
- auto* txn_db_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDBOptions*>(
- jtxn_db_options_handle);
- std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> handles;
- ROCKSDB_NAMESPACE::TransactionDB* tdb = nullptr;
- const ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::TransactionDB::Open(
- *db_options, *txn_db_options, db_path, column_families, &handles, &tdb);
- // check if open operation was successful
- if (s.ok()) {
- const jsize resultsLen = 1 + len_cols; // db handle + column family handles
- std::unique_ptr<jlong[]> results =
- std::unique_ptr<jlong[]>(new jlong[resultsLen]);
- results[0] = reinterpret_cast<jlong>(tdb);
- for (int i = 1; i <= len_cols; i++) {
- results[i] = reinterpret_cast<jlong>(handles[i - 1]);
- }
- jlongArray jresults = env->NewLongArray(resultsLen);
- if (jresults == nullptr) {
- // exception thrown: OutOfMemoryError
- return nullptr;
- }
- env->SetLongArrayRegion(jresults, 0, resultsLen, results.get());
- if (env->ExceptionCheck()) {
- // exception thrown: ArrayIndexOutOfBoundsException
- env->DeleteLocalRef(jresults);
- return nullptr;
- }
- return jresults;
- } else {
- ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
- return nullptr;
- }
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: disposeInternal
- * Signature: (J)V
- */
- void Java_org_rocksdb_TransactionDB_disposeInternal(
- JNIEnv*, jobject, jlong jhandle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- assert(txn_db != nullptr);
- delete txn_db;
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: closeDatabase
- * Signature: (J)V
- */
- void Java_org_rocksdb_TransactionDB_closeDatabase(
- JNIEnv* env, jclass, jlong jhandle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- assert(txn_db != nullptr);
- ROCKSDB_NAMESPACE::Status s = txn_db->Close();
- ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: beginTransaction
- * Signature: (JJ)J
- */
- jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJ(
- JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- auto* write_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
- ROCKSDB_NAMESPACE::Transaction* txn =
- txn_db->BeginTransaction(*write_options);
- return reinterpret_cast<jlong>(txn);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: beginTransaction
- * Signature: (JJJ)J
- */
- jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJJ(
- JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle,
- jlong jtxn_options_handle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- auto* write_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
- auto* txn_options = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionOptions*>(
- jtxn_options_handle);
- ROCKSDB_NAMESPACE::Transaction* txn =
- txn_db->BeginTransaction(*write_options, *txn_options);
- return reinterpret_cast<jlong>(txn);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: beginTransaction_withOld
- * Signature: (JJJ)J
- */
- jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJ(
- JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle,
- jlong jold_txn_handle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- auto* write_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
- auto* old_txn =
- reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jold_txn_handle);
- ROCKSDB_NAMESPACE::TransactionOptions txn_options;
- ROCKSDB_NAMESPACE::Transaction* txn =
- txn_db->BeginTransaction(*write_options, txn_options, old_txn);
- // RocksJava relies on the assumption that
- // we do not allocate a new Transaction object
- // when providing an old_txn
- assert(txn == old_txn);
- return reinterpret_cast<jlong>(txn);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: beginTransaction_withOld
- * Signature: (JJJJ)J
- */
- jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJJ(
- JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle,
- jlong jtxn_options_handle, jlong jold_txn_handle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- auto* write_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
- auto* txn_options = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionOptions*>(
- jtxn_options_handle);
- auto* old_txn =
- reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jold_txn_handle);
- ROCKSDB_NAMESPACE::Transaction* txn =
- txn_db->BeginTransaction(*write_options, *txn_options, old_txn);
- // RocksJava relies on the assumption that
- // we do not allocate a new Transaction object
- // when providing an old_txn
- assert(txn == old_txn);
- return reinterpret_cast<jlong>(txn);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: getTransactionByName
- * Signature: (JLjava/lang/String;)J
- */
- jlong Java_org_rocksdb_TransactionDB_getTransactionByName(
- JNIEnv* env, jobject, jlong jhandle, jstring jname) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- const char* name = env->GetStringUTFChars(jname, nullptr);
- if (name == nullptr) {
- // exception thrown: OutOfMemoryError
- return 0;
- }
- ROCKSDB_NAMESPACE::Transaction* txn = txn_db->GetTransactionByName(name);
- env->ReleaseStringUTFChars(jname, name);
- return reinterpret_cast<jlong>(txn);
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: getAllPreparedTransactions
- * Signature: (J)[J
- */
- jlongArray Java_org_rocksdb_TransactionDB_getAllPreparedTransactions(
- JNIEnv* env, jobject, jlong jhandle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- std::vector<ROCKSDB_NAMESPACE::Transaction*> txns;
- txn_db->GetAllPreparedTransactions(&txns);
- const size_t size = txns.size();
- assert(size < UINT32_MAX); // does it fit in a jint?
- const jsize len = static_cast<jsize>(size);
- std::vector<jlong> tmp(len);
- for (jsize i = 0; i < len; ++i) {
- tmp[i] = reinterpret_cast<jlong>(txns[i]);
- }
- jlongArray jtxns = env->NewLongArray(len);
- if (jtxns == nullptr) {
- // exception thrown: OutOfMemoryError
- return nullptr;
- }
- env->SetLongArrayRegion(jtxns, 0, len, tmp.data());
- if (env->ExceptionCheck()) {
- // exception thrown: ArrayIndexOutOfBoundsException
- env->DeleteLocalRef(jtxns);
- return nullptr;
- }
- return jtxns;
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: getLockStatusData
- * Signature: (J)Ljava/util/Map;
- */
- jobject Java_org_rocksdb_TransactionDB_getLockStatusData(
- JNIEnv* env, jobject, jlong jhandle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- const std::unordered_multimap<uint32_t, ROCKSDB_NAMESPACE::KeyLockInfo>
- lock_status_data = txn_db->GetLockStatusData();
- const jobject jlock_status_data = ROCKSDB_NAMESPACE::HashMapJni::construct(
- env, static_cast<uint32_t>(lock_status_data.size()));
- if (jlock_status_data == nullptr) {
- // exception occurred
- return nullptr;
- }
- const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
- const int32_t, const ROCKSDB_NAMESPACE::KeyLockInfo, jobject, jobject>
- fn_map_kv =
- [env](const std::pair<const int32_t,
- const ROCKSDB_NAMESPACE::KeyLockInfo>& pair) {
- const jobject jlong_column_family_id =
- ROCKSDB_NAMESPACE::LongJni::valueOf(env, pair.first);
- if (jlong_column_family_id == nullptr) {
- // an error occurred
- return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
- }
- const jobject jkey_lock_info =
- ROCKSDB_NAMESPACE::KeyLockInfoJni::construct(env, pair.second);
- if (jkey_lock_info == nullptr) {
- // an error occurred
- return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
- }
- return std::unique_ptr<std::pair<jobject, jobject>>(
- new std::pair<jobject, jobject>(jlong_column_family_id,
- jkey_lock_info));
- };
- if (!ROCKSDB_NAMESPACE::HashMapJni::putAll(
- env, jlock_status_data, lock_status_data.begin(),
- lock_status_data.end(), fn_map_kv)) {
- // exception occcurred
- return nullptr;
- }
- return jlock_status_data;
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: getDeadlockInfoBuffer
- * Signature: (J)[Lorg/rocksdb/TransactionDB/DeadlockPath;
- */
- jobjectArray Java_org_rocksdb_TransactionDB_getDeadlockInfoBuffer(
- JNIEnv* env, jobject jobj, jlong jhandle) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- const std::vector<ROCKSDB_NAMESPACE::DeadlockPath> deadlock_info_buffer =
- txn_db->GetDeadlockInfoBuffer();
- const jsize deadlock_info_buffer_len =
- static_cast<jsize>(deadlock_info_buffer.size());
- jobjectArray jdeadlock_info_buffer = env->NewObjectArray(
- deadlock_info_buffer_len,
- ROCKSDB_NAMESPACE::DeadlockPathJni::getJClass(env), nullptr);
- if (jdeadlock_info_buffer == nullptr) {
- // exception thrown: OutOfMemoryError
- return nullptr;
- }
- jsize jdeadlock_info_buffer_offset = 0;
- auto buf_end = deadlock_info_buffer.end();
- for (auto buf_it = deadlock_info_buffer.begin(); buf_it != buf_end;
- ++buf_it) {
- const ROCKSDB_NAMESPACE::DeadlockPath deadlock_path = *buf_it;
- const std::vector<ROCKSDB_NAMESPACE::DeadlockInfo> deadlock_infos =
- deadlock_path.path;
- const jsize deadlock_infos_len =
- static_cast<jsize>(deadlock_info_buffer.size());
- jobjectArray jdeadlock_infos = env->NewObjectArray(
- deadlock_infos_len, ROCKSDB_NAMESPACE::DeadlockInfoJni::getJClass(env),
- nullptr);
- if (jdeadlock_infos == nullptr) {
- // exception thrown: OutOfMemoryError
- env->DeleteLocalRef(jdeadlock_info_buffer);
- return nullptr;
- }
- jsize jdeadlock_infos_offset = 0;
- auto infos_end = deadlock_infos.end();
- for (auto infos_it = deadlock_infos.begin(); infos_it != infos_end;
- ++infos_it) {
- const ROCKSDB_NAMESPACE::DeadlockInfo deadlock_info = *infos_it;
- const jobject jdeadlock_info =
- ROCKSDB_NAMESPACE::TransactionDBJni::newDeadlockInfo(
- env, jobj, deadlock_info.m_txn_id, deadlock_info.m_cf_id,
- deadlock_info.m_waiting_key, deadlock_info.m_exclusive);
- if (jdeadlock_info == nullptr) {
- // exception occcurred
- env->DeleteLocalRef(jdeadlock_info_buffer);
- return nullptr;
- }
- env->SetObjectArrayElement(jdeadlock_infos, jdeadlock_infos_offset++,
- jdeadlock_info);
- if (env->ExceptionCheck()) {
- // exception thrown: ArrayIndexOutOfBoundsException or
- // ArrayStoreException
- env->DeleteLocalRef(jdeadlock_info);
- env->DeleteLocalRef(jdeadlock_info_buffer);
- return nullptr;
- }
- }
- const jobject jdeadlock_path =
- ROCKSDB_NAMESPACE::DeadlockPathJni::construct(
- env, jdeadlock_infos, deadlock_path.limit_exceeded);
- if (jdeadlock_path == nullptr) {
- // exception occcurred
- env->DeleteLocalRef(jdeadlock_info_buffer);
- return nullptr;
- }
- env->SetObjectArrayElement(jdeadlock_info_buffer,
- jdeadlock_info_buffer_offset++, jdeadlock_path);
- if (env->ExceptionCheck()) {
- // exception thrown: ArrayIndexOutOfBoundsException or ArrayStoreException
- env->DeleteLocalRef(jdeadlock_path);
- env->DeleteLocalRef(jdeadlock_info_buffer);
- return nullptr;
- }
- }
- return jdeadlock_info_buffer;
- }
- /*
- * Class: org_rocksdb_TransactionDB
- * Method: setDeadlockInfoBufferSize
- * Signature: (JI)V
- */
- void Java_org_rocksdb_TransactionDB_setDeadlockInfoBufferSize(
- JNIEnv*, jobject, jlong jhandle, jint jdeadlock_info_buffer_size) {
- auto* txn_db = reinterpret_cast<ROCKSDB_NAMESPACE::TransactionDB*>(jhandle);
- txn_db->SetDeadlockInfoBufferSize(jdeadlock_info_buffer_size);
- }
|