Java wrapper for Native Comparators

Summary:
This is an abstraction for working with custom Comparators implemented in native C++ code from Java. Native code must directly extend `rocksdb::Comparator`. When the native code comparator is compiled into the RocksDB codebase, you can then create a Java Class, and JNI stub to wrap it.

Useful if the C++/JNI barrier overhead is too much for your applications comparator performance.

An example is provided in `java/rocksjni/native_comparator_wrapper_test.cc` and `java/src/main/java/org/rocksdb/NativeComparatorWrapperTest.java`.
Closes https://github.com/facebook/rocksdb/pull/3334

Differential Revision: D7172605

Pulled By: miasantreble

fbshipit-source-id: e24b7eb267a3bcb6afa214e0379a1d5e8a2ceabe
main
Adam Retter 6 years ago committed by Facebook Github Bot
parent e476d0e252
commit c5302a8a58
  1. 6
      java/CMakeLists.txt
  2. 3
      java/Makefile
  3. 13
      java/rocksjni/comparator.cc
  4. 50
      java/rocksjni/native_comparator_wrapper_test.cc
  5. 68
      java/rocksjni/options.cc
  6. 38
      java/rocksjni/sst_file_writerjni.cc
  7. 34
      java/rocksjni/write_batch_with_index.cc
  8. 13
      java/src/main/java/org/rocksdb/AbstractComparator.java
  9. 4
      java/src/main/java/org/rocksdb/ColumnFamilyOptions.java
  10. 5
      java/src/main/java/org/rocksdb/Comparator.java
  11. 49
      java/src/main/java/org/rocksdb/ComparatorType.java
  12. 5
      java/src/main/java/org/rocksdb/DirectComparator.java
  13. 57
      java/src/main/java/org/rocksdb/NativeComparatorWrapper.java
  14. 4
      java/src/main/java/org/rocksdb/Options.java
  15. 4
      java/src/main/java/org/rocksdb/SstFileWriter.java
  16. 6
      java/src/main/java/org/rocksdb/WriteBatchWithIndex.java
  17. 92
      java/src/test/java/org/rocksdb/NativeComparatorWrapperTest.java
  18. 3
      src.mk

