Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ColumnFamilyDescriptor to be RocksObject #12505

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions java/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/cassandra_value_operator.cc
rocksjni/checkpoint.cc
rocksjni/clock_cache.cc
rocksjni/columnfamilydescriptor.cc
rocksjni/columnfamilyhandle.cc
rocksjni/compact_range_options.cc
rocksjni/compaction_filter.cc
Expand Down Expand Up @@ -321,6 +322,7 @@ set(JAVA_TEST_CLASSES
src/test/java/org/rocksdb/BytewiseComparatorRegressionTest.java
src/test/java/org/rocksdb/CheckPointTest.java
src/test/java/org/rocksdb/ClockCacheTest.java
src/test/java/org/rocksdb/ColumnFamilyDescriptorTest.java
src/test/java/org/rocksdb/ColumnFamilyOptionsTest.java
src/test/java/org/rocksdb/ColumnFamilyTest.java
src/test/java/org/rocksdb/CompactRangeOptionsTest.java
Expand Down Expand Up @@ -439,6 +441,7 @@ set(JAVA_TEST_RUNNING_CLASSES
org.rocksdb.BytewiseComparatorRegressionTest
org.rocksdb.CheckPointTest
org.rocksdb.ClockCacheTest
org.rocksdb.ColumnFamilyDescriptorTest
org.rocksdb.ColumnFamilyOptionsTest
org.rocksdb.ColumnFamilyTest
org.rocksdb.CompactRangeOptionsTest
Expand Down
64 changes: 64 additions & 0 deletions java/rocksjni/columnfamilydescriptor.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>

#include "include/org_rocksdb_ColumnFamilyDescriptor.h"
#include "rocksjni/portal.h"

/*
* Class: org_rocksdb_ColumnFamilyDescriptor
* Method: createNativeInstance
* Signature: ([BJ)J
*/
jlong Java_org_rocksdb_ColumnFamilyDescriptor_createNativeInstance(
JNIEnv* env, jclass, jbyteArray jname, jlong jcf_options_handle) {
jboolean has_exception = JNI_FALSE;

auto cf_name = ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
env, jname,
[](const char* str_data, const size_t str_len) {
return std::string(str_data, str_len);
},
&has_exception);

if (has_exception) {
return 0;
}

auto cf_options = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
jcf_options_handle);

ROCKSDB_NAMESPACE::ColumnFamilyDescriptor* cf_descriptor =
new ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options);

return GET_CPLUSPLUS_POINTER(cf_descriptor);
}

/*
* Class: org_rocksdb_ColumnFamilyDescriptor
* Method: getName
* Signature: (J)[B
*/
jbyteArray Java_org_rocksdb_ColumnFamilyDescriptor_getName(
JNIEnv* env, jclass, jlong jcf_descriptor_handle) {
auto cf_options =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
jcf_descriptor_handle);

return ROCKSDB_NAMESPACE::JniUtil::copyBytes(env, cf_options->name);
}

/*
* Class: org_rocksdb_ColumnFamilyDescriptor
* Method: disposeJni
* Signature: (J)V
*/
void Java_org_rocksdb_ColumnFamilyDescriptor_disposeJni(
JNIEnv*, jclass, jlong jcf_descriptor_handle) {
auto cf_options =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
jcf_descriptor_handle);

