JNI support for ReadOptions::iterate_lower_bound (#4444)

Summary:
Fixes: #4401
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4444

Differential Revision: D10282120

Pulled By: sagar0

fbshipit-source-id: d9ddcc1b132208ae7f806fa2106add6fec1baa11
This commit is contained in:
moozzyk 2018-10-09 17:11:53 -07:00 committed by Facebook Github Bot
parent 517d3b8b77
commit f45c0d20de
3 changed files with 115 additions and 2 deletions

View File

@ -6525,6 +6525,31 @@ jlong Java_org_rocksdb_ReadOptions_iterateUpperBound(JNIEnv* /*env*/,
return reinterpret_cast<jlong>(upper_bound_slice_handle);
}
/*
* Class: org_rocksdb_ReadOptions
* Method: setIterateLowerBound
* Signature: (JJ)I
*/
void Java_org_rocksdb_ReadOptions_setIterateLowerBound(
JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle,
jlong jlower_bound_slice_handle) {
reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_lower_bound =
reinterpret_cast<rocksdb::Slice*>(jlower_bound_slice_handle);
}
/*
* Class: org_rocksdb_ReadOptions
* Method: iterateLowerBound
* Signature: (J)J
*/
jlong Java_org_rocksdb_ReadOptions_iterateLowerBound(JNIEnv* /*env*/,
jobject /*jobj*/,
jlong jhandle) {
auto& lower_bound_slice_handle =
reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_lower_bound;
return reinterpret_cast<jlong>(lower_bound_slice_handle);
}
/////////////////////////////////////////////////////////////////////
// rocksdb::ComparatorOptions

View File

@ -27,6 +27,7 @@ public class ReadOptions extends RocksObject {
public ReadOptions(ReadOptions other) {
super(copyReadOptions(other.nativeHandle_));
iterateUpperBoundSlice_ = other.iterateUpperBoundSlice_;
iterateLowerBoundSlice_ = other.iterateLowerBoundSlice_;
}
/**
@ -423,15 +424,65 @@ public class ReadOptions extends RocksObject {
return null;
}
/**
* Defines the smallest key at which the backward iterator can return an
* entry. Once the bound is passed, Valid() will be false.
* `iterate_lower_bound` is inclusive ie the bound value is a valid entry.
*
* If prefix_extractor is not null, the Seek target and `iterate_lower_bound`
* need to have the same prefix. This is because ordering is not guaranteed
* outside of prefix domain.
*
* Default: nullptr
*
* @param iterateLowerBound Slice representing the lower bound
* @return the reference to the current ReadOptions.
*/
public ReadOptions setIterateLowerBound(final Slice iterateLowerBound) {
assert(isOwningHandle());
if (iterateLowerBound != null) {
// Hold onto a reference so it doesn't get garbaged collected out from under us.
iterateLowerBoundSlice_ = iterateLowerBound;
setIterateLowerBound(nativeHandle_, iterateLowerBoundSlice_.getNativeHandle());
}
return this;
}
/**
* Defines the smallest key at which the backward iterator can return an
* entry. Once the bound is passed, Valid() will be false.
* `iterate_lower_bound` is inclusive ie the bound value is a valid entry.
*
* If prefix_extractor is not null, the Seek target and `iterate_lower_bound`
* need to have the same prefix. This is because ordering is not guaranteed
* outside of prefix domain.
*
* Default: nullptr
*
* @return Slice representing current iterate_lower_bound setting, or null if
* one does not exist.
*/
public Slice iterateLowerBound() {
assert(isOwningHandle());
long lowerBoundSliceHandle = iterateLowerBound(nativeHandle_);
if (lowerBoundSliceHandle != 0) {
// Disown the new slice - it's owned by the C++ side of the JNI boundary
// from the perspective of this method.
return new Slice(lowerBoundSliceHandle, false);
}
return null;
}
// instance variables
// NOTE: If you add new member variables, please update the copy constructor above!
//
// Hold a reference to any iterate upper bound that was set on this object
// Hold a reference to any iterate upper/lower bound that was set on this object
// until we're destroyed or it's overwritten. That way the caller can freely
// leave scope without us losing the Java Slice object, which during close()
// would also reap its associated rocksdb::Slice native object since it's
// possibly (likely) to be an owning handle.
protected Slice iterateUpperBoundSlice_;
protected Slice iterateLowerBoundSlice_;
private native static long newReadOptions();
private native static long copyReadOptions(long handle);
@ -465,6 +516,9 @@ public class ReadOptions extends RocksObject {
private native void setIterateUpperBound(final long handle,
final long upperBoundSliceHandle);
private native long iterateUpperBound(final long handle);
private native void setIterateLowerBound(final long handle,
final long upperBoundSliceHandle);
private native long iterateLowerBound(final long handle);
@Override protected final native void disposeInternal(final long handle);

View File

@ -144,16 +144,34 @@ public class ReadOptionsTest {
}
}
@Test
public void iterateLowerBound() {
try (final ReadOptions opt = new ReadOptions()) {
Slice lowerBound = buildRandomSlice();
opt.setIterateLowerBound(lowerBound);
assertThat(Arrays.equals(lowerBound.data(), opt.iterateLowerBound().data())).isTrue();
}
}
@Test
public void iterateLowerBoundNull() {
try (final ReadOptions opt = new ReadOptions()) {
assertThat(opt.iterateLowerBound()).isNull();
}
}
@Test
public void copyConstructor() {
try (final ReadOptions opt = new ReadOptions()) {
opt.setVerifyChecksums(false);
opt.setFillCache(false);
opt.setIterateUpperBound(buildRandomSlice());
opt.setIterateLowerBound(buildRandomSlice());
ReadOptions other = new ReadOptions(opt);
assertThat(opt.verifyChecksums()).isEqualTo(other.verifyChecksums());
assertThat(opt.fillCache()).isEqualTo(other.fillCache());
assertThat(Arrays.equals(opt.iterateUpperBound().data(), other.iterateUpperBound().data())).isTrue();
assertThat(Arrays.equals(opt.iterateLowerBound().data(), other.iterateLowerBound().data())).isTrue();
}
}
@ -237,6 +255,22 @@ public class ReadOptionsTest {
}
}
@Test
public void failSetIterateLowerBoundUninitialized() {
try (final ReadOptions readOptions =
setupUninitializedReadOptions(exception)) {
readOptions.setIterateLowerBound(null);
}
}
@Test
public void failIterateLowerBoundUninitialized() {
try (final ReadOptions readOptions =
setupUninitializedReadOptions(exception)) {
readOptions.iterateLowerBound();
}
}
private ReadOptions setupUninitializedReadOptions(
ExpectedException exception) {
final ReadOptions readOptions = new ReadOptions();