@ -24,6 +24,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/lru_cache.cc rocksjni/lru_cache.cc
rocksjni/memtablejni.cc rocksjni/memtablejni.cc
rocksjni/merge_operator.cc rocksjni/merge_operator.cc
rocksjni/native_comparator_wrapper_test.cc
rocksjni/options.cc rocksjni/options.cc
rocksjni/options_util.cc rocksjni/options_util.cc
rocksjni/ratelimiterjni.cc rocksjni/ratelimiterjni.cc
@ -87,6 +88,8 @@ set(NATIVE_JAVA_CLASSES
org.rocksdb.LRUCache org.rocksdb.LRUCache
org.rocksdb.MemTableConfig org.rocksdb.MemTableConfig
org.rocksdb.MergeOperator org.rocksdb.MergeOperator
org.rocksdb.NativeComparatorWrapper
org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper
org.rocksdb.NativeLibraryLoader org.rocksdb.NativeLibraryLoader
org.rocksdb.Options org.rocksdb.Options
org.rocksdb.OptionsUtil org.rocksdb.OptionsUtil
@ -179,6 +182,7 @@ add_jar(
src/main/java/org/rocksdb/CompactionStyle.java src/main/java/org/rocksdb/CompactionStyle.java
src/main/java/org/rocksdb/Comparator.java src/main/java/org/rocksdb/Comparator.java
src/main/java/org/rocksdb/ComparatorOptions.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/CompressionOptions.java
src/main/java/org/rocksdb/CompressionType.java src/main/java/org/rocksdb/CompressionType.java
src/main/java/org/rocksdb/DBOptions.java src/main/java/org/rocksdb/DBOptions.java
@ -205,6 +209,7 @@ add_jar(
src/main/java/org/rocksdb/MergeOperator.java src/main/java/org/rocksdb/MergeOperator.java
src/main/java/org/rocksdb/MutableColumnFamilyOptions.java src/main/java/org/rocksdb/MutableColumnFamilyOptions.java
src/main/java/org/rocksdb/MutableColumnFamilyOptionsInterface.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/NativeLibraryLoader.java
src/main/java/org/rocksdb/Options.java src/main/java/org/rocksdb/Options.java
src/main/java/org/rocksdb/OptionsUtil.java src/main/java/org/rocksdb/OptionsUtil.java
@ -246,6 +251,7 @@ add_jar(
src/main/java/org/rocksdb/WriteOptions.java src/main/java/org/rocksdb/WriteOptions.java
src/test/java/org/rocksdb/BackupEngineTest.java src/test/java/org/rocksdb/BackupEngineTest.java
src/test/java/org/rocksdb/IngestExternalFileOptionsTest.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/PlatformRandomHelper.java
src/test/java/org/rocksdb/RocksDBExceptionTest.java src/test/java/org/rocksdb/RocksDBExceptionTest.java
src/test/java/org/rocksdb/RocksMemoryResource.java src/test/java/org/rocksdb/RocksMemoryResource.java

@ -30,6 +30,7 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.Logger\ org.rocksdb.Logger\
org.rocksdb.LRUCache\ org.rocksdb.LRUCache\
org.rocksdb.MergeOperator\ org.rocksdb.MergeOperator\
org.rocksdb.NativeComparatorWrapper\
org.rocksdb.OptimisticTransactionDB\ org.rocksdb.OptimisticTransactionDB\
org.rocksdb.OptimisticTransactionOptions\ org.rocksdb.OptimisticTransactionOptions\
org.rocksdb.Options\ org.rocksdb.Options\
@ -64,6 +65,7 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.WBWIRocksIterator org.rocksdb.WBWIRocksIterator
NATIVE_JAVA_TEST_CLASSES = org.rocksdb.RocksDBExceptionTest\ NATIVE_JAVA_TEST_CLASSES = org.rocksdb.RocksDBExceptionTest\
org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper\
org.rocksdb.WriteBatchTest\ org.rocksdb.WriteBatchTest\
org.rocksdb.WriteBatchTestInternalHelper org.rocksdb.WriteBatchTestInternalHelper
@ -111,6 +113,7 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.MergeTest\ org.rocksdb.MergeTest\
org.rocksdb.MixedOptionsTest\ org.rocksdb.MixedOptionsTest\
org.rocksdb.MutableColumnFamilyOptionsTest\ org.rocksdb.MutableColumnFamilyOptionsTest\
org.rocksdb.NativeComparatorWrapperTest\
org.rocksdb.NativeLibraryLoaderTest\ org.rocksdb.NativeLibraryLoaderTest\
org.rocksdb.OptimisticTransactionTest\ org.rocksdb.OptimisticTransactionTest\
org.rocksdb.OptimisticTransactionDBTest\ org.rocksdb.OptimisticTransactionDBTest\

@ -14,6 +14,7 @@
#include "include/org_rocksdb_Comparator.h" #include "include/org_rocksdb_Comparator.h"
#include "include/org_rocksdb_DirectComparator.h" #include "include/org_rocksdb_DirectComparator.h"
#include "include/org_rocksdb_NativeComparatorWrapper.h"
#include "rocksjni/comparatorjnicallback.h" #include "rocksjni/comparatorjnicallback.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
@ -49,4 +50,16 @@ jlong Java_org_rocksdb_DirectComparator_createNewDirectComparator0(
new rocksdb::DirectComparatorJniCallback(env, jobj, copt); new rocksdb::DirectComparatorJniCallback(env, jobj, copt);
return reinterpret_cast<jlong>(c); 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> // </editor-fold>

@ -0,0 +1,50 @@
// 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);
}

@ -158,19 +158,33 @@ void Java_org_rocksdb_Options_setComparatorHandle__JI(
/* /*
* Class: org_rocksdb_Options * Class: org_rocksdb_Options
* Method: setComparatorHandle * 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, JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
jboolean is_direct) { jbyte jcomparator_type) {
auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle); rocksdb::Comparator *comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
opt->comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle); case 0x0:
} else { comparator =
opt->comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
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;
} }
/* /*
@ -2984,19 +2998,33 @@ void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JI(
/* /*
* Class: org_rocksdb_ColumnFamilyOptions * Class: org_rocksdb_ColumnFamilyOptions
* Method: setComparatorHandle * 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, JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
jboolean is_direct) { jbyte jcomparator_type) {
auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle); rocksdb::Comparator *comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
opt->comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle); case 0x0:
} else { comparator =
opt->comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
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;
} }
/* /*

@ -20,24 +20,34 @@
/* /*
* Class: org_rocksdb_SstFileWriter * Class: org_rocksdb_SstFileWriter
* Method: newSstFileWriter * Method: newSstFileWriter
* Signature: (JJJZ)J * Signature: (JJJB)J
*/ */
jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJZ(JNIEnv *env, jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJB(JNIEnv *env,
jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator, jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator_handle,
jboolean is_direct) { 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 = auto *env_options =
reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions); reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions);
auto *options = reinterpret_cast<const rocksdb::Options *>(joptions); 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 = rocksdb::SstFileWriter *sst_file_writer =
new rocksdb::SstFileWriter(*env_options, *options, comparator); new rocksdb::SstFileWriter(*env_options, *options, comparator);
return reinterpret_cast<jlong>(sst_file_writer); return reinterpret_cast<jlong>(sst_file_writer);

@ -39,19 +39,31 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__Z(
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: newWriteBatchWithIndex * 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, JNIEnv* env, jclass jcls, jlong jfallback_index_comparator_handle,
jboolean is_direct, jint jreserved_bytes, jboolean joverwrite_key) { jbyte jcomparator_type, jint jreserved_bytes, jboolean joverwrite_key) {
rocksdb::Comparator *fallback_comparator = nullptr; rocksdb::Comparator *fallback_comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
fallback_comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jfallback_index_comparator_handle); case 0x0:
} else { fallback_comparator =
fallback_comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jfallback_index_comparator_handle);
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 = auto* wbwi =
new rocksdb::WriteBatchWithIndex( new rocksdb::WriteBatchWithIndex(
fallback_comparator, fallback_comparator,

@ -17,10 +17,23 @@ package org.rocksdb;
public abstract class AbstractComparator<T extends AbstractSlice<?>> public abstract class AbstractComparator<T extends AbstractSlice<?>>
extends RocksCallbackObject { extends RocksCallbackObject {
protected AbstractComparator() {
super();
}
protected AbstractComparator(final ComparatorOptions copt) { protected AbstractComparator(final ComparatorOptions copt) {
super(copt.nativeHandle_); 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 * The name of the comparator. Used to check for comparator
* mismatches (i.e., a DB created with one comparator is * mismatches (i.e., a DB created with one comparator is

@ -163,7 +163,7 @@ public class ColumnFamilyOptions extends RocksObject
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert (isOwningHandle()); assert (isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_, setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator); comparator.getComparatorType().getValue());
comparator_ = comparator; comparator_ = comparator;
return this; return this;
} }
@ -816,7 +816,7 @@ public class ColumnFamilyOptions extends RocksObject
long memtableMemoryBudget); long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator); private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle, 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 setMergeOperatorName(long handle, String name);
private native void setMergeOperator(long handle, long mergeOperatorHandle); private native void setMergeOperator(long handle, long mergeOperatorHandle);
private native void setCompactionFilterHandle(long handle, private native void setCompactionFilterHandle(long handle,

@ -25,5 +25,10 @@ public abstract class Comparator extends AbstractComparator<Slice> {
return createNewComparator0(nativeParameterHandles[0]); return createNewComparator0(nativeParameterHandles[0]);
} }
@Override
final ComparatorType getComparatorType() {
return ComparatorType.JAVA_COMPARATOR;
}
private native long createNewComparator0(final long comparatorOptionsHandle); private native long createNewComparator0(final long comparatorOptionsHandle);
} }

@ -0,0 +1,49 @@
// 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.");
}
}

@ -25,6 +25,11 @@ public abstract class DirectComparator extends AbstractComparator<DirectSlice> {
return createNewDirectComparator0(nativeParameterHandles[0]); return createNewDirectComparator0(nativeParameterHandles[0]);
} }
@Override
final ComparatorType getComparatorType() {
return ComparatorType.JAVA_DIRECT_COMPARATOR;
}
private native long createNewDirectComparator0( private native long createNewDirectComparator0(
final long comparatorOptionsHandle); final long comparatorOptionsHandle);
} }

@ -0,0 +1,57 @@
// 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);
}

