rocksjni/lru_cache.cc
rocksjni/memtablejni.cc
rocksjni/merge_operator.cc
+ rocksjni/native_comparator_wrapper_test.cc
rocksjni/options.cc
rocksjni/options_util.cc
rocksjni/ratelimiterjni.cc
org.rocksdb.LRUCache
org.rocksdb.MemTableConfig
org.rocksdb.MergeOperator
+ org.rocksdb.NativeComparatorWrapper
+ org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper
org.rocksdb.NativeLibraryLoader
org.rocksdb.Options
org.rocksdb.OptionsUtil
src/main/java/org/rocksdb/CompactionStyle.java
src/main/java/org/rocksdb/Comparator.java
src/main/java/org/rocksdb/ComparatorOptions.java
+ src/main/java/org/rocksdb/ComparatorType.java
src/main/java/org/rocksdb/CompressionOptions.java
src/main/java/org/rocksdb/CompressionType.java
src/main/java/org/rocksdb/DBOptions.java
src/main/java/org/rocksdb/MergeOperator.java
src/main/java/org/rocksdb/MutableColumnFamilyOptions.java
src/main/java/org/rocksdb/MutableColumnFamilyOptionsInterface.java
+ src/main/java/org/rocksdb/NativeComparatorWrapper.java
src/main/java/org/rocksdb/NativeLibraryLoader.java
src/main/java/org/rocksdb/Options.java
src/main/java/org/rocksdb/OptionsUtil.java
src/main/java/org/rocksdb/WriteOptions.java
src/test/java/org/rocksdb/BackupEngineTest.java
src/test/java/org/rocksdb/IngestExternalFileOptionsTest.java
+ src/test/java/org/rocksdb/NativeComparatorWrapperTest.java
src/test/java/org/rocksdb/PlatformRandomHelper.java
src/test/java/org/rocksdb/RocksDBExceptionTest.java
src/test/java/org/rocksdb/RocksMemoryResource.java
org.rocksdb.Logger\
org.rocksdb.LRUCache\
org.rocksdb.MergeOperator\
+ org.rocksdb.NativeComparatorWrapper\
org.rocksdb.OptimisticTransactionDB\
org.rocksdb.OptimisticTransactionOptions\
org.rocksdb.Options\
org.rocksdb.WBWIRocksIterator
NATIVE_JAVA_TEST_CLASSES = org.rocksdb.RocksDBExceptionTest\
+ org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper\
org.rocksdb.WriteBatchTest\
org.rocksdb.WriteBatchTestInternalHelper
org.rocksdb.MergeTest\
org.rocksdb.MixedOptionsTest\
org.rocksdb.MutableColumnFamilyOptionsTest\
+ org.rocksdb.NativeComparatorWrapperTest\
org.rocksdb.NativeLibraryLoaderTest\
org.rocksdb.OptimisticTransactionTest\
org.rocksdb.OptimisticTransactionDBTest\
#include "include/org_rocksdb_Comparator.h"
#include "include/org_rocksdb_DirectComparator.h"
+#include "include/org_rocksdb_NativeComparatorWrapper.h"
#include "rocksjni/comparatorjnicallback.h"
#include "rocksjni/portal.h"
new rocksdb::DirectComparatorJniCallback(env, jobj, copt);
return reinterpret_cast<jlong>(c);
}
+
+/*
+ * Class: org_rocksdb_NativeComparatorWrapper
+ * Method: disposeInternal
+ * Signature: (J)V
+ */
+void Java_org_rocksdb_NativeComparatorWrapper_disposeInternal(
+ JNIEnv* env, jobject jobj, jlong jcomparator_handle) {
+ auto* comparator =
+ reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
+ delete comparator;
+}
// </editor-fold>
--- /dev/null
+// 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).
+
+#include <jni.h>
+#include <string>
+
+#include "rocksdb/comparator.h"
+#include "rocksdb/slice.h"
+
+#include "include/org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper.h"
+
+namespace rocksdb {
+
+class NativeComparatorWrapperTestStringComparator
+ : public Comparator {
+
+ const char* Name() const {
+ return "NativeComparatorWrapperTestStringComparator";
+ }
+
+ int Compare(
+ const Slice& a, const Slice& b) const {
+ return a.ToString().compare(b.ToString());
+ }
+
+ void FindShortestSeparator(
+ std::string* start, const Slice& limit) const {
+ return;
+ }
+
+ void FindShortSuccessor(
+ std::string* key) const {
+ return;
+ }
+};
+} // end of rocksdb namespace
+
+/*
+ * Class: org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper
+ * Method: newStringComparator
+ * Signature: ()J
+ */
+jlong Java_org_rocksdb_NativeComparatorWrapperTest_00024NativeStringComparatorWrapper_newStringComparator(
+ JNIEnv* env , jobject jobj) {
+ auto* comparator =
+ new rocksdb::NativeComparatorWrapperTestStringComparator();
+ return reinterpret_cast<jlong>(comparator);
+}
/*
* Class: org_rocksdb_Options
* Method: setComparatorHandle
- * Signature: (JJZ)V
+ * Signature: (JJB)V
*/
-void Java_org_rocksdb_Options_setComparatorHandle__JJZ(
+void Java_org_rocksdb_Options_setComparatorHandle__JJB(
JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
- jboolean is_direct) {
- auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle);
- if(is_direct) {
- opt->comparator =
- reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
- } else {
- opt->comparator =
- reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
+ jbyte jcomparator_type) {
+ rocksdb::Comparator *comparator = nullptr;
+ switch(jcomparator_type) {
+ // JAVA_COMPARATOR
+ case 0x0:
+ comparator =
+ reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_DIRECT_COMPARATOR
+ case 0x1:
+ comparator =
+ reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_NATIVE_COMPARATOR_WRAPPER
+ case 0x2:
+ comparator =
+ reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
+ break;
}
+ auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle);
+ opt->comparator = comparator;
}
/*
/*
* Class: org_rocksdb_ColumnFamilyOptions
* Method: setComparatorHandle
- * Signature: (JJZ)V
+ * Signature: (JJB)V
*/
-void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JJZ(
+void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JJB(
JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
- jboolean is_direct) {
- auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle);
- if(is_direct) {
- opt->comparator =
- reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
- } else {
- opt->comparator =
- reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
+ jbyte jcomparator_type) {
+ rocksdb::Comparator *comparator = nullptr;
+ switch(jcomparator_type) {
+ // JAVA_COMPARATOR
+ case 0x0:
+ comparator =
+ reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_DIRECT_COMPARATOR
+ case 0x1:
+ comparator =
+ reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_NATIVE_COMPARATOR_WRAPPER
+ case 0x2:
+ comparator =
+ reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
+ break;
}
+ auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle);
+ opt->comparator = comparator;
}
/*
/*
* Class: org_rocksdb_SstFileWriter
* Method: newSstFileWriter
- * Signature: (JJJZ)J
+ * Signature: (JJJB)J
*/
-jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJZ(JNIEnv *env,
- jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator,
- jboolean is_direct) {
+jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJB(JNIEnv *env,
+ jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator_handle,
+ jbyte jcomparator_type) {
+ rocksdb::Comparator *comparator = nullptr;
+ switch(jcomparator_type) {
+ // JAVA_COMPARATOR
+ case 0x0:
+ comparator =
+ reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_DIRECT_COMPARATOR
+ case 0x1:
+ comparator =
+ reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
+ break;
+
+ // JAVA_NATIVE_COMPARATOR_WRAPPER
+ case 0x2:
+ comparator =
+ reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
+ break;
+ }
auto *env_options =
reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions);
auto *options = reinterpret_cast<const rocksdb::Options *>(joptions);
-
- rocksdb::Comparator *comparator = nullptr;
- if(is_direct) {
- comparator =
- reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator);
- } else {
- comparator =
- reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator);
- }
-
rocksdb::SstFileWriter *sst_file_writer =
new rocksdb::SstFileWriter(*env_options, *options, comparator);
return reinterpret_cast<jlong>(sst_file_writer);
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: newWriteBatchWithIndex
- * Signature: (JZIZ)J
+ * Signature: (JBIZ)J
*/
-jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JZIZ(
+jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JBIZ(
JNIEnv* env, jclass jcls, jlong jfallback_index_comparator_handle,
- jboolean is_direct, jint jreserved_bytes, jboolean joverwrite_key) {
-rocksdb::Comparator *fallback_comparator = nullptr;
-if(is_direct) {
- fallback_comparator =
- reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jfallback_index_comparator_handle);
-} else {
- fallback_comparator =
- reinterpret_cast<rocksdb::ComparatorJniCallback*>(jfallback_index_comparator_handle);
-}
+ jbyte jcomparator_type, jint jreserved_bytes, jboolean joverwrite_key) {
+ rocksdb::Comparator *fallback_comparator = nullptr;
+ switch(jcomparator_type) {
+ // JAVA_COMPARATOR
+ case 0x0:
+ fallback_comparator =
+ reinterpret_cast<rocksdb::ComparatorJniCallback*>(jfallback_index_comparator_handle);
+ break;
+
+ // JAVA_DIRECT_COMPARATOR
+ case 0x1:
+ fallback_comparator =
+ reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jfallback_index_comparator_handle);
+ break;
+
+ // JAVA_NATIVE_COMPARATOR_WRAPPER
+ case 0x2:
+ fallback_comparator =
+ reinterpret_cast<rocksdb::Comparator*>(jfallback_index_comparator_handle);
+ break;
+ }
auto* wbwi =
new rocksdb::WriteBatchWithIndex(
fallback_comparator,
public abstract class AbstractComparator<T extends AbstractSlice<?>>
extends RocksCallbackObject {
+ protected AbstractComparator() {
+ super();
+ }
+
protected AbstractComparator(final ComparatorOptions copt) {
super(copt.nativeHandle_);
}
+ /**
+ * Get the type of this comparator.
+ *
+ * Used for determining the correct C++ cast in native code.
+ *
+ * @return The type of the comparator.
+ */
+ abstract ComparatorType getComparatorType();
+
/**
* The name of the comparator. Used to check for comparator
* mismatches (i.e., a DB created with one comparator is
final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert (isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
- comparator instanceof DirectComparator);
+ comparator.getComparatorType().getValue());
comparator_ = comparator;
return this;
}
long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle,
- long comparatorHandle, boolean isDirect);
+ long comparatorHandle, byte comparatorType);
private native void setMergeOperatorName(long handle, String name);
private native void setMergeOperator(long handle, long mergeOperatorHandle);
private native void setCompactionFilterHandle(long handle,
return createNewComparator0(nativeParameterHandles[0]);
}
+ @Override
+ final ComparatorType getComparatorType() {
+ return ComparatorType.JAVA_COMPARATOR;
+ }
+
private native long createNewComparator0(final long comparatorOptionsHandle);
}
--- /dev/null
+// 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;
+
+enum ComparatorType {
+ JAVA_COMPARATOR((byte)0x0),
+ JAVA_DIRECT_COMPARATOR((byte)0x1),
+ JAVA_NATIVE_COMPARATOR_WRAPPER((byte)0x2);
+
+ private final byte value;
+
+ ComparatorType(final byte value) {
+ this.value = value;
+ }
+
+ /**
+ * <p>Returns the byte value of the enumerations value.</p>
+ *
+ * @return byte representation
+ */
+ byte getValue() {
+ return value;
+ }
+
+ /**
+ * <p>Get the ComparatorType enumeration value by
+ * passing the byte identifier to this method.</p>
+ *
+ * @param byteIdentifier of ComparatorType.
+ *
+ * @return ComparatorType instance.
+ *
+ * @throws IllegalArgumentException if the comparator type for the byteIdentifier
+ * cannot be found
+ */
+ static ComparatorType getComparatorType(final byte byteIdentifier) {
+ for (final ComparatorType comparatorType : ComparatorType.values()) {
+ if (comparatorType.getValue() == byteIdentifier) {
+ return comparatorType;
+ }
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal value provided for ComparatorType.");
+ }
+}
return createNewDirectComparator0(nativeParameterHandles[0]);
}
+ @Override
+ final ComparatorType getComparatorType() {
+ return ComparatorType.JAVA_DIRECT_COMPARATOR;
+ }
+
private native long createNewDirectComparator0(
final long comparatorOptionsHandle);
}
--- /dev/null
+// 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;
+
+/**
+ * A simple abstraction to allow a Java class to wrap a custom comparator
+ * implemented in C++.
+ *
+ * The native comparator must directly extend rocksdb::Comparator.
+ */
+public abstract class NativeComparatorWrapper
+ extends AbstractComparator<Slice> {
+
+ @Override
+ final ComparatorType getComparatorType() {
+ return ComparatorType.JAVA_NATIVE_COMPARATOR_WRAPPER;
+ }
+
+ @Override
+ public final String name() {
+ throw new IllegalStateException("This should not be called. " +
+ "Implementation is in Native code");
+ }
+
+ @Override
+ public final int compare(final Slice s1, final Slice s2) {
+ throw new IllegalStateException("This should not be called. " +
+ "Implementation is in Native code");
+ }
+
+ @Override
+ public final String findShortestSeparator(final String start, final Slice limit) {
+ throw new IllegalStateException("This should not be called. " +
+ "Implementation is in Native code");
+ }
+
+ @Override
+ public final String findShortSuccessor(final String key) {
+ throw new IllegalStateException("This should not be called. " +
+ "Implementation is in Native code");
+ }
+
+ /**
+ * We override {@link RocksCallbackObject#disposeInternal()}
+ * as disposing of a native rocksd::Comparator extension requires
+ * a slightly different approach as it is not really a RocksCallbackObject
+ */
+ @Override
+ protected void disposeInternal() {
+ disposeInternal(nativeHandle_);
+ }
+
+ private native void disposeInternal(final long handle);
+}
final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert(isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
- comparator instanceof DirectComparator);
+ comparator.getComparatorType().getValue());
comparator_ = comparator;
return this;
}
long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle,
- long comparatorHandle, boolean isDirect);
+ long comparatorHandle, byte comparatorType);
private native void setMergeOperatorName(
long handle, String name);
private native void setMergeOperator(
final AbstractComparator<? extends AbstractSlice<?>> comparator) {
super(newSstFileWriter(
envOptions.nativeHandle_, options.nativeHandle_, comparator.nativeHandle_,
- comparator instanceof DirectComparator));
+ comparator.getComparatorType().getValue()));
}
/**
private native static long newSstFileWriter(
final long envOptionsHandle, final long optionsHandle,
- final long userComparatorHandle, final boolean isDirect);
+ final long userComparatorHandle, final byte comparatorType);
private native static long newSstFileWriter(final long envOptionsHandle,
final long optionsHandle);
fallbackIndexComparator, final int reservedBytes,
final boolean overwriteKey) {
super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_,
- fallbackIndexComparator instanceof DirectComparator, reservedBytes, overwriteKey));
+ fallbackIndexComparator.getComparatorType().getValue(), reservedBytes,
+ overwriteKey));
}
/**
private native static long newWriteBatchWithIndex();
private native static long newWriteBatchWithIndex(final boolean overwriteKey);
private native static long newWriteBatchWithIndex(
- final long fallbackIndexComparatorHandle, final boolean isDirect, final int reservedBytes,
+ final long fallbackIndexComparatorHandle,
+ final byte comparatorType, final int reservedBytes,
final boolean overwriteKey);
private native long iterator0(final long handle);
private native long iterator1(final long handle, final long cfHandle);
--- /dev/null
+// 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.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.util.*;
+import java.util.Comparator;
+
+import static org.junit.Assert.assertEquals;
+
+public class NativeComparatorWrapperTest {
+
+ @Rule
+ public TemporaryFolder dbFolder = new TemporaryFolder();
+
+ private static final Random random = new Random();
+
+ @Test
+ public void rountrip() throws RocksDBException {
+ final String dbPath = dbFolder.getRoot().getAbsolutePath();
+ final int ITERATIONS = 1_000;
+
+ final String[] storedKeys = new String[ITERATIONS];
+ try (final NativeStringComparatorWrapper comparator = new NativeStringComparatorWrapper();
+ final Options opt = new Options()
+ .setCreateIfMissing(true)
+ .setComparator(comparator)) {
+
+ // store random integer keys
+ try (final RocksDB db = RocksDB.open(opt, dbPath)) {
+ for (int i = 0; i < ITERATIONS; i++) {
+ final String strKey = randomString();
+ final byte key[] = strKey.getBytes();
+ // does key already exist (avoid duplicates)
+ if (i > 0 && db.get(key) != null) {
+ i--; // generate a different key
+ } else {
+ db.put(key, "value".getBytes());
+ storedKeys[i] = strKey;
+ }
+ }
+ }
+
+ // sort the stored keys into ascending alpha-numeric order
+ Arrays.sort(storedKeys, new Comparator<String>() {
+ @Override
+ public int compare(final String o1, final String o2) {
+ return o1.compareTo(o2);
+ }
+ });
+
+ // re-open db and read from start to end
+ // string keys should be in ascending
+ // order
+ try (final RocksDB db = RocksDB.open(opt, dbPath);
+ final RocksIterator it = db.newIterator()) {
+ int count = 0;
+ for (it.seekToFirst(); it.isValid(); it.next()) {
+ final String strKey = new String(it.key());
+ assertEquals(storedKeys[count++], strKey);
+ }
+ }
+ }
+ }
+
+ private String randomString() {
+ final char[] chars = new char[12];
+ for(int i = 0; i < 12; i++) {
+ final int letterCode = random.nextInt(24);
+ final char letter = (char) (((int) 'a') + letterCode);
+ chars[i] = letter;
+ }
+ return String.copyValueOf(chars);
+ }
+
+ public static class NativeStringComparatorWrapper
+ extends NativeComparatorWrapper {
+
+ @Override
+ protected long initializeNative(final long... nativeParameterHandles) {
+ return newStringComparator();
+ }
+
+ private native long newStringComparator();
+ }
+}
java/rocksjni/lru_cache.cc \
java/rocksjni/memtablejni.cc \
java/rocksjni/merge_operator.cc \
- java/rocksjni/optimistic_transaction_db.cc \
+ java/rocksjni/native_comparator_wrapper_test.cc \
+ java/rocksjni/optimistic_transaction_db.cc \
java/rocksjni/optimistic_transaction_options.cc \
java/rocksjni/options.cc \
java/rocksjni/options_util.cc \