diff --git a/java/Makefile b/java/Makefile index 5311af14f5a1143e00ce554c8358411e089b7fb2..dd8b4b6fe8f5d47f7fc11360e6e10eb98f86bb97 100644 --- a/java/Makefile +++ b/java/Makefile @@ -1,4 +1,4 @@ -NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB org.rocksdb.Options org.rocksdb.WriteBatch org.rocksdb.WriteBatchInternal org.rocksdb.WriteBatchTest org.rocksdb.WriteOptions org.rocksdb.BackupableDB org.rocksdb.BackupableDBOptions org.rocksdb.Statistics org.rocksdb.Iterator org.rocksdb.VectorMemTableConfig org.rocksdb.SkipListMemTableConfig org.rocksdb.HashLinkedListMemTableConfig org.rocksdb.HashSkipListMemTableConfig org.rocksdb.PlainTableConfig org.rocksdb.ReadOptions +NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB org.rocksdb.Options org.rocksdb.WriteBatch org.rocksdb.WriteBatchInternal org.rocksdb.WriteBatchTest org.rocksdb.WriteOptions org.rocksdb.BackupableDB org.rocksdb.BackupableDBOptions org.rocksdb.Statistics org.rocksdb.Iterator org.rocksdb.VectorMemTableConfig org.rocksdb.SkipListMemTableConfig org.rocksdb.HashLinkedListMemTableConfig org.rocksdb.HashSkipListMemTableConfig org.rocksdb.PlainTableConfig org.rocksdb.ReadOptions org.rocksdb.Filter NATIVE_INCLUDE = ./include ROCKSDB_JAR = rocksdbjni.jar diff --git a/java/RocksDBSample.java b/java/RocksDBSample.java index 57e9aa6e7483018f90a7d88f1b5c1175a7880ebd..4bedc592c35f3d0710425dc1d8ec8d27a4071ff1 100644 --- a/java/RocksDBSample.java +++ b/java/RocksDBSample.java @@ -32,6 +32,7 @@ public class RocksDBSample { assert(db == null); } + Filter filter = new Filter(10); options.setCreateIfMissing(true) .createStatistics() .setWriteBufferSize(8 * SizeUnit.KB) @@ -39,7 +40,7 @@ public class RocksDBSample { .setDisableSeekCompaction(true) .setBlockSize(64 * SizeUnit.KB) .setMaxBackgroundCompactions(10) - .createBloomFilter(10); + .setFilter(filter); Statistics stats = options.statisticsPtr(); assert(options.createIfMissing() == true); @@ -225,5 +226,6 @@ public class RocksDBSample { // be sure to dispose c++ pointers options.dispose(); readOptions.dispose(); + filter.dispose(); } } diff --git a/java/org/rocksdb/Filter.java b/java/org/rocksdb/Filter.java new file mode 100644 index 0000000000000000000000000000000000000000..cf6544870c0da15e59b42318d08f43f6727cd5e1 --- /dev/null +++ b/java/org/rocksdb/Filter.java @@ -0,0 +1,50 @@ +// Copyright (c) 2014, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. + +package org.rocksdb; + +/** + * Filters are stored in rocksdb and are consulted automatically + * by rocksdb to decide whether or not to read some + * information from disk. In many cases, a filter can cut down the + * number of disk seeks form a handful to a single disk seek per + * DB::Get() call. + * + * This function a new filter policy that uses a bloom filter + * with approximately the specified number of bits per key. + * A good value for bitsPerKey is 10, which yields a filter + * with ~ 1% false positive rate. + */ +public class Filter { + private long nativeHandle_; + + public Filter(int bitsPerKey) { + newFilter(bitsPerKey); + } + + public long getNativeHandle() { + return nativeHandle_; + } + + /** + * Deletes underlying C++ filter pointer. + */ + public synchronized void dispose() { + if(nativeHandle_ != 0) { + dispose0(nativeHandle_); + } + } + + @Override protected void finalize() { + dispose(); + } + + private boolean isInitialized() { + return (nativeHandle_ != 0); + } + + private native void newFilter(int bitsPerKey); + private native void dispose0(long handle); +} \ No newline at end of file diff --git a/java/org/rocksdb/Options.java b/java/org/rocksdb/Options.java index c05e0d5e4ba9c8084946b1502c25a7f23d5c14f5..aee5f185191ce6b2cda3820dfea1b11ab1a26284 100644 --- a/java/org/rocksdb/Options.java +++ b/java/org/rocksdb/Options.java @@ -145,24 +145,14 @@ public class Options { } /** - * Filters are stored in rocksdb and are consulted automatically - * by rocksdb to decide whether or not to read some - * information from disk. In many cases, a filter can cut down the - * number of disk seeks form a handful to a single disk seek per - * DB::Get() call. - * - * This function a new filter policy that uses a bloom filter - * with approximately the specified number of bits per key. - * A good value for bitsPerKey is 10, which yields a filter - * with ~ 1% false positive rate. - * - * @param Bits per key for bloom filter. + * Use the specified filter policy to reduce disk reads. + * @param Filter policy java instance. * @return the instance of the current Options. * @see RocksDB.open() */ - public Options createBloomFilter(int bitsPerKey) { + public Options setFilter(Filter filter) { assert(isInitialized()); - createBloomFilter0(nativeHandle_, bitsPerKey); + setFilter0(nativeHandle_, filter.getNativeHandle()); return this; } @@ -1260,7 +1250,7 @@ public class Options { private native void useFixedLengthPrefixExtractor( long handle, int prefixLength); - private native void createBloomFilter0(long handle, int bitsPerKey); + private native void setFilter0(long optHandle, long fpHandle); long nativeHandle_; long cacheSize_; diff --git a/java/rocksjni/filter.cc b/java/rocksjni/filter.cc new file mode 100644 index 0000000000000000000000000000000000000000..c363a851a44d34fa2a7cb7c6f63e0e34d19a3fd6 --- /dev/null +++ b/java/rocksjni/filter.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2014, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// This file implements the "bridge" between Java and C++ for rocksdb::Filter. + +#include +#include +#include +#include + +#include "include/org_rocksdb_Filter.h" +#include "rocksjni/portal.h" +#include "rocksdb/filter_policy.h" + +/* + * Class: org_rocksdb_Filter + * Method: newFilter + * Signature: (I)V + */ +void Java_org_rocksdb_Filter_newFilter( + JNIEnv* env, jobject jobj, jint bits_per_key) { + const rocksdb::FilterPolicy* fp = rocksdb::NewBloomFilterPolicy(bits_per_key); + rocksdb::FilterJni::setHandle(env, jobj, fp); +} + +/* + * Class: org_rocksdb_Filter + * Method: dispose0 + * Signature: (J)V + */ +void Java_org_rocksdb_Filter_dispose0( + JNIEnv* env, jobject jobj, jlong handle) { + auto fp = reinterpret_cast(handle); + delete fp; + + rocksdb::FilterJni::setHandle(env, jobj, nullptr); +} \ No newline at end of file diff --git a/java/rocksjni/options.cc b/java/rocksjni/options.cc index 29108e44ce99c93b2ff791cdbe7f01527604e061..dbb10e0c8ab807fc8107a199df900fccc39b6f6e 100644 --- a/java/rocksjni/options.cc +++ b/java/rocksjni/options.cc @@ -122,19 +122,13 @@ jlong Java_org_rocksdb_Options_statisticsPtr( /* * Class: org_rocksdb_Options - * Method: createBloomFilter0 - * Signature: (JI)V + * Method: setFilter0 + * Signature: (JJ)V */ -void Java_org_rocksdb_Options_createBloomFilter0( - JNIEnv* env, jobject jobj, jlong jhandle, jint jbits_per_key) { - rocksdb::Options* opt = reinterpret_cast(jhandle); - - // Delete previously allocated pointer - if(opt->filter_policy) { - delete opt->filter_policy; - } - - opt->filter_policy = rocksdb::NewBloomFilterPolicy(jbits_per_key); +void Java_org_rocksdb_Options_setFilter0( + JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jfp_handle) { + reinterpret_cast(jopt_handle)->filter_policy = + reinterpret_cast(jfp_handle); } /* diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index 0b485e2e3675276120b0777058ef770138dfdccc..61edb8bc436afabf21cbb4ba181659ea1265e231 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -12,6 +12,7 @@ #include #include "rocksdb/db.h" +#include "rocksdb/filter_policy.h" #include "utilities/backupable_db.h" namespace rocksdb { @@ -281,5 +282,38 @@ class IteratorJni { reinterpret_cast(op)); } }; + +class FilterJni { + public: + // Get the java class id of org.rocksdb.Filter. + static jclass getJClass(JNIEnv* env) { + static jclass jclazz = env->FindClass("org/rocksdb/Filter"); + assert(jclazz != nullptr); + return jclazz; + } + + // Get the field id of the member variable of org.rocksdb.Filter + // that stores the pointer to rocksdb::Iterator. + static jfieldID getHandleFieldID(JNIEnv* env) { + static jfieldID fid = env->GetFieldID( + getJClass(env), "nativeHandle_", "J"); + assert(fid != nullptr); + return fid; + } + + // Get the pointer to rocksdb::Filter. + static rocksdb::FilterPolicy* getHandle(JNIEnv* env, jobject jobj) { + return reinterpret_cast( + env->GetLongField(jobj, getHandleFieldID(env))); + } + + // Pass the rocksdb::Filter pointer to the java side. + static void setHandle( + JNIEnv* env, jobject jobj, const rocksdb::FilterPolicy* op) { + env->SetLongField( + jobj, getHandleFieldID(env), + reinterpret_cast(op)); + } +}; } // namespace rocksdb #endif // JAVA_ROCKSJNI_PORTAL_H_