return reinterpret_cast<jlong>(read_options);
}
+/*
+ * Class: org_rocksdb_ReadOptions
+ * Method: copyReadOptions
+ * Signature: (J)J
+ */
+jlong Java_org_rocksdb_ReadOptions_copyReadOptions(
+ JNIEnv* env, jclass jcls, jlong jhandle) {
+ auto old_read_opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle);
+ auto new_read_opt = new rocksdb::ReadOptions();
+ *new_read_opt = *old_read_opt;
+ return reinterpret_cast<jlong>(new_read_opt);
+}
+
/*
* Class: org_rocksdb_ReadOptions
* Method: disposeInternal
static_cast<rocksdb::ReadTier>(jread_tier);
}
+/*
+ * Class: org_rocksdb_ReadOptions
+ * Method: setIterateUpperBound
+ * Signature: (JJ)I
+ */
+void Java_org_rocksdb_ReadOptions_setIterateUpperBound(
+ JNIEnv* env, jobject jobj, jlong jhandle, jlong jupper_bound_slice_handle) {
+ reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_upper_bound =
+ reinterpret_cast<rocksdb::Slice*>(jupper_bound_slice_handle);
+}
+
+/*
+ * Class: org_rocksdb_ReadOptions
+ * Method: iterateUpperBound
+ * Signature: (J)J
+ */
+jlong Java_org_rocksdb_ReadOptions_iterateUpperBound(
+ JNIEnv* env, jobject jobj, jlong jhandle) {
+ auto& upper_bound_slice_handle =
+ reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_upper_bound;
+ return reinterpret_cast<jlong>(upper_bound_slice_handle);
+}
+
/////////////////////////////////////////////////////////////////////
// rocksdb::ComparatorOptions
super(newReadOptions());
}
+ /**
+ * Copy constructor.
+ *
+ * NOTE: This does a shallow copy, which means snapshot, iterate_upper_bound
+ * and other pointers will be cloned!
+ *
+ * @param other The ReadOptions to copy.
+ */
+ public ReadOptions(ReadOptions other) {
+ super(copyReadOptions(other.nativeHandle_));
+ iterateUpperBoundSlice_ = other.iterateUpperBoundSlice_;
+ }
+
/**
* If true, all data read from underlying storage will be
* verified against corresponding checksums.
return this;
}
+ /**
+ * Defines the extent upto which the forward iterator can returns entries.
+ * Once the bound is reached, Valid() will be false. iterate_upper_bound
+ * is exclusive ie the bound value is not a valid entry. If
+ * iterator_extractor is not null, the Seek target and iterator_upper_bound
+ * need to have the same prefix. This is because ordering is not guaranteed
+ * outside of prefix domain. There is no lower bound on the iterator.
+ *
+ * Default: nullptr
+ *
+ * @param iterateUpperBound Slice representing the upper bound
+ * @return the reference to the current ReadOptions.
+ */
+ public ReadOptions setIterateUpperBound(final Slice iterateUpperBound) {
+ assert(isOwningHandle());
+ if (iterateUpperBound != null) {
+ // Hold onto a reference so it doesn't get garbaged collected out from under us.
+ iterateUpperBoundSlice_ = iterateUpperBound;
+ setIterateUpperBound(nativeHandle_, iterateUpperBoundSlice_.getNativeHandle());
+ }
+ return this;
+ }
+
+ /**
+ * Defines the extent upto which the forward iterator can returns entries.
+ * Once the bound is reached, Valid() will be false. iterate_upper_bound
+ * is exclusive ie the bound value is not a valid entry. If
+ * iterator_extractor is not null, the Seek target and iterator_upper_bound
+ * need to have the same prefix. This is because ordering is not guaranteed
+ * outside of prefix domain. There is no lower bound on the iterator.
+ *
+ * Default: nullptr
+ *
+ * @return Slice representing current iterate_upper_bound setting, or null if
+ * one does not exist.
+ */
+ public Slice iterateUpperBound() {
+ assert(isOwningHandle());
+ long upperBoundSliceHandle = iterateUpperBound(nativeHandle_);
+ if (upperBoundSliceHandle != 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(upperBoundSliceHandle, false);
+ }
+ return null;
+ }
+
+ // Hold a reference to any iterate upper 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_;
+
private native static long newReadOptions();
+ private native static long copyReadOptions(long handle);
private native boolean verifyChecksums(long handle);
private native void setVerifyChecksums(long handle, boolean verifyChecksums);
private native boolean fillCache(long handle);
private native boolean ignoreRangeDeletions(final long handle);
private native void setIgnoreRangeDeletions(final long handle,
final boolean ignoreRangeDeletions);
+ private native void setIterateUpperBound(final long handle,
+ final long upperBoundSliceHandle);
+ private native long iterateUpperBound(final long handle);
@Override protected final native void disposeInternal(final long handle);
super();
}
+ /**
+ * <p>Package-private Slice constructor which is used to construct
+ * Slice instances from C++ side. As the reference to this
+ * object is also managed from C++ side the handle will be disowned.</p>
+ *
+ * @param nativeHandle address of native instance.
+ */
+ Slice(final long nativeHandle) {
+ this(nativeHandle, false);
+ }
+
+ /**
+ * <p>Package-private Slice constructor which is used to construct
+ * Slice instances using a handle. </p>
+ *
+ * @param nativeHandle address of native instance.
+ * @param owningNativeHandle whether to own this reference from the C++ side or not
+ */
+ Slice(final long nativeHandle, final boolean owningNativeHandle) {
+ super();
+ setNativeHandle(nativeHandle, owningNativeHandle);
+ }
+
/**
* <p>Constructs a slice where the data is taken from
* a String.</p>
package org.rocksdb;
+import java.util.Arrays;
import java.util.Random;
import org.junit.ClassRule;
}
}
+ @Test
+ public void iterateUpperBound() {
+ try (final ReadOptions opt = new ReadOptions()) {
+ Slice upperBound = buildRandomSlice();
+ opt.setIterateUpperBound(upperBound);
+ assertThat(Arrays.equals(upperBound.data(), opt.iterateUpperBound().data())).isTrue();
+ }
+ }
+
+ @Test
+ public void iterateUpperBoundNull() {
+ try (final ReadOptions opt = new ReadOptions()) {
+ assertThat(opt.iterateUpperBound()).isNull();
+ }
+ }
+
+ @Test
+ public void copyConstructor() {
+ try (final ReadOptions opt = new ReadOptions()) {
+ opt.setVerifyChecksums(false);
+ opt.setFillCache(false);
+ opt.setIterateUpperBound(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();
+ }
+ }
+
@Test
public void failSetVerifyChecksumUninitialized() {
try (final ReadOptions readOptions =
}
}
+ @Test
+ public void failSetIterateUpperBoundUninitialized() {
+ try (final ReadOptions readOptions =
+ setupUninitializedReadOptions(exception)) {
+ readOptions.setIterateUpperBound(null);
+ }
+ }
+
+ @Test
+ public void failIterateUpperBoundUninitialized() {
+ try (final ReadOptions readOptions =
+ setupUninitializedReadOptions(exception)) {
+ readOptions.iterateUpperBound();
+ }
+ }
+
private ReadOptions setupUninitializedReadOptions(
ExpectedException exception) {
final ReadOptions readOptions = new ReadOptions();
exception.expect(AssertionError.class);
return readOptions;
}
+
+ private Slice buildRandomSlice() {
+ final Random rand = new Random();
+ byte[] sliceBytes = new byte[rand.nextInt(100) + 1];
+ rand.nextBytes(sliceBytes);
+ return new Slice(sliceBytes);
+ }
+
}