Add Java API for rocksdb::CancelAllBackgroundWork() (#6657)

Summary:
Adding a Java API for rocksdb::CancelAllBackgroundWork() so that the user can call this (when required) before closing the DB. This is to **prevent the crashes when manual compaction is running and the user decides to close the DB**.

Calling CancelAllBackgroundWork() seems to be the recommended way to make sure that it's safe to close the DB (according to RocksDB FAQ: https://github.com/facebook/rocksdb/wiki/RocksDB-FAQ#basic-readwrite).
Pull Request resolved: https://github.com/facebook/rocksdb/pull/6657

Reviewed By: cheng-chang

Differential Revision: D20896395

Pulled By: pdillinger

fbshipit-source-id: 8a8208c10093db09bd35db9af362211897870d96
This commit is contained in:
Sahib Pandori 2020-04-07 20:13:55 -07:00 committed by Facebook GitHub Bot
parent e5f1bfc263
commit 487ebe4fd5
3 changed files with 75 additions and 0 deletions

View File

@ -2610,6 +2610,17 @@ jobjectArray Java_org_rocksdb_RocksDB_compactFiles(
return ROCKSDB_NAMESPACE::JniUtil::toJavaStrings(env, &output_file_names); return ROCKSDB_NAMESPACE::JniUtil::toJavaStrings(env, &output_file_names);
} }
/*
* Class: org_rocksdb_RocksDB
* Method: cancelAllBackgroundWork
* Signature: (JZ)V
*/
void Java_org_rocksdb_RocksDB_cancelAllBackgroundWork(
JNIEnv*, jobject, jlong jdb_handle, jboolean jwait) {
auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
rocksdb::CancelAllBackgroundWork(db, jwait);
}
/* /*
* Class: org_rocksdb_RocksDB * Class: org_rocksdb_RocksDB
* Method: pauseBackgroundWork * Method: pauseBackgroundWork

View File

@ -3479,6 +3479,17 @@ public class RocksDB extends RocksObject {
compactionJobInfo == null ? 0 : compactionJobInfo.nativeHandle_)); compactionJobInfo == null ? 0 : compactionJobInfo.nativeHandle_));
} }
/**
* This function will cancel all currently running background processes.
*
* @param wait if true, wait for all background work to be cancelled before
* returning.
*
*/
public void cancelAllBackgroundWork(boolean wait) {
cancelAllBackgroundWork(nativeHandle_, wait);
}
/** /**
* This function will wait until all currently running background processes * This function will wait until all currently running background processes
* finish. After it returns, no background process will be run until * finish. After it returns, no background process will be run until
@ -4457,6 +4468,8 @@ public class RocksDB extends RocksObject {
final int outputLevel, final int outputLevel,
final int outputPathId, final int outputPathId,
final long compactionJobInfoHandle) throws RocksDBException; final long compactionJobInfoHandle) throws RocksDBException;
private native void cancelAllBackgroundWork(final long handle,
final boolean wait);
private native void pauseBackgroundWork(final long handle) private native void pauseBackgroundWork(final long handle)
throws RocksDBException; throws RocksDBException;
private native void continueBackgroundWork(final long handle) private native void continueBackgroundWork(final long handle)

View File

@ -1084,6 +1084,57 @@ public class RocksDBTest {
} }
} }
@Test
public void continueBackgroundWorkAfterCancelAllBackgroundWork() throws RocksDBException {
final int KEY_SIZE = 20;
final int VALUE_SIZE = 300;
try (final DBOptions opt = new DBOptions().
setCreateIfMissing(true).
setCreateMissingColumnFamilies(true);
final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions()
) {
final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
Arrays.asList(
new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)
);
final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
// open the database
try (final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath(),
columnFamilyDescriptors,
columnFamilyHandles)) {
try {
db.cancelAllBackgroundWork(true);
try {
db.put(new byte[KEY_SIZE], new byte[VALUE_SIZE]);
db.flush(new FlushOptions().setWaitForFlush(true));
fail("Expected RocksDBException to be thrown if we attempt to trigger a flush after" +
" all background work is cancelled.");
} catch (RocksDBException ignored) { }
} finally {
for (final ColumnFamilyHandle handle : columnFamilyHandles) {
handle.close();
}
}
}
}
}
@Test
public void cancelAllBackgroundWorkTwice() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final RocksDB db = RocksDB.open(options,
dbFolder.getRoot().getAbsolutePath())
) {
// Cancel all background work synchronously
db.cancelAllBackgroundWork(true);
// Cancel all background work asynchronously
db.cancelAllBackgroundWork(false);
}
}
@Test @Test
public void pauseContinueBackgroundWork() throws RocksDBException { public void pauseContinueBackgroundWork() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true); try (final Options options = new Options().setCreateIfMissing(true);