Skip to content

Add support for Wide columns in Java#12334

Open
rhubner wants to merge 17 commits into
facebook:mainfrom
evolvedbinary:eb/wide-columns
Open

Add support for Wide columns in Java#12334
rhubner wants to merge 17 commits into
facebook:mainfrom
evolvedbinary:eb/wide-columns

Conversation

@rhubner

@rhubner rhubner commented Feb 7, 2024

Copy link
Copy Markdown
Contributor

This PR adds support for wide columns in Java. First implementation is primarily focused on correctness rather than performance. We would like to merge this first and hear feedback from RocksDB Java community before refining it.

Fix #12113

@rhubner rhubner force-pushed the eb/wide-columns branch 2 times, most recently from 33d9052 to a0a634e Compare February 9, 2024 04:26
@rhubner rhubner force-pushed the eb/wide-columns branch 2 times, most recently from 47a2294 to 31e973b Compare March 5, 2024 14:07
@adamretter adamretter self-requested a review March 13, 2024 08:18

@adamretter adamretter left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I have done a partial review... There are three main things that you might want to look at IMHO:

  1. Whether you really need std::make_unique for a pointer that never escapes its function scope. It seems superfluous to me.

  2. Clean up of JNI resources you have allocated before you return from a function when an error condition occurs (or even when the function completes normally)

  3. String conversion from JNI types to C++ standard types. There are functions in portal.h to assist in doing this correctly. If they don't suit, we can consider adding an additional one for your use-case.

Comment thread java/rocksjni/portal.h Outdated
Comment thread java/rocksjni/portal.h
"ByteBuffer)");
return;
}
auto name = reinterpret_cast<char*>(_name) + namesOffset[i];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There are utility methods in portal.h to go from jstring to std::string or char* - could we use those here instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We are not working with jstring but with void* here. I cast it to char* so that I can add offset to it.

Comment thread java/rocksjni/portal.h

const auto columns_len = static_cast<int>(env->GetArrayLength(jNames));

auto namesOffset = std::make_unique<jint[]>(columns_len);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

make_unique seems an unnecessary overhead here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's true, but it allows me to automatically release all the memory allocated here and simplify return statements.

Comment thread java/rocksjni/portal.h
auto j_value =
static_cast<jbyteArray>(env->GetObjectArrayElement(jvalues, i));
if (env->ExceptionCheck()) {
return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to free the JNI local references for name/jname here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No we don't need to. doc

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As I understand it, GetObjectArrayElement returns a jobject and when you are finished with this (on either success or error paths), you should call DeleteLocalRef on that object. There are other examples of this pattern already in the existing code-base, for example: https://github.com/facebook/rocksdb/blob/main/java/rocksjni/rocksjni.cc#L462

Comment thread java/rocksjni/portal.h
auto value = std::make_unique<jbyte[]>(jvalue_len);
env->GetByteArrayRegion(j_value, 0, jvalue_len, value.get());
if (env->ExceptionCheck()) {
return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to free the JNI local references for name/jname and value/jvalue here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No we don't need to. GetByteArrayRegion only copies data from java arrays to provide memory. This memory is allocated as a smart pointer and is automatically released when we exit the method.

Comment thread java/rocksjni/rocksjni.cc
auto value = reinterpret_cast<char*>(_value) + valuesOffset[i];
valuesRequiredSize[i] = static_cast<jint>(column.value().size());
max_data_len = std::min(valuesRequiredSize[i], (valuesLen[i]));
std::memcpy(value, column.value().data(), max_data_len);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is explicit memcpy needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, See previous comment

Comment thread java/rocksjni/rocksjni.cc
env->SetIntArrayRegion(jnamesRequiredSize, 0, max_items,
namesRequiredSize.get());
if (env->ExceptionCheck()) {
return nullptr;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to free the previous JNI array fetches and local-references here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No we don't need to. See previous comment

Comment thread java/rocksjni/rocksjni.cc
env->SetIntArrayRegion(jvaluesRequiredSize, 0, max_items,
valuesRequiredSize.get());
if (env->ExceptionCheck()) {
return nullptr;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to free the previous JNI array fetches and local-references here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No we don't need to. See previous comment

Comment thread java/rocksjni/rocksjni.cc Outdated
"Invalid key argument (argument is not a valid direct ByteBuffer)");
return nullptr;
}
auto key = reinterpret_cast<char*>(_key) + key_offset;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could this use portal.h for string conversion

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No. See previous comment

Comment thread java/rocksjni/rocksjni.cc
jlong jcf_handle) {
auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);

auto key = std::make_unique<jbyte[]>(keyLength);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

std::make_unique seems superfluous here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, See previous comment

@rhubner rhubner force-pushed the eb/wide-columns branch 5 times, most recently from 239f9df to a9f7753 Compare March 20, 2024 08:22
@rhubner rhubner marked this pull request as ready for review March 25, 2024 17:16
@test-wangxiaoyu

Copy link
Copy Markdown

Hello, after I finished compiling, the run encountered the following error:
librocksdbjni-osx-x86_64.jnilib was not found inside JAR.
My machine environment is macbook air 2022,The compiled command is as follows:
make clean jclean
DEBUG_LEVEL=0 make -j12 rocksdbjava

@rhubner

rhubner commented Mar 27, 2024

Copy link
Copy Markdown
Contributor Author

Hello @test-wangxiaoyu

librocksdbjni-osx-x86_64.jnilib was not found inside JAR.

This is a very strange error. Considering you have a macbook air 2022, these models have ARM CPU (
Mac computers with Apple silicon ) and Java is trying to search for Intel version of native library. My suggestion is to check that you are running native ARM version of Java. Sometimes also called aarch64. From the error message it looks like you are running Intel version of Java via Rosetta emulation layer. You can download correct version from Adoptium project or Liberica

You can also check what native library is inside the jar archive. For example this is how it looks like on my linux machine.

$ jar -t --file java/target/rocksdbjni-9.2.0-linux64.jar | grep librocksdbjni
librocksdbjni-linux64.so

Radek

@adamretter adamretter self-requested a review July 2, 2024 12:33

@adamretter adamretter left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@adamretter

Copy link
Copy Markdown
Collaborator

@pdillinger @ajkr Can we get this one merged please?

@nomed

nomed commented Sep 18, 2024

Copy link
Copy Markdown

Hi,

Thank you for the great work on this feature! I am very interested in using wide columns in RocksDB. Could you please let me know if this feature is planned to be merged? Also, do you have an estimated timeline for when it might be available in a release?

Thank you!

@rhubner rhubner force-pushed the eb/wide-columns branch 2 times, most recently from 1c944f2 to e1d45d1 Compare September 30, 2024 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment