From c8f3606731dcb8ddc3b6e2b1c8f33c62a5aad1ce Mon Sep 17 00:00:00 2001 From: Sagar Vemuri Date: Thu, 21 Sep 2017 17:15:27 -0700 Subject: [PATCH] Expose LoadLatestOptions, LoadOptionsFromFile and GetLatestOptionsFileName APIs in RocksJava Summary: JNI wrappers for LoadLatestOptions, LoadOptionsFromFile and GetLatestOptionsFileName APIs. Closes https://github.com/facebook/rocksdb/pull/2898 Differential Revision: D5857934 Pulled By: sagar0 fbshipit-source-id: 68b79e83eab8de9416e3f1fef73e11cf7947e90a --- java/Makefile | 4 +- java/rocksjni/options_util.cc | 114 ++++++++++++ java/rocksjni/portal.h | 168 ++++++++++++------ .../java/org/rocksdb/ColumnFamilyOptions.java | 5 +- .../main/java/org/rocksdb/OptionsUtil.java | 142 +++++++++++++++ .../java/org/rocksdb/OptionsUtilTest.java | 126 +++++++++++++ src.mk | 1 + 7 files changed, 506 insertions(+), 54 deletions(-) create mode 100644 java/rocksjni/options_util.cc create mode 100644 java/src/main/java/org/rocksdb/OptionsUtil.java create mode 100644 java/src/test/java/org/rocksdb/OptionsUtilTest.java diff --git a/java/Makefile b/java/Makefile index b29447bd8..92c7923ed 100644 --- a/java/Makefile +++ b/java/Makefile @@ -30,6 +30,7 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\ org.rocksdb.LRUCache\ org.rocksdb.MergeOperator\ org.rocksdb.Options\ + org.rocksdb.OptionsUtil\ org.rocksdb.PlainTableConfig\ org.rocksdb.RateLimiter\ org.rocksdb.ReadOptions\ @@ -96,12 +97,13 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\ org.rocksdb.InfoLogLevelTest\ org.rocksdb.KeyMayExistTest\ org.rocksdb.LoggerTest\ - org.rocksdb.LRUCacheTest\ + org.rocksdb.LRUCacheTest\ org.rocksdb.MemTableTest\ org.rocksdb.MergeTest\ org.rocksdb.MixedOptionsTest\ org.rocksdb.MutableColumnFamilyOptionsTest\ org.rocksdb.NativeLibraryLoaderTest\ + org.rocksdb.OptionsUtilTest\ org.rocksdb.OptionsTest\ org.rocksdb.PlainTableConfigTest\ org.rocksdb.RateLimiterTest\ diff --git a/java/rocksjni/options_util.cc b/java/rocksjni/options_util.cc new file mode 100644 index 000000000..b68b73e13 --- /dev/null +++ b/java/rocksjni/options_util.cc @@ -0,0 +1,114 @@ +// 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++ and enables +// calling C++ rocksdb::OptionsUtil methods from Java side. + +#include + +#include "include/org_rocksdb_OptionsUtil.h" + +#include "rocksdb/db.h" +#include "rocksdb/env.h" +#include "rocksdb/utilities/options_util.h" +#include "rocksjni/portal.h" + +void build_column_family_descriptor_list( + JNIEnv* env, jobject jcfds, + std::vector& cf_descs) { + jmethodID add_mid = rocksdb::ListJni::getListAddMethodId(env); + if (add_mid == nullptr) { + // exception occurred accessing method + return; + } + + // Column family descriptor + for (rocksdb::ColumnFamilyDescriptor& cfd : cf_descs) { + // Construct a ColumnFamilyDescriptor java object + jobject jcfd = rocksdb::ColumnFamilyDescriptorJni::construct(env, &cfd); + if (env->ExceptionCheck()) { + // exception occurred constructing object + if (jcfd != nullptr) { + env->DeleteLocalRef(jcfd); + } + return; + } + + // Add the object to java list. + jboolean rs = env->CallBooleanMethod(jcfds, add_mid, jcfd); + if (env->ExceptionCheck() || rs == JNI_FALSE) { + // exception occurred calling method, or could not add + if (jcfd != nullptr) { + env->DeleteLocalRef(jcfd); + } + return; + } + } +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: loadLatestOptions + * Signature: (Ljava/lang/String;JLjava/util/List;Z)V + */ +void Java_org_rocksdb_OptionsUtil_loadLatestOptions( + JNIEnv* env, jclass jcls, jstring jdbpath, jlong jenv_handle, + jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) { + const char* db_path = env->GetStringUTFChars(jdbpath, nullptr); + std::vector cf_descs; + rocksdb::Status s = rocksdb::LoadLatestOptions( + db_path, reinterpret_cast(jenv_handle), + reinterpret_cast(jdb_opts_handle), &cf_descs, + ignore_unknown_options); + env->ReleaseStringUTFChars(jdbpath, db_path); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } + + build_column_family_descriptor_list(env, jcfds, cf_descs); +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: loadOptionsFromFile + * Signature: (Ljava/lang/String;JJLjava/util/List;Z)V + */ +void Java_org_rocksdb_OptionsUtil_loadOptionsFromFile( + JNIEnv* env, jclass jcls, jstring jopts_file_name, jlong jenv_handle, + jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) { + const char* opts_file_name = env->GetStringUTFChars(jopts_file_name, nullptr); + std::vector cf_descs; + rocksdb::Status s = rocksdb::LoadOptionsFromFile( + opts_file_name, reinterpret_cast(jenv_handle), + reinterpret_cast(jdb_opts_handle), &cf_descs, + ignore_unknown_options); + env->ReleaseStringUTFChars(jopts_file_name, opts_file_name); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } + + build_column_family_descriptor_list(env, jcfds, cf_descs); +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: getLatestOptionsFileName + * Signature: (Ljava/lang/String;J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName( + JNIEnv* env, jclass jcls, jstring jdbpath, jlong jenv_handle) { + const char* db_path = env->GetStringUTFChars(jdbpath, nullptr); + std::string options_file_name; + if (db_path != nullptr) { + rocksdb::GetLatestOptionsFileName( + db_path, reinterpret_cast(jenv_handle), + &options_file_name); + } + env->ReleaseStringUTFChars(jdbpath, db_path); + + return env->NewStringUTF(options_file_name.c_str()); +} diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index ed671ce6e..2edea801b 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -584,10 +584,13 @@ class DBOptionsJni : public RocksDBNativeClass< } }; -class ColumnFamilyDescriptorJni : public JavaClass { +// The portal class for org.rocksdb.ColumnFamilyOptions +class ColumnFamilyOptionsJni + : public RocksDBNativeClass { public: /** - * Get the Java Class org.rocksdb.ColumnFamilyDescriptor + * Get the Java Class org.rocksdb.ColumnFamilyOptions * * @param env A pointer to the Java environment * @@ -596,69 +599,40 @@ class ColumnFamilyDescriptorJni : public JavaClass { * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown */ static jclass getJClass(JNIEnv* env) { - return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyDescriptor"); + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/ColumnFamilyOptions"); } /** - * Get the Java Method: ColumnFamilyDescriptor#columnFamilyName + * Create a new Java org.rocksdb.ColumnFamilyOptions object with the same + * properties as the provided C++ rocksdb::ColumnFamilyOptions object * * @param env A pointer to the Java environment + * @param cfoptions A pointer to rocksdb::ColumnFamilyOptions object * - * @return The Java Method ID or nullptr if the class or method id could not - * be retieved + * @return A reference to a Java org.rocksdb.ColumnFamilyOptions object, or + * nullptr if an an exception occurs */ - static jmethodID getColumnFamilyNameMethod(JNIEnv* env) { + static jobject construct(JNIEnv* env, const ColumnFamilyOptions* cfoptions) { + auto* cfo = new rocksdb::ColumnFamilyOptions(*cfoptions); jclass jclazz = getJClass(env); if(jclazz == nullptr) { // exception occurred accessing class return nullptr; } - static jmethodID mid = - env->GetMethodID(jclazz, "columnFamilyName", "()[B"); - assert(mid != nullptr); - return mid; - } - - /** - * Get the Java Method: ColumnFamilyDescriptor#columnFamilyOptions - * - * @param env A pointer to the Java environment - * - * @return The Java Method ID or nullptr if the class or method id could not - * be retieved - */ - static jmethodID getColumnFamilyOptionsMethod(JNIEnv* env) { - jclass jclazz = getJClass(env); - if(jclazz == nullptr) { - // exception occurred accessing class + jmethodID mid = env->GetMethodID(jclazz, "", "(J)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError return nullptr; } - static jmethodID mid = - env->GetMethodID(jclazz, "columnFamilyOptions", - "()Lorg/rocksdb/ColumnFamilyOptions;"); - assert(mid != nullptr); - return mid; - } -}; + jobject jcfd = env->NewObject(jclazz, mid, reinterpret_cast(cfo)); + if (env->ExceptionCheck()) { + return nullptr; + } -// The portal class for org.rocksdb.ColumnFamilyOptions -class ColumnFamilyOptionsJni : public RocksDBNativeClass< - rocksdb::ColumnFamilyOptions*, ColumnFamilyOptionsJni> { - public: - /** - * Get the Java Class org.rocksdb.ColumnFamilyOptions - * - * @param env A pointer to the Java environment - * - * @return The Java Class or nullptr if one of the - * ClassFormatError, ClassCircularityError, NoClassDefFoundError, - * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown - */ - static jclass getJClass(JNIEnv* env) { - return RocksDBNativeClass::getJClass(env, - "org/rocksdb/ColumnFamilyOptions"); + return jcfd; } }; @@ -1202,7 +1176,7 @@ class SliceJni : public NativeRocksMutableObject< // exception occurred accessing method return nullptr; } - + jobject jslice = env->NewObject(jclazz, mid); if(env->ExceptionCheck()) { return nullptr; @@ -1719,7 +1693,7 @@ class WBWIRocksIteratorJni : public JavaClass { /** * Gets the value of the WBWIRocksIterator#entry * - * @param env A pointer to the Java environment + * @param env A pointer to the Java environment * @param jwbwi_rocks_iterator A reference to a WBWIIterator * * @return A reference to a Java WBWIRocksIterator.WriteEntry object, or @@ -2479,7 +2453,7 @@ class TickerTypeJni { return 0x5C; case rocksdb::Tickers::TICKER_ENUM_MAX: return 0x5D; - + default: // undefined/default return 0x0; @@ -3337,5 +3311,97 @@ class JniUtil { } }; +class ColumnFamilyDescriptorJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.ColumnFamilyDescriptor + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyDescriptor"); + } + + /** + * Create a new Java org.rocksdb.ColumnFamilyDescriptor object with the same + * properties as the provided C++ rocksdb::ColumnFamilyDescriptor object + * + * @param env A pointer to the Java environment + * @param cfd A pointer to rocksdb::ColumnFamilyDescriptor object + * + * @return A reference to a Java org.rocksdb.ColumnFamilyDescriptor object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, ColumnFamilyDescriptor* cfd) { + jbyteArray cfname = JniUtil::copyBytes(env, cfd->name); + jobject cfopts = ColumnFamilyOptionsJni::construct(env, &(cfd->options)); + + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "", + "([BLorg/rocksdb/ColumnFamilyOptions;)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jcfd = env->NewObject(jclazz, mid, cfname, cfopts); + if (env->ExceptionCheck()) { + return nullptr; + } + + return jcfd; + } + + /** + * Get the Java Method: ColumnFamilyDescriptor#columnFamilyName + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getColumnFamilyNameMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "columnFamilyName", "()[B"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: ColumnFamilyDescriptor#columnFamilyOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getColumnFamilyOptionsMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "columnFamilyOptions", "()Lorg/rocksdb/ColumnFamilyOptions;"); + assert(mid != nullptr); + return mid; + } +}; + } // namespace rocksdb #endif // JAVA_ROCKSJNI_PORTAL_H_ diff --git a/java/src/main/java/org/rocksdb/ColumnFamilyOptions.java b/java/src/main/java/org/rocksdb/ColumnFamilyOptions.java index 647b92e16..6665cc493 100644 --- a/java/src/main/java/org/rocksdb/ColumnFamilyOptions.java +++ b/java/src/main/java/org/rocksdb/ColumnFamilyOptions.java @@ -736,12 +736,13 @@ public class ColumnFamilyOptions extends RocksObject } /** - *