delete (cf_options);
}
43 changes: 8 additions & 35 deletions java/rocksjni/optimistic_transaction_db.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,56 +51,29 @@ jlong Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2(
* Signature: (JLjava/lang/String;[[B[J)[J
*/
jlongArray
Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2_3_3B_3J(
Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2_3J(
JNIEnv* env, jclass, jlong jdb_options_handle, jstring jdb_path,
jobjectArray jcolumn_names, jlongArray jcolumn_options_handles) {
jlongArray jcf_descriptors) {
const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
if (db_path == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}

std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> column_families;
const jsize len_cols = env->GetArrayLength(jcolumn_names);
const jsize len_cols = env->GetArrayLength(jcf_descriptors);
if (len_cols > 0) {
jlong* jco = env->GetLongArrayElements(jcolumn_options_handles, nullptr);
if (jco == nullptr) {
// exception thrown: OutOfMemoryError
env->ReleaseStringUTFChars(jdb_path, db_path);
auto cf_descriptors = std::make_unique<jlong[]>(len_cols);
env->GetLongArrayRegion(jcf_descriptors, 0, len_cols, cf_descriptors.get());
if (env->ExceptionCheck()) {
return nullptr;
}

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);
const jsize jcf_name_len = env->GetArrayLength(jcn_ba);
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 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);
*reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
cf_descriptors[i]));
}
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
}

auto* db_options =
Expand Down
4 changes: 2 additions & 2 deletions java/rocksjni/portal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6779,14 +6779,14 @@ class ColumnFamilyDescriptorJni : public JavaClass {
}

jmethodID mid = env->GetMethodID(jclazz, "<init>",
"([BLorg/rocksdb/ColumnFamilyOptions;)V");
"([BLorg/rocksdb/ColumnFamilyOptions;Z)V");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still create Java ColumnFamilyDescriptor objects from C++, I would think not after this refactoring...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I still have doubts. This code is used primarily to load options from file. We can approach creation of ColumnFamilyDescriptor  two ways :

  1. Just wrap the pointer. But then it breaks all existing code with ColumnFamilyOptions.
  2. Create new instances with ColumnFamilyOptions and keep ColumnFamilyDescriptor behavior close to what we already have in the codebase.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay let me look into this a bit deeper and come back to you...

if (mid == nullptr) {
// exception thrown: NoSuchMethodException or OutOfMemoryError
env->DeleteLocalRef(jcf_name);
return nullptr;
}

jobject jcfd = env->NewObject(jclazz, mid, jcf_name, cfopts);
jobject jcfd = env->NewObject(jclazz, mid, jcf_name, cfopts, JNI_TRUE);
if (env->ExceptionCheck()) {
env->DeleteLocalRef(jcf_name);
return nullptr;
Expand Down
138 changes: 40 additions & 98 deletions java/rocksjni/rocksjni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jlong Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2Z(

jlongArray rocksdb_open_helper(
JNIEnv* env, jlong jopt_handle, jstring jdb_path,
jobjectArray jcolumn_names, jlongArray jcolumn_options,
jlongArray jcf_descriptors,
std::function<ROCKSDB_NAMESPACE::Status(
const ROCKSDB_NAMESPACE::DBOptions&, const std::string&,
const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>&,
Expand All @@ -108,35 +108,21 @@ jlongArray rocksdb_open_helper(
return nullptr;
}

const jsize len_cols = env->GetArrayLength(jcolumn_names);
jlong* jco = env->GetLongArrayElements(jcolumn_options, nullptr);
if (jco == nullptr) {
// exception thrown: OutOfMemoryError
const jsize len_cols = env->GetArrayLength(jcf_descriptors);
auto cf_descriptors = std::make_unique<jlong[]>(len_cols);
env->GetLongArrayRegion(jcf_descriptors, 0, len_cols, cf_descriptors.get());
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}

std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> column_families;
jboolean has_exception = JNI_FALSE;
ROCKSDB_NAMESPACE::JniUtil::byteStrings<std::string>(
env, jcolumn_names,
[](const char* str_data, const size_t str_len) {
return std::string(str_data, str_len);
},
[&jco, &column_families](size_t idx, std::string cf_name) {
ROCKSDB_NAMESPACE::ColumnFamilyOptions* cf_options =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(jco[idx]);
column_families.push_back(
ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));
},
&has_exception);

env->ReleaseLongArrayElements(jcolumn_options, jco, JNI_ABORT);

if (has_exception == JNI_TRUE) {
// exception occurred
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
column_families.reserve(len_cols);
for (int i = 0; i < len_cols; i++) {
column_families.push_back(
*reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
cf_descriptors[i]));
}

auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jopt_handle);
Expand Down Expand Up @@ -183,13 +169,12 @@ jlongArray rocksdb_open_helper(
* Method: openROnly
* Signature: (JLjava/lang/String;[[B[JZ)[J
*/
jlongArray Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3_3B_3JZ(
jlongArray Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3JZ(
JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path,
jobjectArray jcolumn_names, jlongArray jcolumn_options,
jboolean jerror_if_wal_file_exists) {
jlongArray jcf_descriptors, jboolean jerror_if_wal_file_exists) {
const bool error_if_wal_file_exists = jerror_if_wal_file_exists == JNI_TRUE;
return rocksdb_open_helper(
env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options,
env, jopt_handle, jdb_path, jcf_descriptors,
[error_if_wal_file_exists](
const ROCKSDB_NAMESPACE::DBOptions& options,
const std::string& db_path,
Expand All @@ -208,11 +193,11 @@ jlongArray Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3_3B_3JZ(
* Method: open
* Signature: (JLjava/lang/String;[[B[J)[J
*/
jlongArray Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2_3_3B_3J(
jlongArray Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2_3J(
JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path,
jobjectArray jcolumn_names, jlongArray jcolumn_options) {
jlongArray jcf_descriptors) {
return rocksdb_open_helper(
env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options,
env, jopt_handle, jdb_path, jcf_descriptors,
(ROCKSDB_NAMESPACE::Status(*)(
const ROCKSDB_NAMESPACE::DBOptions&, const std::string&,
const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>&,
Expand Down Expand Up @@ -257,10 +242,9 @@ jlong Java_org_rocksdb_RocksDB_openAsSecondary__JLjava_lang_String_2Ljava_lang_S
* Signature: (JLjava/lang/String;Ljava/lang/String;[[B[J)[J
*/
jlongArray
Java_org_rocksdb_RocksDB_openAsSecondary__JLjava_lang_String_2Ljava_lang_String_2_3_3B_3J(
Java_org_rocksdb_RocksDB_openAsSecondary__JLjava_lang_String_2Ljava_lang_String_2_3J(
JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path,
jstring jsecondary_db_path, jobjectArray jcolumn_names,
jlongArray jcolumn_options) {
jstring jsecondary_db_path, jlongArray jcf_descriptors) {
const char* secondary_db_path =
env->GetStringUTFChars(jsecondary_db_path, nullptr);
if (secondary_db_path == nullptr) {
Expand All @@ -269,7 +253,7 @@ Java_org_rocksdb_RocksDB_openAsSecondary__JLjava_lang_String_2Ljava_lang_String_
}

jlongArray jhandles = rocksdb_open_helper(
env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options,
env, jopt_handle, jdb_path, jcf_descriptors,
[secondary_db_path](
const ROCKSDB_NAMESPACE::DBOptions& options,
const std::string& db_path,
Expand Down Expand Up @@ -346,27 +330,14 @@ jobjectArray Java_org_rocksdb_RocksDB_listColumnFamilies(JNIEnv* env, jclass,
*/
jlong Java_org_rocksdb_RocksDB_createColumnFamily(JNIEnv* env, jclass,
jlong jhandle,
jbyteArray jcf_name,
jint jcf_name_len,
jlong jcf_options_handle) {
jlong jcf_descriptor) {
auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
jboolean has_exception = JNI_FALSE;
const std::string cf_name =
ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
env, jcf_name, jcf_name_len,
[](const char* str, const size_t len) {
return std::string(str, len);
},
&has_exception);
if (has_exception == JNI_TRUE) {
// exception occurred
return 0;
}
auto* cf_options = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
jcf_options_handle);
auto* cf_descriptor =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
jcf_descriptor);
ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
ROCKSDB_NAMESPACE::Status s =
db->CreateColumnFamily(*cf_options, cf_name, &cf_handle);
ROCKSDB_NAMESPACE::Status s = db->CreateColumnFamily(
cf_descriptor->options, cf_descriptor->name, &cf_handle);
if (!s.ok()) {
// error occurred
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
Expand Down Expand Up @@ -421,69 +392,40 @@ jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__JJ_3_3B(
* Method: createColumnFamilies
* Signature: (J[J[[B)[J
*/
jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__J_3J_3_3B(
JNIEnv* env, jclass, jlong jhandle, jlongArray jcf_options_handles,
jobjectArray jcf_names) {
jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__J_3J(
JNIEnv* env, jclass, jlong jhandle, jlongArray jcf_descriptor_handles) {
auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
const jsize jlen = env->GetArrayLength(jcf_options_handles);
const jsize jlen = env->GetArrayLength(jcf_descriptor_handles);

std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descriptors;
cf_descriptors.reserve(jlen);

jlong* jcf_options_handles_elems =
env->GetLongArrayElements(jcf_options_handles, nullptr);
if (jcf_options_handles_elems == nullptr) {
// exception thrown: OutOfMemoryError
auto cf_descriptor_handles = std::make_unique<jlong[]>(jlen);

env->GetLongArrayRegion(jcf_descriptor_handles, 0, jlen,
cf_descriptor_handles.get());
if (env->ExceptionCheck()) {
return nullptr;
}

// extract the column family descriptors
jboolean has_exception = JNI_FALSE;
for (jsize i = 0; i < jlen; i++) {
auto* cf_options =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
jcf_options_handles_elems[i]);
jbyteArray jcf_name =
static_cast<jbyteArray>(env->GetObjectArrayElement(jcf_names, i));
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->ReleaseLongArrayElements(jcf_options_handles,
jcf_options_handles_elems, JNI_ABORT);
return nullptr;
}
const std::string cf_name =
ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
env, jcf_name,
[](const char* str, const size_t len) {
return std::string(str, len);
},
&has_exception);
if (has_exception == JNI_TRUE) {
// exception occurred
env->DeleteLocalRef(jcf_name);
env->ReleaseLongArrayElements(jcf_options_handles,
jcf_options_handles_elems, JNI_ABORT);
return nullptr;
}

cf_descriptors.push_back(
ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));

env->DeleteLocalRef(jcf_name);
auto cf_descriptor_handle =
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(
cf_descriptor_handles[i]);
cf_descriptors.push_back(*cf_descriptor_handle);
}

std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
ROCKSDB_NAMESPACE::Status s =
db->CreateColumnFamilies(cf_descriptors, &cf_handles);

env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems,
JNI_ABORT);

if (!s.ok()) {
// error occurred
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
return nullptr;
}

jboolean has_exception = JNI_FALSE;
jlongArray jcf_handles = ROCKSDB_NAMESPACE::JniUtil::toJPointers<
ROCKSDB_NAMESPACE::ColumnFamilyHandle>(env, cf_handles, &has_exception);
if (has_exception == JNI_TRUE) {
Expand Down