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

Conversation

rhubner
Copy link
Contributor

@rhubner rhubner commented Apr 4, 2024

Fix memory leak, see #12224 for details

@rhubner rhubner force-pushed the eb/cf-descriptor-refactor branch 2 times, most recently from 9a2c8af to 624b2ae Compare April 5, 2024 05:40
@adamretter adamretter self-requested a review April 5, 2024 07:56
Copy link
Collaborator

@adamretter adamretter left a comment

Choose a reason for hiding this comment

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

Some initial feedback...

(JNIEnv* env, jclass, jlong jcf_descriptor_handle) {
auto cf_options = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor*>(jcf_descriptor_handle);

return GET_CPLUSPLUS_POINTER(&cf_options->options); //TODO -> Should we copy options and leave it on Java developer to delete?
Copy link
Collaborator

Choose a reason for hiding this comment

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

I need to just check through some ownership stuff here, and then I will come back to you on this...

@@ -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...

jcf_options_handles_elems, JNI_ABORT);
return nullptr;
}
env->GetLongArrayRegion(jcf_descriptor_handles, 0, jlen, cf_descriptor_handles.get());
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to check for an exception after this JNI call

}
@Override
protected void disposeInternal(final long handle) {
disposeJni(nativeHandle_);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the order of these functions calls should be swapped, and the disposeJni should go in a finally block.

Copy link
Collaborator

Choose a reason for hiding this comment

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

How about instead, so that we don't for this class have a native method called disposeJni instead of the usual name: disposeInternal:

@Override
protected void disposeInternal() {
  try {
    if (implicitlyCreatedColumnFamilyOptions) {
      columnFamilyOptions.close();
    }
  } finally {
    super.disposeInternal();
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

disposeJni is static. And I can't override method with static method. This is why I have disposeJni

I will swap the order and add finally block.

Copy link
Collaborator

@adamretter adamretter Apr 5, 2024

Choose a reason for hiding this comment

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

Okay but you don't need to add a disposeJni method. Other classes that extend RocksObject add a disposeInternal(nativeHandle) method - we should follow the same pattern here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but you wanted to change native methods from instance method to static method #11882 . So then I need to come with new name. Looking on the PR #11882 I used name disposeInternalJni


assertThat(result).isNotNull();

ColumnFamilyOptions cfOptions = result.getOptions();
Copy link
Collaborator

Choose a reason for hiding this comment

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

final please

try (final RocksDB db =
RocksDB.open(dbFolder.getRoot().getAbsolutePath());
ColumnFamilyDescriptor cfDescriptor = new ColumnFamilyDescriptor("myCf".getBytes(StandardCharsets.UTF_8))) {
ColumnFamilyHandle cfHandle = db.createColumnFamily(cfDescriptor);
Copy link
Collaborator

Choose a reason for hiding this comment

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

final please


try (final RocksDB db =
RocksDB.open(dbFolder.getRoot().getAbsolutePath());
ColumnFamilyDescriptor cfDescriptor = new ColumnFamilyDescriptor("myCf".getBytes(StandardCharsets.UTF_8))) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

final please

ColumnFamilyDescriptor cfDescriptor = new ColumnFamilyDescriptor("myCf".getBytes(StandardCharsets.UTF_8))) {
ColumnFamilyHandle cfHandle = db.createColumnFamily(cfDescriptor);

ColumnFamilyDescriptor result = cfHandle.getDescriptor(); // This creates new ColumnFamilyDescriptor in JNI code.
Copy link
Collaborator

Choose a reason for hiding this comment

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

final please


@Test
public void closeTransitiveResources() throws RocksDBException {
ColumnFamilyDescriptor cfDescriptor = new ColumnFamilyDescriptor("myCf".getBytes(StandardCharsets.UTF_8));
Copy link
Collaborator

Choose a reason for hiding this comment

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

final variables please (also more below!)

@adamretter
Copy link
Collaborator

@rhubner Do you also need to update the src.mk file for the Make build?

@rhubner
Copy link
Contributor Author

rhubner commented Apr 5, 2024

@rhubner Do you also need to update the src.mk file for the Make build?

I did

src.mk Outdated
@@ -651,6 +651,7 @@ JNI_NATIVE_SOURCES = \
java/rocksjni/checkpoint.cc \
java/rocksjni/clock_cache.cc \
java/rocksjni/cache.cc \
java/rocksjni/columncamilydescriptor.cc \
Copy link
Collaborator

Choose a reason for hiding this comment

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

columncamilydescriptor.cc -> columnfamilydescriptor.cc

Copy link
Collaborator

Choose a reason for hiding this comment

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

Just wondering if this indicates that tests have not been run yet with the Make build?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I name the file wrongly and then I copied error everywhere.

Test are running : https://github.com/facebook/rocksdb/actions/runs/8565557203/job/23473783606?pr=12505

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants