]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/java/rocksjni/write_batch_with_index.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / java / rocksjni / write_batch_with_index.cc
index 6a382f894c15f08047f16f12e0ad848f6b360920..12ca299a9d8a2f56481961bdad7339fe086dbe3f 100644 (file)
@@ -1,15 +1,15 @@
 // Copyright (c) 2011-present, 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 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).
 //
 // This file implements the "bridge" between Java and C++ and enables
 // calling c++ rocksdb::WriteBatchWithIndex methods from Java side.
 
+#include "rocksdb/utilities/write_batch_with_index.h"
 #include "include/org_rocksdb_WBWIRocksIterator.h"
 #include "include/org_rocksdb_WriteBatchWithIndex.h"
 #include "rocksdb/comparator.h"
-#include "rocksdb/utilities/write_batch_with_index.h"
 #include "rocksjni/portal.h"
 
 /*
@@ -18,7 +18,7 @@
  * Signature: ()J
  */
 jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__(
-    JNIEnv* env, jclass jcls) {
+    JNIEnv* /*env*/, jclass /*jcls*/) {
   auto* wbwi = new rocksdb::WriteBatchWithIndex();
   return reinterpret_cast<jlong>(wbwi);
 }
@@ -29,25 +29,44 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__(
  * Signature: (Z)J
  */
 jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__Z(
-    JNIEnv* env, jclass jcls, jboolean joverwrite_key) {
-  auto* wbwi =
-      new rocksdb::WriteBatchWithIndex(rocksdb::BytewiseComparator(), 0,
-          static_cast<bool>(joverwrite_key));
+    JNIEnv* /*env*/, jclass /*jcls*/, jboolean joverwrite_key) {
+  auto* wbwi = new rocksdb::WriteBatchWithIndex(
+      rocksdb::BytewiseComparator(), 0, static_cast<bool>(joverwrite_key));
   return reinterpret_cast<jlong>(wbwi);
 }
 
 /*
  * Class:     org_rocksdb_WriteBatchWithIndex
  * Method:    newWriteBatchWithIndex
- * Signature: (JIZ)J
- */
-jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JIZ(
-    JNIEnv* env, jclass jcls, jlong jfallback_index_comparator_handle,
-    jint jreserved_bytes, jboolean joverwrite_key) {
-  auto* wbwi =
-      new rocksdb::WriteBatchWithIndex(
-          reinterpret_cast<rocksdb::Comparator*>(jfallback_index_comparator_handle),
-          static_cast<size_t>(jreserved_bytes), static_cast<bool>(joverwrite_key));
+ * Signature: (JBIZ)J
+ */
+jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JBIZ(
+    JNIEnv* /*env*/, jclass /*jcls*/, jlong 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, static_cast<size_t>(jreserved_bytes),
+      static_cast<bool>(joverwrite_key));
   return reinterpret_cast<jlong>(wbwi);
 }
 
@@ -56,8 +75,9 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JIZ(
  * Method:    count0
  * Signature: (J)I
  */
-jint Java_org_rocksdb_WriteBatchWithIndex_count0(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
+jint Java_org_rocksdb_WriteBatchWithIndex_count0(JNIEnv* /*env*/,
+                                                 jobject /*jobj*/,
+                                                 jlong jwbwi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
 
@@ -74,11 +94,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BI(
     jint jkey_len, jbyteArray jentry_value, jint jentry_value_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
-  auto put = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) {
-    wbwi->Put(key, value);
+  auto put = [&wbwi](rocksdb::Slice key, rocksdb::Slice value) {
+    return wbwi->Put(key, value);
   };
-  rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value,
-      jentry_value_len);
+  std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
+      put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -94,11 +117,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BIJ(
   assert(wbwi != nullptr);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
   assert(cf_handle != nullptr);
-  auto put = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
-    wbwi->Put(cf_handle, key, value);
+  auto put = [&wbwi, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) {
+    return wbwi->Put(cf_handle, key, value);
   };
-  rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value,
-      jentry_value_len);
+  std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
+      put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -111,11 +137,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BI(
     jint jkey_len, jbyteArray jentry_value, jint jentry_value_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
-  auto merge = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) {
-    wbwi->Merge(key, value);
+  auto merge = [&wbwi](rocksdb::Slice key, rocksdb::Slice value) {
+    return wbwi->Merge(key, value);
   };
-  rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value,
-      jentry_value_len);
+  std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
+      merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -131,45 +160,98 @@ void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BIJ(
   assert(wbwi != nullptr);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
   assert(cf_handle != nullptr);
-  auto merge = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
-    wbwi->Merge(cf_handle, key, value);
+  auto merge = [&wbwi, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) {
+    return wbwi->Merge(cf_handle, key, value);
+  };
+  std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
+      merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
+}
+
+/*
+ * Class:     org_rocksdb_WriteBatchWithIndex
+ * Method:    delete
+ * Signature: (J[BI)V
+ */
+void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BI(JNIEnv* env,
+                                                        jobject jobj,
+                                                        jlong jwbwi_handle,
+                                                        jbyteArray jkey,
+                                                        jint jkey_len) {
+  auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
+  assert(wbwi != nullptr);
+  auto remove = [&wbwi](rocksdb::Slice key) { return wbwi->Delete(key); };
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
+}
+
+/*
+ * Class:     org_rocksdb_WriteBatchWithIndex
+ * Method:    delete
+ * Signature: (J[BIJ)V
+ */
+void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BIJ(
+    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
+    jint jkey_len, jlong jcf_handle) {
+  auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
+  assert(wbwi != nullptr);
+  auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
+  assert(cf_handle != nullptr);
+  auto remove = [&wbwi, &cf_handle](rocksdb::Slice key) {
+    return wbwi->Delete(cf_handle, key);
   };
-  rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value,
-      jentry_value_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
  * Class:     org_rocksdb_WriteBatchWithIndex
- * Method:    remove
+ * Method:    singleDelete
  * Signature: (J[BI)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BI(
+void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BI(
     JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
     jint jkey_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
-  auto remove = [&wbwi] (rocksdb::Slice key) {
-    wbwi->Delete(key);
+  auto single_delete = [&wbwi](rocksdb::Slice key) {
+    return wbwi->SingleDelete(key);
   };
-  rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
  * Class:     org_rocksdb_WriteBatchWithIndex
- * Method:    remove
+ * Method:    singleDelete
  * Signature: (J[BIJ)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BIJ(
+void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BIJ(
     JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
     jint jkey_len, jlong jcf_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
   assert(cf_handle != nullptr);
-  auto remove = [&wbwi, &cf_handle] (rocksdb::Slice key) {
-    wbwi->Delete(cf_handle, key);
+  auto single_delete = [&wbwi, &cf_handle](rocksdb::Slice key) {
+    return wbwi->SingleDelete(cf_handle, key);
   };
-  rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -183,10 +265,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BI(
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
   auto deleteRange = [&wbwi](rocksdb::Slice beginKey, rocksdb::Slice endKey) {
-    wbwi->DeleteRange(beginKey, endKey);
+    return wbwi->DeleteRange(beginKey, endKey);
   };
-  rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
-                          jend_key, jend_key_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key,
+                              jbegin_key_len, jend_key, jend_key_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -204,10 +290,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BIJ(
   assert(cf_handle != nullptr);
   auto deleteRange = [&wbwi, &cf_handle](rocksdb::Slice beginKey,
                                          rocksdb::Slice endKey) {
-    wbwi->DeleteRange(cf_handle, beginKey, endKey);
+    return wbwi->DeleteRange(cf_handle, beginKey, endKey);
   };
-  rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
-                          jend_key, jend_key_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key,
+                              jbegin_key_len, jend_key, jend_key_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -215,15 +305,20 @@ void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BIJ(
  * Method:    putLogData
  * Signature: (J[BI)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_putLogData(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jblob,
-    jint jblob_len) {
+void Java_org_rocksdb_WriteBatchWithIndex_putLogData(JNIEnv* env, jobject jobj,
+                                                     jlong jwbwi_handle,
+                                                     jbyteArray jblob,
+                                                     jint jblob_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
-  auto putLogData = [&wbwi] (rocksdb::Slice blob) {
-    wbwi->PutLogData(blob);
+  auto putLogData = [&wbwi](rocksdb::Slice blob) {
+    return wbwi->PutLogData(blob);
   };
-  rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len);
+  std::unique_ptr<rocksdb::Status> status =
+      rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len);
+  if (status != nullptr && !status->ok()) {
+    rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
+  }
 }
 
 /*
@@ -231,8 +326,9 @@ void Java_org_rocksdb_WriteBatchWithIndex_putLogData(
  * Method:    clear
  * Signature: (J)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_clear0(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
+void Java_org_rocksdb_WriteBatchWithIndex_clear0(JNIEnv* /*env*/,
+                                                 jobject /*jobj*/,
+                                                 jlong jwbwi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
 
@@ -244,8 +340,9 @@ void Java_org_rocksdb_WriteBatchWithIndex_clear0(
  * Method:    setSavePoint0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_setSavePoint0(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
+void Java_org_rocksdb_WriteBatchWithIndex_setSavePoint0(JNIEnv* /*env*/,
+                                                        jobject /*jobj*/,
+                                                        jlong jwbwi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
 
@@ -258,7 +355,7 @@ void Java_org_rocksdb_WriteBatchWithIndex_setSavePoint0(
  * Signature: (J)V
  */
 void Java_org_rocksdb_WriteBatchWithIndex_rollbackToSavePoint0(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
+    JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   assert(wbwi != nullptr);
 
@@ -271,13 +368,66 @@ void Java_org_rocksdb_WriteBatchWithIndex_rollbackToSavePoint0(
   rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
 }
 
+/*
+ * Class:     org_rocksdb_WriteBatchWithIndex
+ * Method:    popSavePoint
+ * Signature: (J)V
+ */
+void Java_org_rocksdb_WriteBatchWithIndex_popSavePoint(JNIEnv* env,
+                                                       jobject /*jobj*/,
+                                                       jlong jwbwi_handle) {
+  auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
+  assert(wbwi != nullptr);
+
+  auto s = wbwi->PopSavePoint();
+
+  if (s.ok()) {
+    return;
+  }
+
+  rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
+}
+
+/*
+ * Class:     org_rocksdb_WriteBatchWithIndex
+ * Method:    setMaxBytes
+ * Signature: (JJ)V
+ */
+void Java_org_rocksdb_WriteBatchWithIndex_setMaxBytes(JNIEnv* /*env*/,
+                                                      jobject /*jobj*/,
+                                                      jlong jwbwi_handle,
+                                                      jlong jmax_bytes) {
+  auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
+  assert(wbwi != nullptr);
+
+  wbwi->SetMaxBytes(static_cast<size_t>(jmax_bytes));
+}
+
+/*
+ * Class:     org_rocksdb_WriteBatchWithIndex
+ * Method:    getWriteBatch
+ * Signature: (J)Lorg/rocksdb/WriteBatch;
+ */
+jobject Java_org_rocksdb_WriteBatchWithIndex_getWriteBatch(JNIEnv* env,
+                                                           jobject /*jobj*/,
+                                                           jlong jwbwi_handle) {
+  auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
+  assert(wbwi != nullptr);
+
+  auto* wb = wbwi->GetWriteBatch();
+
+  // TODO(AR) is the `wb` object owned by us?
+  return rocksdb::WriteBatchJni::construct(env, wb);
+}
+
 /*
  * Class:     org_rocksdb_WriteBatchWithIndex
  * Method:    iterator0
  * Signature: (J)J
  */
-jlong Java_org_rocksdb_WriteBatchWithIndex_iterator0(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
+jlong Java_org_rocksdb_WriteBatchWithIndex_iterator0(JNIEnv* /*env*/,
+                                                     jobject /*jobj*/,
+                                                     jlong jwbwi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* wbwi_iterator = wbwi->NewIterator();
   return reinterpret_cast<jlong>(wbwi_iterator);
@@ -288,8 +438,10 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_iterator0(
  * Method:    iterator1
  * Signature: (JJ)J
  */
-jlong Java_org_rocksdb_WriteBatchWithIndex_iterator1(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jcf_handle) {
+jlong Java_org_rocksdb_WriteBatchWithIndex_iterator1(JNIEnv* /*env*/,
+                                                     jobject /*jobj*/,
+                                                     jlong jwbwi_handle,
+                                                     jlong jcf_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
   auto* wbwi_iterator = wbwi->NewIterator(cf_handle);
@@ -301,9 +453,11 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_iterator1(
  * Method:    iteratorWithBase
  * Signature: (JJJ)J
  */
-jlong Java_org_rocksdb_WriteBatchWithIndex_iteratorWithBase(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jcf_handle,
-    jlong jbi_handle) {
+jlong Java_org_rocksdb_WriteBatchWithIndex_iteratorWithBase(JNIEnv* /*env*/,
+                                                            jobject /*jobj*/,
+                                                            jlong jwbwi_handle,
+                                                            jlong jcf_handle,
+                                                            jlong jbi_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
   auto* base_iterator = reinterpret_cast<rocksdb::Iterator*>(jbi_handle);
@@ -317,7 +471,7 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_iteratorWithBase(
  * Signature: (JJ[BI)[B
  */
 jbyteArray JNICALL Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BI(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jdbopt_handle,
+    JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdbopt_handle,
     jbyteArray jkey, jint jkey_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* dbopt = reinterpret_cast<rocksdb::DBOptions*>(jdbopt_handle);
@@ -335,17 +489,16 @@ jbyteArray JNICALL Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BI(
  * Signature: (JJ[BIJ)[B
  */
 jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BIJ(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jdbopt_handle,
+    JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdbopt_handle,
     jbyteArray jkey, jint jkey_len, jlong jcf_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* dbopt = reinterpret_cast<rocksdb::DBOptions*>(jdbopt_handle);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
 
-  auto getter =
-      [&wbwi, &cf_handle, &dbopt](const rocksdb::Slice& key,
-                                  std::string* value) {
-        return wbwi->GetFromBatch(cf_handle, *dbopt, key, value);
-      };
+  auto getter = [&wbwi, &cf_handle, &dbopt](const rocksdb::Slice& key,
+                                            std::string* value) {
+    return wbwi->GetFromBatch(cf_handle, *dbopt, key, value);
+  };
 
   return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len);
 }
@@ -356,16 +509,16 @@ jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BIJ(
  * Signature: (JJJ[BI)[B
  */
 jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BI(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jdb_handle,
+    JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdb_handle,
     jlong jreadopt_handle, jbyteArray jkey, jint jkey_len) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
   auto* readopt = reinterpret_cast<rocksdb::ReadOptions*>(jreadopt_handle);
 
-  auto getter =
-      [&wbwi, &db, &readopt](const rocksdb::Slice& key, std::string* value) {
-        return wbwi->GetFromBatchAndDB(db, *readopt, key, value);
-      };
+  auto getter = [&wbwi, &db, &readopt](const rocksdb::Slice& key,
+                                       std::string* value) {
+    return wbwi->GetFromBatchAndDB(db, *readopt, key, value);
+  };
 
   return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len);
 }
@@ -376,18 +529,17 @@ jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BI(
  * Signature: (JJJ[BIJ)[B
  */
 jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BIJ(
-    JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jdb_handle,
+    JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdb_handle,
     jlong jreadopt_handle, jbyteArray jkey, jint jkey_len, jlong jcf_handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
   auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
   auto* readopt = reinterpret_cast<rocksdb::ReadOptions*>(jreadopt_handle);
   auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
 
-  auto getter =
-      [&wbwi, &db, &cf_handle, &readopt](const rocksdb::Slice& key,
-                                         std::string* value) {
-        return wbwi->GetFromBatchAndDB(db, *readopt, cf_handle, key, value);
-      };
+  auto getter = [&wbwi, &db, &cf_handle, &readopt](const rocksdb::Slice& key,
+                                                   std::string* value) {
+    return wbwi->GetFromBatchAndDB(db, *readopt, cf_handle, key, value);
+  };
 
   return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len);
 }
@@ -397,8 +549,9 @@ jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BIJ(
  * Method:    disposeInternal
  * Signature: (J)V
  */
-void Java_org_rocksdb_WriteBatchWithIndex_disposeInternal(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WriteBatchWithIndex_disposeInternal(JNIEnv* /*env*/,
+                                                          jobject /*jobj*/,
+                                                          jlong handle) {
   auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(handle);
   assert(wbwi != nullptr);
   delete wbwi;
@@ -411,8 +564,9 @@ void Java_org_rocksdb_WriteBatchWithIndex_disposeInternal(
  * Method:    disposeInternal
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_disposeInternal(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_disposeInternal(JNIEnv* /*env*/,
+                                                        jobject /*jobj*/,
+                                                        jlong handle) {
   auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle);
   assert(it != nullptr);
   delete it;
@@ -423,8 +577,9 @@ void Java_org_rocksdb_WBWIRocksIterator_disposeInternal(
  * Method:    isValid0
  * Signature: (J)Z
  */
-jboolean Java_org_rocksdb_WBWIRocksIterator_isValid0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+jboolean Java_org_rocksdb_WBWIRocksIterator_isValid0(JNIEnv* /*env*/,
+                                                     jobject /*jobj*/,
+                                                     jlong handle) {
   return reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Valid();
 }
 
@@ -433,8 +588,9 @@ jboolean Java_org_rocksdb_WBWIRocksIterator_isValid0(
  * Method:    seekToFirst0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_seekToFirst0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_seekToFirst0(JNIEnv* /*env*/,
+                                                     jobject /*jobj*/,
+                                                     jlong handle) {
   reinterpret_cast<rocksdb::WBWIIterator*>(handle)->SeekToFirst();
 }
 
@@ -443,8 +599,9 @@ void Java_org_rocksdb_WBWIRocksIterator_seekToFirst0(
  * Method:    seekToLast0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_seekToLast0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_seekToLast0(JNIEnv* /*env*/,
+                                                    jobject /*jobj*/,
+                                                    jlong handle) {
   reinterpret_cast<rocksdb::WBWIIterator*>(handle)->SeekToLast();
 }
 
@@ -453,8 +610,8 @@ void Java_org_rocksdb_WBWIRocksIterator_seekToLast0(
  * Method:    next0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_next0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_next0(JNIEnv* /*env*/, jobject /*jobj*/,
+                                              jlong handle) {
   reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Next();
 }
 
@@ -463,8 +620,8 @@ void Java_org_rocksdb_WBWIRocksIterator_next0(
  * Method:    prev0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_prev0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_prev0(JNIEnv* /*env*/, jobject /*jobj*/,
+                                              jlong handle) {
   reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Prev();
 }
 
@@ -473,31 +630,54 @@ void Java_org_rocksdb_WBWIRocksIterator_prev0(
  * Method:    seek0
  * Signature: (J[BI)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_seek0(
-    JNIEnv* env, jobject jobj, jlong handle, jbyteArray jtarget,
-    jint jtarget_len) {
+void Java_org_rocksdb_WBWIRocksIterator_seek0(JNIEnv* env, jobject /*jobj*/,
+                                              jlong handle, jbyteArray jtarget,
+                                              jint jtarget_len) {
   auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle);
   jbyte* target = env->GetByteArrayElements(jtarget, nullptr);
-  if(target == nullptr) {
+  if (target == nullptr) {
     // exception thrown: OutOfMemoryError
     return;
   }
 
-  rocksdb::Slice target_slice(
-      reinterpret_cast<char*>(target), jtarget_len);
+  rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len);
 
   it->Seek(target_slice);
 
   env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT);
 }
 
+/*
+ * Class:     org_rocksdb_WBWIRocksIterator
+ * Method:    seekForPrev0
+ * Signature: (J[BI)V
+ */
+void Java_org_rocksdb_WBWIRocksIterator_seekForPrev0(JNIEnv* env,
+                                                     jobject /*jobj*/,
+                                                     jlong handle,
+                                                     jbyteArray jtarget,
+                                                     jint jtarget_len) {
+  auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle);
+  jbyte* target = env->GetByteArrayElements(jtarget, nullptr);
+  if (target == nullptr) {
+    // exception thrown: OutOfMemoryError
+    return;
+  }
+
+  rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len);
+
+  it->SeekForPrev(target_slice);
+
+  env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT);
+}
+
 /*
  * Class:     org_rocksdb_WBWIRocksIterator
  * Method:    status0
  * Signature: (J)V
  */
-void Java_org_rocksdb_WBWIRocksIterator_status0(
-    JNIEnv* env, jobject jobj, jlong handle) {
+void Java_org_rocksdb_WBWIRocksIterator_status0(JNIEnv* env, jobject /*jobj*/,
+                                                jlong handle) {
   auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle);
   rocksdb::Status s = it->status();
 
@@ -513,41 +693,25 @@ void Java_org_rocksdb_WBWIRocksIterator_status0(
  * Method:    entry1
  * Signature: (J)[J
  */
-jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(
-    JNIEnv* env, jobject jobj, jlong handle) {
+jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(JNIEnv* env,
+                                                     jobject /*jobj*/,
+                                                     jlong handle) {
   auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle);
   const rocksdb::WriteEntry& we = it->Entry();
 
   jlong results[3];
 
-  //set the type of the write entry
-  switch (we.type) {
-    case rocksdb::kPutRecord:
-      results[0] = 0x1;
-      break;
-
-    case rocksdb::kMergeRecord:
-      results[0] = 0x2;
-      break;
-
-    case rocksdb::kDeleteRecord:
-      results[0] = 0x4;
-      break;
-
-    case rocksdb::kLogDataRecord:
-      results[0] = 0x8;
-      break;
-
-    default:
-      results[0] = 0x0;
-  }
+  // set the type of the write entry
+  results[0] = rocksdb::WriteTypeJni::toJavaWriteType(we.type);
 
-  // key_slice and value_slice will be freed by org.rocksdb.DirectSlice#close
+  // NOTE: key_slice and value_slice will be freed by
+  // org.rocksdb.DirectSlice#close
 
   auto* key_slice = new rocksdb::Slice(we.key.data(), we.key.size());
   results[1] = reinterpret_cast<jlong>(key_slice);
-  if (we.type == rocksdb::kDeleteRecord
-      || we.type == rocksdb::kLogDataRecord) {
+  if (we.type == rocksdb::kDeleteRecord ||
+      we.type == rocksdb::kSingleDeleteRecord ||
+      we.type == rocksdb::kLogDataRecord) {
     // set native handle of value slice to null if no value available
     results[2] = 0;
   } else {
@@ -556,9 +720,9 @@ jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(
   }
 
   jlongArray jresults = env->NewLongArray(3);
-  if(jresults == nullptr) {
+  if (jresults == nullptr) {
     // exception thrown: OutOfMemoryError
-    if(results[2] != 0) {
+    if (results[2] != 0) {
       auto* value_slice = reinterpret_cast<rocksdb::Slice*>(results[2]);
       delete value_slice;
     }
@@ -567,10 +731,10 @@ jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(
   }
 
   env->SetLongArrayRegion(jresults, 0, 3, results);
-  if(env->ExceptionCheck()) {
+  if (env->ExceptionCheck()) {
     // exception thrown: ArrayIndexOutOfBoundsException
     env->DeleteLocalRef(jresults);
-    if(results[2] != 0) {
+    if (results[2] != 0) {
       auto* value_slice = reinterpret_cast<rocksdb::Slice*>(results[2]);
       delete value_slice;
     }