Private constructor to be used by + *

Constructor to be used by * {@link #getColumnFamilyOptionsFromProps(java.util.Properties)}

+ * and also called via JNI. * * @param handle native handle to ColumnFamilyOptions instance. */ - private ColumnFamilyOptions(final long handle) { + public ColumnFamilyOptions(final long handle) { super(handle); } diff --git a/java/src/main/java/org/rocksdb/OptionsUtil.java b/java/src/main/java/org/rocksdb/OptionsUtil.java new file mode 100644 index 000000000..f153556ba --- /dev/null +++ b/java/src/main/java/org/rocksdb/OptionsUtil.java @@ -0,0 +1,142 @@ +// 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). + +package org.rocksdb; + +import java.util.ArrayList; +import java.util.List; + +public class OptionsUtil { + /** + * A static method to construct the DBOptions and ColumnFamilyDescriptors by + * loading the latest RocksDB options file stored in the specified rocksdb + * database. + * + * Note that the all the pointer options (except table_factory, which will + * be described in more details below) will be initialized with the default + * values. Developers can further initialize them after this function call. + * Below is an example list of pointer options which will be initialized. + * + * - env + * - memtable_factory + * - compaction_filter_factory + * - prefix_extractor + * - comparator + * - merge_operator + * - compaction_filter + * + * For table_factory, this function further supports deserializing + * BlockBasedTableFactory and its BlockBasedTableOptions except the + * pointer options of BlockBasedTableOptions (flush_block_policy_factory, + * block_cache, and block_cache_compressed), which will be initialized with + * default values. Developers can further specify these three options by + * casting the return value of TableFactoroy::GetOptions() to + * BlockBasedTableOptions and making necessary changes. + * + * @param dbPath the path to the RocksDB. + * @param env {@link org.rocksdb.Env} instance. + * @param dbOptions {@link org.rocksdb.DBOptions} instance. This will be + * filled and returned. + * @param cfDescs A list of {@link org.rocksdb.ColumnFamilyDescriptor}'s be + * returned. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + + public static void loadLatestOptions(String dbPath, Env env, DBOptions dbOptions, + List cfDescs) throws RocksDBException { + loadLatestOptions(dbPath, env, dbOptions, cfDescs, false); + } + + /** + * @param dbPath the path to the RocksDB. + * @param env {@link org.rocksdb.Env} instance. + * @param dbOptions {@link org.rocksdb.DBOptions} instance. This will be + * filled and returned. + * @param cfDescs A list of {@link org.rocksdb.ColumnFamilyDescriptor}'s be + * returned. + * @param ignoreUnknownOptions this flag can be set to true if you want to + * ignore options that are from a newer version of the db, esentially for + * forward compatibility. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + public static void loadLatestOptions(String dbPath, Env env, DBOptions dbOptions, + List cfDescs, boolean ignoreUnknownOptions) throws RocksDBException { + loadLatestOptions( + dbPath, env.nativeHandle_, dbOptions.nativeHandle_, cfDescs, ignoreUnknownOptions); + } + + /** + * Similar to LoadLatestOptions, this function constructs the DBOptions + * and ColumnFamilyDescriptors based on the specified RocksDB Options file. + * See LoadLatestOptions above. + * + * @param optionsFileName the RocksDB options file path. + * @param env {@link org.rocksdb.Env} instance. + * @param dbOptions {@link org.rocksdb.DBOptions} instance. This will be + * filled and returned. + * @param cfDescs A list of {@link org.rocksdb.ColumnFamilyDescriptor}'s be + * returned. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + public static void loadOptionsFromFile(String optionsFileName, Env env, DBOptions dbOptions, + List cfDescs) throws RocksDBException { + loadOptionsFromFile(optionsFileName, env, dbOptions, cfDescs, false); + } + + /** + * @param optionsFileName the RocksDB options file path. + * @param env {@link org.rocksdb.Env} instance. + * @param dbOptions {@link org.rocksdb.DBOptions} instance. This will be + * filled and returned. + * @param cfDescs A list of {@link org.rocksdb.ColumnFamilyDescriptor}'s be + * returned. + * @param ignoreUnknownOptions this flag can be set to true if you want to + * ignore options that are from a newer version of the db, esentially for + * forward compatibility. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + public static void loadOptionsFromFile(String optionsFileName, Env env, DBOptions dbOptions, + List cfDescs, boolean ignoreUnknownOptions) throws RocksDBException { + loadOptionsFromFile( + optionsFileName, env.nativeHandle_, dbOptions.nativeHandle_, cfDescs, ignoreUnknownOptions); + } + + /** + * Returns the latest options file name under the specified RocksDB path. + * + * @param dbPath the path to the RocksDB. + * @param env {@link org.rocksdb.Env} instance. + * @return the latest options file name under the db path. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + public static String getLatestOptionsFileName(String dbPath, Env env) throws RocksDBException { + return getLatestOptionsFileName(dbPath, env.nativeHandle_); + } + + /** + * Private constructor. + * This class has only static methods and shouldn't be instantiated. + */ + private OptionsUtil() {} + + // native methods + private native static void loadLatestOptions(String dbPath, long envHandle, long dbOptionsHandle, + List cfDescs, boolean ignoreUnknownOptions) throws RocksDBException; + private native static void loadOptionsFromFile(String optionsFileName, long envHandle, + long dbOptionsHandle, List cfDescs, boolean ignoreUnknownOptions) + throws RocksDBException; + private native static String getLatestOptionsFileName(String dbPath, long envHandle) + throws RocksDBException; +} diff --git a/java/src/test/java/org/rocksdb/OptionsUtilTest.java b/java/src/test/java/org/rocksdb/OptionsUtilTest.java new file mode 100644 index 000000000..e79951aa8 --- /dev/null +++ b/java/src/test/java/org/rocksdb/OptionsUtilTest.java @@ -0,0 +1,126 @@ +// 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). + +package org.rocksdb; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OptionsUtilTest { + @ClassRule + public static final RocksMemoryResource rocksMemoryResource = new RocksMemoryResource(); + + @Rule public TemporaryFolder dbFolder = new TemporaryFolder(); + + enum TestAPI { LOAD_LATEST_OPTIONS, LOAD_OPTIONS_FROM_FILE } + + @Test + public void loadLatestOptions() throws RocksDBException { + verifyOptions(TestAPI.LOAD_LATEST_OPTIONS); + } + + @Test + public void loadOptionsFromFile() throws RocksDBException { + verifyOptions(TestAPI.LOAD_OPTIONS_FROM_FILE); + } + + @Test + public void getLatestOptionsFileName() throws RocksDBException { + final String dbPath = dbFolder.getRoot().getAbsolutePath(); + try (final Options options = new Options().setCreateIfMissing(true); + final RocksDB db = RocksDB.open(options, dbPath)) { + assertThat(db).isNotNull(); + } + + String fName = OptionsUtil.getLatestOptionsFileName(dbPath, Env.getDefault()); + assertThat(fName).isNotNull(); + assert(fName.startsWith("OPTIONS-") == true); + // System.out.println("latest options fileName: " + fName); + } + + private void verifyOptions(TestAPI apiType) throws RocksDBException { + final String dbPath = dbFolder.getRoot().getAbsolutePath(); + final Options options = new Options() + .setCreateIfMissing(true) + .setParanoidChecks(false) + .setMaxOpenFiles(478) + .setDelayedWriteRate(1234567L); + final ColumnFamilyOptions baseDefaultCFOpts = new ColumnFamilyOptions(); + final byte[] secondCFName = "new_cf".getBytes(); + final ColumnFamilyOptions baseSecondCFOpts = + new ColumnFamilyOptions() + .setWriteBufferSize(70 * 1024) + .setMaxWriteBufferNumber(7) + .setMaxBytesForLevelBase(53 * 1024 * 1024) + .setLevel0FileNumCompactionTrigger(3) + .setLevel0SlowdownWritesTrigger(51) + .setBottommostCompressionType(CompressionType.ZSTD_COMPRESSION); + + // Create a database with a new column family + try (final RocksDB db = RocksDB.open(options, dbPath)) { + assertThat(db).isNotNull(); + + // create column family + try (final ColumnFamilyHandle columnFamilyHandle = + db.createColumnFamily(new ColumnFamilyDescriptor(secondCFName, baseSecondCFOpts))) { + assert(columnFamilyHandle != null); + } + } + + // Read the options back and verify + DBOptions dbOptions = new DBOptions(); + final List cfDescs = new ArrayList<>(); + String path = dbPath; + if (apiType == TestAPI.LOAD_LATEST_OPTIONS) { + OptionsUtil.loadLatestOptions(path, Env.getDefault(), dbOptions, cfDescs, false); + } else if (apiType == TestAPI.LOAD_OPTIONS_FROM_FILE) { + path = dbPath + "/" + OptionsUtil.getLatestOptionsFileName(dbPath, Env.getDefault()); + OptionsUtil.loadOptionsFromFile(path, Env.getDefault(), dbOptions, cfDescs, false); + } + + assertThat(dbOptions.createIfMissing()).isEqualTo(options.createIfMissing()); + assertThat(dbOptions.paranoidChecks()).isEqualTo(options.paranoidChecks()); + assertThat(dbOptions.maxOpenFiles()).isEqualTo(options.maxOpenFiles()); + assertThat(dbOptions.delayedWriteRate()).isEqualTo(options.delayedWriteRate()); + + assertThat(cfDescs.size()).isEqualTo(2); + assertThat(cfDescs.get(0)).isNotNull(); + assertThat(cfDescs.get(1)).isNotNull(); + assertThat(cfDescs.get(0).columnFamilyName()).isEqualTo(RocksDB.DEFAULT_COLUMN_FAMILY); + assertThat(cfDescs.get(1).columnFamilyName()).isEqualTo(secondCFName); + + ColumnFamilyOptions defaultCFOpts = cfDescs.get(0).columnFamilyOptions(); + assertThat(defaultCFOpts.writeBufferSize()).isEqualTo(baseDefaultCFOpts.writeBufferSize()); + assertThat(defaultCFOpts.maxWriteBufferNumber()) + .isEqualTo(baseDefaultCFOpts.maxWriteBufferNumber()); + assertThat(defaultCFOpts.maxBytesForLevelBase()) + .isEqualTo(baseDefaultCFOpts.maxBytesForLevelBase()); + assertThat(defaultCFOpts.level0FileNumCompactionTrigger()) + .isEqualTo(baseDefaultCFOpts.level0FileNumCompactionTrigger()); + assertThat(defaultCFOpts.level0SlowdownWritesTrigger()) + .isEqualTo(baseDefaultCFOpts.level0SlowdownWritesTrigger()); + assertThat(defaultCFOpts.bottommostCompressionType()) + .isEqualTo(baseDefaultCFOpts.bottommostCompressionType()); + + ColumnFamilyOptions secondCFOpts = cfDescs.get(1).columnFamilyOptions(); + assertThat(secondCFOpts.writeBufferSize()).isEqualTo(baseSecondCFOpts.writeBufferSize()); + assertThat(secondCFOpts.maxWriteBufferNumber()) + .isEqualTo(baseSecondCFOpts.maxWriteBufferNumber()); + assertThat(secondCFOpts.maxBytesForLevelBase()) + .isEqualTo(baseSecondCFOpts.maxBytesForLevelBase()); + assertThat(secondCFOpts.level0FileNumCompactionTrigger()) + .isEqualTo(baseSecondCFOpts.level0FileNumCompactionTrigger()); + assertThat(secondCFOpts.level0SlowdownWritesTrigger()) + .isEqualTo(baseSecondCFOpts.level0SlowdownWritesTrigger()); + assertThat(secondCFOpts.bottommostCompressionType()) + .isEqualTo(baseSecondCFOpts.bottommostCompressionType()); + } +} diff --git a/src.mk b/src.mk index a81d1d731..af0bb4b3f 100644 --- a/src.mk +++ b/src.mk @@ -390,6 +390,7 @@ JNI_NATIVE_SOURCES = \ java/rocksjni/memtablejni.cc \ java/rocksjni/merge_operator.cc \ java/rocksjni/options.cc \ + java/rocksjni/options_util.cc \ java/rocksjni/ratelimiterjni.cc \ java/rocksjni/remove_emptyvalue_compactionfilterjni.cc \ java/rocksjni/cassandra_compactionfilterjni.cc \