From 5249d0db50a1a629299404206ad9c50cc24eb3a6 Mon Sep 17 00:00:00 2001 From: fyrz Date: Sun, 16 Nov 2014 22:35:54 +0100 Subject: [PATCH 1/2] [RocksJava] Convenience methods for Options RocksDB introduced in 3.7.0 convenience methods for getting ColumnFamilyOptions and DBOptions instances from predefined configuration structures. There is now also a method in RocksJava to load DBOptions as well as ColumnFamilyOptions from a predefined Properties based configuration. --- java/org/rocksdb/ColumnFamilyOptions.java | 57 +++++++++++++++++++ java/org/rocksdb/DBOptions.java | 57 +++++++++++++++++++ .../rocksdb/test/ColumnFamilyOptionsTest.java | 52 +++++++++++++++++ java/org/rocksdb/test/DBOptionsTest.java | 51 +++++++++++++++++ java/rocksjni/options.cc | 51 +++++++++++++++++ 5 files changed, 268 insertions(+) diff --git a/java/org/rocksdb/ColumnFamilyOptions.java b/java/org/rocksdb/ColumnFamilyOptions.java index 9ce1e9a98..7fa4545b5 100644 --- a/java/org/rocksdb/ColumnFamilyOptions.java +++ b/java/org/rocksdb/ColumnFamilyOptions.java @@ -5,6 +5,8 @@ package org.rocksdb; +import java.util.Properties; + /** * ColumnFamilyOptions to control the behavior of a database. It will be used * during the creation of a {@link org.rocksdb.RocksDB} (i.e., RocksDB.open()). @@ -29,6 +31,58 @@ public class ColumnFamilyOptions extends RocksObject newColumnFamilyOptions(); } + /** + *

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

+ * + * @param handle native handle to ColumnFamilyOptions instance. + */ + private ColumnFamilyOptions(long handle) { + super(); + nativeHandle_ = handle; + } + + /** + *

Method to get a options instance by using pre-configured + * property values. If one or many values are undefined in + * the context of RocksDB the method will return a null + * value.

+ * + *

Note: Property keys can be derived from + * getter methods within the options class. Example: the method + * {@code writeBufferSize()} has a property key: + * {@code write_buffer_size}.

+ * + * @param properties {@link java.util.Properties} instance. + * + * @return {@link org.rocksdb.ColumnFamilyOptions instance} + * or null. + * + * @throws java.lang.IllegalArgumentException if null or empty + * {@link Properties} instance is passed to the method call. + */ + public static ColumnFamilyOptions getColumnFamilyOptionsFromProps( + Properties properties) { + if (properties == null || properties.size() == 0) { + throw new IllegalArgumentException( + "Properties value must contain at least one value."); + } + ColumnFamilyOptions columnFamilyOptions = null; + StringBuilder stringBuilder = new StringBuilder(); + for (final String name : properties.stringPropertyNames()){ + stringBuilder.append(name); + stringBuilder.append("="); + stringBuilder.append(properties.getProperty(name)); + stringBuilder.append(";"); + } + long handle = getColumnFamilyOptionsFromProps( + stringBuilder.toString()); + if (handle != 0){ + columnFamilyOptions = new ColumnFamilyOptions(handle); + } + return columnFamilyOptions; + } + @Override public ColumnFamilyOptions optimizeForPointLookup( long blockCacheSizeMb) { @@ -522,6 +576,9 @@ public class ColumnFamilyOptions extends RocksObject disposeInternal(nativeHandle_); } + private static native long getColumnFamilyOptionsFromProps( + String optString); + private native void newColumnFamilyOptions(); private native void disposeInternal(long handle); diff --git a/java/org/rocksdb/DBOptions.java b/java/org/rocksdb/DBOptions.java index e19ee9a0a..45113c0f2 100644 --- a/java/org/rocksdb/DBOptions.java +++ b/java/org/rocksdb/DBOptions.java @@ -5,6 +5,8 @@ package org.rocksdb; +import java.util.Properties; + /** * DBOptions to control the behavior of a database. It will be used * during the creation of a {@link org.rocksdb.RocksDB} (i.e., RocksDB.open()). @@ -29,6 +31,58 @@ public class DBOptions extends RocksObject implements DBOptionsInterface { newDBOptions(); } + /** + *

Private constructor to be used by + * {@link #getDBOptionsFromProps(java.util.Properties)}

+ * + * @param handle native handle to DBOptions instance. + */ + private DBOptions(long handle) { + super(); + nativeHandle_ = handle; + } + + /** + *

Method to get a options instance by using pre-configured + * property values. If one or many values are undefined in + * the context of RocksDB the method will return a null + * value.

+ * + *

Note: Property keys can be derived from + * getter methods within the options class. Example: the method + * {@code allowMmapReads()} has a property key: + * {@code allow_mmap_reads}.

+ * + * @param properties {@link java.util.Properties} instance. + * + * @return {@link org.rocksdb.DBOptions instance} + * or null. + * + * @throws java.lang.IllegalArgumentException if null or empty + * {@link java.util.Properties} instance is passed to the method call. + */ + public static DBOptions getDBOptionsFromProps( + Properties properties) { + if (properties == null || properties.size() == 0) { + throw new IllegalArgumentException( + "Properties value must contain at least one value."); + } + DBOptions dbOptions = null; + StringBuilder stringBuilder = new StringBuilder(); + for (final String name : properties.stringPropertyNames()){ + stringBuilder.append(name); + stringBuilder.append("="); + stringBuilder.append(properties.getProperty(name)); + stringBuilder.append(";"); + } + long handle = getDBOptionsFromProps( + stringBuilder.toString()); + if (handle != 0){ + dbOptions = new DBOptions(handle); + } + return dbOptions; + } + @Override public DBOptions setCreateIfMissing(boolean flag) { assert(isInitialized()); @@ -487,6 +541,9 @@ public class DBOptions extends RocksObject implements DBOptionsInterface { static final int DEFAULT_NUM_SHARD_BITS = -1; + private static native long getDBOptionsFromProps( + String optString); + private native void newDBOptions(); private native void disposeInternal(long handle); diff --git a/java/org/rocksdb/test/ColumnFamilyOptionsTest.java b/java/org/rocksdb/test/ColumnFamilyOptionsTest.java index 7fcfee14c..aae9b5749 100644 --- a/java/org/rocksdb/test/ColumnFamilyOptionsTest.java +++ b/java/org/rocksdb/test/ColumnFamilyOptionsTest.java @@ -9,6 +9,7 @@ import org.junit.ClassRule; import org.junit.Test; import org.rocksdb.*; +import java.util.Properties; import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; @@ -22,6 +23,57 @@ public class ColumnFamilyOptionsTest { public static final Random rand = PlatformRandomHelper. getPlatformSpecificRandomFactory(); + @Test + public void getColumnFamilyOptionsFromProps() { + ColumnFamilyOptions opt = null; + try { + // setup sample properties + Properties properties = new Properties(); + properties.put("write_buffer_size", "112"); + properties.put("max_write_buffer_number", "13"); + opt = ColumnFamilyOptions. + getColumnFamilyOptionsFromProps(properties); + assertThat(opt).isNotNull(); + assertThat(String.valueOf(opt.writeBufferSize())). + isEqualTo(properties.get("write_buffer_size")); + assertThat(String.valueOf(opt.maxWriteBufferNumber())). + isEqualTo(properties.get("max_write_buffer_number")); + } finally { + if (opt != null) { + opt.dispose(); + } + } + } + + @Test + public void failColumnFamilyOptionsFromPropsWithIllegalValue() { + ColumnFamilyOptions opt = null; + try { + // setup sample properties + Properties properties = new Properties(); + properties.put("tomato", "1024"); + properties.put("burger", "2"); + opt = ColumnFamilyOptions. + getColumnFamilyOptionsFromProps(properties); + assertThat(opt).isNull(); + } finally { + if (opt != null) { + opt.dispose(); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void failColumnFamilyOptionsFromPropsWithNullValue() { + ColumnFamilyOptions.getColumnFamilyOptionsFromProps(null); + } + + @Test(expected = IllegalArgumentException.class) + public void failColumnFamilyOptionsFromPropsWithEmptyProps() { + ColumnFamilyOptions.getColumnFamilyOptionsFromProps( + new Properties()); + } + @Test public void writeBufferSize() throws RocksDBException { ColumnFamilyOptions opt = null; diff --git a/java/org/rocksdb/test/DBOptionsTest.java b/java/org/rocksdb/test/DBOptionsTest.java index 9a15658e7..6064dd694 100644 --- a/java/org/rocksdb/test/DBOptionsTest.java +++ b/java/org/rocksdb/test/DBOptionsTest.java @@ -9,6 +9,7 @@ import org.junit.ClassRule; import org.junit.Test; import org.rocksdb.*; +import java.util.Properties; import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; @@ -22,6 +23,56 @@ public class DBOptionsTest { public static final Random rand = PlatformRandomHelper. getPlatformSpecificRandomFactory(); + @Test + public void getDBOptionsFromProps() { + DBOptions opt = null; + try { + // setup sample properties + Properties properties = new Properties(); + properties.put("allow_mmap_reads", "true"); + properties.put("bytes_per_sync", "13"); + opt = DBOptions.getDBOptionsFromProps(properties); + assertThat(opt).isNotNull(); + assertThat(String.valueOf(opt.allowMmapReads())). + isEqualTo(properties.get("allow_mmap_reads")); + assertThat(String.valueOf(opt.bytesPerSync())). + isEqualTo(properties.get("bytes_per_sync")); + } finally { + if (opt != null) { + opt.dispose(); + } + } + } + + @Test + public void failDBOptionsFromPropsWithIllegalValue() { + DBOptions opt = null; + try { + // setup sample properties + Properties properties = new Properties(); + properties.put("tomato", "1024"); + properties.put("burger", "2"); + opt = DBOptions. + getDBOptionsFromProps(properties); + assertThat(opt).isNull(); + } finally { + if (opt != null) { + opt.dispose(); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void failDBOptionsFromPropsWithNullValue() { + DBOptions.getDBOptionsFromProps(null); + } + + @Test(expected = IllegalArgumentException.class) + public void failDBOptionsFromPropsWithEmptyProps() { + DBOptions.getDBOptionsFromProps( + new Properties()); + } + @Test public void createIfMissing() { DBOptions opt = null; diff --git a/java/rocksjni/options.cc b/java/rocksjni/options.cc index 50bab7a1b..82fb1fd1b 100644 --- a/java/rocksjni/options.cc +++ b/java/rocksjni/options.cc @@ -31,6 +31,7 @@ #include "rocksdb/rate_limiter.h" #include "rocksdb/comparator.h" #include "rocksdb/merge_operator.h" +#include "rocksdb/utilities/convenience.h" #include "utilities/merge_operators.h" /* @@ -1776,6 +1777,31 @@ void Java_org_rocksdb_ColumnFamilyOptions_newColumnFamilyOptions( rocksdb::ColumnFamilyOptionsJni::setHandle(env, jobj, op); } +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: getColumnFamilyOptionsFromProps + * Signature: (Ljava/util/String;)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_getColumnFamilyOptionsFromProps( + JNIEnv* env, jclass jclazz, jstring jopt_string) { + jlong ret_value = 0; + rocksdb::ColumnFamilyOptions* cf_options = + new rocksdb::ColumnFamilyOptions(); + const char* opt_string = env->GetStringUTFChars(jopt_string, 0); + bool status = rocksdb::GetColumnFamilyOptionsFromString( + rocksdb::ColumnFamilyOptions(), opt_string, cf_options); + env->ReleaseStringUTFChars(jopt_string, opt_string); + // Check if ColumnFamilyOptions creation was possible. + if (status) { + ret_value = reinterpret_cast(cf_options); + } else { + // if operation failed the ColumnFamilyOptions need to be deleted + // again to prevent a memory leak. + delete cf_options; + } + return ret_value; +} + /* * Class: org_rocksdb_ColumnFamilyOptions * Method: disposeInternal @@ -2751,6 +2777,31 @@ void Java_org_rocksdb_DBOptions_newDBOptions(JNIEnv* env, rocksdb::DBOptionsJni::setHandle(env, jobj, dbop); } +/* + * Class: org_rocksdb_DBOptions + * Method: getDBOptionsFromProps + * Signature: (Ljava/util/String;)J + */ +jlong Java_org_rocksdb_DBOptions_getDBOptionsFromProps( + JNIEnv* env, jclass jclazz, jstring jopt_string) { + jlong ret_value = 0; + rocksdb::DBOptions* db_options = + new rocksdb::DBOptions(); + const char* opt_string = env->GetStringUTFChars(jopt_string, 0); + bool status = rocksdb::GetDBOptionsFromString( + rocksdb::DBOptions(), opt_string, db_options); + env->ReleaseStringUTFChars(jopt_string, opt_string); + // Check if DBOptions creation was possible. + if (status) { + ret_value = reinterpret_cast(db_options); + } else { + // if operation failed the DBOptions need to be deleted + // again to prevent a memory leak. + delete db_options; + } + return ret_value; +} + /* * Class: org_rocksdb_DBOptions * Method: disposeInternal From 91ccc8ebefc48b5f4fcc0e0a7a220fd808dc52d4 Mon Sep 17 00:00:00 2001 From: fyrz Date: Tue, 18 Nov 2014 21:45:12 +0100 Subject: [PATCH 2/2] [RocksJava] Integrated changes in D29025 Addressed review comments. --- java/org/rocksdb/ColumnFamilyOptions.java | 22 +++++++++++----------- java/org/rocksdb/DBOptions.java | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/java/org/rocksdb/ColumnFamilyOptions.java b/java/org/rocksdb/ColumnFamilyOptions.java index 7fa4545b5..3d3b236a2 100644 --- a/java/org/rocksdb/ColumnFamilyOptions.java +++ b/java/org/rocksdb/ColumnFamilyOptions.java @@ -31,17 +31,6 @@ public class ColumnFamilyOptions extends RocksObject newColumnFamilyOptions(); } - /** - *

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

- * - * @param handle native handle to ColumnFamilyOptions instance. - */ - private ColumnFamilyOptions(long handle) { - super(); - nativeHandle_ = handle; - } - /** *

Method to get a options instance by using pre-configured * property values. If one or many values are undefined in @@ -576,6 +565,17 @@ public class ColumnFamilyOptions extends RocksObject disposeInternal(nativeHandle_); } + /** + *

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

+ * + * @param handle native handle to ColumnFamilyOptions instance. + */ + private ColumnFamilyOptions(long handle) { + super(); + nativeHandle_ = handle; + } + private static native long getColumnFamilyOptionsFromProps( String optString); diff --git a/java/org/rocksdb/DBOptions.java b/java/org/rocksdb/DBOptions.java index 45113c0f2..600369dec 100644 --- a/java/org/rocksdb/DBOptions.java +++ b/java/org/rocksdb/DBOptions.java @@ -31,17 +31,6 @@ public class DBOptions extends RocksObject implements DBOptionsInterface { newDBOptions(); } - /** - *

Private constructor to be used by - * {@link #getDBOptionsFromProps(java.util.Properties)}

- * - * @param handle native handle to DBOptions instance. - */ - private DBOptions(long handle) { - super(); - nativeHandle_ = handle; - } - /** *

Method to get a options instance by using pre-configured * property values. If one or many values are undefined in @@ -541,6 +530,17 @@ public class DBOptions extends RocksObject implements DBOptionsInterface { static final int DEFAULT_NUM_SHARD_BITS = -1; + /** + *

Private constructor to be used by + * {@link #getDBOptionsFromProps(java.util.Properties)}

+ * + * @param handle native handle to DBOptions instance. + */ + private DBOptions(long handle) { + super(); + nativeHandle_ = handle; + } + private static native long getDBOptionsFromProps( String optString);