@ -191,7 +191,7 @@ public class Options extends RocksObject
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert(isOwningHandle()); assert(isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_, setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator); comparator.getComparatorType().getValue());
comparator_ = comparator; comparator_ = comparator;
return this; return this;
} }
@ -1756,7 +1756,7 @@ public class Options extends RocksObject
long memtableMemoryBudget); long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator); private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle, private native void setComparatorHandle(long optHandle,
long comparatorHandle, boolean isDirect); long comparatorHandle, byte comparatorType);
private native void setMergeOperatorName( private native void setMergeOperatorName(
long handle, String name); long handle, String name);
private native void setMergeOperator( private native void setMergeOperator(

@ -31,7 +31,7 @@ public class SstFileWriter extends RocksObject {
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
super(newSstFileWriter( super(newSstFileWriter(
envOptions.nativeHandle_, options.nativeHandle_, comparator.nativeHandle_, envOptions.nativeHandle_, options.nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator)); comparator.getComparatorType().getValue()));
} }
/** /**
@ -225,7 +225,7 @@ public void put(final byte[] key, final byte[] value)
private native static long newSstFileWriter( private native static long newSstFileWriter(
final long envOptionsHandle, final long optionsHandle, 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, private native static long newSstFileWriter(final long envOptionsHandle,
final long optionsHandle); final long optionsHandle);

@ -61,7 +61,8 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
fallbackIndexComparator, final int reservedBytes, fallbackIndexComparator, final int reservedBytes,
final boolean overwriteKey) { final boolean overwriteKey) {
super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_, super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_,
fallbackIndexComparator instanceof DirectComparator, reservedBytes, overwriteKey)); fallbackIndexComparator.getComparatorType().getValue(), reservedBytes,
overwriteKey));
} }
/** /**
@ -283,7 +284,8 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
private native static long newWriteBatchWithIndex(); private native static long newWriteBatchWithIndex();
private native static long newWriteBatchWithIndex(final boolean overwriteKey); private native static long newWriteBatchWithIndex(final boolean overwriteKey);
private native static long newWriteBatchWithIndex( 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); final boolean overwriteKey);
private native long iterator0(final long handle); private native long iterator0(final long handle);
private native long iterator1(final long handle, final long cfHandle); private native long iterator1(final long handle, final long cfHandle);

@ -0,0 +1,92 @@
// 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();
}
}

@ -398,7 +398,8 @@ JNI_NATIVE_SOURCES = \
java/rocksjni/lru_cache.cc \ java/rocksjni/lru_cache.cc \
java/rocksjni/memtablejni.cc \ java/rocksjni/memtablejni.cc \
java/rocksjni/merge_operator.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/optimistic_transaction_options.cc \
java/rocksjni/options.cc \ java/rocksjni/options.cc \
java/rocksjni/options_util.cc \ java/rocksjni/options_util.cc \

Loading…
Cancel
Save