1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 // This file is designed for caching those frequently used IDs and provide
7 // efficient portal (i.e, a set of static functions) to access java code
8 // from c++.
9 
10 #ifndef JAVA_ROCKSJNI_PORTAL_H_
11 #define JAVA_ROCKSJNI_PORTAL_H_
12 
13 #include <algorithm>
14 #include <cstring>
15 #include <functional>
16 #include <iostream>
17 #include <iterator>
18 #include <jni.h>
build_column_family_descriptor_list(JNIEnv * env,jobject jcfds,std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> & cf_descs)19 #include <limits>
20 #include <memory>
21 #include <string>
22 #include <type_traits>
23 #include <vector>
24 
25 #include "rocksdb/db.h"
26 #include "rocksdb/filter_policy.h"
27 #include "rocksdb/rate_limiter.h"
28 #include "rocksdb/status.h"
29 #include "rocksdb/table.h"
30 #include "rocksdb/utilities/backupable_db.h"
31 #include "rocksdb/utilities/memory_util.h"
32 #include "rocksdb/utilities/transaction_db.h"
33 #include "rocksdb/utilities/write_batch_with_index.h"
34 #include "rocksjni/compaction_filter_factory_jnicallback.h"
35 #include "rocksjni/comparatorjnicallback.h"
36 #include "rocksjni/loggerjnicallback.h"
37 #include "rocksjni/table_filter_jnicallback.h"
38 #include "rocksjni/trace_writer_jnicallback.h"
39 #include "rocksjni/transaction_notifier_jnicallback.h"
40 #include "rocksjni/wal_filter_jnicallback.h"
41 #include "rocksjni/writebatchhandlerjnicallback.h"
42 
43 // Remove macro on windows
44 #ifdef DELETE
45 #undef DELETE
46 #endif
47 
48 namespace ROCKSDB_NAMESPACE {
49 
50 class JavaClass {
51  public:
52   /**
53    * Gets and initializes a Java Class
54    *
55    * @param env A pointer to the Java environment
56    * @param jclazz_name The fully qualified JNI name of the Java Class
57    *     e.g. "java/lang/String"
58    *
59    * @return The Java Class or nullptr if one of the
60    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
61    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
62    */
63   static jclass getJClass(JNIEnv* env, const char* jclazz_name) {
64     jclass jclazz = env->FindClass(jclazz_name);
65     assert(jclazz != nullptr);
66     return jclazz;
67   }
68 };
69 
70 // Native class template
71 template<class PTR, class DERIVED> class RocksDBNativeClass : public JavaClass {
72 };
73 
74 // Native class template for sub-classes of RocksMutableObject
75 template<class PTR, class DERIVED> class NativeRocksMutableObject
76     : public RocksDBNativeClass<PTR, DERIVED> {
77  public:
78 
79   /**
80    * Gets the Java Method ID for the
81    * RocksMutableObject#setNativeHandle(long, boolean) method
82    *
83    * @param env A pointer to the Java environment
84    * @return The Java Method ID or nullptr the RocksMutableObject class cannot
85    *     be accessed, or if one of the NoSuchMethodError,
86    *     ExceptionInInitializerError or OutOfMemoryError exceptions is thrown
87    */
88   static jmethodID getSetNativeHandleMethod(JNIEnv* env) {
89     static jclass jclazz = DERIVED::getJClass(env);
90     if(jclazz == nullptr) {
91       return nullptr;
92     }
93 
94     static jmethodID mid = env->GetMethodID(
95         jclazz, "setNativeHandle", "(JZ)V");
96     assert(mid != nullptr);
97     return mid;
98   }
99 
100   /**
101    * Sets the C++ object pointer handle in the Java object
102    *
103    * @param env A pointer to the Java environment
104    * @param jobj The Java object on which to set the pointer handle
105    * @param ptr The C++ object pointer
106    * @param java_owns_handle JNI_TRUE if ownership of the C++ object is
107    *     managed by the Java object
108    *
109    * @return true if a Java exception is pending, false otherwise
110    */
111   static bool setHandle(JNIEnv* env, jobject jobj, PTR ptr,
112       jboolean java_owns_handle) {
113     assert(jobj != nullptr);
114     static jmethodID mid = getSetNativeHandleMethod(env);
115     if(mid == nullptr) {
116       return true;  // signal exception
117     }
118 
119     env->CallVoidMethod(jobj, mid, reinterpret_cast<jlong>(ptr), java_owns_handle);
120     if(env->ExceptionCheck()) {
121       return true;  // signal exception
122     }
123 
124     return false;
125   }
126 };
127 
128 // Java Exception template
129 template<class DERIVED> class JavaException : public JavaClass {
130  public:
131   /**
132    * Create and throw a java exception with the provided message
133    *
134    * @param env A pointer to the Java environment
135    * @param msg The message for the exception
136    *
137    * @return true if an exception was thrown, false otherwise
138    */
139   static bool ThrowNew(JNIEnv* env, const std::string& msg) {
140     jclass jclazz = DERIVED::getJClass(env);
141     if(jclazz == nullptr) {
142       // exception occurred accessing class
143       std::cerr << "JavaException::ThrowNew - Error: unexpected exception!" << std::endl;
144       return env->ExceptionCheck();
145     }
146 
147     const jint rs = env->ThrowNew(jclazz, msg.c_str());
148     if(rs != JNI_OK) {
149       // exception could not be thrown
150       std::cerr << "JavaException::ThrowNew - Fatal: could not throw exception!" << std::endl;
151       return env->ExceptionCheck();
152     }
153 
154     return true;
155   }
156 };
157 
158 // The portal class for java.lang.IllegalArgumentException
159 class IllegalArgumentExceptionJni :
160     public JavaException<IllegalArgumentExceptionJni> {
161  public:
162   /**
163    * Get the Java Class java.lang.IllegalArgumentException
164    *
165    * @param env A pointer to the Java environment
166    *
167    * @return The Java Class or nullptr if one of the
168    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
169    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
170    */
171   static jclass getJClass(JNIEnv* env) {
172     return JavaException::getJClass(env, "java/lang/IllegalArgumentException");
173   }
174 
175   /**
176    * Create and throw a Java IllegalArgumentException with the provided status
177    *
178    * If s.ok() == true, then this function will not throw any exception.
179    *
180    * @param env A pointer to the Java environment
181    * @param s The status for the exception
182    *
183    * @return true if an exception was thrown, false otherwise
184    */
185   static bool ThrowNew(JNIEnv* env, const Status& s) {
186     assert(!s.ok());
187     if (s.ok()) {
188       return false;
189     }
190 
191     // get the IllegalArgumentException class
192     jclass jclazz = getJClass(env);
193     if(jclazz == nullptr) {
194       // exception occurred accessing class
195       std::cerr << "IllegalArgumentExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl;
196       return env->ExceptionCheck();
197     }
198 
199     return JavaException::ThrowNew(env, s.ToString());
200   }
201 };
202 
203 // The portal class for org.rocksdb.Status.Code
204 class CodeJni : public JavaClass {
205  public:
206   /**
207    * Get the Java Class org.rocksdb.Status.Code
208    *
209    * @param env A pointer to the Java environment
210    *
211    * @return The Java Class or nullptr if one of the
212    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
213    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
214    */
215   static jclass getJClass(JNIEnv* env) {
216     return JavaClass::getJClass(env, "org/rocksdb/Status$Code");
217   }
218 
219   /**
220    * Get the Java Method: Status.Code#getValue
221    *
222    * @param env A pointer to the Java environment
223    *
224    * @return The Java Method ID or nullptr if the class or method id could not
225    *     be retieved
226    */
227   static jmethodID getValueMethod(JNIEnv* env) {
228     jclass jclazz = getJClass(env);
229     if(jclazz == nullptr) {
230       // exception occurred accessing class
231       return nullptr;
232     }
233 
234     static jmethodID mid =
235         env->GetMethodID(jclazz, "getValue", "()b");
236     assert(mid != nullptr);
237     return mid;
238   }
239 };
240 
241 // The portal class for org.rocksdb.Status.SubCode
242 class SubCodeJni : public JavaClass {
243  public:
244   /**
245    * Get the Java Class org.rocksdb.Status.SubCode
246    *
247    * @param env A pointer to the Java environment
248    *
249    * @return The Java Class or nullptr if one of the
250    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
251    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
252    */
253   static jclass getJClass(JNIEnv* env) {
254     return JavaClass::getJClass(env, "org/rocksdb/Status$SubCode");
255   }
256 
257   /**
258    * Get the Java Method: Status.SubCode#getValue
259    *
260    * @param env A pointer to the Java environment
261    *
262    * @return The Java Method ID or nullptr if the class or method id could not
263    *     be retieved
264    */
265   static jmethodID getValueMethod(JNIEnv* env) {
266     jclass jclazz = getJClass(env);
267     if(jclazz == nullptr) {
268       // exception occurred accessing class
269       return nullptr;
270     }
271 
272     static jmethodID mid =
273         env->GetMethodID(jclazz, "getValue", "()b");
274     assert(mid != nullptr);
275     return mid;
276   }
277 
278   static ROCKSDB_NAMESPACE::Status::SubCode toCppSubCode(
279       const jbyte jsub_code) {
280     switch (jsub_code) {
281       case 0x0:
282         return ROCKSDB_NAMESPACE::Status::SubCode::kNone;
283       case 0x1:
284         return ROCKSDB_NAMESPACE::Status::SubCode::kMutexTimeout;
285       case 0x2:
286         return ROCKSDB_NAMESPACE::Status::SubCode::kLockTimeout;
287       case 0x3:
288         return ROCKSDB_NAMESPACE::Status::SubCode::kLockLimit;
289       case 0x4:
290         return ROCKSDB_NAMESPACE::Status::SubCode::kNoSpace;
291       case 0x5:
292         return ROCKSDB_NAMESPACE::Status::SubCode::kDeadlock;
293       case 0x6:
294         return ROCKSDB_NAMESPACE::Status::SubCode::kStaleFile;
295       case 0x7:
296         return ROCKSDB_NAMESPACE::Status::SubCode::kMemoryLimit;
297 
298       case 0x7F:
299       default:
300         return ROCKSDB_NAMESPACE::Status::SubCode::kNone;
301     }
302   }
303 };
304 
305 // The portal class for org.rocksdb.Status
306 class StatusJni
307     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::Status*, StatusJni> {
308  public:
309   /**
310    * Get the Java Class org.rocksdb.Status
311    *
312    * @param env A pointer to the Java environment
313    *
314    * @return The Java Class or nullptr if one of the
315    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
316    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
317    */
318   static jclass getJClass(JNIEnv* env) {
319     return RocksDBNativeClass::getJClass(env, "org/rocksdb/Status");
320   }
321 
322   /**
323    * Get the Java Method: Status#getCode
324    *
325    * @param env A pointer to the Java environment
326    *
327    * @return The Java Method ID or nullptr if the class or method id could not
328    *     be retieved
329    */
330   static jmethodID getCodeMethod(JNIEnv* env) {
331     jclass jclazz = getJClass(env);
332     if(jclazz == nullptr) {
333       // exception occurred accessing class
334       return nullptr;
335     }
336 
337     static jmethodID mid =
338         env->GetMethodID(jclazz, "getCode", "()Lorg/rocksdb/Status$Code;");
339     assert(mid != nullptr);
340     return mid;
341   }
342 
343   /**
344    * Get the Java Method: Status#getSubCode
345    *
346    * @param env A pointer to the Java environment
347    *
348    * @return The Java Method ID or nullptr if the class or method id could not
349    *     be retieved
350    */
351   static jmethodID getSubCodeMethod(JNIEnv* env) {
352     jclass jclazz = getJClass(env);
353     if(jclazz == nullptr) {
354       // exception occurred accessing class
355       return nullptr;
356     }
357 
358     static jmethodID mid =
359         env->GetMethodID(jclazz, "getSubCode", "()Lorg/rocksdb/Status$SubCode;");
360     assert(mid != nullptr);
361     return mid;
362   }
363 
364   /**
365    * Get the Java Method: Status#getState
366    *
367    * @param env A pointer to the Java environment
368    *
369    * @return The Java Method ID or nullptr if the class or method id could not
370    *     be retieved
371    */
372   static jmethodID getStateMethod(JNIEnv* env) {
373     jclass jclazz = getJClass(env);
374     if(jclazz == nullptr) {
375       // exception occurred accessing class
376       return nullptr;
377     }
378 
379     static jmethodID mid =
380         env->GetMethodID(jclazz, "getState", "()Ljava/lang/String;");
381     assert(mid != nullptr);
382     return mid;
383   }
384 
385   /**
386    * Create a new Java org.rocksdb.Status object with the same properties as
387    * the provided C++ ROCKSDB_NAMESPACE::Status object
388    *
389    * @param env A pointer to the Java environment
390    * @param status The ROCKSDB_NAMESPACE::Status object
391    *
392    * @return A reference to a Java org.rocksdb.Status object, or nullptr
393    *     if an an exception occurs
394    */
395   static jobject construct(JNIEnv* env, const Status& status) {
396     jclass jclazz = getJClass(env);
397     if(jclazz == nullptr) {
398       // exception occurred accessing class
399       return nullptr;
400     }
401 
402     jmethodID mid =
403         env->GetMethodID(jclazz, "<init>", "(BBLjava/lang/String;)V");
404     if(mid == nullptr) {
405       // exception thrown: NoSuchMethodException or OutOfMemoryError
406       return nullptr;
407     }
408 
409     // convert the Status state for Java
410     jstring jstate = nullptr;
411     if (status.getState() != nullptr) {
412       const char* const state = status.getState();
413       jstate = env->NewStringUTF(state);
414       if(env->ExceptionCheck()) {
415         if(jstate != nullptr) {
416           env->DeleteLocalRef(jstate);
417         }
418         return nullptr;
419       }
420     }
421 
422     jobject jstatus =
423         env->NewObject(jclazz, mid, toJavaStatusCode(status.code()),
424             toJavaStatusSubCode(status.subcode()), jstate);
425     if(env->ExceptionCheck()) {
426       // exception occurred
427       if(jstate != nullptr) {
428         env->DeleteLocalRef(jstate);
429       }
430       return nullptr;
431     }
432 
433     if(jstate != nullptr) {
434       env->DeleteLocalRef(jstate);
435     }
436 
437     return jstatus;
438   }
439 
440   // Returns the equivalent org.rocksdb.Status.Code for the provided
441   // C++ ROCKSDB_NAMESPACE::Status::Code enum
442   static jbyte toJavaStatusCode(const ROCKSDB_NAMESPACE::Status::Code& code) {
443     switch (code) {
444       case ROCKSDB_NAMESPACE::Status::Code::kOk:
445         return 0x0;
446       case ROCKSDB_NAMESPACE::Status::Code::kNotFound:
447         return 0x1;
448       case ROCKSDB_NAMESPACE::Status::Code::kCorruption:
449         return 0x2;
450       case ROCKSDB_NAMESPACE::Status::Code::kNotSupported:
451         return 0x3;
452       case ROCKSDB_NAMESPACE::Status::Code::kInvalidArgument:
453         return 0x4;
454       case ROCKSDB_NAMESPACE::Status::Code::kIOError:
455         return 0x5;
456       case ROCKSDB_NAMESPACE::Status::Code::kMergeInProgress:
457         return 0x6;
458       case ROCKSDB_NAMESPACE::Status::Code::kIncomplete:
459         return 0x7;
460       case ROCKSDB_NAMESPACE::Status::Code::kShutdownInProgress:
461         return 0x8;
462       case ROCKSDB_NAMESPACE::Status::Code::kTimedOut:
463         return 0x9;
464       case ROCKSDB_NAMESPACE::Status::Code::kAborted:
465         return 0xA;
466       case ROCKSDB_NAMESPACE::Status::Code::kBusy:
467         return 0xB;
468       case ROCKSDB_NAMESPACE::Status::Code::kExpired:
469         return 0xC;
470       case ROCKSDB_NAMESPACE::Status::Code::kTryAgain:
471         return 0xD;
472       case ROCKSDB_NAMESPACE::Status::Code::kColumnFamilyDropped:
473         return 0xE;
474       default:
475         return 0x7F;  // undefined
476     }
477   }
478 
479   // Returns the equivalent org.rocksdb.Status.SubCode for the provided
480   // C++ ROCKSDB_NAMESPACE::Status::SubCode enum
481   static jbyte toJavaStatusSubCode(
482       const ROCKSDB_NAMESPACE::Status::SubCode& subCode) {
483     switch (subCode) {
484       case ROCKSDB_NAMESPACE::Status::SubCode::kNone:
485         return 0x0;
486       case ROCKSDB_NAMESPACE::Status::SubCode::kMutexTimeout:
487         return 0x1;
488       case ROCKSDB_NAMESPACE::Status::SubCode::kLockTimeout:
489         return 0x2;
490       case ROCKSDB_NAMESPACE::Status::SubCode::kLockLimit:
491         return 0x3;
492       case ROCKSDB_NAMESPACE::Status::SubCode::kNoSpace:
493         return 0x4;
494       case ROCKSDB_NAMESPACE::Status::SubCode::kDeadlock:
495         return 0x5;
496       case ROCKSDB_NAMESPACE::Status::SubCode::kStaleFile:
497         return 0x6;
498       case ROCKSDB_NAMESPACE::Status::SubCode::kMemoryLimit:
499         return 0x7;
500       default:
501         return 0x7F;  // undefined
502     }
503   }
504 
505   static std::unique_ptr<ROCKSDB_NAMESPACE::Status> toCppStatus(
506       const jbyte jcode_value, const jbyte jsub_code_value) {
507     std::unique_ptr<ROCKSDB_NAMESPACE::Status> status;
508     switch (jcode_value) {
509       case 0x0:
510         //Ok
511         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
512             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::OK()));
513         break;
514       case 0x1:
515         //NotFound
516         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
517             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::NotFound(
518                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
519         break;
520       case 0x2:
521         //Corruption
522         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
523             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::Corruption(
524                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
525         break;
526       case 0x3:
527         //NotSupported
528         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
529             new ROCKSDB_NAMESPACE::Status(
530                 ROCKSDB_NAMESPACE::Status::NotSupported(
531                     ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(
532                         jsub_code_value))));
533         break;
534       case 0x4:
535         //InvalidArgument
536         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
537             new ROCKSDB_NAMESPACE::Status(
538                 ROCKSDB_NAMESPACE::Status::InvalidArgument(
539                     ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(
540                         jsub_code_value))));
541         break;
542       case 0x5:
543         //IOError
544         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
545             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::IOError(
546                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
547         break;
548       case 0x6:
549         //MergeInProgress
550         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
551             new ROCKSDB_NAMESPACE::Status(
552                 ROCKSDB_NAMESPACE::Status::MergeInProgress(
553                     ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(
554                         jsub_code_value))));
555         break;
556       case 0x7:
557         //Incomplete
558         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
559             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::Incomplete(
560                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
561         break;
562       case 0x8:
563         //ShutdownInProgress
564         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
565             new ROCKSDB_NAMESPACE::Status(
566                 ROCKSDB_NAMESPACE::Status::ShutdownInProgress(
567                     ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(
568                         jsub_code_value))));
569         break;
570       case 0x9:
571         //TimedOut
572         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
573             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::TimedOut(
574                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
575         break;
576       case 0xA:
577         //Aborted
578         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
579             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::Aborted(
580                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
581         break;
582       case 0xB:
583         //Busy
584         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
585             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::Busy(
586                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
587         break;
588       case 0xC:
589         //Expired
590         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
591             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::Expired(
592                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
593         break;
594       case 0xD:
595         //TryAgain
596         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
597             new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::TryAgain(
598                 ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(jsub_code_value))));
599         break;
600       case 0xE:
601         // ColumnFamilyDropped
602         status = std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
603             new ROCKSDB_NAMESPACE::Status(
604                 ROCKSDB_NAMESPACE::Status::ColumnFamilyDropped(
605                     ROCKSDB_NAMESPACE::SubCodeJni::toCppSubCode(
606                         jsub_code_value))));
607         break;
608       case 0x7F:
609       default:
610         return nullptr;
611     }
612     return status;
613   }
614 
615   // Returns the equivalent ROCKSDB_NAMESPACE::Status for the Java
616   // org.rocksdb.Status
617   static std::unique_ptr<ROCKSDB_NAMESPACE::Status> toCppStatus(
618       JNIEnv* env, const jobject jstatus) {
619     jmethodID mid_code = getCodeMethod(env);
620     if (mid_code == nullptr) {
621       // exception occurred
622       return nullptr;
623     }
624     jobject jcode = env->CallObjectMethod(jstatus, mid_code);
625     if (env->ExceptionCheck()) {
626       // exception occurred
627       return nullptr;
628     }
629 
630     jmethodID mid_code_value = ROCKSDB_NAMESPACE::CodeJni::getValueMethod(env);
631     if (mid_code_value == nullptr) {
632       // exception occurred
633       return nullptr;
634     }
635     jbyte jcode_value = env->CallByteMethod(jcode, mid_code_value);
636     if (env->ExceptionCheck()) {
637       // exception occurred
638       if (jcode != nullptr) {
639         env->DeleteLocalRef(jcode);
640       }
641       return nullptr;
642     }
643 
644     jmethodID mid_subCode = getSubCodeMethod(env);
645     if (mid_subCode == nullptr) {
646       // exception occurred
647       return nullptr;
648     }
649     jobject jsubCode = env->CallObjectMethod(jstatus, mid_subCode);
650     if (env->ExceptionCheck()) {
651       // exception occurred
652       if (jcode != nullptr) {
653         env->DeleteLocalRef(jcode);
654       }
655       return nullptr;
656     }
657 
658     jbyte jsub_code_value = 0x0;  // None
659     if (jsubCode != nullptr) {
660       jmethodID mid_subCode_value =
661           ROCKSDB_NAMESPACE::SubCodeJni::getValueMethod(env);
662       if (mid_subCode_value == nullptr) {
663         // exception occurred
664         return nullptr;
665       }
666       jsub_code_value = env->CallByteMethod(jsubCode, mid_subCode_value);
667       if (env->ExceptionCheck()) {
668         // exception occurred
669         if (jcode != nullptr) {
670           env->DeleteLocalRef(jcode);
671         }
672         return nullptr;
673       }
674     }
675 
676     jmethodID mid_state = getStateMethod(env);
677     if (mid_state == nullptr) {
678       // exception occurred
679       return nullptr;
680     }
681     jobject jstate = env->CallObjectMethod(jstatus, mid_state);
682     if (env->ExceptionCheck()) {
683       // exception occurred
684       if (jsubCode != nullptr) {
685         env->DeleteLocalRef(jsubCode);
686       }
687       if (jcode != nullptr) {
688         env->DeleteLocalRef(jcode);
689       }
690       return nullptr;
691     }
692 
693     std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
694         toCppStatus(jcode_value, jsub_code_value);
695 
696     // delete all local refs
697     if (jstate != nullptr) {
698       env->DeleteLocalRef(jstate);
699     }
700     if (jsubCode != nullptr) {
701       env->DeleteLocalRef(jsubCode);
702     }
703     if (jcode != nullptr) {
704       env->DeleteLocalRef(jcode);
705     }
706 
707     return status;
708   }
709 };
710 
711 // The portal class for org.rocksdb.RocksDBException
712 class RocksDBExceptionJni :
713     public JavaException<RocksDBExceptionJni> {
714  public:
715   /**
716    * Get the Java Class org.rocksdb.RocksDBException
717    *
718    * @param env A pointer to the Java environment
719    *
720    * @return The Java Class or nullptr if one of the
721    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
722    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
723    */
724   static jclass getJClass(JNIEnv* env) {
725     return JavaException::getJClass(env, "org/rocksdb/RocksDBException");
726   }
727 
728   /**
729    * Create and throw a Java RocksDBException with the provided message
730    *
731    * @param env A pointer to the Java environment
732    * @param msg The message for the exception
733    *
734    * @return true if an exception was thrown, false otherwise
735    */
736   static bool ThrowNew(JNIEnv* env, const std::string& msg) {
737     return JavaException::ThrowNew(env, msg);
738   }
739 
740   /**
741    * Create and throw a Java RocksDBException with the provided status
742    *
743    * If s->ok() == true, then this function will not throw any exception.
744    *
745    * @param env A pointer to the Java environment
746    * @param s The status for the exception
747    *
748    * @return true if an exception was thrown, false otherwise
749    */
750   static bool ThrowNew(JNIEnv* env, std::unique_ptr<Status>& s) {
751     return ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, *(s.get()));
752   }
753 
754   /**
755    * Create and throw a Java RocksDBException with the provided status
756    *
757    * If s.ok() == true, then this function will not throw any exception.
758    *
759    * @param env A pointer to the Java environment
760    * @param s The status for the exception
761    *
762    * @return true if an exception was thrown, false otherwise
763    */
764   static bool ThrowNew(JNIEnv* env, const Status& s) {
765     if (s.ok()) {
766       return false;
767     }
768 
769     // get the RocksDBException class
770     jclass jclazz = getJClass(env);
771     if(jclazz == nullptr) {
772       // exception occurred accessing class
773       std::cerr << "RocksDBExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl;
774       return env->ExceptionCheck();
775     }
776 
777     // get the constructor of org.rocksdb.RocksDBException
778     jmethodID mid =
779         env->GetMethodID(jclazz, "<init>", "(Lorg/rocksdb/Status;)V");
780     if(mid == nullptr) {
781       // exception thrown: NoSuchMethodException or OutOfMemoryError
782       std::cerr << "RocksDBExceptionJni::ThrowNew/cstr - Error: unexpected exception!" << std::endl;
783       return env->ExceptionCheck();
784     }
785 
786     // get the Java status object
787     jobject jstatus = StatusJni::construct(env, s);
788     if(jstatus == nullptr) {
789       // exception occcurred
790       std::cerr << "RocksDBExceptionJni::ThrowNew/StatusJni - Error: unexpected exception!" << std::endl;
791       return env->ExceptionCheck();
792     }
793 
794     // construct the RocksDBException
795     jthrowable rocksdb_exception = reinterpret_cast<jthrowable>(env->NewObject(jclazz, mid, jstatus));
796     if(env->ExceptionCheck()) {
797       if(jstatus != nullptr) {
798         env->DeleteLocalRef(jstatus);
799       }
800       if(rocksdb_exception != nullptr) {
801         env->DeleteLocalRef(rocksdb_exception);
802       }
803       std::cerr << "RocksDBExceptionJni::ThrowNew/NewObject - Error: unexpected exception!" << std::endl;
804       return true;
805     }
806 
807     // throw the RocksDBException
808     const jint rs = env->Throw(rocksdb_exception);
809     if(rs != JNI_OK) {
810       // exception could not be thrown
811       std::cerr << "RocksDBExceptionJni::ThrowNew - Fatal: could not throw exception!" << std::endl;
812       if(jstatus != nullptr) {
813         env->DeleteLocalRef(jstatus);
814       }
815       if(rocksdb_exception != nullptr) {
816         env->DeleteLocalRef(rocksdb_exception);
817       }
818       return env->ExceptionCheck();
819     }
820 
821     if(jstatus != nullptr) {
822       env->DeleteLocalRef(jstatus);
823     }
824     if(rocksdb_exception != nullptr) {
825       env->DeleteLocalRef(rocksdb_exception);
826     }
827 
828     return true;
829   }
830 
831   /**
832    * Create and throw a Java RocksDBException with the provided message
833    * and status
834    *
835    * If s.ok() == true, then this function will not throw any exception.
836    *
837    * @param env A pointer to the Java environment
838    * @param msg The message for the exception
839    * @param s The status for the exception
840    *
841    * @return true if an exception was thrown, false otherwise
842    */
843   static bool ThrowNew(JNIEnv* env, const std::string& msg, const Status& s) {
844     assert(!s.ok());
845     if (s.ok()) {
846       return false;
847     }
848 
849     // get the RocksDBException class
850     jclass jclazz = getJClass(env);
851     if(jclazz == nullptr) {
852       // exception occurred accessing class
853       std::cerr << "RocksDBExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl;
854       return env->ExceptionCheck();
855     }
856 
857     // get the constructor of org.rocksdb.RocksDBException
858     jmethodID mid =
859         env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;Lorg/rocksdb/Status;)V");
860     if(mid == nullptr) {
861       // exception thrown: NoSuchMethodException or OutOfMemoryError
862       std::cerr << "RocksDBExceptionJni::ThrowNew/cstr - Error: unexpected exception!" << std::endl;
863       return env->ExceptionCheck();
864     }
865 
866     jstring jmsg = env->NewStringUTF(msg.c_str());
867     if(jmsg == nullptr) {
868       // exception thrown: OutOfMemoryError
869       std::cerr << "RocksDBExceptionJni::ThrowNew/msg - Error: unexpected exception!" << std::endl;
870       return env->ExceptionCheck();
871     }
872 
873     // get the Java status object
874     jobject jstatus = StatusJni::construct(env, s);
875     if(jstatus == nullptr) {
876       // exception occcurred
877       std::cerr << "RocksDBExceptionJni::ThrowNew/StatusJni - Error: unexpected exception!" << std::endl;
878       if(jmsg != nullptr) {
879         env->DeleteLocalRef(jmsg);
880       }
881       return env->ExceptionCheck();
882     }
883 
884     // construct the RocksDBException
885     jthrowable rocksdb_exception = reinterpret_cast<jthrowable>(env->NewObject(jclazz, mid, jmsg, jstatus));
886     if(env->ExceptionCheck()) {
887       if(jstatus != nullptr) {
888         env->DeleteLocalRef(jstatus);
889       }
890       if(jmsg != nullptr) {
891         env->DeleteLocalRef(jmsg);
892       }
893       if(rocksdb_exception != nullptr) {
894         env->DeleteLocalRef(rocksdb_exception);
895       }
896       std::cerr << "RocksDBExceptionJni::ThrowNew/NewObject - Error: unexpected exception!" << std::endl;
897       return true;
898     }
899 
900     // throw the RocksDBException
901     const jint rs = env->Throw(rocksdb_exception);
902     if(rs != JNI_OK) {
903       // exception could not be thrown
904       std::cerr << "RocksDBExceptionJni::ThrowNew - Fatal: could not throw exception!" << std::endl;
905       if(jstatus != nullptr) {
906         env->DeleteLocalRef(jstatus);
907       }
908       if(jmsg != nullptr) {
909         env->DeleteLocalRef(jmsg);
910       }
911       if(rocksdb_exception != nullptr) {
912         env->DeleteLocalRef(rocksdb_exception);
913       }
914       return env->ExceptionCheck();
915     }
916 
917     if(jstatus != nullptr) {
918       env->DeleteLocalRef(jstatus);
919     }
920     if(jmsg != nullptr) {
921       env->DeleteLocalRef(jmsg);
922     }
923     if(rocksdb_exception != nullptr) {
924       env->DeleteLocalRef(rocksdb_exception);
925     }
926 
927     return true;
928   }
929 
930   /**
931    * Get the Java Method: RocksDBException#getStatus
932    *
933    * @param env A pointer to the Java environment
934    *
935    * @return The Java Method ID or nullptr if the class or method id could not
936    *     be retieved
937    */
938   static jmethodID getStatusMethod(JNIEnv* env) {
939     jclass jclazz = getJClass(env);
940     if(jclazz == nullptr) {
941       // exception occurred accessing class
942       return nullptr;
943     }
944 
945     static jmethodID mid =
946         env->GetMethodID(jclazz, "getStatus", "()Lorg/rocksdb/Status;");
947     assert(mid != nullptr);
948     return mid;
949   }
950 
951   static std::unique_ptr<ROCKSDB_NAMESPACE::Status> toCppStatus(
952       JNIEnv* env, jthrowable jrocksdb_exception) {
953     if(!env->IsInstanceOf(jrocksdb_exception, getJClass(env))) {
954       // not an instance of RocksDBException
955       return nullptr;
956     }
957 
958     // get the java status object
959     jmethodID mid = getStatusMethod(env);
960     if(mid == nullptr) {
961       // exception occurred accessing class or method
962       return nullptr;
963     }
964 
965     jobject jstatus = env->CallObjectMethod(jrocksdb_exception, mid);
966     if(env->ExceptionCheck()) {
967       // exception occurred
968       return nullptr;
969     }
970 
971     if(jstatus == nullptr) {
972       return nullptr;   // no status available
973     }
974 
975     return ROCKSDB_NAMESPACE::StatusJni::toCppStatus(env, jstatus);
976   }
977 };
978 
979 // The portal class for java.util.List
980 class ListJni : public JavaClass {
981  public:
982   /**
983    * Get the Java Class java.util.List
984    *
985    * @param env A pointer to the Java environment
986    *
987    * @return The Java Class or nullptr if one of the
988    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
989    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
990    */
991   static jclass getListClass(JNIEnv* env) {
992     return JavaClass::getJClass(env, "java/util/List");
993   }
994 
995   /**
996    * Get the Java Class java.util.ArrayList
997    *
998    * @param env A pointer to the Java environment
999    *
1000    * @return The Java Class or nullptr if one of the
1001    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1002    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1003    */
1004   static jclass getArrayListClass(JNIEnv* env) {
1005     return JavaClass::getJClass(env, "java/util/ArrayList");
1006   }
1007 
1008   /**
1009    * Get the Java Class java.util.Iterator
1010    *
1011    * @param env A pointer to the Java environment
1012    *
1013    * @return The Java Class or nullptr if one of the
1014    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1015    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1016    */
1017   static jclass getIteratorClass(JNIEnv* env) {
1018     return JavaClass::getJClass(env, "java/util/Iterator");
1019   }
1020 
1021   /**
1022    * Get the Java Method: List#iterator
1023    *
1024    * @param env A pointer to the Java environment
1025    *
1026    * @return The Java Method ID or nullptr if the class or method id could not
1027    *     be retieved
1028    */
1029   static jmethodID getIteratorMethod(JNIEnv* env) {
1030     jclass jlist_clazz = getListClass(env);
1031     if(jlist_clazz == nullptr) {
1032       // exception occurred accessing class
1033       return nullptr;
1034     }
1035 
1036     static jmethodID mid =
1037         env->GetMethodID(jlist_clazz, "iterator", "()Ljava/util/Iterator;");
1038     assert(mid != nullptr);
1039     return mid;
1040   }
1041 
1042   /**
1043    * Get the Java Method: Iterator#hasNext
1044    *
1045    * @param env A pointer to the Java environment
1046    *
1047    * @return The Java Method ID or nullptr if the class or method id could not
1048    *     be retieved
1049    */
1050   static jmethodID getHasNextMethod(JNIEnv* env) {
1051     jclass jiterator_clazz = getIteratorClass(env);
1052     if(jiterator_clazz == nullptr) {
1053       // exception occurred accessing class
1054       return nullptr;
1055     }
1056 
1057     static jmethodID mid = env->GetMethodID(jiterator_clazz, "hasNext", "()Z");
1058     assert(mid != nullptr);
1059     return mid;
1060   }
1061 
1062   /**
1063    * Get the Java Method: Iterator#next
1064    *
1065    * @param env A pointer to the Java environment
1066    *
1067    * @return The Java Method ID or nullptr if the class or method id could not
1068    *     be retieved
1069    */
1070   static jmethodID getNextMethod(JNIEnv* env) {
1071     jclass jiterator_clazz = getIteratorClass(env);
1072     if(jiterator_clazz == nullptr) {
1073       // exception occurred accessing class
1074       return nullptr;
1075     }
1076 
1077     static jmethodID mid =
1078         env->GetMethodID(jiterator_clazz, "next", "()Ljava/lang/Object;");
1079     assert(mid != nullptr);
1080     return mid;
1081   }
1082 
1083   /**
1084    * Get the Java Method: ArrayList constructor
1085    *
1086    * @param env A pointer to the Java environment
1087    *
1088    * @return The Java Method ID or nullptr if the class or method id could not
1089    *     be retieved
1090    */
1091   static jmethodID getArrayListConstructorMethodId(JNIEnv* env) {
1092     jclass jarray_list_clazz = getArrayListClass(env);
1093     if(jarray_list_clazz == nullptr) {
1094       // exception occurred accessing class
1095       return nullptr;
1096     }
1097     static jmethodID mid =
1098         env->GetMethodID(jarray_list_clazz, "<init>", "(I)V");
1099     assert(mid != nullptr);
1100     return mid;
1101   }
1102 
1103   /**
1104    * Get the Java Method: List#add
1105    *
1106    * @param env A pointer to the Java environment
1107    *
1108    * @return The Java Method ID or nullptr if the class or method id could not
1109    *     be retieved
1110    */
1111   static jmethodID getListAddMethodId(JNIEnv* env) {
1112     jclass jlist_clazz = getListClass(env);
1113     if(jlist_clazz == nullptr) {
1114       // exception occurred accessing class
1115       return nullptr;
1116     }
1117 
1118     static jmethodID mid =
1119         env->GetMethodID(jlist_clazz, "add", "(Ljava/lang/Object;)Z");
1120     assert(mid != nullptr);
1121     return mid;
1122   }
1123 };
1124 
1125 // The portal class for java.lang.Byte
1126 class ByteJni : public JavaClass {
1127  public:
1128   /**
1129    * Get the Java Class java.lang.Byte
1130    *
1131    * @param env A pointer to the Java environment
1132    *
1133    * @return The Java Class or nullptr if one of the
1134    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1135    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1136    */
1137   static jclass getJClass(JNIEnv* env) {
1138     return JavaClass::getJClass(env, "java/lang/Byte");
1139   }
1140 
1141   /**
1142    * Get the Java Class byte[]
1143    *
1144    * @param env A pointer to the Java environment
1145    *
1146    * @return The Java Class or nullptr if one of the
1147    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1148    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1149    */
1150   static jclass getArrayJClass(JNIEnv* env) {
1151     return JavaClass::getJClass(env, "[B");
1152   }
1153 
1154   /**
1155    * Creates a new 2-dimensional Java Byte Array byte[][]
1156    *
1157    * @param env A pointer to the Java environment
1158    * @param len The size of the first dimension
1159    *
1160    * @return A reference to the Java byte[][] or nullptr if an exception occurs
1161    */
1162   static jobjectArray new2dByteArray(JNIEnv* env, const jsize len) {
1163     jclass clazz = getArrayJClass(env);
1164     if(clazz == nullptr) {
1165       // exception occurred accessing class
1166       return nullptr;
1167     }
1168 
1169     return env->NewObjectArray(len, clazz, nullptr);
1170   }
1171 
1172   /**
1173    * Get the Java Method: Byte#byteValue
1174    *
1175    * @param env A pointer to the Java environment
1176    *
1177    * @return The Java Method ID or nullptr if the class or method id could not
1178    *     be retrieved
1179    */
1180   static jmethodID getByteValueMethod(JNIEnv* env) {
1181     jclass clazz = getJClass(env);
1182     if(clazz == nullptr) {
1183       // exception occurred accessing class
1184       return nullptr;
1185     }
1186 
1187     static jmethodID mid = env->GetMethodID(clazz, "byteValue", "()B");
1188     assert(mid != nullptr);
1189     return mid;
1190   }
1191 
1192   /**
1193    * Calls the Java Method: Byte#valueOf, returning a constructed Byte jobject
1194    *
1195    * @param env A pointer to the Java environment
1196    *
1197    * @return A constructing Byte object or nullptr if the class or method id could not
1198    *     be retrieved, or an exception occurred
1199    */
1200   static jobject valueOf(JNIEnv* env, jbyte jprimitive_byte) {
1201     jclass clazz = getJClass(env);
1202     if (clazz == nullptr) {
1203       // exception occurred accessing class
1204       return nullptr;
1205     }
1206 
1207     static jmethodID mid =
1208         env->GetStaticMethodID(clazz, "valueOf", "(B)Ljava/lang/Byte;");
1209     if (mid == nullptr) {
1210       // exception thrown: NoSuchMethodException or OutOfMemoryError
1211       return nullptr;
1212     }
1213 
1214     const jobject jbyte_obj =
1215         env->CallStaticObjectMethod(clazz, mid, jprimitive_byte);
1216     if (env->ExceptionCheck()) {
1217       // exception occurred
1218       return nullptr;
1219     }
1220 
1221     return jbyte_obj;
1222   }
1223 
1224 };
1225 
1226 // The portal class for java.nio.ByteBuffer
1227 class ByteBufferJni : public JavaClass {
1228  public:
1229   /**
1230    * Get the Java Class java.nio.ByteBuffer
1231    *
1232    * @param env A pointer to the Java environment
1233    *
1234    * @return The Java Class or nullptr if one of the
1235    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1236    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1237    */
1238   static jclass getJClass(JNIEnv* env) {
1239     return JavaClass::getJClass(env, "java/nio/ByteBuffer");
1240   }
1241 
1242   /**
1243    * Get the Java Method: ByteBuffer#allocate
1244    *
1245    * @param env A pointer to the Java environment
1246    * @param jbytebuffer_clazz if you have a reference to a ByteBuffer class, or nullptr
1247    *
1248    * @return The Java Method ID or nullptr if the class or method id could not
1249    *     be retieved
1250    */
1251   static jmethodID getAllocateMethodId(JNIEnv* env,
1252       jclass jbytebuffer_clazz = nullptr) {
1253     const jclass jclazz =
1254         jbytebuffer_clazz == nullptr ? getJClass(env) : jbytebuffer_clazz;
1255     if (jclazz == nullptr) {
1256       // exception occurred accessing class
1257       return nullptr;
1258     }
1259 
1260     static jmethodID mid = env->GetStaticMethodID(
1261         jclazz, "allocate", "(I)Ljava/nio/ByteBuffer;");
1262     assert(mid != nullptr);
1263     return mid;
1264   }
1265 
1266   /**
1267    * Get the Java Method: ByteBuffer#array
1268    *
1269    * @param env A pointer to the Java environment
1270    *
1271    * @return The Java Method ID or nullptr if the class or method id could not
1272    *     be retieved
1273    */
1274   static jmethodID getArrayMethodId(JNIEnv* env,
1275       jclass jbytebuffer_clazz = nullptr) {
1276     const jclass jclazz =
1277         jbytebuffer_clazz == nullptr ? getJClass(env) : jbytebuffer_clazz;
1278     if(jclazz == nullptr) {
1279       // exception occurred accessing class
1280       return nullptr;
1281     }
1282 
1283     static jmethodID mid = env->GetMethodID(jclazz, "array", "()[B");
1284     assert(mid != nullptr);
1285     return mid;
1286   }
1287 
1288   static jobject construct(
1289       JNIEnv* env, const bool direct, const size_t capacity,
1290       jclass jbytebuffer_clazz = nullptr) {
1291     return constructWith(env, direct, nullptr, capacity, jbytebuffer_clazz);
1292   }
1293 
1294   static jobject constructWith(
1295       JNIEnv* env, const bool direct, const char* buf, const size_t capacity,
1296       jclass jbytebuffer_clazz = nullptr) {
1297     if (direct) {
1298       bool allocated = false;
1299       if (buf == nullptr) {
1300         buf = new char[capacity];
1301         allocated = true;
1302       }
1303       jobject jbuf = env->NewDirectByteBuffer(const_cast<char*>(buf), static_cast<jlong>(capacity));
1304       if (jbuf == nullptr) {
1305         // exception occurred
1306         if (allocated) {
1307           delete[] static_cast<const char*>(buf);
1308         }
1309         return nullptr;
1310       }
1311       return jbuf;
1312     } else {
1313       const jclass jclazz =
1314         jbytebuffer_clazz == nullptr ? getJClass(env) : jbytebuffer_clazz;
1315       if (jclazz == nullptr) {
1316         // exception occurred accessing class
1317         return nullptr;
1318       }
1319       const jmethodID jmid_allocate = getAllocateMethodId(env, jbytebuffer_clazz);
1320       if (jmid_allocate == nullptr) {
1321         // exception occurred accessing class, or NoSuchMethodException or OutOfMemoryError
1322         return nullptr;
1323       }
1324       const jobject jbuf = env->CallStaticObjectMethod(
1325           jclazz, jmid_allocate, static_cast<jint>(capacity));
1326       if (env->ExceptionCheck()) {
1327         // exception occurred
1328         return nullptr;
1329       }
1330 
1331       // set buffer data?
1332       if (buf != nullptr) {
1333         jbyteArray jarray = array(env, jbuf, jbytebuffer_clazz);
1334         if (jarray == nullptr) {
1335           // exception occurred
1336           env->DeleteLocalRef(jbuf);
1337           return nullptr;
1338         }
1339 
1340         jboolean is_copy = JNI_FALSE;
1341         jbyte* ja = reinterpret_cast<jbyte*>(
1342             env->GetPrimitiveArrayCritical(jarray, &is_copy));
1343         if (ja == nullptr) {
1344           // exception occurred
1345            env->DeleteLocalRef(jarray);
1346            env->DeleteLocalRef(jbuf);
1347            return nullptr;
1348         }
1349 
1350         memcpy(ja, const_cast<char*>(buf), capacity);
1351 
1352         env->ReleasePrimitiveArrayCritical(jarray, ja, 0);
1353 
1354         env->DeleteLocalRef(jarray);
1355       }
1356 
1357       return jbuf;
1358     }
1359   }
1360 
1361   static jbyteArray array(JNIEnv* env, const jobject& jbyte_buffer,
1362       jclass jbytebuffer_clazz = nullptr) {
1363     const jmethodID mid = getArrayMethodId(env, jbytebuffer_clazz);
1364     if (mid == nullptr) {
1365       // exception occurred accessing class, or NoSuchMethodException or OutOfMemoryError
1366       return nullptr;
1367     }
1368     const jobject jarray = env->CallObjectMethod(jbyte_buffer, mid);
1369     if (env->ExceptionCheck()) {
1370       // exception occurred
1371       return nullptr;
1372     }
1373     return static_cast<jbyteArray>(jarray);
1374   }
1375 };
1376 
1377 // The portal class for java.lang.Integer
1378 class IntegerJni : public JavaClass {
1379  public:
1380   /**
1381    * Get the Java Class java.lang.Integer
1382    *
1383    * @param env A pointer to the Java environment
1384    *
1385    * @return The Java Class or nullptr if one of the
1386    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1387    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1388    */
1389   static jclass getJClass(JNIEnv* env) {
1390     return JavaClass::getJClass(env, "java/lang/Integer");
1391   }
1392 
1393   static jobject valueOf(JNIEnv* env, jint jprimitive_int) {
1394     jclass jclazz = getJClass(env);
1395     if (jclazz == nullptr) {
1396       // exception occurred accessing class
1397       return nullptr;
1398     }
1399 
1400     jmethodID mid =
1401         env->GetStaticMethodID(jclazz, "valueOf", "(I)Ljava/lang/Integer;");
1402     if (mid == nullptr) {
1403       // exception thrown: NoSuchMethodException or OutOfMemoryError
1404       return nullptr;
1405     }
1406 
1407     const jobject jinteger_obj =
1408         env->CallStaticObjectMethod(jclazz, mid, jprimitive_int);
1409     if (env->ExceptionCheck()) {
1410       // exception occurred
1411       return nullptr;
1412     }
1413 
1414     return jinteger_obj;
1415   }
1416 };
1417 
1418 // The portal class for java.lang.Long
1419 class LongJni : public JavaClass {
1420  public:
1421   /**
1422    * Get the Java Class java.lang.Long
1423    *
1424    * @param env A pointer to the Java environment
1425    *
1426    * @return The Java Class or nullptr if one of the
1427    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1428    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1429    */
1430   static jclass getJClass(JNIEnv* env) {
1431     return JavaClass::getJClass(env, "java/lang/Long");
1432   }
1433 
1434   static jobject valueOf(JNIEnv* env, jlong jprimitive_long) {
1435     jclass jclazz = getJClass(env);
1436     if (jclazz == nullptr) {
1437       // exception occurred accessing class
1438       return nullptr;
1439     }
1440 
1441     jmethodID mid =
1442         env->GetStaticMethodID(jclazz, "valueOf", "(J)Ljava/lang/Long;");
1443     if (mid == nullptr) {
1444       // exception thrown: NoSuchMethodException or OutOfMemoryError
1445       return nullptr;
1446     }
1447 
1448     const jobject jlong_obj =
1449         env->CallStaticObjectMethod(jclazz, mid, jprimitive_long);
1450     if (env->ExceptionCheck()) {
1451       // exception occurred
1452       return nullptr;
1453     }
1454 
1455     return jlong_obj;
1456   }
1457 };
1458 
1459 // The portal class for java.lang.StringBuilder
1460 class StringBuilderJni : public JavaClass {
1461   public:
1462   /**
1463    * Get the Java Class java.lang.StringBuilder
1464    *
1465    * @param env A pointer to the Java environment
1466    *
1467    * @return The Java Class or nullptr if one of the
1468    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
1469    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
1470    */
1471   static jclass getJClass(JNIEnv* env) {
1472     return JavaClass::getJClass(env, "java/lang/StringBuilder");
1473   }
1474 
1475   /**
1476    * Get the Java Method: StringBuilder#append
1477    *
1478    * @param env A pointer to the Java environment
1479    *
1480    * @return The Java Method ID or nullptr if the class or method id could not
1481    *     be retieved
1482    */
1483   static jmethodID getListAddMethodId(JNIEnv* env) {
1484     jclass jclazz = getJClass(env);
1485     if(jclazz == nullptr) {
1486       // exception occurred accessing class
1487       return nullptr;
1488     }
1489 
1490     static jmethodID mid =
1491         env->GetMethodID(jclazz, "append",
1492             "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1493     assert(mid != nullptr);
1494     return mid;
1495   }
1496 
1497   /**
1498    * Appends a C-style string to a StringBuilder
1499    *
1500    * @param env A pointer to the Java environment
1501    * @param jstring_builder Reference to a java.lang.StringBuilder
1502    * @param c_str A C-style string to append to the StringBuilder
1503    *
1504    * @return A reference to the updated StringBuilder, or a nullptr if
1505    *     an exception occurs
1506    */
1507   static jobject append(JNIEnv* env, jobject jstring_builder,
1508       const char* c_str) {
1509     jmethodID mid = getListAddMethodId(env);
1510     if(mid == nullptr) {
1511       // exception occurred accessing class or method
1512       return nullptr;
1513     }
1514 
1515     jstring new_value_str = env->NewStringUTF(c_str);
1516     if(new_value_str == nullptr) {
1517       // exception thrown: OutOfMemoryError
1518       return nullptr;
1519     }
1520 
1521     jobject jresult_string_builder =
1522         env->CallObjectMethod(jstring_builder, mid, new_value_str);
1523     if(env->ExceptionCheck()) {
1524       // exception occurred
1525       env->DeleteLocalRef(new_value_str);
1526       return nullptr;
1527     }
1528 
1529     return jresult_string_builder;
1530   }
1531 };
1532 
1533 // various utility functions for working with RocksDB and JNI
1534 class JniUtil {
1535  public:
1536     /**
1537      * Detect if jlong overflows size_t
1538      *
1539      * @param jvalue the jlong value
1540      *
1541      * @return
1542      */
1543     inline static Status check_if_jlong_fits_size_t(const jlong& jvalue) {
1544       Status s = Status::OK();
1545       if (static_cast<uint64_t>(jvalue) > std::numeric_limits<size_t>::max()) {
1546         s = Status::InvalidArgument(Slice("jlong overflows 32 bit value."));
1547       }
1548       return s;
1549     }
1550 
1551     /**
1552      * Obtains a reference to the JNIEnv from
1553      * the JVM
1554      *
1555      * If the current thread is not attached to the JavaVM
1556      * then it will be attached so as to retrieve the JNIEnv
1557      *
1558      * If a thread is attached, it must later be manually
1559      * released by calling JavaVM::DetachCurrentThread.
1560      * This can be handled by always matching calls to this
1561      * function with calls to {@link JniUtil::releaseJniEnv(JavaVM*, jboolean)}
1562      *
1563      * @param jvm (IN) A pointer to the JavaVM instance
1564      * @param attached (OUT) A pointer to a boolean which
1565      *     will be set to JNI_TRUE if we had to attach the thread
1566      *
1567      * @return A pointer to the JNIEnv or nullptr if a fatal error
1568      *     occurs and the JNIEnv cannot be retrieved
1569      */
1570     static JNIEnv* getJniEnv(JavaVM* jvm, jboolean* attached) {
1571       assert(jvm != nullptr);
1572 
1573       JNIEnv *env;
1574       const jint env_rs = jvm->GetEnv(reinterpret_cast<void**>(&env),
1575           JNI_VERSION_1_6);
1576 
1577       if(env_rs == JNI_OK) {
1578         // current thread is already attached, return the JNIEnv
1579         *attached = JNI_FALSE;
1580         return env;
1581       } else if(env_rs == JNI_EDETACHED) {
1582         // current thread is not attached, attempt to attach
1583         const jint rs_attach = jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL);
1584         if(rs_attach == JNI_OK) {
1585           *attached = JNI_TRUE;
1586           return env;
1587         } else {
1588           // error, could not attach the thread
1589           std::cerr << "JniUtil::getJniEnv - Fatal: could not attach current thread to JVM!" << std::endl;
1590           return nullptr;
1591         }
1592       } else if(env_rs == JNI_EVERSION) {
1593         // error, JDK does not support JNI_VERSION_1_6+
1594         std::cerr << "JniUtil::getJniEnv - Fatal: JDK does not support JNI_VERSION_1_6" << std::endl;
1595         return nullptr;
1596       } else {
1597         std::cerr << "JniUtil::getJniEnv - Fatal: Unknown error: env_rs=" << env_rs << std::endl;
1598         return nullptr;
1599       }
1600     }
1601 
1602     /**
1603      * Counterpart to {@link JniUtil::getJniEnv(JavaVM*, jboolean*)}
1604      *
1605      * Detachess the current thread from the JVM if it was previously
1606      * attached
1607      *
1608      * @param jvm (IN) A pointer to the JavaVM instance
1609      * @param attached (IN) JNI_TRUE if we previously had to attach the thread
1610      *     to the JavaVM to get the JNIEnv
1611      */
1612     static void releaseJniEnv(JavaVM* jvm, jboolean& attached) {
1613       assert(jvm != nullptr);
1614       if(attached == JNI_TRUE) {
1615         const jint rs_detach = jvm->DetachCurrentThread();
1616         assert(rs_detach == JNI_OK);
1617         if(rs_detach != JNI_OK) {
1618           std::cerr << "JniUtil::getJniEnv - Warn: Unable to detach current thread from JVM!" << std::endl;
1619         }
1620       }
1621     }
1622 
1623     /**
1624      * Copies a Java String[] to a C++ std::vector<std::string>
1625      *
1626      * @param env (IN) A pointer to the java environment
1627      * @param jss (IN) The Java String array to copy
1628      * @param has_exception (OUT) will be set to JNI_TRUE
1629      *     if an OutOfMemoryError or ArrayIndexOutOfBoundsException
1630      *     exception occurs
1631      *
1632      * @return A std::vector<std:string> containing copies of the Java strings
1633      */
1634     static std::vector<std::string> copyStrings(JNIEnv* env,
1635         jobjectArray jss, jboolean* has_exception) {
1636       return ROCKSDB_NAMESPACE::JniUtil::copyStrings(
1637           env, jss, env->GetArrayLength(jss), has_exception);
1638     }
1639 
1640     /**
1641      * Copies a Java String[] to a C++ std::vector<std::string>
1642      *
1643      * @param env (IN) A pointer to the java environment
1644      * @param jss (IN) The Java String array to copy
1645      * @param jss_len (IN) The length of the Java String array to copy
1646      * @param has_exception (OUT) will be set to JNI_TRUE
1647      *     if an OutOfMemoryError or ArrayIndexOutOfBoundsException
1648      *     exception occurs
1649      *
1650      * @return A std::vector<std:string> containing copies of the Java strings
1651      */
1652     static std::vector<std::string> copyStrings(JNIEnv* env,
1653         jobjectArray jss, const jsize jss_len, jboolean* has_exception) {
1654       std::vector<std::string> strs;
1655       strs.reserve(jss_len);
1656       for (jsize i = 0; i < jss_len; i++) {
1657         jobject js = env->GetObjectArrayElement(jss, i);
1658         if(env->ExceptionCheck()) {
1659           // exception thrown: ArrayIndexOutOfBoundsException
1660           *has_exception = JNI_TRUE;
1661           return strs;
1662         }
1663 
1664         jstring jstr = static_cast<jstring>(js);
1665         const char* str = env->GetStringUTFChars(jstr, nullptr);
1666         if(str == nullptr) {
1667           // exception thrown: OutOfMemoryError
1668           env->DeleteLocalRef(js);
1669           *has_exception = JNI_TRUE;
1670           return strs;
1671         }
1672 
1673         strs.push_back(std::string(str));
1674 
1675         env->ReleaseStringUTFChars(jstr, str);
1676         env->DeleteLocalRef(js);
1677       }
1678 
1679       *has_exception = JNI_FALSE;
1680       return strs;
1681     }
1682 
1683     /**
1684      * Copies a jstring to a C-style null-terminated byte string
1685      * and releases the original jstring
1686      *
1687      * The jstring is copied as UTF-8
1688      *
1689      * If an exception occurs, then JNIEnv::ExceptionCheck()
1690      * will have been called
1691      *
1692      * @param env (IN) A pointer to the java environment
1693      * @param js (IN) The java string to copy
1694      * @param has_exception (OUT) will be set to JNI_TRUE
1695      *     if an OutOfMemoryError exception occurs
1696      *
1697      * @return A pointer to the copied string, or a
1698      *     nullptr if has_exception == JNI_TRUE
1699      */
1700     static std::unique_ptr<char[]> copyString(JNIEnv* env, jstring js,
1701         jboolean* has_exception) {
1702       const char *utf = env->GetStringUTFChars(js, nullptr);
1703       if(utf == nullptr) {
1704         // exception thrown: OutOfMemoryError
1705         env->ExceptionCheck();
1706         *has_exception = JNI_TRUE;
1707         return nullptr;
1708       } else if(env->ExceptionCheck()) {
1709         // exception thrown
1710         env->ReleaseStringUTFChars(js, utf);
1711         *has_exception = JNI_TRUE;
1712         return nullptr;
1713       }
1714 
1715       const jsize utf_len = env->GetStringUTFLength(js);
1716       std::unique_ptr<char[]> str(new char[utf_len + 1]);  // Note: + 1 is needed for the c_str null terminator
1717       std::strcpy(str.get(), utf);
1718       env->ReleaseStringUTFChars(js, utf);
1719       *has_exception = JNI_FALSE;
1720       return str;
1721     }
1722 
1723     /**
1724      * Copies a jstring to a std::string
1725      * and releases the original jstring
1726      *
1727      * If an exception occurs, then JNIEnv::ExceptionCheck()
1728      * will have been called
1729      *
1730      * @param env (IN) A pointer to the java environment
1731      * @param js (IN) The java string to copy
1732      * @param has_exception (OUT) will be set to JNI_TRUE
1733      *     if an OutOfMemoryError exception occurs
1734      *
1735      * @return A std:string copy of the jstring, or an
1736      *     empty std::string if has_exception == JNI_TRUE
1737      */
1738     static std::string copyStdString(JNIEnv* env, jstring js,
1739       jboolean* has_exception) {
1740       const char *utf = env->GetStringUTFChars(js, nullptr);
1741       if(utf == nullptr) {
1742         // exception thrown: OutOfMemoryError
1743         env->ExceptionCheck();
1744         *has_exception = JNI_TRUE;
1745         return std::string();
1746       } else if(env->ExceptionCheck()) {
1747         // exception thrown
1748         env->ReleaseStringUTFChars(js, utf);
1749         *has_exception = JNI_TRUE;
1750         return std::string();
1751       }
1752 
1753       std::string name(utf);
1754       env->ReleaseStringUTFChars(js, utf);
1755       *has_exception = JNI_FALSE;
1756       return name;
1757     }
1758 
1759     /**
1760      * Copies bytes from a std::string to a jByteArray
1761      *
1762      * @param env A pointer to the java environment
1763      * @param bytes The bytes to copy
1764      *
1765      * @return the Java byte[], or nullptr if an exception occurs
1766      *
1767      * @throws RocksDBException thrown
1768      *   if memory size to copy exceeds general java specific array size limitation.
1769      */
1770     static jbyteArray copyBytes(JNIEnv* env, std::string bytes) {
1771       return createJavaByteArrayWithSizeCheck(env, bytes.c_str(), bytes.size());
1772     }
1773 
1774     /**
1775      * Given a Java byte[][] which is an array of java.lang.Strings
1776      * where each String is a byte[], the passed function `string_fn`
1777      * will be called on each String, the result is the collected by
1778      * calling the passed function `collector_fn`
1779      *
1780      * @param env (IN) A pointer to the java environment
1781      * @param jbyte_strings (IN) A Java array of Strings expressed as bytes
1782      * @param string_fn (IN) A transform function to call for each String
1783      * @param collector_fn (IN) A collector which is called for the result
1784      *     of each `string_fn`
1785      * @param has_exception (OUT) will be set to JNI_TRUE
1786      *     if an ArrayIndexOutOfBoundsException or OutOfMemoryError
1787      *     exception occurs
1788      */
1789     template <typename T> static void byteStrings(JNIEnv* env,
1790         jobjectArray jbyte_strings,
1791         std::function<T(const char*, const size_t)> string_fn,
1792         std::function<void(size_t, T)> collector_fn,
1793         jboolean *has_exception) {
1794       const jsize jlen = env->GetArrayLength(jbyte_strings);
1795 
1796       for(jsize i = 0; i < jlen; i++) {
1797         jobject jbyte_string_obj = env->GetObjectArrayElement(jbyte_strings, i);
1798         if(env->ExceptionCheck()) {
1799           // exception thrown: ArrayIndexOutOfBoundsException
1800           *has_exception = JNI_TRUE;  // signal error
1801           return;
1802         }
1803 
1804         jbyteArray jbyte_string_ary =
1805             reinterpret_cast<jbyteArray>(jbyte_string_obj);
1806         T result = byteString(env, jbyte_string_ary, string_fn, has_exception);
1807 
1808         env->DeleteLocalRef(jbyte_string_obj);
1809 
1810         if(*has_exception == JNI_TRUE) {
1811           // exception thrown: OutOfMemoryError
1812           return;
1813         }
1814 
1815         collector_fn(i, result);
1816       }
1817 
1818       *has_exception = JNI_FALSE;
1819     }
1820 
1821     /**
1822      * Given a Java String which is expressed as a Java Byte Array byte[],
1823      * the passed function `string_fn` will be called on the String
1824      * and the result returned
1825      *
1826      * @param env (IN) A pointer to the java environment
1827      * @param jbyte_string_ary (IN) A Java String expressed in bytes
1828      * @param string_fn (IN) A transform function to call on the String
1829      * @param has_exception (OUT) will be set to JNI_TRUE
1830      *     if an OutOfMemoryError exception occurs
1831      */
1832     template <typename T> static T byteString(JNIEnv* env,
1833         jbyteArray jbyte_string_ary,
1834         std::function<T(const char*, const size_t)> string_fn,
1835         jboolean* has_exception) {
1836       const jsize jbyte_string_len = env->GetArrayLength(jbyte_string_ary);
1837       return byteString<T>(env, jbyte_string_ary, jbyte_string_len, string_fn,
1838           has_exception);
1839     }
1840 
1841     /**
1842      * Given a Java String which is expressed as a Java Byte Array byte[],
1843      * the passed function `string_fn` will be called on the String
1844      * and the result returned
1845      *
1846      * @param env (IN) A pointer to the java environment
1847      * @param jbyte_string_ary (IN) A Java String expressed in bytes
1848      * @param jbyte_string_len (IN) The length of the Java String
1849      *     expressed in bytes
1850      * @param string_fn (IN) A transform function to call on the String
1851      * @param has_exception (OUT) will be set to JNI_TRUE
1852      *     if an OutOfMemoryError exception occurs
1853      */
1854     template <typename T> static T byteString(JNIEnv* env,
1855         jbyteArray jbyte_string_ary, const jsize jbyte_string_len,
1856         std::function<T(const char*, const size_t)> string_fn,
1857         jboolean* has_exception) {
1858       jbyte* jbyte_string =
1859           env->GetByteArrayElements(jbyte_string_ary, nullptr);
1860       if(jbyte_string == nullptr) {
1861         // exception thrown: OutOfMemoryError
1862         *has_exception = JNI_TRUE;
1863         return nullptr;  // signal error
1864       }
1865 
1866       T result =
1867           string_fn(reinterpret_cast<char *>(jbyte_string), jbyte_string_len);
1868 
1869       env->ReleaseByteArrayElements(jbyte_string_ary, jbyte_string, JNI_ABORT);
1870 
1871       *has_exception = JNI_FALSE;
1872       return result;
1873     }
1874 
1875     /**
1876      * Converts a std::vector<string> to a Java byte[][] where each Java String
1877      * is expressed as a Java Byte Array byte[].
1878      *
1879      * @param env A pointer to the java environment
1880      * @param strings A vector of Strings
1881      *
1882      * @return A Java array of Strings expressed as bytes,
1883      *     or nullptr if an exception is thrown
1884      */
1885     static jobjectArray stringsBytes(JNIEnv* env, std::vector<std::string> strings) {
1886       jclass jcls_ba = ByteJni::getArrayJClass(env);
1887       if(jcls_ba == nullptr) {
1888         // exception occurred
1889         return nullptr;
1890       }
1891 
1892       const jsize len = static_cast<jsize>(strings.size());
1893 
1894       jobjectArray jbyte_strings = env->NewObjectArray(len, jcls_ba, nullptr);
1895       if(jbyte_strings == nullptr) {
1896         // exception thrown: OutOfMemoryError
1897         return nullptr;
1898       }
1899 
1900       for (jsize i = 0; i < len; i++) {
1901         std::string *str = &strings[i];
1902         const jsize str_len = static_cast<jsize>(str->size());
1903 
1904         jbyteArray jbyte_string_ary = env->NewByteArray(str_len);
1905         if(jbyte_string_ary == nullptr) {
1906           // exception thrown: OutOfMemoryError
1907           env->DeleteLocalRef(jbyte_strings);
1908           return nullptr;
1909         }
1910 
1911         env->SetByteArrayRegion(
1912           jbyte_string_ary, 0, str_len,
1913           const_cast<jbyte*>(reinterpret_cast<const jbyte*>(str->c_str())));
1914         if(env->ExceptionCheck()) {
1915           // exception thrown: ArrayIndexOutOfBoundsException
1916           env->DeleteLocalRef(jbyte_string_ary);
1917           env->DeleteLocalRef(jbyte_strings);
1918           return nullptr;
1919         }
1920 
1921         env->SetObjectArrayElement(jbyte_strings, i, jbyte_string_ary);
1922         if(env->ExceptionCheck()) {
1923           // exception thrown: ArrayIndexOutOfBoundsException
1924           // or ArrayStoreException
1925           env->DeleteLocalRef(jbyte_string_ary);
1926           env->DeleteLocalRef(jbyte_strings);
1927           return nullptr;
1928         }
1929 
1930         env->DeleteLocalRef(jbyte_string_ary);
1931       }
1932 
1933       return jbyte_strings;
1934     }
1935 
1936      /**
1937      * Converts a std::vector<std::string> to a Java String[].
1938      *
1939      * @param env A pointer to the java environment
1940      * @param strings A vector of Strings
1941      *
1942      * @return A Java array of Strings,
1943      *     or nullptr if an exception is thrown
1944      */
1945     static jobjectArray toJavaStrings(JNIEnv* env,
1946         const std::vector<std::string>* strings) {
1947       jclass jcls_str = env->FindClass("java/lang/String");
1948       if(jcls_str == nullptr) {
1949         // exception occurred
1950         return nullptr;
1951       }
1952 
1953       const jsize len = static_cast<jsize>(strings->size());
1954 
1955       jobjectArray jstrings = env->NewObjectArray(len, jcls_str, nullptr);
1956       if(jstrings == nullptr) {
1957         // exception thrown: OutOfMemoryError
1958         return nullptr;
1959       }
1960 
1961       for (jsize i = 0; i < len; i++) {
1962         const std::string *str = &((*strings)[i]);
1963         jstring js = ROCKSDB_NAMESPACE::JniUtil::toJavaString(env, str);
1964         if (js == nullptr) {
1965           env->DeleteLocalRef(jstrings);
1966           return nullptr;
1967         }
1968 
1969         env->SetObjectArrayElement(jstrings, i, js);
1970         if(env->ExceptionCheck()) {
1971           // exception thrown: ArrayIndexOutOfBoundsException
1972           // or ArrayStoreException
1973           env->DeleteLocalRef(js);
1974           env->DeleteLocalRef(jstrings);
1975           return nullptr;
1976         }
1977       }
1978 
1979       return jstrings;
1980     }
1981 
1982     /**
1983      * Creates a Java UTF String from a C++ std::string
1984      *
1985      * @param env A pointer to the java environment
1986      * @param string the C++ std::string
1987      * @param treat_empty_as_null true if empty strings should be treated as null
1988      *
1989      * @return the Java UTF string, or nullptr if the provided string
1990      *     is null (or empty and treat_empty_as_null is set), or if an
1991      *     exception occurs allocating the Java String.
1992      */
1993     static jstring toJavaString(JNIEnv* env, const std::string* string,
1994         const bool treat_empty_as_null = false) {
1995       if (string == nullptr) {
1996         return nullptr;
1997       }
1998 
1999       if (treat_empty_as_null && string->empty()) {
2000         return nullptr;
2001       }
2002 
2003       return env->NewStringUTF(string->c_str());
2004     }
2005 
2006     /**
2007       * Copies bytes to a new jByteArray with the check of java array size limitation.
2008       *
2009       * @param bytes pointer to memory to copy to a new jByteArray
2010       * @param size number of bytes to copy
2011       *
2012       * @return the Java byte[], or nullptr if an exception occurs
2013       *
2014       * @throws RocksDBException thrown
2015       *   if memory size to copy exceeds general java array size limitation to avoid overflow.
2016       */
2017     static jbyteArray createJavaByteArrayWithSizeCheck(JNIEnv* env, const char* bytes, const size_t size) {
2018       // Limitation for java array size is vm specific
2019       // In general it cannot exceed Integer.MAX_VALUE (2^31 - 1)
2020       // Current HotSpot VM limitation for array size is Integer.MAX_VALUE - 5 (2^31 - 1 - 5)
2021       // It means that the next call to env->NewByteArray can still end with
2022       // OutOfMemoryError("Requested array size exceeds VM limit") coming from VM
2023       static const size_t MAX_JARRAY_SIZE = (static_cast<size_t>(1)) << 31;
2024       if(size > MAX_JARRAY_SIZE) {
2025         ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2026             env, "Requested array size exceeds VM limit");
2027         return nullptr;
2028       }
2029 
2030       const jsize jlen = static_cast<jsize>(size);
2031       jbyteArray jbytes = env->NewByteArray(jlen);
2032       if(jbytes == nullptr) {
2033         // exception thrown: OutOfMemoryError
2034         return nullptr;
2035       }
2036 
2037       env->SetByteArrayRegion(jbytes, 0, jlen,
2038         const_cast<jbyte*>(reinterpret_cast<const jbyte*>(bytes)));
2039       if(env->ExceptionCheck()) {
2040         // exception thrown: ArrayIndexOutOfBoundsException
2041         env->DeleteLocalRef(jbytes);
2042         return nullptr;
2043       }
2044 
2045       return jbytes;
2046     }
2047 
2048     /**
2049      * Copies bytes from a ROCKSDB_NAMESPACE::Slice to a jByteArray
2050      *
2051      * @param env A pointer to the java environment
2052      * @param bytes The bytes to copy
2053      *
2054      * @return the Java byte[] or nullptr if an exception occurs
2055      *
2056      * @throws RocksDBException thrown
2057      *   if memory size to copy exceeds general java specific array size
2058      * limitation.
2059      */
2060     static jbyteArray copyBytes(JNIEnv* env, const Slice& bytes) {
2061       return createJavaByteArrayWithSizeCheck(env, bytes.data(), bytes.size());
2062     }
2063 
2064     /*
2065      * Helper for operations on a key and value
2066      * for example WriteBatch->Put
2067      *
2068      * TODO(AR) could be used for RocksDB->Put etc.
2069      */
2070     static std::unique_ptr<ROCKSDB_NAMESPACE::Status> kv_op(
2071         std::function<ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Slice,
2072                                                 ROCKSDB_NAMESPACE::Slice)>
2073             op,
2074         JNIEnv* env, jobject /*jobj*/, jbyteArray jkey, jint jkey_len,
2075         jbyteArray jvalue, jint jvalue_len) {
2076       jbyte* key = env->GetByteArrayElements(jkey, nullptr);
2077       if(env->ExceptionCheck()) {
2078         // exception thrown: OutOfMemoryError
2079         return nullptr;
2080       }
2081 
2082       jbyte* value = env->GetByteArrayElements(jvalue, nullptr);
2083       if(env->ExceptionCheck()) {
2084         // exception thrown: OutOfMemoryError
2085         if(key != nullptr) {
2086           env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
2087         }
2088         return nullptr;
2089       }
2090 
2091       ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key),
2092                                          jkey_len);
2093       ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char*>(value),
2094                                            jvalue_len);
2095 
2096       auto status = op(key_slice, value_slice);
2097 
2098       if(value != nullptr) {
2099         env->ReleaseByteArrayElements(jvalue, value, JNI_ABORT);
2100       }
2101       if(key != nullptr) {
2102         env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
2103       }
2104 
2105       return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
2106           new ROCKSDB_NAMESPACE::Status(status));
2107     }
2108 
2109     /*
2110      * Helper for operations on a key
2111      * for example WriteBatch->Delete
2112      *
2113      * TODO(AR) could be used for RocksDB->Delete etc.
2114      */
2115     static std::unique_ptr<ROCKSDB_NAMESPACE::Status> k_op(
2116         std::function<ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Slice)> op,
2117         JNIEnv* env, jobject /*jobj*/, jbyteArray jkey, jint jkey_len) {
2118       jbyte* key = env->GetByteArrayElements(jkey, nullptr);
2119       if(env->ExceptionCheck()) {
2120         // exception thrown: OutOfMemoryError
2121         return nullptr;
2122       }
2123 
2124       ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key),
2125                                          jkey_len);
2126 
2127       auto status = op(key_slice);
2128 
2129       if(key != nullptr) {
2130         env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
2131       }
2132 
2133       return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
2134           new ROCKSDB_NAMESPACE::Status(status));
2135     }
2136 
2137     /*
2138      * Helper for operations on a value
2139      * for example WriteBatchWithIndex->GetFromBatch
2140      */
2141     static jbyteArray v_op(std::function<ROCKSDB_NAMESPACE::Status(
2142                                ROCKSDB_NAMESPACE::Slice, std::string*)>
2143                                op,
2144                            JNIEnv* env, jbyteArray jkey, jint jkey_len) {
2145       jbyte* key = env->GetByteArrayElements(jkey, nullptr);
2146       if(env->ExceptionCheck()) {
2147         // exception thrown: OutOfMemoryError
2148         return nullptr;
2149       }
2150 
2151       ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key),
2152                                          jkey_len);
2153 
2154       std::string value;
2155       ROCKSDB_NAMESPACE::Status s = op(key_slice, &value);
2156 
2157       if(key != nullptr) {
2158         env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
2159       }
2160 
2161       if (s.IsNotFound()) {
2162         return nullptr;
2163       }
2164 
2165       if (s.ok()) {
2166         jbyteArray jret_value =
2167             env->NewByteArray(static_cast<jsize>(value.size()));
2168         if(jret_value == nullptr) {
2169           // exception thrown: OutOfMemoryError
2170           return nullptr;
2171         }
2172 
2173         env->SetByteArrayRegion(jret_value, 0, static_cast<jsize>(value.size()),
2174                                 const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value.c_str())));
2175         if(env->ExceptionCheck()) {
2176           // exception thrown: ArrayIndexOutOfBoundsException
2177           if(jret_value != nullptr) {
2178             env->DeleteLocalRef(jret_value);
2179           }
2180           return nullptr;
2181         }
2182 
2183         return jret_value;
2184       }
2185 
2186       ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2187       return nullptr;
2188     }
2189 
2190     /**
2191      * Creates a vector<T*> of C++ pointers from
2192      *     a Java array of C++ pointer addresses.
2193      *
2194      * @param env (IN) A pointer to the java environment
2195      * @param pointers (IN) A Java array of C++ pointer addresses
2196      * @param has_exception (OUT) will be set to JNI_TRUE
2197      *     if an ArrayIndexOutOfBoundsException or OutOfMemoryError
2198      *     exception occurs.
2199      *
2200      * @return A vector of C++ pointers.
2201      */
2202     template<typename T> static std::vector<T*> fromJPointers(
2203         JNIEnv* env, jlongArray jptrs, jboolean *has_exception) {
2204       const jsize jptrs_len = env->GetArrayLength(jptrs);
2205       std::vector<T*> ptrs;
2206       jlong* jptr = env->GetLongArrayElements(jptrs, nullptr);
2207       if (jptr == nullptr) {
2208         // exception thrown: OutOfMemoryError
2209         *has_exception = JNI_TRUE;
2210         return ptrs;
2211       }
2212       ptrs.reserve(jptrs_len);
2213       for (jsize i = 0; i < jptrs_len; i++) {
2214         ptrs.push_back(reinterpret_cast<T*>(jptr[i]));
2215       }
2216       env->ReleaseLongArrayElements(jptrs, jptr, JNI_ABORT);
2217       return ptrs;
2218     }
2219 
2220     /**
2221      * Creates a Java array of C++ pointer addresses
2222      *     from a vector of C++ pointers.
2223      *
2224      * @param env (IN) A pointer to the java environment
2225      * @param pointers (IN) A vector of C++ pointers
2226      * @param has_exception (OUT) will be set to JNI_TRUE
2227      *     if an ArrayIndexOutOfBoundsException or OutOfMemoryError
2228      *     exception occurs
2229      *
2230      * @return Java array of C++ pointer addresses.
2231      */
2232     template<typename T> static jlongArray toJPointers(JNIEnv* env,
2233         const std::vector<T*> &pointers,
2234         jboolean *has_exception) {
2235       const jsize len = static_cast<jsize>(pointers.size());
2236       std::unique_ptr<jlong[]> results(new jlong[len]);
2237       std::transform(pointers.begin(), pointers.end(), results.get(), [](T* pointer) -> jlong {
2238         return reinterpret_cast<jlong>(pointer);
2239       });
2240 
2241       jlongArray jpointers = env->NewLongArray(len);
2242       if (jpointers == nullptr) {
2243         // exception thrown: OutOfMemoryError
2244         *has_exception = JNI_TRUE;
2245         return nullptr;
2246       }
2247 
2248       env->SetLongArrayRegion(jpointers, 0, len, results.get());
2249       if (env->ExceptionCheck()) {
2250         // exception thrown: ArrayIndexOutOfBoundsException
2251         *has_exception = JNI_TRUE;
2252         env->DeleteLocalRef(jpointers);
2253         return nullptr;
2254       }
2255 
2256       *has_exception = JNI_FALSE;
2257 
2258       return jpointers;
2259     }
2260 
2261     /*
2262      * Helper for operations on a key and value
2263      * for example WriteBatch->Put
2264      *
2265      * TODO(AR) could be extended to cover returning ROCKSDB_NAMESPACE::Status
2266      * from `op` and used for RocksDB->Put etc.
2267      */
2268     static void kv_op_direct(std::function<void(ROCKSDB_NAMESPACE::Slice&,
2269                                                 ROCKSDB_NAMESPACE::Slice&)>
2270                                  op,
2271                              JNIEnv* env, jobject jkey, jint jkey_off,
2272                              jint jkey_len, jobject jval, jint jval_off,
2273                              jint jval_len) {
2274       char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
2275       if (key == nullptr ||
2276           env->GetDirectBufferCapacity(jkey) < (jkey_off + jkey_len)) {
2277         ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2278             env, "Invalid key argument");
2279         return;
2280       }
2281 
2282       char* value = reinterpret_cast<char*>(env->GetDirectBufferAddress(jval));
2283       if (value == nullptr ||
2284           env->GetDirectBufferCapacity(jval) < (jval_off + jval_len)) {
2285         ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2286             env, "Invalid value argument");
2287         return;
2288       }
2289 
2290       key += jkey_off;
2291       value += jval_off;
2292 
2293       ROCKSDB_NAMESPACE::Slice key_slice(key, jkey_len);
2294       ROCKSDB_NAMESPACE::Slice value_slice(value, jval_len);
2295 
2296       op(key_slice, value_slice);
2297     }
2298 
2299     /*
2300      * Helper for operations on a key and value
2301      * for example WriteBatch->Delete
2302      *
2303      * TODO(AR) could be extended to cover returning ROCKSDB_NAMESPACE::Status
2304      * from `op` and used for RocksDB->Delete etc.
2305      */
2306     static void k_op_direct(std::function<void(ROCKSDB_NAMESPACE::Slice&)> op,
2307                             JNIEnv* env, jobject jkey, jint jkey_off,
2308                             jint jkey_len) {
2309       char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
2310       if (key == nullptr ||
2311           env->GetDirectBufferCapacity(jkey) < (jkey_off + jkey_len)) {
2312         ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2313             env, "Invalid key argument");
2314         return;
2315       }
2316 
2317       key += jkey_off;
2318 
2319       ROCKSDB_NAMESPACE::Slice key_slice(key, jkey_len);
2320 
2321       return op(key_slice);
2322     }
2323 
2324     template <class T>
2325     static jint copyToDirect(JNIEnv* env, T& source, jobject jtarget,
2326                              jint jtarget_off, jint jtarget_len) {
2327       char* target =
2328           reinterpret_cast<char*>(env->GetDirectBufferAddress(jtarget));
2329       if (target == nullptr ||
2330           env->GetDirectBufferCapacity(jtarget) < (jtarget_off + jtarget_len)) {
2331         ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2332             env, "Invalid target argument");
2333         return 0;
2334       }
2335 
2336       target += jtarget_off;
2337 
2338       const jint cvalue_len = static_cast<jint>(source.size());
2339       const jint length = std::min(jtarget_len, cvalue_len);
2340 
2341       memcpy(target, source.data(), length);
2342 
2343       return cvalue_len;
2344     }
2345 };
2346 
2347 class MapJni : public JavaClass {
2348  public:
2349   /**
2350    * Get the Java Class java.util.Map
2351    *
2352    * @param env A pointer to the Java environment
2353    *
2354    * @return The Java Class or nullptr if one of the
2355    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2356    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2357    */
2358   static jclass getJClass(JNIEnv* env) {
2359     return JavaClass::getJClass(env, "java/util/Map");
2360   }
2361 
2362   /**
2363    * Get the Java Method: Map#put
2364    *
2365    * @param env A pointer to the Java environment
2366    *
2367    * @return The Java Method ID or nullptr if the class or method id could not
2368    *     be retieved
2369    */
2370   static jmethodID getMapPutMethodId(JNIEnv* env) {
2371     jclass jlist_clazz = getJClass(env);
2372     if(jlist_clazz == nullptr) {
2373       // exception occurred accessing class
2374       return nullptr;
2375     }
2376 
2377     static jmethodID mid =
2378         env->GetMethodID(jlist_clazz, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
2379     assert(mid != nullptr);
2380     return mid;
2381   }
2382 };
2383 
2384 class HashMapJni : public JavaClass {
2385  public:
2386   /**
2387    * Get the Java Class java.util.HashMap
2388    *
2389    * @param env A pointer to the Java environment
2390    *
2391    * @return The Java Class or nullptr if one of the
2392    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2393    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2394    */
2395   static jclass getJClass(JNIEnv* env) {
2396     return JavaClass::getJClass(env, "java/util/HashMap");
2397   }
2398 
2399   /**
2400    * Create a new Java java.util.HashMap object.
2401    *
2402    * @param env A pointer to the Java environment
2403    *
2404    * @return A reference to a Java java.util.HashMap object, or
2405    * nullptr if an an exception occurs
2406    */
2407   static jobject construct(JNIEnv* env, const uint32_t initial_capacity = 16) {
2408     jclass jclazz = getJClass(env);
2409     if (jclazz == nullptr) {
2410       // exception occurred accessing class
2411       return nullptr;
2412     }
2413 
2414     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(I)V");
2415     if (mid == nullptr) {
2416       // exception thrown: NoSuchMethodException or OutOfMemoryError
2417       return nullptr;
2418     }
2419 
2420     jobject jhash_map = env->NewObject(jclazz, mid, static_cast<jint>(initial_capacity));
2421     if (env->ExceptionCheck()) {
2422       return nullptr;
2423     }
2424 
2425     return jhash_map;
2426   }
2427 
2428   /**
2429    * A function which maps a std::pair<K,V> to a std::pair<JK, JV>
2430    *
2431    * @return Either a pointer to a std::pair<jobject, jobject>, or nullptr
2432    *     if an error occurs during the mapping
2433    */
2434   template <typename K, typename V, typename JK, typename JV>
2435   using FnMapKV = std::function<std::unique_ptr<std::pair<JK, JV>> (const std::pair<K, V>&)>;
2436 
2437   // template <class I, typename K, typename V, typename K1, typename V1, typename std::enable_if<std::is_same<typename std::iterator_traits<I>::value_type, std::pair<const K,V>>::value, int32_t>::type = 0>
2438   // static void putAll(JNIEnv* env, const jobject jhash_map, I iterator, const FnMapKV<const K,V,K1,V1> &fn_map_kv) {
2439   /**
2440    * Returns true if it succeeds, false if an error occurs
2441    */
2442   template<class iterator_type, typename K, typename V>
2443   static bool putAll(JNIEnv* env, const jobject jhash_map, iterator_type iterator, iterator_type end, const FnMapKV<K, V, jobject, jobject> &fn_map_kv) {
2444     const jmethodID jmid_put =
2445         ROCKSDB_NAMESPACE::MapJni::getMapPutMethodId(env);
2446     if (jmid_put == nullptr) {
2447       return false;
2448     }
2449 
2450     for (auto it = iterator; it != end; ++it) {
2451       const std::unique_ptr<std::pair<jobject, jobject>> result = fn_map_kv(*it);
2452       if (result == nullptr) {
2453           // an error occurred during fn_map_kv
2454           return false;
2455       }
2456       env->CallObjectMethod(jhash_map, jmid_put, result->first, result->second);
2457       if (env->ExceptionCheck()) {
2458         // exception occurred
2459         env->DeleteLocalRef(result->second);
2460         env->DeleteLocalRef(result->first);
2461         return false;
2462       }
2463 
2464       // release local references
2465       env->DeleteLocalRef(result->second);
2466       env->DeleteLocalRef(result->first);
2467     }
2468 
2469     return true;
2470   }
2471 
2472   /**
2473    * Creates a java.util.Map<String, String> from a std::map<std::string, std::string>
2474    *
2475    * @param env A pointer to the Java environment
2476    * @param map the Cpp map
2477    *
2478    * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred
2479    */
2480   static jobject fromCppMap(JNIEnv* env, const std::map<std::string, std::string>* map) {
2481     if (map == nullptr) {
2482       return nullptr;
2483     }
2484 
2485     jobject jhash_map = construct(env, static_cast<uint32_t>(map->size()));
2486     if (jhash_map == nullptr) {
2487       // exception occurred
2488       return nullptr;
2489     }
2490 
2491     const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
2492         const std::string, const std::string, jobject, jobject>
2493         fn_map_kv =
2494             [env](const std::pair<const std::string, const std::string>& kv) {
2495               jstring jkey = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
2496                   env, &(kv.first), false);
2497               if (env->ExceptionCheck()) {
2498                 // an error occurred
2499                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2500               }
2501 
2502               jstring jvalue = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
2503                   env, &(kv.second), true);
2504               if (env->ExceptionCheck()) {
2505                 // an error occurred
2506                 env->DeleteLocalRef(jkey);
2507                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2508               }
2509 
2510               return std::unique_ptr<std::pair<jobject, jobject>>(
2511                   new std::pair<jobject, jobject>(
2512                       static_cast<jobject>(jkey),
2513                       static_cast<jobject>(jvalue)));
2514             };
2515 
2516     if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) {
2517       // exception occurred
2518       return nullptr;
2519     }
2520 
2521     return jhash_map;
2522   }
2523 
2524   /**
2525    * Creates a java.util.Map<String, Long> from a std::map<std::string, uint32_t>
2526    *
2527    * @param env A pointer to the Java environment
2528    * @param map the Cpp map
2529    *
2530    * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred
2531    */
2532   static jobject fromCppMap(JNIEnv* env, const std::map<std::string, uint32_t>* map) {
2533     if (map == nullptr) {
2534       return nullptr;
2535     }
2536 
2537     if (map == nullptr) {
2538       return nullptr;
2539     }
2540 
2541     jobject jhash_map = construct(env, static_cast<uint32_t>(map->size()));
2542     if (jhash_map == nullptr) {
2543       // exception occurred
2544       return nullptr;
2545     }
2546 
2547     const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
2548         const std::string, const uint32_t, jobject, jobject>
2549         fn_map_kv =
2550             [env](const std::pair<const std::string, const uint32_t>& kv) {
2551               jstring jkey = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
2552                   env, &(kv.first), false);
2553               if (env->ExceptionCheck()) {
2554                 // an error occurred
2555                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2556               }
2557 
2558               jobject jvalue = ROCKSDB_NAMESPACE::IntegerJni::valueOf(
2559                   env, static_cast<jint>(kv.second));
2560               if (env->ExceptionCheck()) {
2561                 // an error occurred
2562                 env->DeleteLocalRef(jkey);
2563                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2564               }
2565 
2566               return std::unique_ptr<std::pair<jobject, jobject>>(
2567                   new std::pair<jobject, jobject>(static_cast<jobject>(jkey),
2568                                                   jvalue));
2569             };
2570 
2571     if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) {
2572       // exception occurred
2573       return nullptr;
2574     }
2575 
2576     return jhash_map;
2577   }
2578 
2579   /**
2580    * Creates a java.util.Map<String, Long> from a std::map<std::string, uint64_t>
2581    *
2582    * @param env A pointer to the Java environment
2583    * @param map the Cpp map
2584    *
2585    * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred
2586    */
2587   static jobject fromCppMap(JNIEnv* env, const std::map<std::string, uint64_t>* map) {
2588     if (map == nullptr) {
2589       return nullptr;
2590     }
2591 
2592     jobject jhash_map = construct(env, static_cast<uint32_t>(map->size()));
2593     if (jhash_map == nullptr) {
2594       // exception occurred
2595       return nullptr;
2596     }
2597 
2598     const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
2599         const std::string, const uint64_t, jobject, jobject>
2600         fn_map_kv =
2601             [env](const std::pair<const std::string, const uint64_t>& kv) {
2602               jstring jkey = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
2603                   env, &(kv.first), false);
2604               if (env->ExceptionCheck()) {
2605                 // an error occurred
2606                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2607               }
2608 
2609               jobject jvalue = ROCKSDB_NAMESPACE::LongJni::valueOf(
2610                   env, static_cast<jlong>(kv.second));
2611               if (env->ExceptionCheck()) {
2612                 // an error occurred
2613                 env->DeleteLocalRef(jkey);
2614                 return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2615               }
2616 
2617               return std::unique_ptr<std::pair<jobject, jobject>>(
2618                   new std::pair<jobject, jobject>(static_cast<jobject>(jkey),
2619                                                   jvalue));
2620             };
2621 
2622     if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) {
2623       // exception occurred
2624       return nullptr;
2625     }
2626 
2627     return jhash_map;
2628   }
2629 
2630     /**
2631    * Creates a java.util.Map<String, Long> from a std::map<uint32_t, uint64_t>
2632    *
2633    * @param env A pointer to the Java environment
2634    * @param map the Cpp map
2635    *
2636    * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred
2637    */
2638   static jobject fromCppMap(JNIEnv* env, const std::map<uint32_t, uint64_t>* map) {
2639     if (map == nullptr) {
2640       return nullptr;
2641     }
2642 
2643     jobject jhash_map = construct(env, static_cast<uint32_t>(map->size()));
2644     if (jhash_map == nullptr) {
2645       // exception occurred
2646       return nullptr;
2647     }
2648 
2649     const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<const uint32_t, const uint64_t,
2650                                                  jobject, jobject>
2651         fn_map_kv = [env](const std::pair<const uint32_t, const uint64_t>& kv) {
2652           jobject jkey = ROCKSDB_NAMESPACE::IntegerJni::valueOf(
2653               env, static_cast<jint>(kv.first));
2654           if (env->ExceptionCheck()) {
2655             // an error occurred
2656             return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2657           }
2658 
2659           jobject jvalue = ROCKSDB_NAMESPACE::LongJni::valueOf(
2660               env, static_cast<jlong>(kv.second));
2661           if (env->ExceptionCheck()) {
2662             // an error occurred
2663             env->DeleteLocalRef(jkey);
2664             return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
2665           }
2666 
2667           return std::unique_ptr<std::pair<jobject, jobject>>(
2668               new std::pair<jobject, jobject>(static_cast<jobject>(jkey),
2669                                               jvalue));
2670         };
2671 
2672     if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) {
2673       // exception occurred
2674       return nullptr;
2675     }
2676 
2677     return jhash_map;
2678   }
2679 };
2680 
2681 // The portal class for org.rocksdb.RocksDB
2682 class RocksDBJni
2683     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::DB*, RocksDBJni> {
2684  public:
2685   /**
2686    * Get the Java Class org.rocksdb.RocksDB
2687    *
2688    * @param env A pointer to the Java environment
2689    *
2690    * @return The Java Class or nullptr if one of the
2691    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2692    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2693    */
2694   static jclass getJClass(JNIEnv* env) {
2695     return RocksDBNativeClass::getJClass(env, "org/rocksdb/RocksDB");
2696   }
2697 };
2698 
2699 // The portal class for org.rocksdb.Options
2700 class OptionsJni
2701     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::Options*, OptionsJni> {
2702  public:
2703   /**
2704    * Get the Java Class org.rocksdb.Options
2705    *
2706    * @param env A pointer to the Java environment
2707    *
2708    * @return The Java Class or nullptr if one of the
2709    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2710    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2711    */
2712   static jclass getJClass(JNIEnv* env) {
2713     return RocksDBNativeClass::getJClass(env, "org/rocksdb/Options");
2714   }
2715 };
2716 
2717 // The portal class for org.rocksdb.DBOptions
2718 class DBOptionsJni
2719     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::DBOptions*, DBOptionsJni> {
2720  public:
2721   /**
2722    * Get the Java Class org.rocksdb.DBOptions
2723    *
2724    * @param env A pointer to the Java environment
2725    *
2726    * @return The Java Class or nullptr if one of the
2727    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2728    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2729    */
2730   static jclass getJClass(JNIEnv* env) {
2731     return RocksDBNativeClass::getJClass(env, "org/rocksdb/DBOptions");
2732   }
2733 };
2734 
2735 // The portal class for org.rocksdb.ColumnFamilyOptions
2736 class ColumnFamilyOptionsJni
2737     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::ColumnFamilyOptions*,
2738                                 ColumnFamilyOptionsJni> {
2739  public:
2740   /**
2741    * Get the Java Class org.rocksdb.ColumnFamilyOptions
2742    *
2743    * @param env A pointer to the Java environment
2744    *
2745    * @return The Java Class or nullptr if one of the
2746    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2747    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2748    */
2749   static jclass getJClass(JNIEnv* env) {
2750     return RocksDBNativeClass::getJClass(env,
2751                                          "org/rocksdb/ColumnFamilyOptions");
2752   }
2753 
2754   /**
2755    * Create a new Java org.rocksdb.ColumnFamilyOptions object with the same
2756    * properties as the provided C++ ROCKSDB_NAMESPACE::ColumnFamilyOptions
2757    * object
2758    *
2759    * @param env A pointer to the Java environment
2760    * @param cfoptions A pointer to ROCKSDB_NAMESPACE::ColumnFamilyOptions object
2761    *
2762    * @return A reference to a Java org.rocksdb.ColumnFamilyOptions object, or
2763    * nullptr if an an exception occurs
2764    */
2765   static jobject construct(JNIEnv* env, const ColumnFamilyOptions* cfoptions) {
2766     auto* cfo = new ROCKSDB_NAMESPACE::ColumnFamilyOptions(*cfoptions);
2767     jclass jclazz = getJClass(env);
2768     if(jclazz == nullptr) {
2769       // exception occurred accessing class
2770       return nullptr;
2771     }
2772 
2773     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(J)V");
2774     if (mid == nullptr) {
2775       // exception thrown: NoSuchMethodException or OutOfMemoryError
2776       return nullptr;
2777     }
2778 
2779     jobject jcfd = env->NewObject(jclazz, mid, reinterpret_cast<jlong>(cfo));
2780     if (env->ExceptionCheck()) {
2781       return nullptr;
2782     }
2783 
2784     return jcfd;
2785   }
2786 };
2787 
2788 // The portal class for org.rocksdb.WriteOptions
2789 class WriteOptionsJni
2790     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::WriteOptions*,
2791                                 WriteOptionsJni> {
2792  public:
2793   /**
2794    * Get the Java Class org.rocksdb.WriteOptions
2795    *
2796    * @param env A pointer to the Java environment
2797    *
2798    * @return The Java Class or nullptr if one of the
2799    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2800    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2801    */
2802   static jclass getJClass(JNIEnv* env) {
2803     return RocksDBNativeClass::getJClass(env, "org/rocksdb/WriteOptions");
2804   }
2805 };
2806 
2807 // The portal class for org.rocksdb.ReadOptions
2808 class ReadOptionsJni
2809     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::ReadOptions*,
2810                                 ReadOptionsJni> {
2811  public:
2812   /**
2813    * Get the Java Class org.rocksdb.ReadOptions
2814    *
2815    * @param env A pointer to the Java environment
2816    *
2817    * @return The Java Class or nullptr if one of the
2818    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2819    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2820    */
2821   static jclass getJClass(JNIEnv* env) {
2822     return RocksDBNativeClass::getJClass(env, "org/rocksdb/ReadOptions");
2823   }
2824 };
2825 
2826 // The portal class for org.rocksdb.WriteBatch
2827 class WriteBatchJni
2828     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::WriteBatch*, WriteBatchJni> {
2829  public:
2830   /**
2831    * Get the Java Class org.rocksdb.WriteBatch
2832    *
2833    * @param env A pointer to the Java environment
2834    *
2835    * @return The Java Class or nullptr if one of the
2836    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2837    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2838    */
2839   static jclass getJClass(JNIEnv* env) {
2840     return RocksDBNativeClass::getJClass(env, "org/rocksdb/WriteBatch");
2841   }
2842 
2843   /**
2844    * Create a new Java org.rocksdb.WriteBatch object
2845    *
2846    * @param env A pointer to the Java environment
2847    * @param wb A pointer to ROCKSDB_NAMESPACE::WriteBatch object
2848    *
2849    * @return A reference to a Java org.rocksdb.WriteBatch object, or
2850    * nullptr if an an exception occurs
2851    */
2852   static jobject construct(JNIEnv* env, const WriteBatch* wb) {
2853     jclass jclazz = getJClass(env);
2854     if(jclazz == nullptr) {
2855       // exception occurred accessing class
2856       return nullptr;
2857     }
2858 
2859     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(J)V");
2860     if (mid == nullptr) {
2861       // exception thrown: NoSuchMethodException or OutOfMemoryError
2862       return nullptr;
2863     }
2864 
2865     jobject jwb = env->NewObject(jclazz, mid, reinterpret_cast<jlong>(wb));
2866     if (env->ExceptionCheck()) {
2867       return nullptr;
2868     }
2869 
2870     return jwb;
2871   }
2872 };
2873 
2874 // The portal class for org.rocksdb.WriteBatch.Handler
2875 class WriteBatchHandlerJni
2876     : public RocksDBNativeClass<
2877           const ROCKSDB_NAMESPACE::WriteBatchHandlerJniCallback*,
2878           WriteBatchHandlerJni> {
2879  public:
2880   /**
2881    * Get the Java Class org.rocksdb.WriteBatch.Handler
2882    *
2883    * @param env A pointer to the Java environment
2884    *
2885    * @return The Java Class or nullptr if one of the
2886    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
2887    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
2888    */
2889   static jclass getJClass(JNIEnv* env) {
2890     return RocksDBNativeClass::getJClass(env,
2891         "org/rocksdb/WriteBatch$Handler");
2892   }
2893 
2894   /**
2895    * Get the Java Method: WriteBatch.Handler#put
2896    *
2897    * @param env A pointer to the Java environment
2898    *
2899    * @return The Java Method ID or nullptr if the class or method id could not
2900    *     be retieved
2901    */
2902   static jmethodID getPutCfMethodId(JNIEnv* env) {
2903     jclass jclazz = getJClass(env);
2904     if(jclazz == nullptr) {
2905       // exception occurred accessing class
2906       return nullptr;
2907     }
2908 
2909     static jmethodID mid = env->GetMethodID(jclazz, "put", "(I[B[B)V");
2910     assert(mid != nullptr);
2911     return mid;
2912   }
2913 
2914   /**
2915    * Get the Java Method: WriteBatch.Handler#put
2916    *
2917    * @param env A pointer to the Java environment
2918    *
2919    * @return The Java Method ID or nullptr if the class or method id could not
2920    *     be retieved
2921    */
2922   static jmethodID getPutMethodId(JNIEnv* env) {
2923     jclass jclazz = getJClass(env);
2924     if(jclazz == nullptr) {
2925       // exception occurred accessing class
2926       return nullptr;
2927     }
2928 
2929     static jmethodID mid = env->GetMethodID(jclazz, "put", "([B[B)V");
2930     assert(mid != nullptr);
2931     return mid;
2932   }
2933 
2934   /**
2935    * Get the Java Method: WriteBatch.Handler#merge
2936    *
2937    * @param env A pointer to the Java environment
2938    *
2939    * @return The Java Method ID or nullptr if the class or method id could not
2940    *     be retieved
2941    */
2942   static jmethodID getMergeCfMethodId(JNIEnv* env) {
2943     jclass jclazz = getJClass(env);
2944     if(jclazz == nullptr) {
2945       // exception occurred accessing class
2946       return nullptr;
2947     }
2948 
2949     static jmethodID mid = env->GetMethodID(jclazz, "merge", "(I[B[B)V");
2950     assert(mid != nullptr);
2951     return mid;
2952   }
2953 
2954   /**
2955    * Get the Java Method: WriteBatch.Handler#merge
2956    *
2957    * @param env A pointer to the Java environment
2958    *
2959    * @return The Java Method ID or nullptr if the class or method id could not
2960    *     be retieved
2961    */
2962   static jmethodID getMergeMethodId(JNIEnv* env) {
2963     jclass jclazz = getJClass(env);
2964     if(jclazz == nullptr) {
2965       // exception occurred accessing class
2966       return nullptr;
2967     }
2968 
2969     static jmethodID mid = env->GetMethodID(jclazz, "merge", "([B[B)V");
2970     assert(mid != nullptr);
2971     return mid;
2972   }
2973 
2974   /**
2975    * Get the Java Method: WriteBatch.Handler#delete
2976    *
2977    * @param env A pointer to the Java environment
2978    *
2979    * @return The Java Method ID or nullptr if the class or method id could not
2980    *     be retieved
2981    */
2982   static jmethodID getDeleteCfMethodId(JNIEnv* env) {
2983     jclass jclazz = getJClass(env);
2984     if(jclazz == nullptr) {
2985       // exception occurred accessing class
2986       return nullptr;
2987     }
2988 
2989     static jmethodID mid = env->GetMethodID(jclazz, "delete", "(I[B)V");
2990     assert(mid != nullptr);
2991     return mid;
2992   }
2993 
2994   /**
2995    * Get the Java Method: WriteBatch.Handler#delete
2996    *
2997    * @param env A pointer to the Java environment
2998    *
2999    * @return The Java Method ID or nullptr if the class or method id could not
3000    *     be retieved
3001    */
3002   static jmethodID getDeleteMethodId(JNIEnv* env) {
3003     jclass jclazz = getJClass(env);
3004     if(jclazz == nullptr) {
3005       // exception occurred accessing class
3006       return nullptr;
3007     }
3008 
3009     static jmethodID mid = env->GetMethodID(jclazz, "delete", "([B)V");
3010     assert(mid != nullptr);
3011     return mid;
3012   }
3013 
3014   /**
3015    * Get the Java Method: WriteBatch.Handler#singleDelete
3016    *
3017    * @param env A pointer to the Java environment
3018    *
3019    * @return The Java Method ID or nullptr if the class or method id could not
3020    *     be retieved
3021    */
3022   static jmethodID getSingleDeleteCfMethodId(JNIEnv* env) {
3023     jclass jclazz = getJClass(env);
3024     if(jclazz == nullptr) {
3025       // exception occurred accessing class
3026       return nullptr;
3027     }
3028 
3029     static jmethodID mid = env->GetMethodID(jclazz, "singleDelete", "(I[B)V");
3030     assert(mid != nullptr);
3031     return mid;
3032   }
3033 
3034   /**
3035    * Get the Java Method: WriteBatch.Handler#singleDelete
3036    *
3037    * @param env A pointer to the Java environment
3038    *
3039    * @return The Java Method ID or nullptr if the class or method id could not
3040    *     be retieved
3041    */
3042   static jmethodID getSingleDeleteMethodId(JNIEnv* env) {
3043     jclass jclazz = getJClass(env);
3044     if(jclazz == nullptr) {
3045       // exception occurred accessing class
3046       return nullptr;
3047     }
3048 
3049     static jmethodID mid = env->GetMethodID(jclazz, "singleDelete", "([B)V");
3050     assert(mid != nullptr);
3051     return mid;
3052   }
3053 
3054   /**
3055    * Get the Java Method: WriteBatch.Handler#deleteRange
3056    *
3057    * @param env A pointer to the Java environment
3058    *
3059    * @return The Java Method ID or nullptr if the class or method id could not
3060    *     be retieved
3061    */
3062   static jmethodID getDeleteRangeCfMethodId(JNIEnv* env) {
3063     jclass jclazz = getJClass(env);
3064     if (jclazz == nullptr) {
3065       // exception occurred accessing class
3066       return nullptr;
3067     }
3068 
3069     static jmethodID mid = env->GetMethodID(jclazz, "deleteRange", "(I[B[B)V");
3070     assert(mid != nullptr);
3071     return mid;
3072   }
3073 
3074   /**
3075    * Get the Java Method: WriteBatch.Handler#deleteRange
3076    *
3077    * @param env A pointer to the Java environment
3078    *
3079    * @return The Java Method ID or nullptr if the class or method id could not
3080    *     be retieved
3081    */
3082   static jmethodID getDeleteRangeMethodId(JNIEnv* env) {
3083     jclass jclazz = getJClass(env);
3084     if (jclazz == nullptr) {
3085       // exception occurred accessing class
3086       return nullptr;
3087     }
3088 
3089     static jmethodID mid = env->GetMethodID(jclazz, "deleteRange", "([B[B)V");
3090     assert(mid != nullptr);
3091     return mid;
3092   }
3093 
3094   /**
3095    * Get the Java Method: WriteBatch.Handler#logData
3096    *
3097    * @param env A pointer to the Java environment
3098    *
3099    * @return The Java Method ID or nullptr if the class or method id could not
3100    *     be retieved
3101    */
3102   static jmethodID getLogDataMethodId(JNIEnv* env) {
3103     jclass jclazz = getJClass(env);
3104     if(jclazz == nullptr) {
3105       // exception occurred accessing class
3106       return nullptr;
3107     }
3108 
3109     static jmethodID mid = env->GetMethodID(jclazz, "logData", "([B)V");
3110     assert(mid != nullptr);
3111     return mid;
3112   }
3113 
3114   /**
3115    * Get the Java Method: WriteBatch.Handler#putBlobIndex
3116    *
3117    * @param env A pointer to the Java environment
3118    *
3119    * @return The Java Method ID or nullptr if the class or method id could not
3120    *     be retieved
3121    */
3122   static jmethodID getPutBlobIndexCfMethodId(JNIEnv* env) {
3123     jclass jclazz = getJClass(env);
3124     if(jclazz == nullptr) {
3125       // exception occurred accessing class
3126       return nullptr;
3127     }
3128 
3129     static jmethodID mid = env->GetMethodID(jclazz, "putBlobIndex", "(I[B[B)V");
3130     assert(mid != nullptr);
3131     return mid;
3132   }
3133 
3134   /**
3135    * Get the Java Method: WriteBatch.Handler#markBeginPrepare
3136    *
3137    * @param env A pointer to the Java environment
3138    *
3139    * @return The Java Method ID or nullptr if the class or method id could not
3140    *     be retieved
3141    */
3142   static jmethodID getMarkBeginPrepareMethodId(JNIEnv* env) {
3143     jclass jclazz = getJClass(env);
3144     if(jclazz == nullptr) {
3145       // exception occurred accessing class
3146       return nullptr;
3147     }
3148 
3149     static jmethodID mid = env->GetMethodID(jclazz, "markBeginPrepare", "()V");
3150     assert(mid != nullptr);
3151     return mid;
3152   }
3153 
3154   /**
3155    * Get the Java Method: WriteBatch.Handler#markEndPrepare
3156    *
3157    * @param env A pointer to the Java environment
3158    *
3159    * @return The Java Method ID or nullptr if the class or method id could not
3160    *     be retieved
3161    */
3162   static jmethodID getMarkEndPrepareMethodId(JNIEnv* env) {
3163     jclass jclazz = getJClass(env);
3164     if(jclazz == nullptr) {
3165       // exception occurred accessing class
3166       return nullptr;
3167     }
3168 
3169     static jmethodID mid = env->GetMethodID(jclazz, "markEndPrepare", "([B)V");
3170     assert(mid != nullptr);
3171     return mid;
3172   }
3173 
3174   /**
3175    * Get the Java Method: WriteBatch.Handler#markNoop
3176    *
3177    * @param env A pointer to the Java environment
3178    *
3179    * @return The Java Method ID or nullptr if the class or method id could not
3180    *     be retieved
3181    */
3182   static jmethodID getMarkNoopMethodId(JNIEnv* env) {
3183     jclass jclazz = getJClass(env);
3184     if(jclazz == nullptr) {
3185       // exception occurred accessing class
3186       return nullptr;
3187     }
3188 
3189     static jmethodID mid = env->GetMethodID(jclazz, "markNoop", "(Z)V");
3190     assert(mid != nullptr);
3191     return mid;
3192   }
3193 
3194   /**
3195    * Get the Java Method: WriteBatch.Handler#markRollback
3196    *
3197    * @param env A pointer to the Java environment
3198    *
3199    * @return The Java Method ID or nullptr if the class or method id could not
3200    *     be retieved
3201    */
3202   static jmethodID getMarkRollbackMethodId(JNIEnv* env) {
3203     jclass jclazz = getJClass(env);
3204     if(jclazz == nullptr) {
3205       // exception occurred accessing class
3206       return nullptr;
3207     }
3208 
3209     static jmethodID mid = env->GetMethodID(jclazz, "markRollback", "([B)V");
3210     assert(mid != nullptr);
3211     return mid;
3212   }
3213 
3214   /**
3215    * Get the Java Method: WriteBatch.Handler#markCommit
3216    *
3217    * @param env A pointer to the Java environment
3218    *
3219    * @return The Java Method ID or nullptr if the class or method id could not
3220    *     be retieved
3221    */
3222   static jmethodID getMarkCommitMethodId(JNIEnv* env) {
3223     jclass jclazz = getJClass(env);
3224     if(jclazz == nullptr) {
3225       // exception occurred accessing class
3226       return nullptr;
3227     }
3228 
3229     static jmethodID mid = env->GetMethodID(jclazz, "markCommit", "([B)V");
3230     assert(mid != nullptr);
3231     return mid;
3232   }
3233 
3234   /**
3235    * Get the Java Method: WriteBatch.Handler#shouldContinue
3236    *
3237    * @param env A pointer to the Java environment
3238    *
3239    * @return The Java Method ID or nullptr if the class or method id could not
3240    *     be retieved
3241    */
3242   static jmethodID getContinueMethodId(JNIEnv* env) {
3243     jclass jclazz = getJClass(env);
3244     if(jclazz == nullptr) {
3245       // exception occurred accessing class
3246       return nullptr;
3247     }
3248 
3249     static jmethodID mid = env->GetMethodID(jclazz, "shouldContinue", "()Z");
3250     assert(mid != nullptr);
3251     return mid;
3252   }
3253 };
3254 
3255 class WriteBatchSavePointJni : public JavaClass {
3256  public:
3257   /**
3258    * Get the Java Class org.rocksdb.WriteBatch.SavePoint
3259    *
3260    * @param env A pointer to the Java environment
3261    *
3262    * @return The Java Class or nullptr if one of the
3263    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3264    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3265    */
3266   static jclass getJClass(JNIEnv* env) {
3267     return JavaClass::getJClass(env, "org/rocksdb/WriteBatch$SavePoint");
3268   }
3269 
3270   /**
3271    * Get the Java Method: HistogramData constructor
3272    *
3273    * @param env A pointer to the Java environment
3274    *
3275    * @return The Java Method ID or nullptr if the class or method id could not
3276    *     be retieved
3277    */
3278   static jmethodID getConstructorMethodId(JNIEnv* env) {
3279     jclass jclazz = getJClass(env);
3280     if(jclazz == nullptr) {
3281       // exception occurred accessing class
3282       return nullptr;
3283     }
3284 
3285     static jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJJ)V");
3286     assert(mid != nullptr);
3287     return mid;
3288   }
3289 
3290   /**
3291    * Create a new Java org.rocksdb.WriteBatch.SavePoint object
3292    *
3293    * @param env A pointer to the Java environment
3294    * @param savePoint A pointer to ROCKSDB_NAMESPACE::WriteBatch::SavePoint
3295    * object
3296    *
3297    * @return A reference to a Java org.rocksdb.WriteBatch.SavePoint object, or
3298    * nullptr if an an exception occurs
3299    */
3300   static jobject construct(JNIEnv* env, const SavePoint &save_point) {
3301     jclass jclazz = getJClass(env);
3302     if(jclazz == nullptr) {
3303       // exception occurred accessing class
3304       return nullptr;
3305     }
3306 
3307     jmethodID mid = getConstructorMethodId(env);
3308     if (mid == nullptr) {
3309       // exception thrown: NoSuchMethodException or OutOfMemoryError
3310       return nullptr;
3311     }
3312 
3313     jobject jsave_point = env->NewObject(jclazz, mid,
3314         static_cast<jlong>(save_point.size),
3315         static_cast<jlong>(save_point.count),
3316         static_cast<jlong>(save_point.content_flags));
3317     if (env->ExceptionCheck()) {
3318       return nullptr;
3319     }
3320 
3321     return jsave_point;
3322   }
3323 };
3324 
3325 // The portal class for org.rocksdb.WriteBatchWithIndex
3326 class WriteBatchWithIndexJni
3327     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::WriteBatchWithIndex*,
3328                                 WriteBatchWithIndexJni> {
3329  public:
3330   /**
3331    * Get the Java Class org.rocksdb.WriteBatchWithIndex
3332    *
3333    * @param env A pointer to the Java environment
3334    *
3335    * @return The Java Class or nullptr if one of the
3336    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3337    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3338    */
3339   static jclass getJClass(JNIEnv* env) {
3340     return RocksDBNativeClass::getJClass(env,
3341         "org/rocksdb/WriteBatchWithIndex");
3342   }
3343 };
3344 
3345 // The portal class for org.rocksdb.HistogramData
3346 class HistogramDataJni : public JavaClass {
3347  public:
3348   /**
3349    * Get the Java Class org.rocksdb.HistogramData
3350    *
3351    * @param env A pointer to the Java environment
3352    *
3353    * @return The Java Class or nullptr if one of the
3354    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3355    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3356    */
3357   static jclass getJClass(JNIEnv* env) {
3358     return JavaClass::getJClass(env, "org/rocksdb/HistogramData");
3359   }
3360 
3361   /**
3362    * Get the Java Method: HistogramData constructor
3363    *
3364    * @param env A pointer to the Java environment
3365    *
3366    * @return The Java Method ID or nullptr if the class or method id could not
3367    *     be retieved
3368    */
3369   static jmethodID getConstructorMethodId(JNIEnv* env) {
3370     jclass jclazz = getJClass(env);
3371     if(jclazz == nullptr) {
3372       // exception occurred accessing class
3373       return nullptr;
3374     }
3375 
3376     static jmethodID mid = env->GetMethodID(jclazz, "<init>", "(DDDDDDJJD)V");
3377     assert(mid != nullptr);
3378     return mid;
3379   }
3380 };
3381 
3382 // The portal class for org.rocksdb.BackupableDBOptions
3383 class BackupableDBOptionsJni
3384     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::BackupableDBOptions*,
3385                                 BackupableDBOptionsJni> {
3386  public:
3387   /**
3388    * Get the Java Class org.rocksdb.BackupableDBOptions
3389    *
3390    * @param env A pointer to the Java environment
3391    *
3392    * @return The Java Class or nullptr if one of the
3393    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3394    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3395    */
3396   static jclass getJClass(JNIEnv* env) {
3397     return RocksDBNativeClass::getJClass(env,
3398         "org/rocksdb/BackupableDBOptions");
3399   }
3400 };
3401 
3402 // The portal class for org.rocksdb.BackupEngine
3403 class BackupEngineJni
3404     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::BackupEngine*,
3405                                 BackupEngineJni> {
3406  public:
3407   /**
3408    * Get the Java Class org.rocksdb.BackupableEngine
3409    *
3410    * @param env A pointer to the Java environment
3411    *
3412    * @return The Java Class or nullptr if one of the
3413    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3414    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3415    */
3416   static jclass getJClass(JNIEnv* env) {
3417     return RocksDBNativeClass::getJClass(env, "org/rocksdb/BackupEngine");
3418   }
3419 };
3420 
3421 // The portal class for org.rocksdb.RocksIterator
3422 class IteratorJni
3423     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::Iterator*, IteratorJni> {
3424  public:
3425   /**
3426    * Get the Java Class org.rocksdb.RocksIterator
3427    *
3428    * @param env A pointer to the Java environment
3429    *
3430    * @return The Java Class or nullptr if one of the
3431    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3432    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3433    */
3434   static jclass getJClass(JNIEnv* env) {
3435     return RocksDBNativeClass::getJClass(env, "org/rocksdb/RocksIterator");
3436   }
3437 };
3438 
3439 // The portal class for org.rocksdb.Filter
3440 class FilterJni
3441     : public RocksDBNativeClass<
3442           std::shared_ptr<ROCKSDB_NAMESPACE::FilterPolicy>*, FilterJni> {
3443  public:
3444   /**
3445    * Get the Java Class org.rocksdb.Filter
3446    *
3447    * @param env A pointer to the Java environment
3448    *
3449    * @return The Java Class or nullptr if one of the
3450    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3451    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3452    */
3453   static jclass getJClass(JNIEnv* env) {
3454     return RocksDBNativeClass::getJClass(env, "org/rocksdb/Filter");
3455   }
3456 };
3457 
3458 // The portal class for org.rocksdb.ColumnFamilyHandle
3459 class ColumnFamilyHandleJni
3460     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::ColumnFamilyHandle*,
3461                                 ColumnFamilyHandleJni> {
3462  public:
3463   /**
3464    * Get the Java Class org.rocksdb.ColumnFamilyHandle
3465    *
3466    * @param env A pointer to the Java environment
3467    *
3468    * @return The Java Class or nullptr if one of the
3469    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3470    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3471    */
3472   static jclass getJClass(JNIEnv* env) {
3473     return RocksDBNativeClass::getJClass(env,
3474         "org/rocksdb/ColumnFamilyHandle");
3475   }
3476 };
3477 
3478 // The portal class for org.rocksdb.FlushOptions
3479 class FlushOptionsJni
3480     : public RocksDBNativeClass<ROCKSDB_NAMESPACE::FlushOptions*,
3481                                 FlushOptionsJni> {
3482  public:
3483   /**
3484    * Get the Java Class org.rocksdb.FlushOptions
3485    *
3486    * @param env A pointer to the Java environment
3487    *
3488    * @return The Java Class or nullptr if one of the
3489    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3490    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3491    */
3492   static jclass getJClass(JNIEnv* env) {
3493     return RocksDBNativeClass::getJClass(env, "org/rocksdb/FlushOptions");
3494   }
3495 };
3496 
3497 // The portal class for org.rocksdb.ComparatorOptions
3498 class ComparatorOptionsJni
3499     : public RocksDBNativeClass<
3500           ROCKSDB_NAMESPACE::ComparatorJniCallbackOptions*,
3501           ComparatorOptionsJni> {
3502  public:
3503   /**
3504    * Get the Java Class org.rocksdb.ComparatorOptions
3505    *
3506    * @param env A pointer to the Java environment
3507    *
3508    * @return The Java Class or nullptr if one of the
3509    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3510    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3511    */
3512   static jclass getJClass(JNIEnv* env) {
3513     return RocksDBNativeClass::getJClass(env, "org/rocksdb/ComparatorOptions");
3514   }
3515 };
3516 
3517 // The portal class for org.rocksdb.AbstractCompactionFilterFactory
3518 class AbstractCompactionFilterFactoryJni
3519     : public RocksDBNativeClass<
3520           const ROCKSDB_NAMESPACE::CompactionFilterFactoryJniCallback*,
3521           AbstractCompactionFilterFactoryJni> {
3522  public:
3523   /**
3524    * Get the Java Class org.rocksdb.AbstractCompactionFilterFactory
3525    *
3526    * @param env A pointer to the Java environment
3527    *
3528    * @return The Java Class or nullptr if one of the
3529    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3530    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3531    */
3532   static jclass getJClass(JNIEnv* env) {
3533     return RocksDBNativeClass::getJClass(env,
3534         "org/rocksdb/AbstractCompactionFilterFactory");
3535   }
3536 
3537   /**
3538    * Get the Java Method: AbstractCompactionFilterFactory#name
3539    *
3540    * @param env A pointer to the Java environment
3541    *
3542    * @return The Java Method ID or nullptr if the class or method id could not
3543    *     be retieved
3544    */
3545   static jmethodID getNameMethodId(JNIEnv* env) {
3546     jclass jclazz = getJClass(env);
3547     if(jclazz == nullptr) {
3548       // exception occurred accessing class
3549       return nullptr;
3550     }
3551 
3552     static jmethodID mid = env->GetMethodID(
3553         jclazz, "name", "()Ljava/lang/String;");
3554     assert(mid != nullptr);
3555     return mid;
3556   }
3557 
3558   /**
3559    * Get the Java Method: AbstractCompactionFilterFactory#createCompactionFilter
3560    *
3561    * @param env A pointer to the Java environment
3562    *
3563    * @return The Java Method ID or nullptr if the class or method id could not
3564    *     be retieved
3565    */
3566   static jmethodID getCreateCompactionFilterMethodId(JNIEnv* env) {
3567     jclass jclazz = getJClass(env);
3568     if(jclazz == nullptr) {
3569       // exception occurred accessing class
3570       return nullptr;
3571     }
3572 
3573     static jmethodID mid = env->GetMethodID(jclazz,
3574       "createCompactionFilter",
3575       "(ZZ)J");
3576     assert(mid != nullptr);
3577     return mid;
3578   }
3579 };
3580 
3581 // The portal class for org.rocksdb.AbstractTransactionNotifier
3582 class AbstractTransactionNotifierJni
3583     : public RocksDBNativeClass<
3584           const ROCKSDB_NAMESPACE::TransactionNotifierJniCallback*,
3585           AbstractTransactionNotifierJni> {
3586  public:
3587   static jclass getJClass(JNIEnv* env) {
3588     return RocksDBNativeClass::getJClass(env,
3589         "org/rocksdb/AbstractTransactionNotifier");
3590   }
3591 
3592   // Get the java method `snapshotCreated`
3593   // of org.rocksdb.AbstractTransactionNotifier.
3594   static jmethodID getSnapshotCreatedMethodId(JNIEnv* env) {
3595     jclass jclazz = getJClass(env);
3596     if(jclazz == nullptr) {
3597       // exception occurred accessing class
3598       return nullptr;
3599     }
3600 
3601     static jmethodID mid = env->GetMethodID(jclazz, "snapshotCreated", "(J)V");
3602     assert(mid != nullptr);
3603     return mid;
3604   }
3605 };
3606 
3607 // The portal class for org.rocksdb.AbstractComparatorJniBridge
3608 class AbstractComparatorJniBridge : public JavaClass {
3609  public:
3610   /**
3611    * Get the Java Class org.rocksdb.AbstractComparatorJniBridge
3612    *
3613    * @param env A pointer to the Java environment
3614    *
3615    * @return The Java Class or nullptr if one of the
3616    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3617    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3618    */
3619   static jclass getJClass(JNIEnv* env) {
3620     return JavaClass::getJClass(env,
3621         "org/rocksdb/AbstractComparatorJniBridge");
3622   }
3623 
3624   /**
3625    * Get the Java Method: Comparator#compareInternal
3626    *
3627    * @param env A pointer to the Java environment
3628    * @param jclazz the AbstractComparatorJniBridge class
3629    *
3630    * @return The Java Method ID or nullptr if the class or method id could not
3631    *     be retieved
3632    */
3633   static jmethodID getCompareInternalMethodId(JNIEnv* env, jclass jclazz) {
3634     static jmethodID mid =
3635         env->GetStaticMethodID(jclazz, "compareInternal",
3636             "(Lorg/rocksdb/AbstractComparator;Ljava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I");
3637     assert(mid != nullptr);
3638     return mid;
3639   }
3640 
3641   /**
3642    * Get the Java Method: Comparator#findShortestSeparatorInternal
3643    *
3644    * @param env A pointer to the Java environment
3645    * @param jclazz the AbstractComparatorJniBridge class
3646    *
3647    * @return The Java Method ID or nullptr if the class or method id could not
3648    *     be retieved
3649    */
3650   static jmethodID getFindShortestSeparatorInternalMethodId(JNIEnv* env, jclass jclazz) {
3651     static jmethodID mid =
3652         env->GetStaticMethodID(jclazz, "findShortestSeparatorInternal",
3653             "(Lorg/rocksdb/AbstractComparator;Ljava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I");
3654     assert(mid != nullptr);
3655     return mid;
3656   }
3657 
3658   /**
3659    * Get the Java Method: Comparator#findShortSuccessorInternal
3660    *
3661    * @param env A pointer to the Java environment
3662    * @param jclazz the AbstractComparatorJniBridge class
3663    *
3664    * @return The Java Method ID or nullptr if the class or method id could not
3665    *     be retieved
3666    */
3667   static jmethodID getFindShortSuccessorInternalMethodId(JNIEnv* env, jclass jclazz) {
3668     static jmethodID mid =
3669         env->GetStaticMethodID(jclazz, "findShortSuccessorInternal",
3670             "(Lorg/rocksdb/AbstractComparator;Ljava/nio/ByteBuffer;I)I");
3671     assert(mid != nullptr);
3672     return mid;
3673   }
3674 };
3675 
3676 // The portal class for org.rocksdb.AbstractComparator
3677 class AbstractComparatorJni
3678     : public RocksDBNativeClass<const ROCKSDB_NAMESPACE::ComparatorJniCallback*,
3679                                 AbstractComparatorJni> {
3680  public:
3681   /**
3682    * Get the Java Class org.rocksdb.AbstractComparator
3683    *
3684    * @param env A pointer to the Java environment
3685    *
3686    * @return The Java Class or nullptr if one of the
3687    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3688    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3689    */
3690   static jclass getJClass(JNIEnv* env) {
3691     return RocksDBNativeClass::getJClass(env,
3692         "org/rocksdb/AbstractComparator");
3693   }
3694 
3695   /**
3696    * Get the Java Method: Comparator#name
3697    *
3698    * @param env A pointer to the Java environment
3699    *
3700    * @return The Java Method ID or nullptr if the class or method id could not
3701    *     be retieved
3702    */
3703   static jmethodID getNameMethodId(JNIEnv* env) {
3704     jclass jclazz = getJClass(env);
3705     if(jclazz == nullptr) {
3706       // exception occurred accessing class
3707       return nullptr;
3708     }
3709 
3710     static jmethodID mid =
3711         env->GetMethodID(jclazz, "name", "()Ljava/lang/String;");
3712     assert(mid != nullptr);
3713     return mid;
3714   }
3715 };
3716 
3717 // The portal class for org.rocksdb.AbstractSlice
3718 class AbstractSliceJni
3719     : public NativeRocksMutableObject<const ROCKSDB_NAMESPACE::Slice*,
3720                                       AbstractSliceJni> {
3721  public:
3722   /**
3723    * Get the Java Class org.rocksdb.AbstractSlice
3724    *
3725    * @param env A pointer to the Java environment
3726    *
3727    * @return The Java Class or nullptr if one of the
3728    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3729    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3730    */
3731   static jclass getJClass(JNIEnv* env) {
3732     return RocksDBNativeClass::getJClass(env, "org/rocksdb/AbstractSlice");
3733   }
3734 };
3735 
3736 // The portal class for org.rocksdb.Slice
3737 class SliceJni
3738     : public NativeRocksMutableObject<const ROCKSDB_NAMESPACE::Slice*,
3739                                       AbstractSliceJni> {
3740  public:
3741   /**
3742    * Get the Java Class org.rocksdb.Slice
3743    *
3744    * @param env A pointer to the Java environment
3745    *
3746    * @return The Java Class or nullptr if one of the
3747    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3748    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3749    */
3750   static jclass getJClass(JNIEnv* env) {
3751     return RocksDBNativeClass::getJClass(env, "org/rocksdb/Slice");
3752   }
3753 
3754   /**
3755    * Constructs a Slice object
3756    *
3757    * @param env A pointer to the Java environment
3758    *
3759    * @return A reference to a Java Slice object, or a nullptr if an
3760    *     exception occurs
3761    */
3762   static jobject construct0(JNIEnv* env) {
3763     jclass jclazz = getJClass(env);
3764     if(jclazz == nullptr) {
3765       // exception occurred accessing class
3766       return nullptr;
3767     }
3768 
3769     static jmethodID mid = env->GetMethodID(jclazz, "<init>", "()V");
3770     if(mid == nullptr) {
3771       // exception occurred accessing method
3772       return nullptr;
3773     }
3774 
3775     jobject jslice = env->NewObject(jclazz, mid);
3776     if(env->ExceptionCheck()) {
3777       return nullptr;
3778     }
3779 
3780     return jslice;
3781   }
3782 };
3783 
3784 // The portal class for org.rocksdb.DirectSlice
3785 class DirectSliceJni
3786     : public NativeRocksMutableObject<const ROCKSDB_NAMESPACE::Slice*,
3787                                       AbstractSliceJni> {
3788  public:
3789   /**
3790    * Get the Java Class org.rocksdb.DirectSlice
3791    *
3792    * @param env A pointer to the Java environment
3793    *
3794    * @return The Java Class or nullptr if one of the
3795    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3796    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3797    */
3798   static jclass getJClass(JNIEnv* env) {
3799     return RocksDBNativeClass::getJClass(env, "org/rocksdb/DirectSlice");
3800   }
3801 
3802   /**
3803    * Constructs a DirectSlice object
3804    *
3805    * @param env A pointer to the Java environment
3806    *
3807    * @return A reference to a Java DirectSlice object, or a nullptr if an
3808    *     exception occurs
3809    */
3810   static jobject construct0(JNIEnv* env) {
3811     jclass jclazz = getJClass(env);
3812     if(jclazz == nullptr) {
3813       // exception occurred accessing class
3814       return nullptr;
3815     }
3816 
3817     static jmethodID mid = env->GetMethodID(jclazz, "<init>", "()V");
3818     if(mid == nullptr) {
3819       // exception occurred accessing method
3820       return nullptr;
3821     }
3822 
3823     jobject jdirect_slice = env->NewObject(jclazz, mid);
3824     if(env->ExceptionCheck()) {
3825       return nullptr;
3826     }
3827 
3828     return jdirect_slice;
3829   }
3830 };
3831 
3832 // The portal class for org.rocksdb.BackupInfo
3833 class BackupInfoJni : public JavaClass {
3834  public:
3835   /**
3836    * Get the Java Class org.rocksdb.BackupInfo
3837    *
3838    * @param env A pointer to the Java environment
3839    *
3840    * @return The Java Class or nullptr if one of the
3841    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3842    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3843    */
3844   static jclass getJClass(JNIEnv* env) {
3845     return JavaClass::getJClass(env, "org/rocksdb/BackupInfo");
3846   }
3847 
3848   /**
3849    * Constructs a BackupInfo object
3850    *
3851    * @param env A pointer to the Java environment
3852    * @param backup_id id of the backup
3853    * @param timestamp timestamp of the backup
3854    * @param size size of the backup
3855    * @param number_files number of files related to the backup
3856    * @param app_metadata application specific metadata
3857    *
3858    * @return A reference to a Java BackupInfo object, or a nullptr if an
3859    *     exception occurs
3860    */
3861   static jobject construct0(JNIEnv* env, uint32_t backup_id, int64_t timestamp,
3862                             uint64_t size, uint32_t number_files,
3863                             const std::string& app_metadata) {
3864     jclass jclazz = getJClass(env);
3865     if(jclazz == nullptr) {
3866       // exception occurred accessing class
3867       return nullptr;
3868     }
3869 
3870     static jmethodID mid =
3871         env->GetMethodID(jclazz, "<init>", "(IJJILjava/lang/String;)V");
3872     if(mid == nullptr) {
3873       // exception occurred accessing method
3874       return nullptr;
3875     }
3876 
3877     jstring japp_metadata = nullptr;
3878     if (app_metadata != nullptr) {
3879       japp_metadata = env->NewStringUTF(app_metadata.c_str());
3880       if (japp_metadata == nullptr) {
3881         // exception occurred creating java string
3882         return nullptr;
3883       }
3884     }
3885 
3886     jobject jbackup_info = env->NewObject(jclazz, mid, backup_id, timestamp,
3887                                           size, number_files, japp_metadata);
3888     if(env->ExceptionCheck()) {
3889       env->DeleteLocalRef(japp_metadata);
3890       return nullptr;
3891     }
3892 
3893     return jbackup_info;
3894   }
3895 };
3896 
3897 class BackupInfoListJni {
3898  public:
3899   /**
3900    * Converts a C++ std::vector<BackupInfo> object to
3901    * a Java ArrayList<org.rocksdb.BackupInfo> object
3902    *
3903    * @param env A pointer to the Java environment
3904    * @param backup_infos A vector of BackupInfo
3905    *
3906    * @return Either a reference to a Java ArrayList object, or a nullptr
3907    *     if an exception occurs
3908    */
3909   static jobject getBackupInfo(JNIEnv* env,
3910       std::vector<BackupInfo> backup_infos) {
3911     jclass jarray_list_clazz =
3912         ROCKSDB_NAMESPACE::ListJni::getArrayListClass(env);
3913     if(jarray_list_clazz == nullptr) {
3914       // exception occurred accessing class
3915       return nullptr;
3916     }
3917 
3918     jmethodID cstr_mid =
3919         ROCKSDB_NAMESPACE::ListJni::getArrayListConstructorMethodId(env);
3920     if(cstr_mid == nullptr) {
3921       // exception occurred accessing method
3922       return nullptr;
3923     }
3924 
3925     jmethodID add_mid = ROCKSDB_NAMESPACE::ListJni::getListAddMethodId(env);
3926     if(add_mid == nullptr) {
3927       // exception occurred accessing method
3928       return nullptr;
3929     }
3930 
3931     // create java list
3932     jobject jbackup_info_handle_list =
3933         env->NewObject(jarray_list_clazz, cstr_mid, backup_infos.size());
3934     if(env->ExceptionCheck()) {
3935       // exception occurred constructing object
3936       return nullptr;
3937     }
3938 
3939     // insert in java list
3940     auto end = backup_infos.end();
3941     for (auto it = backup_infos.begin(); it != end; ++it) {
3942       auto backup_info = *it;
3943 
3944       jobject obj = ROCKSDB_NAMESPACE::BackupInfoJni::construct0(
3945           env, backup_info.backup_id, backup_info.timestamp, backup_info.size,
3946           backup_info.number_files, backup_info.app_metadata);
3947       if(env->ExceptionCheck()) {
3948         // exception occurred constructing object
3949         if(obj != nullptr) {
3950           env->DeleteLocalRef(obj);
3951         }
3952         if(jbackup_info_handle_list != nullptr) {
3953           env->DeleteLocalRef(jbackup_info_handle_list);
3954         }
3955         return nullptr;
3956       }
3957 
3958       jboolean rs =
3959           env->CallBooleanMethod(jbackup_info_handle_list, add_mid, obj);
3960       if(env->ExceptionCheck() || rs == JNI_FALSE) {
3961         // exception occurred calling method, or could not add
3962         if(obj != nullptr) {
3963           env->DeleteLocalRef(obj);
3964         }
3965         if(jbackup_info_handle_list != nullptr) {
3966           env->DeleteLocalRef(jbackup_info_handle_list);
3967         }
3968         return nullptr;
3969       }
3970     }
3971 
3972     return jbackup_info_handle_list;
3973   }
3974 };
3975 
3976 // The portal class for org.rocksdb.WBWIRocksIterator
3977 class WBWIRocksIteratorJni : public JavaClass {
3978  public:
3979   /**
3980    * Get the Java Class org.rocksdb.WBWIRocksIterator
3981    *
3982    * @param env A pointer to the Java environment
3983    *
3984    * @return The Java Class or nullptr if one of the
3985    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
3986    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
3987    */
3988   static jclass getJClass(JNIEnv* env) {
3989     return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator");
3990   }
3991 
3992   /**
3993    * Get the Java Field: WBWIRocksIterator#entry
3994    *
3995    * @param env A pointer to the Java environment
3996    *
3997    * @return The Java Field ID or nullptr if the class or field id could not
3998    *     be retieved
3999    */
4000   static jfieldID getWriteEntryField(JNIEnv* env) {
4001     jclass jclazz = getJClass(env);
4002     if(jclazz == nullptr) {
4003       // exception occurred accessing class
4004       return nullptr;
4005     }
4006 
4007     static jfieldID fid =
4008         env->GetFieldID(jclazz, "entry",
4009             "Lorg/rocksdb/WBWIRocksIterator$WriteEntry;");
4010     assert(fid != nullptr);
4011     return fid;
4012   }
4013 
4014   /**
4015    * Gets the value of the WBWIRocksIterator#entry
4016    *
4017    * @param env A pointer to the Java environment
4018    * @param jwbwi_rocks_iterator A reference to a WBWIIterator
4019    *
4020    * @return A reference to a Java WBWIRocksIterator.WriteEntry object, or
4021    *     a nullptr if an exception occurs
4022    */
4023   static jobject getWriteEntry(JNIEnv* env, jobject jwbwi_rocks_iterator) {
4024     assert(jwbwi_rocks_iterator != nullptr);
4025 
4026     jfieldID jwrite_entry_field = getWriteEntryField(env);
4027     if(jwrite_entry_field == nullptr) {
4028       // exception occurred accessing the field
4029       return nullptr;
4030     }
4031 
4032     jobject jwe = env->GetObjectField(jwbwi_rocks_iterator, jwrite_entry_field);
4033     assert(jwe != nullptr);
4034     return jwe;
4035   }
4036 };
4037 
4038 // The portal class for org.rocksdb.WBWIRocksIterator.WriteType
4039 class WriteTypeJni : public JavaClass {
4040  public:
4041   /**
4042    * Get the PUT enum field value of WBWIRocksIterator.WriteType
4043    *
4044    * @param env A pointer to the Java environment
4045    *
4046    * @return A reference to the enum field value or a nullptr if
4047    *     the enum field value could not be retrieved
4048    */
4049   static jobject PUT(JNIEnv* env) {
4050     return getEnum(env, "PUT");
4051   }
4052 
4053   /**
4054    * Get the MERGE enum field value of WBWIRocksIterator.WriteType
4055    *
4056    * @param env A pointer to the Java environment
4057    *
4058    * @return A reference to the enum field value or a nullptr if
4059    *     the enum field value could not be retrieved
4060    */
4061   static jobject MERGE(JNIEnv* env) {
4062     return getEnum(env, "MERGE");
4063   }
4064 
4065   /**
4066    * Get the DELETE enum field value of WBWIRocksIterator.WriteType
4067    *
4068    * @param env A pointer to the Java environment
4069    *
4070    * @return A reference to the enum field value or a nullptr if
4071    *     the enum field value could not be retrieved
4072    */
4073   static jobject DELETE(JNIEnv* env) {
4074     return getEnum(env, "DELETE");
4075   }
4076 
4077   /**
4078    * Get the LOG enum field value of WBWIRocksIterator.WriteType
4079    *
4080    * @param env A pointer to the Java environment
4081    *
4082    * @return A reference to the enum field value or a nullptr if
4083    *     the enum field value could not be retrieved
4084    */
4085   static jobject LOG(JNIEnv* env) {
4086     return getEnum(env, "LOG");
4087   }
4088 
4089   // Returns the equivalent org.rocksdb.WBWIRocksIterator.WriteType for the
4090   // provided C++ ROCKSDB_NAMESPACE::WriteType enum
4091   static jbyte toJavaWriteType(const ROCKSDB_NAMESPACE::WriteType& writeType) {
4092     switch (writeType) {
4093       case ROCKSDB_NAMESPACE::WriteType::kPutRecord:
4094         return 0x0;
4095       case ROCKSDB_NAMESPACE::WriteType::kMergeRecord:
4096         return 0x1;
4097       case ROCKSDB_NAMESPACE::WriteType::kDeleteRecord:
4098         return 0x2;
4099       case ROCKSDB_NAMESPACE::WriteType::kSingleDeleteRecord:
4100         return 0x3;
4101       case ROCKSDB_NAMESPACE::WriteType::kDeleteRangeRecord:
4102         return 0x4;
4103       case ROCKSDB_NAMESPACE::WriteType::kLogDataRecord:
4104         return 0x5;
4105       case ROCKSDB_NAMESPACE::WriteType::kXIDRecord:
4106         return 0x6;
4107       default:
4108         return 0x7F;  // undefined
4109     }
4110   }
4111 
4112  private:
4113   /**
4114    * Get the Java Class org.rocksdb.WBWIRocksIterator.WriteType
4115    *
4116    * @param env A pointer to the Java environment
4117    *
4118    * @return The Java Class or nullptr if one of the
4119    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
4120    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
4121    */
4122   static jclass getJClass(JNIEnv* env) {
4123     return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator$WriteType");
4124   }
4125 
4126   /**
4127    * Get an enum field of org.rocksdb.WBWIRocksIterator.WriteType
4128    *
4129    * @param env A pointer to the Java environment
4130    * @param name The name of the enum field
4131    *
4132    * @return A reference to the enum field value or a nullptr if
4133    *     the enum field value could not be retrieved
4134    */
4135   static jobject getEnum(JNIEnv* env, const char name[]) {
4136     jclass jclazz = getJClass(env);
4137     if(jclazz == nullptr) {
4138       // exception occurred accessing class
4139       return nullptr;
4140     }
4141 
4142     jfieldID jfid =
4143         env->GetStaticFieldID(jclazz, name,
4144             "Lorg/rocksdb/WBWIRocksIterator$WriteType;");
4145     if(env->ExceptionCheck()) {
4146       // exception occurred while getting field
4147       return nullptr;
4148     } else if(jfid == nullptr) {
4149       return nullptr;
4150     }
4151 
4152     jobject jwrite_type = env->GetStaticObjectField(jclazz, jfid);
4153     assert(jwrite_type != nullptr);
4154     return jwrite_type;
4155   }
4156 };
4157 
4158 // The portal class for org.rocksdb.WBWIRocksIterator.WriteEntry
4159 class WriteEntryJni : public JavaClass {
4160  public:
4161   /**
4162    * Get the Java Class org.rocksdb.WBWIRocksIterator.WriteEntry
4163    *
4164    * @param env A pointer to the Java environment
4165    *
4166    * @return The Java Class or nullptr if one of the
4167    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
4168    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
4169    */
4170     static jclass getJClass(JNIEnv* env) {
4171       return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator$WriteEntry");
4172     }
4173 };
4174 
4175 // The portal class for org.rocksdb.InfoLogLevel
4176 class InfoLogLevelJni : public JavaClass {
4177  public:
4178     /**
4179      * Get the DEBUG_LEVEL enum field value of InfoLogLevel
4180      *
4181      * @param env A pointer to the Java environment
4182      *
4183      * @return A reference to the enum field value or a nullptr if
4184      *     the enum field value could not be retrieved
4185      */
4186     static jobject DEBUG_LEVEL(JNIEnv* env) {
4187       return getEnum(env, "DEBUG_LEVEL");
4188     }
4189 
4190     /**
4191      * Get the INFO_LEVEL enum field value of InfoLogLevel
4192      *
4193      * @param env A pointer to the Java environment
4194      *
4195      * @return A reference to the enum field value or a nullptr if
4196      *     the enum field value could not be retrieved
4197      */
4198     static jobject INFO_LEVEL(JNIEnv* env) {
4199       return getEnum(env, "INFO_LEVEL");
4200     }
4201 
4202     /**
4203      * Get the WARN_LEVEL enum field value of InfoLogLevel
4204      *
4205      * @param env A pointer to the Java environment
4206      *
4207      * @return A reference to the enum field value or a nullptr if
4208      *     the enum field value could not be retrieved
4209      */
4210     static jobject WARN_LEVEL(JNIEnv* env) {
4211       return getEnum(env, "WARN_LEVEL");
4212     }
4213 
4214     /**
4215      * Get the ERROR_LEVEL enum field value of InfoLogLevel
4216      *
4217      * @param env A pointer to the Java environment
4218      *
4219      * @return A reference to the enum field value or a nullptr if
4220      *     the enum field value could not be retrieved
4221      */
4222     static jobject ERROR_LEVEL(JNIEnv* env) {
4223       return getEnum(env, "ERROR_LEVEL");
4224     }
4225 
4226     /**
4227      * Get the FATAL_LEVEL enum field value of InfoLogLevel
4228      *
4229      * @param env A pointer to the Java environment
4230      *
4231      * @return A reference to the enum field value or a nullptr if
4232      *     the enum field value could not be retrieved
4233      */
4234     static jobject FATAL_LEVEL(JNIEnv* env) {
4235       return getEnum(env, "FATAL_LEVEL");
4236     }
4237 
4238     /**
4239      * Get the HEADER_LEVEL enum field value of InfoLogLevel
4240      *
4241      * @param env A pointer to the Java environment
4242      *
4243      * @return A reference to the enum field value or a nullptr if
4244      *     the enum field value could not be retrieved
4245      */
4246     static jobject HEADER_LEVEL(JNIEnv* env) {
4247       return getEnum(env, "HEADER_LEVEL");
4248     }
4249 
4250  private:
4251   /**
4252    * Get the Java Class org.rocksdb.InfoLogLevel
4253    *
4254    * @param env A pointer to the Java environment
4255    *
4256    * @return The Java Class or nullptr if one of the
4257    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
4258    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
4259    */
4260   static jclass getJClass(JNIEnv* env) {
4261     return JavaClass::getJClass(env, "org/rocksdb/InfoLogLevel");
4262   }
4263 
4264   /**
4265    * Get an enum field of org.rocksdb.InfoLogLevel
4266    *
4267    * @param env A pointer to the Java environment
4268    * @param name The name of the enum field
4269    *
4270    * @return A reference to the enum field value or a nullptr if
4271    *     the enum field value could not be retrieved
4272    */
4273   static jobject getEnum(JNIEnv* env, const char name[]) {
4274     jclass jclazz = getJClass(env);
4275     if(jclazz == nullptr) {
4276       // exception occurred accessing class
4277       return nullptr;
4278     }
4279 
4280     jfieldID jfid =
4281         env->GetStaticFieldID(jclazz, name, "Lorg/rocksdb/InfoLogLevel;");
4282     if(env->ExceptionCheck()) {
4283       // exception occurred while getting field
4284       return nullptr;
4285     } else if(jfid == nullptr) {
4286       return nullptr;
4287     }
4288 
4289     jobject jinfo_log_level = env->GetStaticObjectField(jclazz, jfid);
4290     assert(jinfo_log_level != nullptr);
4291     return jinfo_log_level;
4292   }
4293 };
4294 
4295 // The portal class for org.rocksdb.Logger
4296 class LoggerJni
4297     : public RocksDBNativeClass<
4298           std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*, LoggerJni> {
4299  public:
4300   /**
4301    * Get the Java Class org/rocksdb/Logger
4302    *
4303    * @param env A pointer to the Java environment
4304    *
4305    * @return The Java Class or nullptr if one of the
4306    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
4307    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
4308    */
4309   static jclass getJClass(JNIEnv* env) {
4310     return RocksDBNativeClass::getJClass(env, "org/rocksdb/Logger");
4311   }
4312 
4313   /**
4314    * Get the Java Method: Logger#log
4315    *
4316    * @param env A pointer to the Java environment
4317    *
4318    * @return The Java Method ID or nullptr if the class or method id could not
4319    *     be retieved
4320    */
4321   static jmethodID getLogMethodId(JNIEnv* env) {
4322     jclass jclazz = getJClass(env);
4323     if(jclazz == nullptr) {
4324       // exception occurred accessing class
4325       return nullptr;
4326     }
4327 
4328     static jmethodID mid =
4329         env->GetMethodID(jclazz, "log",
4330             "(Lorg/rocksdb/InfoLogLevel;Ljava/lang/String;)V");
4331     assert(mid != nullptr);
4332     return mid;
4333   }
4334 };
4335 
4336 // The portal class for org.rocksdb.TransactionLogIterator.BatchResult
4337 class BatchResultJni : public JavaClass {
4338   public:
4339   /**
4340    * Get the Java Class org.rocksdb.TransactionLogIterator.BatchResult
4341    *
4342    * @param env A pointer to the Java environment
4343    *
4344    * @return The Java Class or nullptr if one of the
4345    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
4346    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
4347    */
4348   static jclass getJClass(JNIEnv* env) {
4349     return JavaClass::getJClass(env,
4350         "org/rocksdb/TransactionLogIterator$BatchResult");
4351   }
4352 
4353   /**
4354    * Create a new Java org.rocksdb.TransactionLogIterator.BatchResult object
4355    * with the same properties as the provided C++ ROCKSDB_NAMESPACE::BatchResult
4356    * object
4357    *
4358    * @param env A pointer to the Java environment
4359    * @param batch_result The ROCKSDB_NAMESPACE::BatchResult object
4360    *
4361    * @return A reference to a Java
4362    *     org.rocksdb.TransactionLogIterator.BatchResult object,
4363    *     or nullptr if an an exception occurs
4364    */
4365   static jobject construct(JNIEnv* env,
4366                            ROCKSDB_NAMESPACE::BatchResult& batch_result) {
4367     jclass jclazz = getJClass(env);
4368     if(jclazz == nullptr) {
4369       // exception occurred accessing class
4370       return nullptr;
4371     }
4372 
4373     jmethodID mid = env->GetMethodID(
4374       jclazz, "<init>", "(JJ)V");
4375     if(mid == nullptr) {
4376       // exception thrown: NoSuchMethodException or OutOfMemoryError
4377       return nullptr;
4378     }
4379 
4380     jobject jbatch_result = env->NewObject(jclazz, mid,
4381       batch_result.sequence, batch_result.writeBatchPtr.get());
4382     if(jbatch_result == nullptr) {
4383       // exception thrown: InstantiationException or OutOfMemoryError
4384       return nullptr;
4385     }
4386 
4387     batch_result.writeBatchPtr.release();
4388     return jbatch_result;
4389   }
4390 };
4391 
4392 // The portal class for org.rocksdb.BottommostLevelCompaction
4393 class BottommostLevelCompactionJni {
4394  public:
4395   // Returns the equivalent org.rocksdb.BottommostLevelCompaction for the
4396   // provided C++ ROCKSDB_NAMESPACE::BottommostLevelCompaction enum
4397   static jint toJavaBottommostLevelCompaction(
4398       const ROCKSDB_NAMESPACE::BottommostLevelCompaction&
4399           bottommost_level_compaction) {
4400     switch(bottommost_level_compaction) {
4401       case ROCKSDB_NAMESPACE::BottommostLevelCompaction::kSkip:
4402         return 0x0;
4403       case ROCKSDB_NAMESPACE::BottommostLevelCompaction::
4404           kIfHaveCompactionFilter:
4405         return 0x1;
4406       case ROCKSDB_NAMESPACE::BottommostLevelCompaction::kForce:
4407         return 0x2;
4408       case ROCKSDB_NAMESPACE::BottommostLevelCompaction::kForceOptimized:
4409         return 0x3;
4410       default:
4411         return 0x7F;  // undefined
4412     }
4413   }
4414 
4415   // Returns the equivalent C++ ROCKSDB_NAMESPACE::BottommostLevelCompaction
4416   // enum for the provided Java org.rocksdb.BottommostLevelCompaction
4417   static ROCKSDB_NAMESPACE::BottommostLevelCompaction
4418   toCppBottommostLevelCompaction(jint bottommost_level_compaction) {
4419     switch(bottommost_level_compaction) {
4420       case 0x0:
4421         return ROCKSDB_NAMESPACE::BottommostLevelCompaction::kSkip;
4422       case 0x1:
4423         return ROCKSDB_NAMESPACE::BottommostLevelCompaction::
4424             kIfHaveCompactionFilter;
4425       case 0x2:
4426         return ROCKSDB_NAMESPACE::BottommostLevelCompaction::kForce;
4427       case 0x3:
4428         return ROCKSDB_NAMESPACE::BottommostLevelCompaction::kForceOptimized;
4429       default:
4430         // undefined/default
4431         return ROCKSDB_NAMESPACE::BottommostLevelCompaction::
4432             kIfHaveCompactionFilter;
4433     }
4434   }
4435 };
4436 
4437 // The portal class for org.rocksdb.CompactionStopStyle
4438 class CompactionStopStyleJni {
4439  public:
4440   // Returns the equivalent org.rocksdb.CompactionStopStyle for the provided
4441   // C++ ROCKSDB_NAMESPACE::CompactionStopStyle enum
4442   static jbyte toJavaCompactionStopStyle(
4443       const ROCKSDB_NAMESPACE::CompactionStopStyle& compaction_stop_style) {
4444     switch(compaction_stop_style) {
4445       case ROCKSDB_NAMESPACE::CompactionStopStyle::
4446           kCompactionStopStyleSimilarSize:
4447         return 0x0;
4448       case ROCKSDB_NAMESPACE::CompactionStopStyle::
4449           kCompactionStopStyleTotalSize:
4450         return 0x1;
4451       default:
4452         return 0x7F;  // undefined
4453     }
4454   }
4455 
4456   // Returns the equivalent C++ ROCKSDB_NAMESPACE::CompactionStopStyle enum for
4457   // the provided Java org.rocksdb.CompactionStopStyle
4458   static ROCKSDB_NAMESPACE::CompactionStopStyle toCppCompactionStopStyle(
4459       jbyte jcompaction_stop_style) {
4460     switch(jcompaction_stop_style) {
4461       case 0x0:
4462         return ROCKSDB_NAMESPACE::CompactionStopStyle::
4463             kCompactionStopStyleSimilarSize;
4464       case 0x1:
4465         return ROCKSDB_NAMESPACE::CompactionStopStyle::
4466             kCompactionStopStyleTotalSize;
4467       default:
4468         // undefined/default
4469         return ROCKSDB_NAMESPACE::CompactionStopStyle::
4470             kCompactionStopStyleSimilarSize;
4471     }
4472   }
4473 };
4474 
4475 // The portal class for org.rocksdb.CompressionType
4476 class CompressionTypeJni {
4477  public:
4478   // Returns the equivalent org.rocksdb.CompressionType for the provided
4479   // C++ ROCKSDB_NAMESPACE::CompressionType enum
4480   static jbyte toJavaCompressionType(
4481       const ROCKSDB_NAMESPACE::CompressionType& compression_type) {
4482     switch(compression_type) {
4483       case ROCKSDB_NAMESPACE::CompressionType::kNoCompression:
4484         return 0x0;
4485       case ROCKSDB_NAMESPACE::CompressionType::kSnappyCompression:
4486         return 0x1;
4487       case ROCKSDB_NAMESPACE::CompressionType::kZlibCompression:
4488         return 0x2;
4489       case ROCKSDB_NAMESPACE::CompressionType::kBZip2Compression:
4490         return 0x3;
4491       case ROCKSDB_NAMESPACE::CompressionType::kLZ4Compression:
4492         return 0x4;
4493       case ROCKSDB_NAMESPACE::CompressionType::kLZ4HCCompression:
4494         return 0x5;
4495       case ROCKSDB_NAMESPACE::CompressionType::kXpressCompression:
4496         return 0x6;
4497       case ROCKSDB_NAMESPACE::CompressionType::kZSTD:
4498         return 0x7;
4499       case ROCKSDB_NAMESPACE::CompressionType::kDisableCompressionOption:
4500       default:
4501         return 0x7F;
4502     }
4503   }
4504 
4505   // Returns the equivalent C++ ROCKSDB_NAMESPACE::CompressionType enum for the
4506   // provided Java org.rocksdb.CompressionType
4507   static ROCKSDB_NAMESPACE::CompressionType toCppCompressionType(
4508       jbyte jcompression_type) {
4509     switch(jcompression_type) {
4510       case 0x0:
4511         return ROCKSDB_NAMESPACE::CompressionType::kNoCompression;
4512       case 0x1:
4513         return ROCKSDB_NAMESPACE::CompressionType::kSnappyCompression;
4514       case 0x2:
4515         return ROCKSDB_NAMESPACE::CompressionType::kZlibCompression;
4516       case 0x3:
4517         return ROCKSDB_NAMESPACE::CompressionType::kBZip2Compression;
4518       case 0x4:
4519         return ROCKSDB_NAMESPACE::CompressionType::kLZ4Compression;
4520       case 0x5:
4521         return ROCKSDB_NAMESPACE::CompressionType::kLZ4HCCompression;
4522       case 0x6:
4523         return ROCKSDB_NAMESPACE::CompressionType::kXpressCompression;
4524       case 0x7:
4525         return ROCKSDB_NAMESPACE::CompressionType::kZSTD;
4526       case 0x7F:
4527       default:
4528         return ROCKSDB_NAMESPACE::CompressionType::kDisableCompressionOption;
4529     }
4530   }
4531 };
4532 
4533 // The portal class for org.rocksdb.CompactionPriority
4534 class CompactionPriorityJni {
4535  public:
4536   // Returns the equivalent org.rocksdb.CompactionPriority for the provided
4537   // C++ ROCKSDB_NAMESPACE::CompactionPri enum
4538   static jbyte toJavaCompactionPriority(
4539       const ROCKSDB_NAMESPACE::CompactionPri& compaction_priority) {
4540     switch(compaction_priority) {
4541       case ROCKSDB_NAMESPACE::CompactionPri::kByCompensatedSize:
4542         return 0x0;
4543       case ROCKSDB_NAMESPACE::CompactionPri::kOldestLargestSeqFirst:
4544         return 0x1;
4545       case ROCKSDB_NAMESPACE::CompactionPri::kOldestSmallestSeqFirst:
4546         return 0x2;
4547       case ROCKSDB_NAMESPACE::CompactionPri::kMinOverlappingRatio:
4548         return 0x3;
4549       default:
4550         return 0x0;  // undefined
4551     }
4552   }
4553 
4554   // Returns the equivalent C++ ROCKSDB_NAMESPACE::CompactionPri enum for the
4555   // provided Java org.rocksdb.CompactionPriority
4556   static ROCKSDB_NAMESPACE::CompactionPri toCppCompactionPriority(
4557       jbyte jcompaction_priority) {
4558     switch(jcompaction_priority) {
4559       case 0x0:
4560         return ROCKSDB_NAMESPACE::CompactionPri::kByCompensatedSize;
4561       case 0x1:
4562         return ROCKSDB_NAMESPACE::CompactionPri::kOldestLargestSeqFirst;
4563       case 0x2:
4564         return ROCKSDB_NAMESPACE::CompactionPri::kOldestSmallestSeqFirst;
4565       case 0x3:
4566         return ROCKSDB_NAMESPACE::CompactionPri::kMinOverlappingRatio;
4567       default:
4568         // undefined/default
4569         return ROCKSDB_NAMESPACE::CompactionPri::kByCompensatedSize;
4570     }
4571   }
4572 };
4573 
4574 // The portal class for org.rocksdb.AccessHint
4575 class AccessHintJni {
4576  public:
4577   // Returns the equivalent org.rocksdb.AccessHint for the provided
4578   // C++ ROCKSDB_NAMESPACE::DBOptions::AccessHint enum
4579   static jbyte toJavaAccessHint(
4580       const ROCKSDB_NAMESPACE::DBOptions::AccessHint& access_hint) {
4581     switch(access_hint) {
4582       case ROCKSDB_NAMESPACE::DBOptions::AccessHint::NONE:
4583         return 0x0;
4584       case ROCKSDB_NAMESPACE::DBOptions::AccessHint::NORMAL:
4585         return 0x1;
4586       case ROCKSDB_NAMESPACE::DBOptions::AccessHint::SEQUENTIAL:
4587         return 0x2;
4588       case ROCKSDB_NAMESPACE::DBOptions::AccessHint::WILLNEED:
4589         return 0x3;
4590       default:
4591         // undefined/default
4592         return 0x1;
4593     }
4594   }
4595 
4596   // Returns the equivalent C++ ROCKSDB_NAMESPACE::DBOptions::AccessHint enum
4597   // for the provided Java org.rocksdb.AccessHint
4598   static ROCKSDB_NAMESPACE::DBOptions::AccessHint toCppAccessHint(
4599       jbyte jaccess_hint) {
4600     switch(jaccess_hint) {
4601       case 0x0:
4602         return ROCKSDB_NAMESPACE::DBOptions::AccessHint::NONE;
4603       case 0x1:
4604         return ROCKSDB_NAMESPACE::DBOptions::AccessHint::NORMAL;
4605       case 0x2:
4606         return ROCKSDB_NAMESPACE::DBOptions::AccessHint::SEQUENTIAL;
4607       case 0x3:
4608         return ROCKSDB_NAMESPACE::DBOptions::AccessHint::WILLNEED;
4609       default:
4610         // undefined/default
4611         return ROCKSDB_NAMESPACE::DBOptions::AccessHint::NORMAL;
4612     }
4613   }
4614 };
4615 
4616 // The portal class for org.rocksdb.WALRecoveryMode
4617 class WALRecoveryModeJni {
4618  public:
4619   // Returns the equivalent org.rocksdb.WALRecoveryMode for the provided
4620   // C++ ROCKSDB_NAMESPACE::WALRecoveryMode enum
4621   static jbyte toJavaWALRecoveryMode(
4622       const ROCKSDB_NAMESPACE::WALRecoveryMode& wal_recovery_mode) {
4623     switch(wal_recovery_mode) {
4624       case ROCKSDB_NAMESPACE::WALRecoveryMode::kTolerateCorruptedTailRecords:
4625         return 0x0;
4626       case ROCKSDB_NAMESPACE::WALRecoveryMode::kAbsoluteConsistency:
4627         return 0x1;
4628       case ROCKSDB_NAMESPACE::WALRecoveryMode::kPointInTimeRecovery:
4629         return 0x2;
4630       case ROCKSDB_NAMESPACE::WALRecoveryMode::kSkipAnyCorruptedRecords:
4631         return 0x3;
4632       default:
4633         // undefined/default
4634         return 0x2;
4635     }
4636   }
4637 
4638   // Returns the equivalent C++ ROCKSDB_NAMESPACE::WALRecoveryMode enum for the
4639   // provided Java org.rocksdb.WALRecoveryMode
4640   static ROCKSDB_NAMESPACE::WALRecoveryMode toCppWALRecoveryMode(
4641       jbyte jwal_recovery_mode) {
4642     switch(jwal_recovery_mode) {
4643       case 0x0:
4644         return ROCKSDB_NAMESPACE::WALRecoveryMode::
4645             kTolerateCorruptedTailRecords;
4646       case 0x1:
4647         return ROCKSDB_NAMESPACE::WALRecoveryMode::kAbsoluteConsistency;
4648       case 0x2:
4649         return ROCKSDB_NAMESPACE::WALRecoveryMode::kPointInTimeRecovery;
4650       case 0x3:
4651         return ROCKSDB_NAMESPACE::WALRecoveryMode::kSkipAnyCorruptedRecords;
4652       default:
4653         // undefined/default
4654         return ROCKSDB_NAMESPACE::WALRecoveryMode::kPointInTimeRecovery;
4655     }
4656   }
4657 };
4658 
4659 // The portal class for org.rocksdb.TickerType
4660 class TickerTypeJni {
4661  public:
4662   // Returns the equivalent org.rocksdb.TickerType for the provided
4663   // C++ ROCKSDB_NAMESPACE::Tickers enum
4664   static jbyte toJavaTickerType(const ROCKSDB_NAMESPACE::Tickers& tickers) {
4665     switch(tickers) {
4666       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_MISS:
4667         return 0x0;
4668       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_HIT:
4669         return 0x1;
4670       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_ADD:
4671         return 0x2;
4672       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_ADD_FAILURES:
4673         return 0x3;
4674       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_MISS:
4675         return 0x4;
4676       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_HIT:
4677         return 0x5;
4678       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_ADD:
4679         return 0x6;
4680       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT:
4681         return 0x7;
4682       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT:
4683         return 0x8;
4684       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_MISS:
4685         return 0x9;
4686       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_HIT:
4687         return 0xA;
4688       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_ADD:
4689         return 0xB;
4690       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT:
4691         return 0xC;
4692       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT:
4693         return 0xD;
4694       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_MISS:
4695         return 0xE;
4696       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_HIT:
4697         return 0xF;
4698       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_ADD:
4699         return 0x10;
4700       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT:
4701         return 0x11;
4702       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_BYTES_READ:
4703         return 0x12;
4704       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_BYTES_WRITE:
4705         return 0x13;
4706       case ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_USEFUL:
4707         return 0x14;
4708       case ROCKSDB_NAMESPACE::Tickers::PERSISTENT_CACHE_HIT:
4709         return 0x15;
4710       case ROCKSDB_NAMESPACE::Tickers::PERSISTENT_CACHE_MISS:
4711         return 0x16;
4712       case ROCKSDB_NAMESPACE::Tickers::SIM_BLOCK_CACHE_HIT:
4713         return 0x17;
4714       case ROCKSDB_NAMESPACE::Tickers::SIM_BLOCK_CACHE_MISS:
4715         return 0x18;
4716       case ROCKSDB_NAMESPACE::Tickers::MEMTABLE_HIT:
4717         return 0x19;
4718       case ROCKSDB_NAMESPACE::Tickers::MEMTABLE_MISS:
4719         return 0x1A;
4720       case ROCKSDB_NAMESPACE::Tickers::GET_HIT_L0:
4721         return 0x1B;
4722       case ROCKSDB_NAMESPACE::Tickers::GET_HIT_L1:
4723         return 0x1C;
4724       case ROCKSDB_NAMESPACE::Tickers::GET_HIT_L2_AND_UP:
4725         return 0x1D;
4726       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY:
4727         return 0x1E;
4728       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_OBSOLETE:
4729         return 0x1F;
4730       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_RANGE_DEL:
4731         return 0x20;
4732       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_USER:
4733         return 0x21;
4734       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE:
4735         return 0x22;
4736       case ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_WRITTEN:
4737         return 0x23;
4738       case ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_READ:
4739         return 0x24;
4740       case ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_UPDATED:
4741         return 0x25;
4742       case ROCKSDB_NAMESPACE::Tickers::BYTES_WRITTEN:
4743         return 0x26;
4744       case ROCKSDB_NAMESPACE::Tickers::BYTES_READ:
4745         return 0x27;
4746       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_SEEK:
4747         return 0x28;
4748       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_NEXT:
4749         return 0x29;
4750       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_PREV:
4751         return 0x2A;
4752       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_SEEK_FOUND:
4753         return 0x2B;
4754       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_NEXT_FOUND:
4755         return 0x2C;
4756       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_PREV_FOUND:
4757         return 0x2D;
4758       case ROCKSDB_NAMESPACE::Tickers::ITER_BYTES_READ:
4759         return 0x2E;
4760       case ROCKSDB_NAMESPACE::Tickers::NO_FILE_CLOSES:
4761         return 0x2F;
4762       case ROCKSDB_NAMESPACE::Tickers::NO_FILE_OPENS:
4763         return 0x30;
4764       case ROCKSDB_NAMESPACE::Tickers::NO_FILE_ERRORS:
4765         return 0x31;
4766       case ROCKSDB_NAMESPACE::Tickers::STALL_L0_SLOWDOWN_MICROS:
4767         return 0x32;
4768       case ROCKSDB_NAMESPACE::Tickers::STALL_MEMTABLE_COMPACTION_MICROS:
4769         return 0x33;
4770       case ROCKSDB_NAMESPACE::Tickers::STALL_L0_NUM_FILES_MICROS:
4771         return 0x34;
4772       case ROCKSDB_NAMESPACE::Tickers::STALL_MICROS:
4773         return 0x35;
4774       case ROCKSDB_NAMESPACE::Tickers::DB_MUTEX_WAIT_MICROS:
4775         return 0x36;
4776       case ROCKSDB_NAMESPACE::Tickers::RATE_LIMIT_DELAY_MILLIS:
4777         return 0x37;
4778       case ROCKSDB_NAMESPACE::Tickers::NO_ITERATORS:
4779         return 0x38;
4780       case ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_CALLS:
4781         return 0x39;
4782       case ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_KEYS_READ:
4783         return 0x3A;
4784       case ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_BYTES_READ:
4785         return 0x3B;
4786       case ROCKSDB_NAMESPACE::Tickers::NUMBER_FILTERED_DELETES:
4787         return 0x3C;
4788       case ROCKSDB_NAMESPACE::Tickers::NUMBER_MERGE_FAILURES:
4789         return 0x3D;
4790       case ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_PREFIX_CHECKED:
4791         return 0x3E;
4792       case ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_PREFIX_USEFUL:
4793         return 0x3F;
4794       case ROCKSDB_NAMESPACE::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION:
4795         return 0x40;
4796       case ROCKSDB_NAMESPACE::Tickers::GET_UPDATES_SINCE_CALLS:
4797         return 0x41;
4798       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_MISS:
4799         return 0x42;
4800       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_HIT:
4801         return 0x43;
4802       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_ADD:
4803         return 0x44;
4804       case ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES:
4805         return 0x45;
4806       case ROCKSDB_NAMESPACE::Tickers::WAL_FILE_SYNCED:
4807         return 0x46;
4808       case ROCKSDB_NAMESPACE::Tickers::WAL_FILE_BYTES:
4809         return 0x47;
4810       case ROCKSDB_NAMESPACE::Tickers::WRITE_DONE_BY_SELF:
4811         return 0x48;
4812       case ROCKSDB_NAMESPACE::Tickers::WRITE_DONE_BY_OTHER:
4813         return 0x49;
4814       case ROCKSDB_NAMESPACE::Tickers::WRITE_TIMEDOUT:
4815         return 0x4A;
4816       case ROCKSDB_NAMESPACE::Tickers::WRITE_WITH_WAL:
4817         return 0x4B;
4818       case ROCKSDB_NAMESPACE::Tickers::COMPACT_READ_BYTES:
4819         return 0x4C;
4820       case ROCKSDB_NAMESPACE::Tickers::COMPACT_WRITE_BYTES:
4821         return 0x4D;
4822       case ROCKSDB_NAMESPACE::Tickers::FLUSH_WRITE_BYTES:
4823         return 0x4E;
4824       case ROCKSDB_NAMESPACE::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES:
4825         return 0x4F;
4826       case ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_ACQUIRES:
4827         return 0x50;
4828       case ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_RELEASES:
4829         return 0x51;
4830       case ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_CLEANUPS:
4831         return 0x52;
4832       case ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_COMPRESSED:
4833         return 0x53;
4834       case ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_DECOMPRESSED:
4835         return 0x54;
4836       case ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_NOT_COMPRESSED:
4837         return 0x55;
4838       case ROCKSDB_NAMESPACE::Tickers::MERGE_OPERATION_TOTAL_TIME:
4839         return 0x56;
4840       case ROCKSDB_NAMESPACE::Tickers::FILTER_OPERATION_TOTAL_TIME:
4841         return 0x57;
4842       case ROCKSDB_NAMESPACE::Tickers::ROW_CACHE_HIT:
4843         return 0x58;
4844       case ROCKSDB_NAMESPACE::Tickers::ROW_CACHE_MISS:
4845         return 0x59;
4846       case ROCKSDB_NAMESPACE::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES:
4847         return 0x5A;
4848       case ROCKSDB_NAMESPACE::Tickers::READ_AMP_TOTAL_READ_BYTES:
4849         return 0x5B;
4850       case ROCKSDB_NAMESPACE::Tickers::NUMBER_RATE_LIMITER_DRAINS:
4851         return 0x5C;
4852       case ROCKSDB_NAMESPACE::Tickers::NUMBER_ITER_SKIP:
4853         return 0x5D;
4854       case ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_KEYS_FOUND:
4855         return 0x5E;
4856       case ROCKSDB_NAMESPACE::Tickers::NO_ITERATOR_CREATED:
4857         // -0x01 to fixate the new value that incorrectly changed TICKER_ENUM_MAX.
4858         return -0x01;
4859       case ROCKSDB_NAMESPACE::Tickers::NO_ITERATOR_DELETED:
4860         return 0x60;
4861       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE:
4862         return 0x61;
4863       case ROCKSDB_NAMESPACE::Tickers::COMPACTION_CANCELLED:
4864         return 0x62;
4865       case ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_FULL_POSITIVE:
4866         return 0x63;
4867       case ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_FULL_TRUE_POSITIVE:
4868         return 0x64;
4869       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_PUT:
4870         return 0x65;
4871       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_WRITE:
4872         return 0x66;
4873       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_GET:
4874         return 0x67;
4875       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_MULTIGET:
4876         return 0x68;
4877       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_SEEK:
4878         return 0x69;
4879       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_NEXT:
4880         return 0x6A;
4881       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_PREV:
4882         return 0x6B;
4883       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_KEYS_WRITTEN:
4884         return 0x6C;
4885       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_KEYS_READ:
4886         return 0x6D;
4887       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BYTES_WRITTEN:
4888         return 0x6E;
4889       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BYTES_READ:
4890         return 0x6F;
4891       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_INLINED:
4892         return 0x70;
4893       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_INLINED_TTL:
4894         return 0x71;
4895       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_BLOB:
4896         return 0x72;
4897       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_BLOB_TTL:
4898         return 0x73;
4899       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_BYTES_WRITTEN:
4900         return 0x74;
4901       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_BYTES_READ:
4902         return 0x75;
4903       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_SYNCED:
4904         return 0x76;
4905       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_COUNT:
4906         return 0x77;
4907       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_SIZE:
4908         return 0x78;
4909       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_COUNT:
4910         return 0x79;
4911       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_SIZE:
4912         return 0x7A;
4913       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_FILES:
4914         return 0x7B;
4915       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_NEW_FILES:
4916         return 0x7C;
4917       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_FAILURES:
4918         return 0x7D;
4919       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_OVERWRITTEN:
4920         return 0x7E;
4921       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_EXPIRED:
4922         return 0x7F;
4923       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_RELOCATED:
4924         return -0x02;
4925       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_OVERWRITTEN:
4926         return -0x03;
4927       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_EXPIRED:
4928         return -0x04;
4929       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_RELOCATED:
4930         return -0x05;
4931       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_NUM_FILES_EVICTED:
4932         return -0x06;
4933       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_NUM_KEYS_EVICTED:
4934         return -0x07;
4935       case ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_BYTES_EVICTED:
4936         return -0x08;
4937       case ROCKSDB_NAMESPACE::Tickers::TXN_PREPARE_MUTEX_OVERHEAD:
4938         return -0x09;
4939       case ROCKSDB_NAMESPACE::Tickers::TXN_OLD_COMMIT_MAP_MUTEX_OVERHEAD:
4940         return -0x0A;
4941       case ROCKSDB_NAMESPACE::Tickers::TXN_DUPLICATE_KEY_OVERHEAD:
4942         return -0x0B;
4943       case ROCKSDB_NAMESPACE::Tickers::TXN_SNAPSHOT_MUTEX_OVERHEAD:
4944         return -0x0C;
4945       case ROCKSDB_NAMESPACE::Tickers::TXN_GET_TRY_AGAIN:
4946         return -0x0D;
4947       case ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX:
4948         // 0x5F for backwards compatibility on current minor version.
4949         return 0x5F;
4950       default:
4951         // undefined/default
4952         return 0x0;
4953     }
4954   }
4955 
4956   // Returns the equivalent C++ ROCKSDB_NAMESPACE::Tickers enum for the
4957   // provided Java org.rocksdb.TickerType
4958   static ROCKSDB_NAMESPACE::Tickers toCppTickers(jbyte jticker_type) {
4959     switch(jticker_type) {
4960       case 0x0:
4961         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_MISS;
4962       case 0x1:
4963         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_HIT;
4964       case 0x2:
4965         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_ADD;
4966       case 0x3:
4967         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_ADD_FAILURES;
4968       case 0x4:
4969         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_MISS;
4970       case 0x5:
4971         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_HIT;
4972       case 0x6:
4973         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_ADD;
4974       case 0x7:
4975         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT;
4976       case 0x8:
4977         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT;
4978       case 0x9:
4979         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_MISS;
4980       case 0xA:
4981         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_HIT;
4982       case 0xB:
4983         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_ADD;
4984       case 0xC:
4985         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT;
4986       case 0xD:
4987         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT;
4988       case 0xE:
4989         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_MISS;
4990       case 0xF:
4991         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_HIT;
4992       case 0x10:
4993         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_ADD;
4994       case 0x11:
4995         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT;
4996       case 0x12:
4997         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_BYTES_READ;
4998       case 0x13:
4999         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_BYTES_WRITE;
5000       case 0x14:
5001         return ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_USEFUL;
5002       case 0x15:
5003         return ROCKSDB_NAMESPACE::Tickers::PERSISTENT_CACHE_HIT;
5004       case 0x16:
5005         return ROCKSDB_NAMESPACE::Tickers::PERSISTENT_CACHE_MISS;
5006       case 0x17:
5007         return ROCKSDB_NAMESPACE::Tickers::SIM_BLOCK_CACHE_HIT;
5008       case 0x18:
5009         return ROCKSDB_NAMESPACE::Tickers::SIM_BLOCK_CACHE_MISS;
5010       case 0x19:
5011         return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_HIT;
5012       case 0x1A:
5013         return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_MISS;
5014       case 0x1B:
5015         return ROCKSDB_NAMESPACE::Tickers::GET_HIT_L0;
5016       case 0x1C:
5017         return ROCKSDB_NAMESPACE::Tickers::GET_HIT_L1;
5018       case 0x1D:
5019         return ROCKSDB_NAMESPACE::Tickers::GET_HIT_L2_AND_UP;
5020       case 0x1E:
5021         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY;
5022       case 0x1F:
5023         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_OBSOLETE;
5024       case 0x20:
5025         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_RANGE_DEL;
5026       case 0x21:
5027         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_KEY_DROP_USER;
5028       case 0x22:
5029         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE;
5030       case 0x23:
5031         return ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_WRITTEN;
5032       case 0x24:
5033         return ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_READ;
5034       case 0x25:
5035         return ROCKSDB_NAMESPACE::Tickers::NUMBER_KEYS_UPDATED;
5036       case 0x26:
5037         return ROCKSDB_NAMESPACE::Tickers::BYTES_WRITTEN;
5038       case 0x27:
5039         return ROCKSDB_NAMESPACE::Tickers::BYTES_READ;
5040       case 0x28:
5041         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_SEEK;
5042       case 0x29:
5043         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_NEXT;
5044       case 0x2A:
5045         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_PREV;
5046       case 0x2B:
5047         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_SEEK_FOUND;
5048       case 0x2C:
5049         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_NEXT_FOUND;
5050       case 0x2D:
5051         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DB_PREV_FOUND;
5052       case 0x2E:
5053         return ROCKSDB_NAMESPACE::Tickers::ITER_BYTES_READ;
5054       case 0x2F:
5055         return ROCKSDB_NAMESPACE::Tickers::NO_FILE_CLOSES;
5056       case 0x30:
5057         return ROCKSDB_NAMESPACE::Tickers::NO_FILE_OPENS;
5058       case 0x31:
5059         return ROCKSDB_NAMESPACE::Tickers::NO_FILE_ERRORS;
5060       case 0x32:
5061         return ROCKSDB_NAMESPACE::Tickers::STALL_L0_SLOWDOWN_MICROS;
5062       case 0x33:
5063         return ROCKSDB_NAMESPACE::Tickers::STALL_MEMTABLE_COMPACTION_MICROS;
5064       case 0x34:
5065         return ROCKSDB_NAMESPACE::Tickers::STALL_L0_NUM_FILES_MICROS;
5066       case 0x35:
5067         return ROCKSDB_NAMESPACE::Tickers::STALL_MICROS;
5068       case 0x36:
5069         return ROCKSDB_NAMESPACE::Tickers::DB_MUTEX_WAIT_MICROS;
5070       case 0x37:
5071         return ROCKSDB_NAMESPACE::Tickers::RATE_LIMIT_DELAY_MILLIS;
5072       case 0x38:
5073         return ROCKSDB_NAMESPACE::Tickers::NO_ITERATORS;
5074       case 0x39:
5075         return ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_CALLS;
5076       case 0x3A:
5077         return ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_KEYS_READ;
5078       case 0x3B:
5079         return ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_BYTES_READ;
5080       case 0x3C:
5081         return ROCKSDB_NAMESPACE::Tickers::NUMBER_FILTERED_DELETES;
5082       case 0x3D:
5083         return ROCKSDB_NAMESPACE::Tickers::NUMBER_MERGE_FAILURES;
5084       case 0x3E:
5085         return ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_PREFIX_CHECKED;
5086       case 0x3F:
5087         return ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_PREFIX_USEFUL;
5088       case 0x40:
5089         return ROCKSDB_NAMESPACE::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION;
5090       case 0x41:
5091         return ROCKSDB_NAMESPACE::Tickers::GET_UPDATES_SINCE_CALLS;
5092       case 0x42:
5093         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_MISS;
5094       case 0x43:
5095         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_HIT;
5096       case 0x44:
5097         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_ADD;
5098       case 0x45:
5099         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES;
5100       case 0x46:
5101         return ROCKSDB_NAMESPACE::Tickers::WAL_FILE_SYNCED;
5102       case 0x47:
5103         return ROCKSDB_NAMESPACE::Tickers::WAL_FILE_BYTES;
5104       case 0x48:
5105         return ROCKSDB_NAMESPACE::Tickers::WRITE_DONE_BY_SELF;
5106       case 0x49:
5107         return ROCKSDB_NAMESPACE::Tickers::WRITE_DONE_BY_OTHER;
5108       case 0x4A:
5109         return ROCKSDB_NAMESPACE::Tickers::WRITE_TIMEDOUT;
5110       case 0x4B:
5111         return ROCKSDB_NAMESPACE::Tickers::WRITE_WITH_WAL;
5112       case 0x4C:
5113         return ROCKSDB_NAMESPACE::Tickers::COMPACT_READ_BYTES;
5114       case 0x4D:
5115         return ROCKSDB_NAMESPACE::Tickers::COMPACT_WRITE_BYTES;
5116       case 0x4E:
5117         return ROCKSDB_NAMESPACE::Tickers::FLUSH_WRITE_BYTES;
5118       case 0x4F:
5119         return ROCKSDB_NAMESPACE::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES;
5120       case 0x50:
5121         return ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_ACQUIRES;
5122       case 0x51:
5123         return ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_RELEASES;
5124       case 0x52:
5125         return ROCKSDB_NAMESPACE::Tickers::NUMBER_SUPERVERSION_CLEANUPS;
5126       case 0x53:
5127         return ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_COMPRESSED;
5128       case 0x54:
5129         return ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_DECOMPRESSED;
5130       case 0x55:
5131         return ROCKSDB_NAMESPACE::Tickers::NUMBER_BLOCK_NOT_COMPRESSED;
5132       case 0x56:
5133         return ROCKSDB_NAMESPACE::Tickers::MERGE_OPERATION_TOTAL_TIME;
5134       case 0x57:
5135         return ROCKSDB_NAMESPACE::Tickers::FILTER_OPERATION_TOTAL_TIME;
5136       case 0x58:
5137         return ROCKSDB_NAMESPACE::Tickers::ROW_CACHE_HIT;
5138       case 0x59:
5139         return ROCKSDB_NAMESPACE::Tickers::ROW_CACHE_MISS;
5140       case 0x5A:
5141         return ROCKSDB_NAMESPACE::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES;
5142       case 0x5B:
5143         return ROCKSDB_NAMESPACE::Tickers::READ_AMP_TOTAL_READ_BYTES;
5144       case 0x5C:
5145         return ROCKSDB_NAMESPACE::Tickers::NUMBER_RATE_LIMITER_DRAINS;
5146       case 0x5D:
5147         return ROCKSDB_NAMESPACE::Tickers::NUMBER_ITER_SKIP;
5148       case 0x5E:
5149         return ROCKSDB_NAMESPACE::Tickers::NUMBER_MULTIGET_KEYS_FOUND;
5150       case -0x01:
5151         // -0x01 to fixate the new value that incorrectly changed TICKER_ENUM_MAX.
5152         return ROCKSDB_NAMESPACE::Tickers::NO_ITERATOR_CREATED;
5153       case 0x60:
5154         return ROCKSDB_NAMESPACE::Tickers::NO_ITERATOR_DELETED;
5155       case 0x61:
5156         return ROCKSDB_NAMESPACE::Tickers::
5157             COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE;
5158       case 0x62:
5159         return ROCKSDB_NAMESPACE::Tickers::COMPACTION_CANCELLED;
5160       case 0x63:
5161         return ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_FULL_POSITIVE;
5162       case 0x64:
5163         return ROCKSDB_NAMESPACE::Tickers::BLOOM_FILTER_FULL_TRUE_POSITIVE;
5164       case 0x65:
5165         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_PUT;
5166       case 0x66:
5167         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_WRITE;
5168       case 0x67:
5169         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_GET;
5170       case 0x68:
5171         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_MULTIGET;
5172       case 0x69:
5173         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_SEEK;
5174       case 0x6A:
5175         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_NEXT;
5176       case 0x6B:
5177         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_PREV;
5178       case 0x6C:
5179         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_KEYS_WRITTEN;
5180       case 0x6D:
5181         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_NUM_KEYS_READ;
5182       case 0x6E:
5183         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BYTES_WRITTEN;
5184       case 0x6F:
5185         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BYTES_READ;
5186       case 0x70:
5187         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_INLINED;
5188       case 0x71:
5189         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_INLINED_TTL;
5190       case 0x72:
5191         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_BLOB;
5192       case 0x73:
5193         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_WRITE_BLOB_TTL;
5194       case 0x74:
5195         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_BYTES_WRITTEN;
5196       case 0x75:
5197         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_BYTES_READ;
5198       case 0x76:
5199         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_FILE_SYNCED;
5200       case 0x77:
5201         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_COUNT;
5202       case 0x78:
5203         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_SIZE;
5204       case 0x79:
5205         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_COUNT;
5206       case 0x7A:
5207         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_SIZE;
5208       case 0x7B:
5209         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_FILES;
5210       case 0x7C:
5211         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_NEW_FILES;
5212       case 0x7D:
5213         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_FAILURES;
5214       case 0x7E:
5215         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_OVERWRITTEN;
5216       case 0x7F:
5217         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_EXPIRED;
5218       case -0x02:
5219         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_NUM_KEYS_RELOCATED;
5220       case -0x03:
5221         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_OVERWRITTEN;
5222       case -0x04:
5223         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_EXPIRED;
5224       case -0x05:
5225         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_GC_BYTES_RELOCATED;
5226       case -0x06:
5227         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_NUM_FILES_EVICTED;
5228       case -0x07:
5229         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_NUM_KEYS_EVICTED;
5230       case -0x08:
5231         return ROCKSDB_NAMESPACE::Tickers::BLOB_DB_FIFO_BYTES_EVICTED;
5232       case -0x09:
5233         return ROCKSDB_NAMESPACE::Tickers::TXN_PREPARE_MUTEX_OVERHEAD;
5234       case -0x0A:
5235         return ROCKSDB_NAMESPACE::Tickers::TXN_OLD_COMMIT_MAP_MUTEX_OVERHEAD;
5236       case -0x0B:
5237         return ROCKSDB_NAMESPACE::Tickers::TXN_DUPLICATE_KEY_OVERHEAD;
5238       case -0x0C:
5239         return ROCKSDB_NAMESPACE::Tickers::TXN_SNAPSHOT_MUTEX_OVERHEAD;
5240       case -0x0D:
5241         return ROCKSDB_NAMESPACE::Tickers::TXN_GET_TRY_AGAIN;
5242       case 0x5F:
5243         // 0x5F for backwards compatibility on current minor version.
5244         return ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX;
5245 
5246       default:
5247         // undefined/default
5248         return ROCKSDB_NAMESPACE::Tickers::BLOCK_CACHE_MISS;
5249     }
5250   }
5251 };
5252 
5253 // The portal class for org.rocksdb.HistogramType
5254 class HistogramTypeJni {
5255  public:
5256   // Returns the equivalent org.rocksdb.HistogramType for the provided
5257   // C++ ROCKSDB_NAMESPACE::Histograms enum
5258   static jbyte toJavaHistogramsType(
5259       const ROCKSDB_NAMESPACE::Histograms& histograms) {
5260     switch(histograms) {
5261       case ROCKSDB_NAMESPACE::Histograms::DB_GET:
5262         return 0x0;
5263       case ROCKSDB_NAMESPACE::Histograms::DB_WRITE:
5264         return 0x1;
5265       case ROCKSDB_NAMESPACE::Histograms::COMPACTION_TIME:
5266         return 0x2;
5267       case ROCKSDB_NAMESPACE::Histograms::SUBCOMPACTION_SETUP_TIME:
5268         return 0x3;
5269       case ROCKSDB_NAMESPACE::Histograms::TABLE_SYNC_MICROS:
5270         return 0x4;
5271       case ROCKSDB_NAMESPACE::Histograms::COMPACTION_OUTFILE_SYNC_MICROS:
5272         return 0x5;
5273       case ROCKSDB_NAMESPACE::Histograms::WAL_FILE_SYNC_MICROS:
5274         return 0x6;
5275       case ROCKSDB_NAMESPACE::Histograms::MANIFEST_FILE_SYNC_MICROS:
5276         return 0x7;
5277       case ROCKSDB_NAMESPACE::Histograms::TABLE_OPEN_IO_MICROS:
5278         return 0x8;
5279       case ROCKSDB_NAMESPACE::Histograms::DB_MULTIGET:
5280         return 0x9;
5281       case ROCKSDB_NAMESPACE::Histograms::READ_BLOCK_COMPACTION_MICROS:
5282         return 0xA;
5283       case ROCKSDB_NAMESPACE::Histograms::READ_BLOCK_GET_MICROS:
5284         return 0xB;
5285       case ROCKSDB_NAMESPACE::Histograms::WRITE_RAW_BLOCK_MICROS:
5286         return 0xC;
5287       case ROCKSDB_NAMESPACE::Histograms::STALL_L0_SLOWDOWN_COUNT:
5288         return 0xD;
5289       case ROCKSDB_NAMESPACE::Histograms::STALL_MEMTABLE_COMPACTION_COUNT:
5290         return 0xE;
5291       case ROCKSDB_NAMESPACE::Histograms::STALL_L0_NUM_FILES_COUNT:
5292         return 0xF;
5293       case ROCKSDB_NAMESPACE::Histograms::HARD_RATE_LIMIT_DELAY_COUNT:
5294         return 0x10;
5295       case ROCKSDB_NAMESPACE::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT:
5296         return 0x11;
5297       case ROCKSDB_NAMESPACE::Histograms::NUM_FILES_IN_SINGLE_COMPACTION:
5298         return 0x12;
5299       case ROCKSDB_NAMESPACE::Histograms::DB_SEEK:
5300         return 0x13;
5301       case ROCKSDB_NAMESPACE::Histograms::WRITE_STALL:
5302         return 0x14;
5303       case ROCKSDB_NAMESPACE::Histograms::SST_READ_MICROS:
5304         return 0x15;
5305       case ROCKSDB_NAMESPACE::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED:
5306         return 0x16;
5307       case ROCKSDB_NAMESPACE::Histograms::BYTES_PER_READ:
5308         return 0x17;
5309       case ROCKSDB_NAMESPACE::Histograms::BYTES_PER_WRITE:
5310         return 0x18;
5311       case ROCKSDB_NAMESPACE::Histograms::BYTES_PER_MULTIGET:
5312         return 0x19;
5313       case ROCKSDB_NAMESPACE::Histograms::BYTES_COMPRESSED:
5314         return 0x1A;
5315       case ROCKSDB_NAMESPACE::Histograms::BYTES_DECOMPRESSED:
5316         return 0x1B;
5317       case ROCKSDB_NAMESPACE::Histograms::COMPRESSION_TIMES_NANOS:
5318         return 0x1C;
5319       case ROCKSDB_NAMESPACE::Histograms::DECOMPRESSION_TIMES_NANOS:
5320         return 0x1D;
5321       case ROCKSDB_NAMESPACE::Histograms::READ_NUM_MERGE_OPERANDS:
5322         return 0x1E;
5323       // 0x20 to skip 0x1F so TICKER_ENUM_MAX remains unchanged for minor version compatibility.
5324       case ROCKSDB_NAMESPACE::Histograms::FLUSH_TIME:
5325         return 0x20;
5326       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_KEY_SIZE:
5327         return 0x21;
5328       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_VALUE_SIZE:
5329         return 0x22;
5330       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_WRITE_MICROS:
5331         return 0x23;
5332       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_GET_MICROS:
5333         return 0x24;
5334       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_MULTIGET_MICROS:
5335         return 0x25;
5336       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_SEEK_MICROS:
5337         return 0x26;
5338       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_NEXT_MICROS:
5339         return 0x27;
5340       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_PREV_MICROS:
5341         return 0x28;
5342       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS:
5343         return 0x29;
5344       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_READ_MICROS:
5345         return 0x2A;
5346       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_SYNC_MICROS:
5347         return 0x2B;
5348       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_GC_MICROS:
5349         return 0x2C;
5350       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_COMPRESSION_MICROS:
5351         return 0x2D;
5352       case ROCKSDB_NAMESPACE::Histograms::BLOB_DB_DECOMPRESSION_MICROS:
5353         return 0x2E;
5354       case ROCKSDB_NAMESPACE::Histograms::HISTOGRAM_ENUM_MAX:
5355         // 0x1F for backwards compatibility on current minor version.
5356         return 0x1F;
5357 
5358       default:
5359         // undefined/default
5360         return 0x0;
5361     }
5362   }
5363 
5364   // Returns the equivalent C++ ROCKSDB_NAMESPACE::Histograms enum for the
5365   // provided Java org.rocksdb.HistogramsType
5366   static ROCKSDB_NAMESPACE::Histograms toCppHistograms(jbyte jhistograms_type) {
5367     switch(jhistograms_type) {
5368       case 0x0:
5369         return ROCKSDB_NAMESPACE::Histograms::DB_GET;
5370       case 0x1:
5371         return ROCKSDB_NAMESPACE::Histograms::DB_WRITE;
5372       case 0x2:
5373         return ROCKSDB_NAMESPACE::Histograms::COMPACTION_TIME;
5374       case 0x3:
5375         return ROCKSDB_NAMESPACE::Histograms::SUBCOMPACTION_SETUP_TIME;
5376       case 0x4:
5377         return ROCKSDB_NAMESPACE::Histograms::TABLE_SYNC_MICROS;
5378       case 0x5:
5379         return ROCKSDB_NAMESPACE::Histograms::COMPACTION_OUTFILE_SYNC_MICROS;
5380       case 0x6:
5381         return ROCKSDB_NAMESPACE::Histograms::WAL_FILE_SYNC_MICROS;
5382       case 0x7:
5383         return ROCKSDB_NAMESPACE::Histograms::MANIFEST_FILE_SYNC_MICROS;
5384       case 0x8:
5385         return ROCKSDB_NAMESPACE::Histograms::TABLE_OPEN_IO_MICROS;
5386       case 0x9:
5387         return ROCKSDB_NAMESPACE::Histograms::DB_MULTIGET;
5388       case 0xA:
5389         return ROCKSDB_NAMESPACE::Histograms::READ_BLOCK_COMPACTION_MICROS;
5390       case 0xB:
5391         return ROCKSDB_NAMESPACE::Histograms::READ_BLOCK_GET_MICROS;
5392       case 0xC:
5393         return ROCKSDB_NAMESPACE::Histograms::WRITE_RAW_BLOCK_MICROS;
5394       case 0xD:
5395         return ROCKSDB_NAMESPACE::Histograms::STALL_L0_SLOWDOWN_COUNT;
5396       case 0xE:
5397         return ROCKSDB_NAMESPACE::Histograms::STALL_MEMTABLE_COMPACTION_COUNT;
5398       case 0xF:
5399         return ROCKSDB_NAMESPACE::Histograms::STALL_L0_NUM_FILES_COUNT;
5400       case 0x10:
5401         return ROCKSDB_NAMESPACE::Histograms::HARD_RATE_LIMIT_DELAY_COUNT;
5402       case 0x11:
5403         return ROCKSDB_NAMESPACE::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT;
5404       case 0x12:
5405         return ROCKSDB_NAMESPACE::Histograms::NUM_FILES_IN_SINGLE_COMPACTION;
5406       case 0x13:
5407         return ROCKSDB_NAMESPACE::Histograms::DB_SEEK;
5408       case 0x14:
5409         return ROCKSDB_NAMESPACE::Histograms::WRITE_STALL;
5410       case 0x15:
5411         return ROCKSDB_NAMESPACE::Histograms::SST_READ_MICROS;
5412       case 0x16:
5413         return ROCKSDB_NAMESPACE::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED;
5414       case 0x17:
5415         return ROCKSDB_NAMESPACE::Histograms::BYTES_PER_READ;
5416       case 0x18:
5417         return ROCKSDB_NAMESPACE::Histograms::BYTES_PER_WRITE;
5418       case 0x19:
5419         return ROCKSDB_NAMESPACE::Histograms::BYTES_PER_MULTIGET;
5420       case 0x1A:
5421         return ROCKSDB_NAMESPACE::Histograms::BYTES_COMPRESSED;
5422       case 0x1B:
5423         return ROCKSDB_NAMESPACE::Histograms::BYTES_DECOMPRESSED;
5424       case 0x1C:
5425         return ROCKSDB_NAMESPACE::Histograms::COMPRESSION_TIMES_NANOS;
5426       case 0x1D:
5427         return ROCKSDB_NAMESPACE::Histograms::DECOMPRESSION_TIMES_NANOS;
5428       case 0x1E:
5429         return ROCKSDB_NAMESPACE::Histograms::READ_NUM_MERGE_OPERANDS;
5430       // 0x20 to skip 0x1F so TICKER_ENUM_MAX remains unchanged for minor version compatibility.
5431       case 0x20:
5432         return ROCKSDB_NAMESPACE::Histograms::FLUSH_TIME;
5433       case 0x21:
5434         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_KEY_SIZE;
5435       case 0x22:
5436         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_VALUE_SIZE;
5437       case 0x23:
5438         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_WRITE_MICROS;
5439       case 0x24:
5440         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_GET_MICROS;
5441       case 0x25:
5442         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_MULTIGET_MICROS;
5443       case 0x26:
5444         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_SEEK_MICROS;
5445       case 0x27:
5446         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_NEXT_MICROS;
5447       case 0x28:
5448         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_PREV_MICROS;
5449       case 0x29:
5450         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS;
5451       case 0x2A:
5452         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_READ_MICROS;
5453       case 0x2B:
5454         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_BLOB_FILE_SYNC_MICROS;
5455       case 0x2C:
5456         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_GC_MICROS;
5457       case 0x2D:
5458         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_COMPRESSION_MICROS;
5459       case 0x2E:
5460         return ROCKSDB_NAMESPACE::Histograms::BLOB_DB_DECOMPRESSION_MICROS;
5461       case 0x1F:
5462         // 0x1F for backwards compatibility on current minor version.
5463         return ROCKSDB_NAMESPACE::Histograms::HISTOGRAM_ENUM_MAX;
5464 
5465       default:
5466         // undefined/default
5467         return ROCKSDB_NAMESPACE::Histograms::DB_GET;
5468     }
5469   }
5470 };
5471 
5472 // The portal class for org.rocksdb.StatsLevel
5473 class StatsLevelJni {
5474  public:
5475   // Returns the equivalent org.rocksdb.StatsLevel for the provided
5476   // C++ ROCKSDB_NAMESPACE::StatsLevel enum
5477   static jbyte toJavaStatsLevel(
5478       const ROCKSDB_NAMESPACE::StatsLevel& stats_level) {
5479     switch(stats_level) {
5480       case ROCKSDB_NAMESPACE::StatsLevel::kExceptDetailedTimers:
5481         return 0x0;
5482       case ROCKSDB_NAMESPACE::StatsLevel::kExceptTimeForMutex:
5483         return 0x1;
5484       case ROCKSDB_NAMESPACE::StatsLevel::kAll:
5485         return 0x2;
5486 
5487       default:
5488         // undefined/default
5489         return 0x0;
5490     }
5491   }
5492 
5493   // Returns the equivalent C++ ROCKSDB_NAMESPACE::StatsLevel enum for the
5494   // provided Java org.rocksdb.StatsLevel
5495   static ROCKSDB_NAMESPACE::StatsLevel toCppStatsLevel(jbyte jstats_level) {
5496     switch(jstats_level) {
5497       case 0x0:
5498         return ROCKSDB_NAMESPACE::StatsLevel::kExceptDetailedTimers;
5499       case 0x1:
5500         return ROCKSDB_NAMESPACE::StatsLevel::kExceptTimeForMutex;
5501       case 0x2:
5502         return ROCKSDB_NAMESPACE::StatsLevel::kAll;
5503 
5504       default:
5505         // undefined/default
5506         return ROCKSDB_NAMESPACE::StatsLevel::kExceptDetailedTimers;
5507     }
5508   }
5509 };
5510 
5511 // The portal class for org.rocksdb.RateLimiterMode
5512 class RateLimiterModeJni {
5513  public:
5514   // Returns the equivalent org.rocksdb.RateLimiterMode for the provided
5515   // C++ ROCKSDB_NAMESPACE::RateLimiter::Mode enum
5516   static jbyte toJavaRateLimiterMode(
5517       const ROCKSDB_NAMESPACE::RateLimiter::Mode& rate_limiter_mode) {
5518     switch(rate_limiter_mode) {
5519       case ROCKSDB_NAMESPACE::RateLimiter::Mode::kReadsOnly:
5520         return 0x0;
5521       case ROCKSDB_NAMESPACE::RateLimiter::Mode::kWritesOnly:
5522         return 0x1;
5523       case ROCKSDB_NAMESPACE::RateLimiter::Mode::kAllIo:
5524         return 0x2;
5525 
5526       default:
5527         // undefined/default
5528         return 0x1;
5529     }
5530   }
5531 
5532   // Returns the equivalent C++ ROCKSDB_NAMESPACE::RateLimiter::Mode enum for
5533   // the provided Java org.rocksdb.RateLimiterMode
5534   static ROCKSDB_NAMESPACE::RateLimiter::Mode toCppRateLimiterMode(
5535       jbyte jrate_limiter_mode) {
5536     switch(jrate_limiter_mode) {
5537       case 0x0:
5538         return ROCKSDB_NAMESPACE::RateLimiter::Mode::kReadsOnly;
5539       case 0x1:
5540         return ROCKSDB_NAMESPACE::RateLimiter::Mode::kWritesOnly;
5541       case 0x2:
5542         return ROCKSDB_NAMESPACE::RateLimiter::Mode::kAllIo;
5543 
5544       default:
5545         // undefined/default
5546         return ROCKSDB_NAMESPACE::RateLimiter::Mode::kWritesOnly;
5547     }
5548   }
5549 };
5550 
5551 // The portal class for org.rocksdb.MemoryUsageType
5552 class MemoryUsageTypeJni {
5553 public:
5554  // Returns the equivalent org.rocksdb.MemoryUsageType for the provided
5555  // C++ ROCKSDB_NAMESPACE::MemoryUtil::UsageType enum
5556  static jbyte toJavaMemoryUsageType(
5557      const ROCKSDB_NAMESPACE::MemoryUtil::UsageType& usage_type) {
5558    switch (usage_type) {
5559      case ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kMemTableTotal:
5560        return 0x0;
5561      case ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kMemTableUnFlushed:
5562        return 0x1;
5563      case ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kTableReadersTotal:
5564        return 0x2;
5565      case ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kCacheTotal:
5566        return 0x3;
5567      default:
5568        // undefined: use kNumUsageTypes
5569        return 0x4;
5570    }
5571  }
5572 
5573  // Returns the equivalent C++ ROCKSDB_NAMESPACE::MemoryUtil::UsageType enum for
5574  // the provided Java org.rocksdb.MemoryUsageType
5575  static ROCKSDB_NAMESPACE::MemoryUtil::UsageType toCppMemoryUsageType(
5576      jbyte usage_type) {
5577    switch (usage_type) {
5578      case 0x0:
5579        return ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kMemTableTotal;
5580      case 0x1:
5581        return ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kMemTableUnFlushed;
5582      case 0x2:
5583        return ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kTableReadersTotal;
5584      case 0x3:
5585        return ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kCacheTotal;
5586      default:
5587        // undefined/default: use kNumUsageTypes
5588        return ROCKSDB_NAMESPACE::MemoryUtil::UsageType::kNumUsageTypes;
5589    }
5590  }
5591 };
5592 
5593 // The portal class for org.rocksdb.Transaction
5594 class TransactionJni : public JavaClass {
5595  public:
5596   /**
5597    * Get the Java Class org.rocksdb.Transaction
5598    *
5599    * @param env A pointer to the Java environment
5600    *
5601    * @return The Java Class or nullptr if one of the
5602    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
5603    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
5604    */
5605   static jclass getJClass(JNIEnv* env) {
5606     return JavaClass::getJClass(env,
5607         "org/rocksdb/Transaction");
5608   }
5609 
5610   /**
5611    * Create a new Java org.rocksdb.Transaction.WaitingTransactions object
5612    *
5613    * @param env A pointer to the Java environment
5614    * @param jtransaction A Java org.rocksdb.Transaction object
5615    * @param column_family_id The id of the column family
5616    * @param key The key
5617    * @param transaction_ids The transaction ids
5618    *
5619    * @return A reference to a Java
5620    *     org.rocksdb.Transaction.WaitingTransactions object,
5621    *     or nullptr if an an exception occurs
5622    */
5623   static jobject newWaitingTransactions(JNIEnv* env, jobject jtransaction,
5624       const uint32_t column_family_id, const std::string &key,
5625       const std::vector<TransactionID> &transaction_ids) {
5626     jclass jclazz = getJClass(env);
5627     if(jclazz == nullptr) {
5628       // exception occurred accessing class
5629       return nullptr;
5630     }
5631 
5632     jmethodID mid = env->GetMethodID(
5633       jclazz, "newWaitingTransactions", "(JLjava/lang/String;[J)Lorg/rocksdb/Transaction$WaitingTransactions;");
5634     if(mid == nullptr) {
5635       // exception thrown: NoSuchMethodException or OutOfMemoryError
5636       return nullptr;
5637     }
5638 
5639     jstring jkey = env->NewStringUTF(key.c_str());
5640     if(jkey == nullptr) {
5641       // exception thrown: OutOfMemoryError
5642       return nullptr;
5643     }
5644 
5645     const size_t len = transaction_ids.size();
5646     jlongArray jtransaction_ids = env->NewLongArray(static_cast<jsize>(len));
5647     if(jtransaction_ids == nullptr) {
5648       // exception thrown: OutOfMemoryError
5649       env->DeleteLocalRef(jkey);
5650       return nullptr;
5651     }
5652 
5653     jlong *body = env->GetLongArrayElements(jtransaction_ids, nullptr);
5654     if(body == nullptr) {
5655         // exception thrown: OutOfMemoryError
5656         env->DeleteLocalRef(jkey);
5657         env->DeleteLocalRef(jtransaction_ids);
5658         return nullptr;
5659     }
5660     for(size_t i = 0; i < len; ++i) {
5661       body[i] = static_cast<jlong>(transaction_ids[i]);
5662     }
5663     env->ReleaseLongArrayElements(jtransaction_ids, body, 0);
5664 
5665     jobject jwaiting_transactions = env->CallObjectMethod(jtransaction,
5666       mid, static_cast<jlong>(column_family_id), jkey, jtransaction_ids);
5667     if(env->ExceptionCheck()) {
5668       // exception thrown: InstantiationException or OutOfMemoryError
5669       env->DeleteLocalRef(jkey);
5670       env->DeleteLocalRef(jtransaction_ids);
5671       return nullptr;
5672     }
5673 
5674     return jwaiting_transactions;
5675   }
5676 };
5677 
5678 // The portal class for org.rocksdb.TransactionDB
5679 class TransactionDBJni : public JavaClass {
5680  public:
5681  /**
5682   * Get the Java Class org.rocksdb.TransactionDB
5683   *
5684   * @param env A pointer to the Java environment
5685   *
5686   * @return The Java Class or nullptr if one of the
5687   *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
5688   *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
5689   */
5690   static jclass getJClass(JNIEnv* env) {
5691     return JavaClass::getJClass(env,
5692        "org/rocksdb/TransactionDB");
5693   }
5694 
5695   /**
5696    * Create a new Java org.rocksdb.TransactionDB.DeadlockInfo object
5697    *
5698    * @param env A pointer to the Java environment
5699    * @param jtransaction A Java org.rocksdb.Transaction object
5700    * @param column_family_id The id of the column family
5701    * @param key The key
5702    * @param transaction_ids The transaction ids
5703    *
5704    * @return A reference to a Java
5705    *     org.rocksdb.Transaction.WaitingTransactions object,
5706    *     or nullptr if an an exception occurs
5707    */
5708   static jobject newDeadlockInfo(
5709       JNIEnv* env, jobject jtransaction_db,
5710       const ROCKSDB_NAMESPACE::TransactionID transaction_id,
5711       const uint32_t column_family_id, const std::string& waiting_key,
5712       const bool exclusive) {
5713     jclass jclazz = getJClass(env);
5714     if(jclazz == nullptr) {
5715       // exception occurred accessing class
5716       return nullptr;
5717     }
5718 
5719     jmethodID mid = env->GetMethodID(
5720         jclazz, "newDeadlockInfo", "(JJLjava/lang/String;Z)Lorg/rocksdb/TransactionDB$DeadlockInfo;");
5721     if(mid == nullptr) {
5722       // exception thrown: NoSuchMethodException or OutOfMemoryError
5723       return nullptr;
5724     }
5725 
5726     jstring jwaiting_key = env->NewStringUTF(waiting_key.c_str());
5727     if(jwaiting_key == nullptr) {
5728       // exception thrown: OutOfMemoryError
5729       return nullptr;
5730     }
5731 
5732     // resolve the column family id to a ColumnFamilyHandle
5733     jobject jdeadlock_info = env->CallObjectMethod(jtransaction_db,
5734         mid, transaction_id, static_cast<jlong>(column_family_id),
5735         jwaiting_key, exclusive);
5736     if(env->ExceptionCheck()) {
5737       // exception thrown: InstantiationException or OutOfMemoryError
5738       env->DeleteLocalRef(jwaiting_key);
5739       return nullptr;
5740     }
5741 
5742     return jdeadlock_info;
5743   }
5744 };
5745 
5746 // The portal class for org.rocksdb.TxnDBWritePolicy
5747 class TxnDBWritePolicyJni {
5748  public:
5749   // Returns the equivalent org.rocksdb.TxnDBWritePolicy for the provided
5750   // C++ ROCKSDB_NAMESPACE::TxnDBWritePolicy enum
5751   static jbyte toJavaTxnDBWritePolicy(
5752       const ROCKSDB_NAMESPACE::TxnDBWritePolicy& txndb_write_policy) {
5753     switch (txndb_write_policy) {
5754       case ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_COMMITTED:
5755         return 0x0;
5756       case ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_PREPARED:
5757         return 0x1;
5758       case ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_UNPREPARED:
5759         return 0x2;
5760       default:
5761         return 0x7F;  // undefined
5762     }
5763   }
5764 
5765   // Returns the equivalent C++ ROCKSDB_NAMESPACE::TxnDBWritePolicy enum for the
5766   // provided Java org.rocksdb.TxnDBWritePolicy
5767   static ROCKSDB_NAMESPACE::TxnDBWritePolicy toCppTxnDBWritePolicy(
5768       jbyte jtxndb_write_policy) {
5769     switch (jtxndb_write_policy) {
5770       case 0x0:
5771         return ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_COMMITTED;
5772       case 0x1:
5773         return ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_PREPARED;
5774       case 0x2:
5775         return ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_UNPREPARED;
5776       default:
5777         // undefined/default
5778         return ROCKSDB_NAMESPACE::TxnDBWritePolicy::WRITE_COMMITTED;
5779     }
5780   }
5781 };
5782 
5783 // The portal class for org.rocksdb.TransactionDB.KeyLockInfo
5784 class KeyLockInfoJni : public JavaClass {
5785  public:
5786   /**
5787    * Get the Java Class org.rocksdb.TransactionDB.KeyLockInfo
5788    *
5789    * @param env A pointer to the Java environment
5790    *
5791    * @return The Java Class or nullptr if one of the
5792    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
5793    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
5794    */
5795   static jclass getJClass(JNIEnv* env) {
5796     return JavaClass::getJClass(env,
5797         "org/rocksdb/TransactionDB$KeyLockInfo");
5798   }
5799 
5800   /**
5801    * Create a new Java org.rocksdb.TransactionDB.KeyLockInfo object
5802    * with the same properties as the provided C++ ROCKSDB_NAMESPACE::KeyLockInfo
5803    * object
5804    *
5805    * @param env A pointer to the Java environment
5806    * @param key_lock_info The ROCKSDB_NAMESPACE::KeyLockInfo object
5807    *
5808    * @return A reference to a Java
5809    *     org.rocksdb.TransactionDB.KeyLockInfo object,
5810    *     or nullptr if an an exception occurs
5811    */
5812   static jobject construct(
5813       JNIEnv* env, const ROCKSDB_NAMESPACE::KeyLockInfo& key_lock_info) {
5814     jclass jclazz = getJClass(env);
5815     if(jclazz == nullptr) {
5816       // exception occurred accessing class
5817       return nullptr;
5818     }
5819 
5820     jmethodID mid = env->GetMethodID(
5821       jclazz, "<init>", "(Ljava/lang/String;[JZ)V");
5822     if (mid == nullptr) {
5823       // exception thrown: NoSuchMethodException or OutOfMemoryError
5824       return nullptr;
5825     }
5826 
5827     jstring jkey = env->NewStringUTF(key_lock_info.key.c_str());
5828     if (jkey == nullptr) {
5829       // exception thrown: OutOfMemoryError
5830       return nullptr;
5831     }
5832 
5833     const jsize jtransaction_ids_len = static_cast<jsize>(key_lock_info.ids.size());
5834     jlongArray jtransactions_ids = env->NewLongArray(jtransaction_ids_len);
5835     if (jtransactions_ids == nullptr) {
5836       // exception thrown: OutOfMemoryError
5837       env->DeleteLocalRef(jkey);
5838       return nullptr;
5839     }
5840 
5841     const jobject jkey_lock_info = env->NewObject(jclazz, mid,
5842       jkey, jtransactions_ids, key_lock_info.exclusive);
5843     if(jkey_lock_info == nullptr) {
5844       // exception thrown: InstantiationException or OutOfMemoryError
5845       env->DeleteLocalRef(jtransactions_ids);
5846       env->DeleteLocalRef(jkey);
5847       return nullptr;
5848     }
5849 
5850     return jkey_lock_info;
5851   }
5852 };
5853 
5854 // The portal class for org.rocksdb.TransactionDB.DeadlockInfo
5855 class DeadlockInfoJni : public JavaClass {
5856  public:
5857   /**
5858    * Get the Java Class org.rocksdb.TransactionDB.DeadlockInfo
5859    *
5860    * @param env A pointer to the Java environment
5861    *
5862    * @return The Java Class or nullptr if one of the
5863    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
5864    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
5865    */
5866    static jclass getJClass(JNIEnv* env) {
5867      return JavaClass::getJClass(env,"org/rocksdb/TransactionDB$DeadlockInfo");
5868   }
5869 };
5870 
5871 // The portal class for org.rocksdb.TransactionDB.DeadlockPath
5872 class DeadlockPathJni : public JavaClass {
5873  public:
5874   /**
5875    * Get the Java Class org.rocksdb.TransactionDB.DeadlockPath
5876    *
5877    * @param env A pointer to the Java environment
5878    *
5879    * @return The Java Class or nullptr if one of the
5880    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
5881    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
5882    */
5883   static jclass getJClass(JNIEnv* env) {
5884     return JavaClass::getJClass(env,
5885         "org/rocksdb/TransactionDB$DeadlockPath");
5886   }
5887 
5888   /**
5889    * Create a new Java org.rocksdb.TransactionDB.DeadlockPath object
5890    *
5891    * @param env A pointer to the Java environment
5892    *
5893    * @return A reference to a Java
5894    *     org.rocksdb.TransactionDB.DeadlockPath object,
5895    *     or nullptr if an an exception occurs
5896    */
5897   static jobject construct(JNIEnv* env,
5898     const jobjectArray jdeadlock_infos, const bool limit_exceeded) {
5899     jclass jclazz = getJClass(env);
5900     if(jclazz == nullptr) {
5901       // exception occurred accessing class
5902       return nullptr;
5903     }
5904 
5905     jmethodID mid = env->GetMethodID(
5906       jclazz, "<init>", "([LDeadlockInfo;Z)V");
5907     if (mid == nullptr) {
5908       // exception thrown: NoSuchMethodException or OutOfMemoryError
5909       return nullptr;
5910     }
5911 
5912     const jobject jdeadlock_path = env->NewObject(jclazz, mid,
5913       jdeadlock_infos, limit_exceeded);
5914     if(jdeadlock_path == nullptr) {
5915       // exception thrown: InstantiationException or OutOfMemoryError
5916       return nullptr;
5917     }
5918 
5919     return jdeadlock_path;
5920   }
5921 };
5922 
5923 class AbstractTableFilterJni
5924     : public RocksDBNativeClass<
5925           const ROCKSDB_NAMESPACE::TableFilterJniCallback*,
5926           AbstractTableFilterJni> {
5927  public:
5928   /**
5929    * Get the Java Method: TableFilter#filter(TableProperties)
5930    *
5931    * @param env A pointer to the Java environment
5932    *
5933    * @return The Java Method ID or nullptr if the class or method id could not
5934    *     be retieved
5935    */
5936   static jmethodID getFilterMethod(JNIEnv* env) {
5937     jclass jclazz = getJClass(env);
5938     if(jclazz == nullptr) {
5939       // exception occurred accessing class
5940       return nullptr;
5941     }
5942 
5943     static jmethodID mid =
5944         env->GetMethodID(jclazz, "filter", "(Lorg/rocksdb/TableProperties;)Z");
5945     assert(mid != nullptr);
5946     return mid;
5947   }
5948 
5949  private:
5950   static jclass getJClass(JNIEnv* env) {
5951     return JavaClass::getJClass(env, "org/rocksdb/TableFilter");
5952   }
5953 };
5954 
5955 class TablePropertiesJni : public JavaClass {
5956  public:
5957   /**
5958    * Create a new Java org.rocksdb.TableProperties object.
5959    *
5960    * @param env A pointer to the Java environment
5961    * @param table_properties A Cpp table properties object
5962    *
5963    * @return A reference to a Java org.rocksdb.TableProperties object, or
5964    * nullptr if an an exception occurs
5965    */
5966   static jobject fromCppTableProperties(
5967       JNIEnv* env, const ROCKSDB_NAMESPACE::TableProperties& table_properties) {
5968     jclass jclazz = getJClass(env);
5969     if (jclazz == nullptr) {
5970       // exception occurred accessing class
5971       return nullptr;
5972     }
5973 
5974     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJJJJJJJJJJJJJJJJJJ[BLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V");
5975     if (mid == nullptr) {
5976       // exception thrown: NoSuchMethodException or OutOfMemoryError
5977       return nullptr;
5978     }
5979 
5980     jbyteArray jcolumn_family_name = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
5981         env, table_properties.column_family_name);
5982     if (jcolumn_family_name == nullptr) {
5983       // exception occurred creating java string
5984       return nullptr;
5985     }
5986 
5987     jstring jfilter_policy_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
5988         env, &table_properties.filter_policy_name, true);
5989     if (env->ExceptionCheck()) {
5990       // exception occurred creating java string
5991       env->DeleteLocalRef(jcolumn_family_name);
5992       return nullptr;
5993     }
5994 
5995     jstring jcomparator_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
5996         env, &table_properties.comparator_name, true);
5997     if (env->ExceptionCheck()) {
5998       // exception occurred creating java string
5999       env->DeleteLocalRef(jcolumn_family_name);
6000       env->DeleteLocalRef(jfilter_policy_name);
6001       return nullptr;
6002     }
6003 
6004     jstring jmerge_operator_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6005         env, &table_properties.merge_operator_name, true);
6006     if (env->ExceptionCheck()) {
6007       // exception occurred creating java string
6008       env->DeleteLocalRef(jcolumn_family_name);
6009       env->DeleteLocalRef(jfilter_policy_name);
6010       env->DeleteLocalRef(jcomparator_name);
6011       return nullptr;
6012     }
6013 
6014     jstring jprefix_extractor_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6015         env, &table_properties.prefix_extractor_name, true);
6016     if (env->ExceptionCheck()) {
6017       // exception occurred creating java string
6018       env->DeleteLocalRef(jcolumn_family_name);
6019       env->DeleteLocalRef(jfilter_policy_name);
6020       env->DeleteLocalRef(jcomparator_name);
6021       env->DeleteLocalRef(jmerge_operator_name);
6022       return nullptr;
6023     }
6024 
6025     jstring jproperty_collectors_names =
6026         ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6027             env, &table_properties.property_collectors_names, true);
6028     if (env->ExceptionCheck()) {
6029       // exception occurred creating java string
6030       env->DeleteLocalRef(jcolumn_family_name);
6031       env->DeleteLocalRef(jfilter_policy_name);
6032       env->DeleteLocalRef(jcomparator_name);
6033       env->DeleteLocalRef(jmerge_operator_name);
6034       env->DeleteLocalRef(jprefix_extractor_name);
6035       return nullptr;
6036     }
6037 
6038     jstring jcompression_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6039         env, &table_properties.compression_name, true);
6040     if (env->ExceptionCheck()) {
6041       // exception occurred creating java string
6042       env->DeleteLocalRef(jcolumn_family_name);
6043       env->DeleteLocalRef(jfilter_policy_name);
6044       env->DeleteLocalRef(jcomparator_name);
6045       env->DeleteLocalRef(jmerge_operator_name);
6046       env->DeleteLocalRef(jprefix_extractor_name);
6047       env->DeleteLocalRef(jproperty_collectors_names);
6048       return nullptr;
6049     }
6050 
6051     // Map<String, String>
6052     jobject juser_collected_properties =
6053         ROCKSDB_NAMESPACE::HashMapJni::fromCppMap(
6054             env, &table_properties.user_collected_properties);
6055     if (env->ExceptionCheck()) {
6056       // exception occurred creating java map
6057       env->DeleteLocalRef(jcolumn_family_name);
6058       env->DeleteLocalRef(jfilter_policy_name);
6059       env->DeleteLocalRef(jcomparator_name);
6060       env->DeleteLocalRef(jmerge_operator_name);
6061       env->DeleteLocalRef(jprefix_extractor_name);
6062       env->DeleteLocalRef(jproperty_collectors_names);
6063       env->DeleteLocalRef(jcompression_name);
6064       return nullptr;
6065     }
6066 
6067     // Map<String, String>
6068     jobject jreadable_properties = ROCKSDB_NAMESPACE::HashMapJni::fromCppMap(
6069         env, &table_properties.readable_properties);
6070     if (env->ExceptionCheck()) {
6071       // exception occurred creating java map
6072       env->DeleteLocalRef(jcolumn_family_name);
6073       env->DeleteLocalRef(jfilter_policy_name);
6074       env->DeleteLocalRef(jcomparator_name);
6075       env->DeleteLocalRef(jmerge_operator_name);
6076       env->DeleteLocalRef(jprefix_extractor_name);
6077       env->DeleteLocalRef(jproperty_collectors_names);
6078       env->DeleteLocalRef(jcompression_name);
6079       env->DeleteLocalRef(juser_collected_properties);
6080       return nullptr;
6081     }
6082 
6083     // Map<String, Long>
6084     jobject jproperties_offsets = ROCKSDB_NAMESPACE::HashMapJni::fromCppMap(
6085         env, &table_properties.properties_offsets);
6086     if (env->ExceptionCheck()) {
6087       // exception occurred creating java map
6088       env->DeleteLocalRef(jcolumn_family_name);
6089       env->DeleteLocalRef(jfilter_policy_name);
6090       env->DeleteLocalRef(jcomparator_name);
6091       env->DeleteLocalRef(jmerge_operator_name);
6092       env->DeleteLocalRef(jprefix_extractor_name);
6093       env->DeleteLocalRef(jproperty_collectors_names);
6094       env->DeleteLocalRef(jcompression_name);
6095       env->DeleteLocalRef(juser_collected_properties);
6096       env->DeleteLocalRef(jreadable_properties);
6097       return nullptr;
6098     }
6099 
6100     jobject jtable_properties = env->NewObject(jclazz, mid,
6101         static_cast<jlong>(table_properties.data_size),
6102         static_cast<jlong>(table_properties.index_size),
6103         static_cast<jlong>(table_properties.index_partitions),
6104         static_cast<jlong>(table_properties.top_level_index_size),
6105         static_cast<jlong>(table_properties.index_key_is_user_key),
6106         static_cast<jlong>(table_properties.index_value_is_delta_encoded),
6107         static_cast<jlong>(table_properties.filter_size),
6108         static_cast<jlong>(table_properties.raw_key_size),
6109         static_cast<jlong>(table_properties.raw_value_size),
6110         static_cast<jlong>(table_properties.num_data_blocks),
6111         static_cast<jlong>(table_properties.num_entries),
6112         static_cast<jlong>(table_properties.num_deletions),
6113         static_cast<jlong>(table_properties.num_merge_operands),
6114         static_cast<jlong>(table_properties.num_range_deletions),
6115         static_cast<jlong>(table_properties.format_version),
6116         static_cast<jlong>(table_properties.fixed_key_len),
6117         static_cast<jlong>(table_properties.column_family_id),
6118         static_cast<jlong>(table_properties.creation_time),
6119         static_cast<jlong>(table_properties.oldest_key_time),
6120         jcolumn_family_name,
6121         jfilter_policy_name,
6122         jcomparator_name,
6123         jmerge_operator_name,
6124         jprefix_extractor_name,
6125         jproperty_collectors_names,
6126         jcompression_name,
6127         juser_collected_properties,
6128         jreadable_properties,
6129         jproperties_offsets
6130     );
6131 
6132     if (env->ExceptionCheck()) {
6133       return nullptr;
6134     }
6135 
6136     return jtable_properties;
6137   }
6138 
6139  private:
6140   static jclass getJClass(JNIEnv* env) {
6141     return JavaClass::getJClass(env, "org/rocksdb/TableProperties");
6142   }
6143 };
6144 
6145 class ColumnFamilyDescriptorJni : public JavaClass {
6146  public:
6147   /**
6148    * Get the Java Class org.rocksdb.ColumnFamilyDescriptor
6149    *
6150    * @param env A pointer to the Java environment
6151    *
6152    * @return The Java Class or nullptr if one of the
6153    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
6154    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
6155    */
6156   static jclass getJClass(JNIEnv* env) {
6157     return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyDescriptor");
6158   }
6159 
6160   /**
6161    * Create a new Java org.rocksdb.ColumnFamilyDescriptor object with the same
6162    * properties as the provided C++ ROCKSDB_NAMESPACE::ColumnFamilyDescriptor
6163    * object
6164    *
6165    * @param env A pointer to the Java environment
6166    * @param cfd A pointer to ROCKSDB_NAMESPACE::ColumnFamilyDescriptor object
6167    *
6168    * @return A reference to a Java org.rocksdb.ColumnFamilyDescriptor object, or
6169    * nullptr if an an exception occurs
6170    */
6171   static jobject construct(JNIEnv* env, ColumnFamilyDescriptor* cfd) {
6172     jbyteArray jcf_name = JniUtil::copyBytes(env, cfd->name);
6173     jobject cfopts = ColumnFamilyOptionsJni::construct(env, &(cfd->options));
6174 
6175     jclass jclazz = getJClass(env);
6176     if (jclazz == nullptr) {
6177       // exception occurred accessing class
6178       return nullptr;
6179     }
6180 
6181     jmethodID mid = env->GetMethodID(jclazz, "<init>",
6182                                      "([BLorg/rocksdb/ColumnFamilyOptions;)V");
6183     if (mid == nullptr) {
6184       // exception thrown: NoSuchMethodException or OutOfMemoryError
6185       env->DeleteLocalRef(jcf_name);
6186       return nullptr;
6187     }
6188 
6189     jobject jcfd = env->NewObject(jclazz, mid, jcf_name, cfopts);
6190     if (env->ExceptionCheck()) {
6191       env->DeleteLocalRef(jcf_name);
6192       return nullptr;
6193     }
6194 
6195     return jcfd;
6196   }
6197 
6198   /**
6199    * Get the Java Method: ColumnFamilyDescriptor#columnFamilyName
6200    *
6201    * @param env A pointer to the Java environment
6202    *
6203    * @return The Java Method ID or nullptr if the class or method id could not
6204    *     be retieved
6205    */
6206   static jmethodID getColumnFamilyNameMethod(JNIEnv* env) {
6207     jclass jclazz = getJClass(env);
6208     if (jclazz == nullptr) {
6209       // exception occurred accessing class
6210       return nullptr;
6211     }
6212 
6213     static jmethodID mid = env->GetMethodID(jclazz, "columnFamilyName", "()[B");
6214     assert(mid != nullptr);
6215     return mid;
6216   }
6217 
6218   /**
6219    * Get the Java Method: ColumnFamilyDescriptor#columnFamilyOptions
6220    *
6221    * @param env A pointer to the Java environment
6222    *
6223    * @return The Java Method ID or nullptr if the class or method id could not
6224    *     be retieved
6225    */
6226   static jmethodID getColumnFamilyOptionsMethod(JNIEnv* env) {
6227     jclass jclazz = getJClass(env);
6228     if (jclazz == nullptr) {
6229       // exception occurred accessing class
6230       return nullptr;
6231     }
6232 
6233     static jmethodID mid = env->GetMethodID(
6234         jclazz, "columnFamilyOptions", "()Lorg/rocksdb/ColumnFamilyOptions;");
6235     assert(mid != nullptr);
6236     return mid;
6237   }
6238 };
6239 
6240 // The portal class for org.rocksdb.IndexType
6241 class IndexTypeJni {
6242  public:
6243   // Returns the equivalent org.rocksdb.IndexType for the provided
6244   // C++ ROCKSDB_NAMESPACE::IndexType enum
6245   static jbyte toJavaIndexType(
6246       const ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType& index_type) {
6247     switch (index_type) {
6248       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::kBinarySearch:
6249         return 0x0;
6250       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::kHashSearch:
6251         return 0x1;
6252       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6253           kTwoLevelIndexSearch:
6254         return 0x2;
6255       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6256           kBinarySearchWithFirstKey:
6257         return 0x3;
6258       default:
6259         return 0x7F;  // undefined
6260     }
6261   }
6262 
6263   // Returns the equivalent C++ ROCKSDB_NAMESPACE::IndexType enum for the
6264   // provided Java org.rocksdb.IndexType
6265   static ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType toCppIndexType(
6266       jbyte jindex_type) {
6267     switch (jindex_type) {
6268       case 0x0:
6269         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6270             kBinarySearch;
6271       case 0x1:
6272         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6273             kHashSearch;
6274       case 0x2:
6275         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6276             kTwoLevelIndexSearch;
6277       case 0x3:
6278         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6279             kBinarySearchWithFirstKey;
6280       default:
6281         // undefined/default
6282         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::IndexType::
6283             kBinarySearch;
6284     }
6285   }
6286 };
6287 
6288 // The portal class for org.rocksdb.DataBlockIndexType
6289 class DataBlockIndexTypeJni {
6290  public:
6291   // Returns the equivalent org.rocksdb.DataBlockIndexType for the provided
6292   // C++ ROCKSDB_NAMESPACE::DataBlockIndexType enum
6293   static jbyte toJavaDataBlockIndexType(
6294       const ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType&
6295           index_type) {
6296     switch (index_type) {
6297       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType::
6298           kDataBlockBinarySearch:
6299         return 0x0;
6300       case ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType::
6301           kDataBlockBinaryAndHash:
6302         return 0x1;
6303       default:
6304         return 0x7F;  // undefined
6305     }
6306   }
6307 
6308   // Returns the equivalent C++ ROCKSDB_NAMESPACE::DataBlockIndexType enum for
6309   // the provided Java org.rocksdb.DataBlockIndexType
6310   static ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType
6311   toCppDataBlockIndexType(jbyte jindex_type) {
6312     switch (jindex_type) {
6313       case 0x0:
6314         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType::
6315             kDataBlockBinarySearch;
6316       case 0x1:
6317         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType::
6318             kDataBlockBinaryAndHash;
6319       default:
6320         // undefined/default
6321         return ROCKSDB_NAMESPACE::BlockBasedTableOptions::DataBlockIndexType::
6322             kDataBlockBinarySearch;
6323     }
6324   }
6325 };
6326 
6327 // The portal class for org.rocksdb.ChecksumType
6328 class ChecksumTypeJni {
6329  public:
6330   // Returns the equivalent org.rocksdb.ChecksumType for the provided
6331   // C++ ROCKSDB_NAMESPACE::ChecksumType enum
6332   static jbyte toJavaChecksumType(
6333       const ROCKSDB_NAMESPACE::ChecksumType& checksum_type) {
6334     switch (checksum_type) {
6335       case ROCKSDB_NAMESPACE::ChecksumType::kNoChecksum:
6336         return 0x0;
6337       case ROCKSDB_NAMESPACE::ChecksumType::kCRC32c:
6338         return 0x1;
6339       case ROCKSDB_NAMESPACE::ChecksumType::kxxHash:
6340         return 0x2;
6341       case ROCKSDB_NAMESPACE::ChecksumType::kxxHash64:
6342         return 0x3;
6343       default:
6344         return 0x7F;  // undefined
6345     }
6346   }
6347 
6348   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ChecksumType enum for the
6349   // provided Java org.rocksdb.ChecksumType
6350   static ROCKSDB_NAMESPACE::ChecksumType toCppChecksumType(
6351       jbyte jchecksum_type) {
6352     switch (jchecksum_type) {
6353       case 0x0:
6354         return ROCKSDB_NAMESPACE::ChecksumType::kNoChecksum;
6355       case 0x1:
6356         return ROCKSDB_NAMESPACE::ChecksumType::kCRC32c;
6357       case 0x2:
6358         return ROCKSDB_NAMESPACE::ChecksumType::kxxHash;
6359       case 0x3:
6360         return ROCKSDB_NAMESPACE::ChecksumType::kxxHash64;
6361       default:
6362         // undefined/default
6363         return ROCKSDB_NAMESPACE::ChecksumType::kCRC32c;
6364     }
6365   }
6366 };
6367 
6368 // The portal class for org.rocksdb.Priority
6369 class PriorityJni {
6370  public:
6371   // Returns the equivalent org.rocksdb.Priority for the provided
6372   // C++ ROCKSDB_NAMESPACE::Env::Priority enum
6373   static jbyte toJavaPriority(
6374       const ROCKSDB_NAMESPACE::Env::Priority& priority) {
6375     switch (priority) {
6376       case ROCKSDB_NAMESPACE::Env::Priority::BOTTOM:
6377         return 0x0;
6378       case ROCKSDB_NAMESPACE::Env::Priority::LOW:
6379         return 0x1;
6380       case ROCKSDB_NAMESPACE::Env::Priority::HIGH:
6381         return 0x2;
6382       case ROCKSDB_NAMESPACE::Env::Priority::TOTAL:
6383         return 0x3;
6384       default:
6385         return 0x7F;  // undefined
6386     }
6387   }
6388 
6389   // Returns the equivalent C++ ROCKSDB_NAMESPACE::env::Priority enum for the
6390   // provided Java org.rocksdb.Priority
6391   static ROCKSDB_NAMESPACE::Env::Priority toCppPriority(jbyte jpriority) {
6392     switch (jpriority) {
6393       case 0x0:
6394         return ROCKSDB_NAMESPACE::Env::Priority::BOTTOM;
6395       case 0x1:
6396         return ROCKSDB_NAMESPACE::Env::Priority::LOW;
6397       case 0x2:
6398         return ROCKSDB_NAMESPACE::Env::Priority::HIGH;
6399       case 0x3:
6400         return ROCKSDB_NAMESPACE::Env::Priority::TOTAL;
6401       default:
6402         // undefined/default
6403         return ROCKSDB_NAMESPACE::Env::Priority::LOW;
6404     }
6405   }
6406 };
6407 
6408 // The portal class for org.rocksdb.ThreadType
6409 class ThreadTypeJni {
6410  public:
6411   // Returns the equivalent org.rocksdb.ThreadType for the provided
6412   // C++ ROCKSDB_NAMESPACE::ThreadStatus::ThreadType enum
6413   static jbyte toJavaThreadType(
6414       const ROCKSDB_NAMESPACE::ThreadStatus::ThreadType& thread_type) {
6415     switch (thread_type) {
6416       case ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::HIGH_PRIORITY:
6417         return 0x0;
6418       case ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::LOW_PRIORITY:
6419         return 0x1;
6420       case ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::USER:
6421         return 0x2;
6422       case ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::BOTTOM_PRIORITY:
6423         return 0x3;
6424       default:
6425         return 0x7F;  // undefined
6426     }
6427   }
6428 
6429   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ThreadStatus::ThreadType enum
6430   // for the provided Java org.rocksdb.ThreadType
6431   static ROCKSDB_NAMESPACE::ThreadStatus::ThreadType toCppThreadType(
6432       jbyte jthread_type) {
6433     switch (jthread_type) {
6434       case 0x0:
6435         return ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::HIGH_PRIORITY;
6436       case 0x1:
6437         return ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::LOW_PRIORITY;
6438       case 0x2:
6439         return ThreadStatus::ThreadType::USER;
6440       case 0x3:
6441         return ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::BOTTOM_PRIORITY;
6442       default:
6443         // undefined/default
6444         return ROCKSDB_NAMESPACE::ThreadStatus::ThreadType::LOW_PRIORITY;
6445     }
6446   }
6447 };
6448 
6449 // The portal class for org.rocksdb.OperationType
6450 class OperationTypeJni {
6451  public:
6452   // Returns the equivalent org.rocksdb.OperationType for the provided
6453   // C++ ROCKSDB_NAMESPACE::ThreadStatus::OperationType enum
6454   static jbyte toJavaOperationType(
6455       const ROCKSDB_NAMESPACE::ThreadStatus::OperationType& operation_type) {
6456     switch (operation_type) {
6457       case ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_UNKNOWN:
6458         return 0x0;
6459       case ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_COMPACTION:
6460         return 0x1;
6461       case ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_FLUSH:
6462         return 0x2;
6463       default:
6464         return 0x7F;  // undefined
6465     }
6466   }
6467 
6468   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ThreadStatus::OperationType
6469   // enum for the provided Java org.rocksdb.OperationType
6470   static ROCKSDB_NAMESPACE::ThreadStatus::OperationType toCppOperationType(
6471       jbyte joperation_type) {
6472     switch (joperation_type) {
6473       case 0x0:
6474         return ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_UNKNOWN;
6475       case 0x1:
6476         return ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_COMPACTION;
6477       case 0x2:
6478         return ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_FLUSH;
6479       default:
6480         // undefined/default
6481         return ROCKSDB_NAMESPACE::ThreadStatus::OperationType::OP_UNKNOWN;
6482     }
6483   }
6484 };
6485 
6486 // The portal class for org.rocksdb.OperationStage
6487 class OperationStageJni {
6488  public:
6489   // Returns the equivalent org.rocksdb.OperationStage for the provided
6490   // C++ ROCKSDB_NAMESPACE::ThreadStatus::OperationStage enum
6491   static jbyte toJavaOperationStage(
6492       const ROCKSDB_NAMESPACE::ThreadStatus::OperationStage& operation_stage) {
6493     switch (operation_stage) {
6494       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::STAGE_UNKNOWN:
6495         return 0x0;
6496       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::STAGE_FLUSH_RUN:
6497         return 0x1;
6498       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6499           STAGE_FLUSH_WRITE_L0:
6500         return 0x2;
6501       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6502           STAGE_COMPACTION_PREPARE:
6503         return 0x3;
6504       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6505           STAGE_COMPACTION_RUN:
6506         return 0x4;
6507       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6508           STAGE_COMPACTION_PROCESS_KV:
6509         return 0x5;
6510       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6511           STAGE_COMPACTION_INSTALL:
6512         return 0x6;
6513       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6514           STAGE_COMPACTION_SYNC_FILE:
6515         return 0x7;
6516       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6517           STAGE_PICK_MEMTABLES_TO_FLUSH:
6518         return 0x8;
6519       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6520           STAGE_MEMTABLE_ROLLBACK:
6521         return 0x9;
6522       case ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6523           STAGE_MEMTABLE_INSTALL_FLUSH_RESULTS:
6524         return 0xA;
6525       default:
6526         return 0x7F;  // undefined
6527     }
6528   }
6529 
6530   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ThreadStatus::OperationStage
6531   // enum for the provided Java org.rocksdb.OperationStage
6532   static ROCKSDB_NAMESPACE::ThreadStatus::OperationStage toCppOperationStage(
6533       jbyte joperation_stage) {
6534     switch (joperation_stage) {
6535       case 0x0:
6536         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::STAGE_UNKNOWN;
6537       case 0x1:
6538         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::STAGE_FLUSH_RUN;
6539       case 0x2:
6540         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6541             STAGE_FLUSH_WRITE_L0;
6542       case 0x3:
6543         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6544             STAGE_COMPACTION_PREPARE;
6545       case 0x4:
6546         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6547             STAGE_COMPACTION_RUN;
6548       case 0x5:
6549         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6550             STAGE_COMPACTION_PROCESS_KV;
6551       case 0x6:
6552         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6553             STAGE_COMPACTION_INSTALL;
6554       case 0x7:
6555         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6556             STAGE_COMPACTION_SYNC_FILE;
6557       case 0x8:
6558         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6559             STAGE_PICK_MEMTABLES_TO_FLUSH;
6560       case 0x9:
6561         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6562             STAGE_MEMTABLE_ROLLBACK;
6563       case 0xA:
6564         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::
6565             STAGE_MEMTABLE_INSTALL_FLUSH_RESULTS;
6566       default:
6567         // undefined/default
6568         return ROCKSDB_NAMESPACE::ThreadStatus::OperationStage::STAGE_UNKNOWN;
6569     }
6570   }
6571 };
6572 
6573 // The portal class for org.rocksdb.StateType
6574 class StateTypeJni {
6575  public:
6576   // Returns the equivalent org.rocksdb.StateType for the provided
6577   // C++ ROCKSDB_NAMESPACE::ThreadStatus::StateType enum
6578   static jbyte toJavaStateType(
6579       const ROCKSDB_NAMESPACE::ThreadStatus::StateType& state_type) {
6580     switch (state_type) {
6581       case ROCKSDB_NAMESPACE::ThreadStatus::StateType::STATE_UNKNOWN:
6582         return 0x0;
6583       case ROCKSDB_NAMESPACE::ThreadStatus::StateType::STATE_MUTEX_WAIT:
6584         return 0x1;
6585       default:
6586         return 0x7F;  // undefined
6587     }
6588   }
6589 
6590   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ThreadStatus::StateType enum
6591   // for the provided Java org.rocksdb.StateType
6592   static ROCKSDB_NAMESPACE::ThreadStatus::StateType toCppStateType(
6593       jbyte jstate_type) {
6594     switch (jstate_type) {
6595       case 0x0:
6596         return ROCKSDB_NAMESPACE::ThreadStatus::StateType::STATE_UNKNOWN;
6597       case 0x1:
6598         return ROCKSDB_NAMESPACE::ThreadStatus::StateType::STATE_MUTEX_WAIT;
6599       default:
6600         // undefined/default
6601         return ROCKSDB_NAMESPACE::ThreadStatus::StateType::STATE_UNKNOWN;
6602     }
6603   }
6604 };
6605 
6606 // The portal class for org.rocksdb.ThreadStatus
6607 class ThreadStatusJni : public JavaClass {
6608  public:
6609   /**
6610    * Get the Java Class org.rocksdb.ThreadStatus
6611    *
6612    * @param env A pointer to the Java environment
6613    *
6614    * @return The Java Class or nullptr if one of the
6615    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
6616    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
6617    */
6618   static jclass getJClass(JNIEnv* env) {
6619     return JavaClass::getJClass(env,
6620         "org/rocksdb/ThreadStatus");
6621   }
6622 
6623   /**
6624    * Create a new Java org.rocksdb.ThreadStatus object with the same
6625    * properties as the provided C++ ROCKSDB_NAMESPACE::ThreadStatus object
6626    *
6627    * @param env A pointer to the Java environment
6628    * @param thread_status A pointer to ROCKSDB_NAMESPACE::ThreadStatus object
6629    *
6630    * @return A reference to a Java org.rocksdb.ColumnFamilyOptions object, or
6631    * nullptr if an an exception occurs
6632    */
6633   static jobject construct(
6634       JNIEnv* env, const ROCKSDB_NAMESPACE::ThreadStatus* thread_status) {
6635     jclass jclazz = getJClass(env);
6636     if(jclazz == nullptr) {
6637       // exception occurred accessing class
6638       return nullptr;
6639     }
6640 
6641     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JBLjava/lang/String;Ljava/lang/String;BJB[JB)V");
6642     if (mid == nullptr) {
6643       // exception thrown: NoSuchMethodException or OutOfMemoryError
6644       return nullptr;
6645     }
6646 
6647     jstring jdb_name =
6648         JniUtil::toJavaString(env, &(thread_status->db_name), true);
6649     if (env->ExceptionCheck()) {
6650         // an error occurred
6651         return nullptr;
6652     }
6653 
6654     jstring jcf_name =
6655         JniUtil::toJavaString(env, &(thread_status->cf_name), true);
6656     if (env->ExceptionCheck()) {
6657         // an error occurred
6658         env->DeleteLocalRef(jdb_name);
6659         return nullptr;
6660     }
6661 
6662     // long[]
6663     const jsize len = static_cast<jsize>(
6664         ROCKSDB_NAMESPACE::ThreadStatus::kNumOperationProperties);
6665     jlongArray joperation_properties =
6666         env->NewLongArray(len);
6667     if (joperation_properties == nullptr) {
6668       // an exception occurred
6669       env->DeleteLocalRef(jdb_name);
6670       env->DeleteLocalRef(jcf_name);
6671       return nullptr;
6672     }
6673     jlong *body = env->GetLongArrayElements(joperation_properties, nullptr);
6674     if (body == nullptr) {
6675         // exception thrown: OutOfMemoryError
6676         env->DeleteLocalRef(jdb_name);
6677         env->DeleteLocalRef(jcf_name);
6678         env->DeleteLocalRef(joperation_properties);
6679         return nullptr;
6680     }
6681     for (size_t i = 0; i < len; ++i) {
6682       body[i] = static_cast<jlong>(thread_status->op_properties[i]);
6683     }
6684     env->ReleaseLongArrayElements(joperation_properties, body, 0);
6685 
6686     jobject jcfd = env->NewObject(jclazz, mid,
6687         static_cast<jlong>(thread_status->thread_id),
6688         ThreadTypeJni::toJavaThreadType(thread_status->thread_type),
6689         jdb_name,
6690         jcf_name,
6691         OperationTypeJni::toJavaOperationType(thread_status->operation_type),
6692         static_cast<jlong>(thread_status->op_elapsed_micros),
6693         OperationStageJni::toJavaOperationStage(thread_status->operation_stage),
6694         joperation_properties,
6695         StateTypeJni::toJavaStateType(thread_status->state_type));
6696     if (env->ExceptionCheck()) {
6697       // exception occurred
6698         env->DeleteLocalRef(jdb_name);
6699         env->DeleteLocalRef(jcf_name);
6700         env->DeleteLocalRef(joperation_properties);
6701       return nullptr;
6702     }
6703 
6704     // cleanup
6705     env->DeleteLocalRef(jdb_name);
6706     env->DeleteLocalRef(jcf_name);
6707     env->DeleteLocalRef(joperation_properties);
6708 
6709     return jcfd;
6710   }
6711 };
6712 
6713 // The portal class for org.rocksdb.CompactionStyle
6714 class CompactionStyleJni {
6715  public:
6716   // Returns the equivalent org.rocksdb.CompactionStyle for the provided
6717   // C++ ROCKSDB_NAMESPACE::CompactionStyle enum
6718   static jbyte toJavaCompactionStyle(
6719       const ROCKSDB_NAMESPACE::CompactionStyle& compaction_style) {
6720     switch (compaction_style) {
6721       case ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleLevel:
6722         return 0x0;
6723       case ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleUniversal:
6724         return 0x1;
6725       case ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleFIFO:
6726         return 0x2;
6727       case ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleNone:
6728         return 0x3;
6729       default:
6730         return 0x7F;  // undefined
6731     }
6732   }
6733 
6734   // Returns the equivalent C++ ROCKSDB_NAMESPACE::CompactionStyle enum for the
6735   // provided Java org.rocksdb.CompactionStyle
6736   static ROCKSDB_NAMESPACE::CompactionStyle toCppCompactionStyle(
6737       jbyte jcompaction_style) {
6738     switch (jcompaction_style) {
6739       case 0x0:
6740         return ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleLevel;
6741       case 0x1:
6742         return ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleUniversal;
6743       case 0x2:
6744         return ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleFIFO;
6745       case 0x3:
6746         return ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleNone;
6747       default:
6748         // undefined/default
6749         return ROCKSDB_NAMESPACE::CompactionStyle::kCompactionStyleLevel;
6750     }
6751   }
6752 };
6753 
6754 // The portal class for org.rocksdb.CompactionReason
6755 class CompactionReasonJni {
6756  public:
6757   // Returns the equivalent org.rocksdb.CompactionReason for the provided
6758   // C++ ROCKSDB_NAMESPACE::CompactionReason enum
6759   static jbyte toJavaCompactionReason(
6760       const ROCKSDB_NAMESPACE::CompactionReason& compaction_reason) {
6761     switch (compaction_reason) {
6762       case ROCKSDB_NAMESPACE::CompactionReason::kUnknown:
6763         return 0x0;
6764       case ROCKSDB_NAMESPACE::CompactionReason::kLevelL0FilesNum:
6765         return 0x1;
6766       case ROCKSDB_NAMESPACE::CompactionReason::kLevelMaxLevelSize:
6767         return 0x2;
6768       case ROCKSDB_NAMESPACE::CompactionReason::kUniversalSizeAmplification:
6769         return 0x3;
6770       case ROCKSDB_NAMESPACE::CompactionReason::kUniversalSizeRatio:
6771         return 0x4;
6772       case ROCKSDB_NAMESPACE::CompactionReason::kUniversalSortedRunNum:
6773         return 0x5;
6774       case ROCKSDB_NAMESPACE::CompactionReason::kFIFOMaxSize:
6775         return 0x6;
6776       case ROCKSDB_NAMESPACE::CompactionReason::kFIFOReduceNumFiles:
6777         return 0x7;
6778       case ROCKSDB_NAMESPACE::CompactionReason::kFIFOTtl:
6779         return 0x8;
6780       case ROCKSDB_NAMESPACE::CompactionReason::kManualCompaction:
6781         return 0x9;
6782       case ROCKSDB_NAMESPACE::CompactionReason::kFilesMarkedForCompaction:
6783         return 0x10;
6784       case ROCKSDB_NAMESPACE::CompactionReason::kBottommostFiles:
6785         return 0x0A;
6786       case ROCKSDB_NAMESPACE::CompactionReason::kTtl:
6787         return 0x0B;
6788       case ROCKSDB_NAMESPACE::CompactionReason::kFlush:
6789         return 0x0C;
6790       case ROCKSDB_NAMESPACE::CompactionReason::kExternalSstIngestion:
6791         return 0x0D;
6792       default:
6793         return 0x7F;  // undefined
6794     }
6795   }
6796 
6797   // Returns the equivalent C++ ROCKSDB_NAMESPACE::CompactionReason enum for the
6798   // provided Java org.rocksdb.CompactionReason
6799   static ROCKSDB_NAMESPACE::CompactionReason toCppCompactionReason(
6800       jbyte jcompaction_reason) {
6801     switch (jcompaction_reason) {
6802       case 0x0:
6803         return ROCKSDB_NAMESPACE::CompactionReason::kUnknown;
6804       case 0x1:
6805         return ROCKSDB_NAMESPACE::CompactionReason::kLevelL0FilesNum;
6806       case 0x2:
6807         return ROCKSDB_NAMESPACE::CompactionReason::kLevelMaxLevelSize;
6808       case 0x3:
6809         return ROCKSDB_NAMESPACE::CompactionReason::kUniversalSizeAmplification;
6810       case 0x4:
6811         return ROCKSDB_NAMESPACE::CompactionReason::kUniversalSizeRatio;
6812       case 0x5:
6813         return ROCKSDB_NAMESPACE::CompactionReason::kUniversalSortedRunNum;
6814       case 0x6:
6815         return ROCKSDB_NAMESPACE::CompactionReason::kFIFOMaxSize;
6816       case 0x7:
6817         return ROCKSDB_NAMESPACE::CompactionReason::kFIFOReduceNumFiles;
6818       case 0x8:
6819         return ROCKSDB_NAMESPACE::CompactionReason::kFIFOTtl;
6820       case 0x9:
6821         return ROCKSDB_NAMESPACE::CompactionReason::kManualCompaction;
6822       case 0x10:
6823         return ROCKSDB_NAMESPACE::CompactionReason::kFilesMarkedForCompaction;
6824       case 0x0A:
6825         return ROCKSDB_NAMESPACE::CompactionReason::kBottommostFiles;
6826       case 0x0B:
6827         return ROCKSDB_NAMESPACE::CompactionReason::kTtl;
6828       case 0x0C:
6829         return ROCKSDB_NAMESPACE::CompactionReason::kFlush;
6830       case 0x0D:
6831         return ROCKSDB_NAMESPACE::CompactionReason::kExternalSstIngestion;
6832       default:
6833         // undefined/default
6834         return ROCKSDB_NAMESPACE::CompactionReason::kUnknown;
6835     }
6836   }
6837 };
6838 
6839 // The portal class for org.rocksdb.WalFileType
6840 class WalFileTypeJni {
6841  public:
6842   // Returns the equivalent org.rocksdb.WalFileType for the provided
6843   // C++ ROCKSDB_NAMESPACE::WalFileType enum
6844   static jbyte toJavaWalFileType(
6845       const ROCKSDB_NAMESPACE::WalFileType& wal_file_type) {
6846     switch (wal_file_type) {
6847       case ROCKSDB_NAMESPACE::WalFileType::kArchivedLogFile:
6848         return 0x0;
6849       case ROCKSDB_NAMESPACE::WalFileType::kAliveLogFile:
6850         return 0x1;
6851       default:
6852         return 0x7F;  // undefined
6853     }
6854   }
6855 
6856   // Returns the equivalent C++ ROCKSDB_NAMESPACE::WalFileType enum for the
6857   // provided Java org.rocksdb.WalFileType
6858   static ROCKSDB_NAMESPACE::WalFileType toCppWalFileType(jbyte jwal_file_type) {
6859     switch (jwal_file_type) {
6860       case 0x0:
6861         return ROCKSDB_NAMESPACE::WalFileType::kArchivedLogFile;
6862       case 0x1:
6863         return ROCKSDB_NAMESPACE::WalFileType::kAliveLogFile;
6864       default:
6865         // undefined/default
6866         return ROCKSDB_NAMESPACE::WalFileType::kAliveLogFile;
6867     }
6868   }
6869 };
6870 
6871 class LogFileJni : public JavaClass {
6872  public:
6873   /**
6874    * Create a new Java org.rocksdb.LogFile object.
6875    *
6876    * @param env A pointer to the Java environment
6877    * @param log_file A Cpp log file object
6878    *
6879    * @return A reference to a Java org.rocksdb.LogFile object, or
6880    * nullptr if an an exception occurs
6881    */
6882   static jobject fromCppLogFile(JNIEnv* env,
6883                                 ROCKSDB_NAMESPACE::LogFile* log_file) {
6884     jclass jclazz = getJClass(env);
6885     if (jclazz == nullptr) {
6886       // exception occurred accessing class
6887       return nullptr;
6888     }
6889 
6890     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;JBJJ)V");
6891     if (mid == nullptr) {
6892       // exception thrown: NoSuchMethodException or OutOfMemoryError
6893       return nullptr;
6894     }
6895 
6896     std::string path_name = log_file->PathName();
6897     jstring jpath_name =
6898         ROCKSDB_NAMESPACE::JniUtil::toJavaString(env, &path_name, true);
6899     if (env->ExceptionCheck()) {
6900       // exception occurred creating java string
6901       return nullptr;
6902     }
6903 
6904     jobject jlog_file = env->NewObject(
6905         jclazz, mid, jpath_name, static_cast<jlong>(log_file->LogNumber()),
6906         ROCKSDB_NAMESPACE::WalFileTypeJni::toJavaWalFileType(log_file->Type()),
6907         static_cast<jlong>(log_file->StartSequence()),
6908         static_cast<jlong>(log_file->SizeFileBytes()));
6909 
6910     if (env->ExceptionCheck()) {
6911       env->DeleteLocalRef(jpath_name);
6912       return nullptr;
6913     }
6914 
6915     // cleanup
6916     env->DeleteLocalRef(jpath_name);
6917 
6918     return jlog_file;
6919   }
6920 
6921   static jclass getJClass(JNIEnv* env) {
6922     return JavaClass::getJClass(env, "org/rocksdb/LogFile");
6923   }
6924 };
6925 
6926 class LiveFileMetaDataJni : public JavaClass {
6927  public:
6928   /**
6929    * Create a new Java org.rocksdb.LiveFileMetaData object.
6930    *
6931    * @param env A pointer to the Java environment
6932    * @param live_file_meta_data A Cpp live file meta data object
6933    *
6934    * @return A reference to a Java org.rocksdb.LiveFileMetaData object, or
6935    * nullptr if an an exception occurs
6936    */
6937   static jobject fromCppLiveFileMetaData(
6938       JNIEnv* env, ROCKSDB_NAMESPACE::LiveFileMetaData* live_file_meta_data) {
6939     jclass jclazz = getJClass(env);
6940     if (jclazz == nullptr) {
6941       // exception occurred accessing class
6942       return nullptr;
6943     }
6944 
6945     jmethodID mid = env->GetMethodID(jclazz, "<init>", "([BILjava/lang/String;Ljava/lang/String;JJJ[B[BJZJJ)V");
6946     if (mid == nullptr) {
6947       // exception thrown: NoSuchMethodException or OutOfMemoryError
6948       return nullptr;
6949     }
6950 
6951     jbyteArray jcolumn_family_name = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
6952         env, live_file_meta_data->column_family_name);
6953     if (jcolumn_family_name == nullptr) {
6954       // exception occurred creating java byte array
6955       return nullptr;
6956     }
6957 
6958     jstring jfile_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6959         env, &live_file_meta_data->name, true);
6960     if (env->ExceptionCheck()) {
6961       // exception occurred creating java string
6962       env->DeleteLocalRef(jcolumn_family_name);
6963       return nullptr;
6964     }
6965 
6966     jstring jpath = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
6967         env, &live_file_meta_data->db_path, true);
6968     if (env->ExceptionCheck()) {
6969       // exception occurred creating java string
6970       env->DeleteLocalRef(jcolumn_family_name);
6971       env->DeleteLocalRef(jfile_name);
6972       return nullptr;
6973     }
6974 
6975     jbyteArray jsmallest_key = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
6976         env, live_file_meta_data->smallestkey);
6977     if (jsmallest_key == nullptr) {
6978       // exception occurred creating java byte array
6979       env->DeleteLocalRef(jcolumn_family_name);
6980       env->DeleteLocalRef(jfile_name);
6981       env->DeleteLocalRef(jpath);
6982       return nullptr;
6983     }
6984 
6985     jbyteArray jlargest_key = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
6986         env, live_file_meta_data->largestkey);
6987     if (jlargest_key == nullptr) {
6988       // exception occurred creating java byte array
6989       env->DeleteLocalRef(jcolumn_family_name);
6990       env->DeleteLocalRef(jfile_name);
6991       env->DeleteLocalRef(jpath);
6992       env->DeleteLocalRef(jsmallest_key);
6993       return nullptr;
6994     }
6995 
6996     jobject jlive_file_meta_data = env->NewObject(jclazz, mid,
6997         jcolumn_family_name,
6998         static_cast<jint>(live_file_meta_data->level),
6999         jfile_name,
7000         jpath,
7001         static_cast<jlong>(live_file_meta_data->size),
7002         static_cast<jlong>(live_file_meta_data->smallest_seqno),
7003         static_cast<jlong>(live_file_meta_data->largest_seqno),
7004         jsmallest_key,
7005         jlargest_key,
7006         static_cast<jlong>(live_file_meta_data->num_reads_sampled),
7007         static_cast<jboolean>(live_file_meta_data->being_compacted),
7008         static_cast<jlong>(live_file_meta_data->num_entries),
7009         static_cast<jlong>(live_file_meta_data->num_deletions)
7010     );
7011 
7012     if (env->ExceptionCheck()) {
7013       env->DeleteLocalRef(jcolumn_family_name);
7014       env->DeleteLocalRef(jfile_name);
7015       env->DeleteLocalRef(jpath);
7016       env->DeleteLocalRef(jsmallest_key);
7017       env->DeleteLocalRef(jlargest_key);
7018       return nullptr;
7019     }
7020 
7021     // cleanup
7022     env->DeleteLocalRef(jcolumn_family_name);
7023     env->DeleteLocalRef(jfile_name);
7024     env->DeleteLocalRef(jpath);
7025     env->DeleteLocalRef(jsmallest_key);
7026     env->DeleteLocalRef(jlargest_key);
7027 
7028     return jlive_file_meta_data;
7029   }
7030 
7031   static jclass getJClass(JNIEnv* env) {
7032     return JavaClass::getJClass(env, "org/rocksdb/LiveFileMetaData");
7033   }
7034 };
7035 
7036 class SstFileMetaDataJni : public JavaClass {
7037  public:
7038   /**
7039    * Create a new Java org.rocksdb.SstFileMetaData object.
7040    *
7041    * @param env A pointer to the Java environment
7042    * @param sst_file_meta_data A Cpp sst file meta data object
7043    *
7044    * @return A reference to a Java org.rocksdb.SstFileMetaData object, or
7045    * nullptr if an an exception occurs
7046    */
7047   static jobject fromCppSstFileMetaData(
7048       JNIEnv* env,
7049       const ROCKSDB_NAMESPACE::SstFileMetaData* sst_file_meta_data) {
7050     jclass jclazz = getJClass(env);
7051     if (jclazz == nullptr) {
7052       // exception occurred accessing class
7053       return nullptr;
7054     }
7055 
7056     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;JJJ[B[BJZJJ)V");
7057     if (mid == nullptr) {
7058       // exception thrown: NoSuchMethodException or OutOfMemoryError
7059       return nullptr;
7060     }
7061 
7062     jstring jfile_name = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
7063         env, &sst_file_meta_data->name, true);
7064     if (jfile_name == nullptr) {
7065       // exception occurred creating java byte array
7066       return nullptr;
7067     }
7068 
7069     jstring jpath = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
7070         env, &sst_file_meta_data->db_path, true);
7071     if (jpath == nullptr) {
7072       // exception occurred creating java byte array
7073       env->DeleteLocalRef(jfile_name);
7074       return nullptr;
7075     }
7076 
7077     jbyteArray jsmallest_key = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
7078         env, sst_file_meta_data->smallestkey);
7079     if (jsmallest_key == nullptr) {
7080       // exception occurred creating java byte array
7081       env->DeleteLocalRef(jfile_name);
7082       env->DeleteLocalRef(jpath);
7083       return nullptr;
7084     }
7085 
7086     jbyteArray jlargest_key = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
7087         env, sst_file_meta_data->largestkey);
7088     if (jlargest_key == nullptr) {
7089       // exception occurred creating java byte array
7090       env->DeleteLocalRef(jfile_name);
7091       env->DeleteLocalRef(jpath);
7092       env->DeleteLocalRef(jsmallest_key);
7093       return nullptr;
7094     }
7095 
7096     jobject jsst_file_meta_data = env->NewObject(jclazz, mid,
7097         jfile_name,
7098         jpath,
7099         static_cast<jlong>(sst_file_meta_data->size),
7100         static_cast<jint>(sst_file_meta_data->smallest_seqno),
7101         static_cast<jlong>(sst_file_meta_data->largest_seqno),
7102         jsmallest_key,
7103         jlargest_key,
7104         static_cast<jlong>(sst_file_meta_data->num_reads_sampled),
7105         static_cast<jboolean>(sst_file_meta_data->being_compacted),
7106         static_cast<jlong>(sst_file_meta_data->num_entries),
7107         static_cast<jlong>(sst_file_meta_data->num_deletions)
7108     );
7109 
7110     if (env->ExceptionCheck()) {
7111       env->DeleteLocalRef(jfile_name);
7112       env->DeleteLocalRef(jpath);
7113       env->DeleteLocalRef(jsmallest_key);
7114       env->DeleteLocalRef(jlargest_key);
7115       return nullptr;
7116     }
7117 
7118     // cleanup
7119       env->DeleteLocalRef(jfile_name);
7120       env->DeleteLocalRef(jpath);
7121       env->DeleteLocalRef(jsmallest_key);
7122       env->DeleteLocalRef(jlargest_key);
7123 
7124     return jsst_file_meta_data;
7125   }
7126 
7127   static jclass getJClass(JNIEnv* env) {
7128     return JavaClass::getJClass(env, "org/rocksdb/SstFileMetaData");
7129   }
7130 };
7131 
7132 class LevelMetaDataJni : public JavaClass {
7133  public:
7134   /**
7135    * Create a new Java org.rocksdb.LevelMetaData object.
7136    *
7137    * @param env A pointer to the Java environment
7138    * @param level_meta_data A Cpp level meta data object
7139    *
7140    * @return A reference to a Java org.rocksdb.LevelMetaData object, or
7141    * nullptr if an an exception occurs
7142    */
7143   static jobject fromCppLevelMetaData(
7144       JNIEnv* env, const ROCKSDB_NAMESPACE::LevelMetaData* level_meta_data) {
7145     jclass jclazz = getJClass(env);
7146     if (jclazz == nullptr) {
7147       // exception occurred accessing class
7148       return nullptr;
7149     }
7150 
7151     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(IJ[Lorg/rocksdb/SstFileMetaData;)V");
7152     if (mid == nullptr) {
7153       // exception thrown: NoSuchMethodException or OutOfMemoryError
7154       return nullptr;
7155     }
7156 
7157     const jsize jlen =
7158         static_cast<jsize>(level_meta_data->files.size());
7159     jobjectArray jfiles = env->NewObjectArray(jlen, SstFileMetaDataJni::getJClass(env), nullptr);
7160     if (jfiles == nullptr) {
7161       // exception thrown: OutOfMemoryError
7162       return nullptr;
7163     }
7164 
7165     jsize i = 0;
7166     for (auto it = level_meta_data->files.begin();
7167         it != level_meta_data->files.end(); ++it) {
7168       jobject jfile = SstFileMetaDataJni::fromCppSstFileMetaData(env, &(*it));
7169       if (jfile == nullptr) {
7170         // exception occurred
7171         env->DeleteLocalRef(jfiles);
7172         return nullptr;
7173       }
7174       env->SetObjectArrayElement(jfiles, i++, jfile);
7175     }
7176 
7177     jobject jlevel_meta_data = env->NewObject(jclazz, mid,
7178         static_cast<jint>(level_meta_data->level),
7179         static_cast<jlong>(level_meta_data->size),
7180         jfiles
7181     );
7182 
7183     if (env->ExceptionCheck()) {
7184       env->DeleteLocalRef(jfiles);
7185       return nullptr;
7186     }
7187 
7188     // cleanup
7189     env->DeleteLocalRef(jfiles);
7190 
7191     return jlevel_meta_data;
7192   }
7193 
7194   static jclass getJClass(JNIEnv* env) {
7195     return JavaClass::getJClass(env, "org/rocksdb/LevelMetaData");
7196   }
7197 };
7198 
7199 class ColumnFamilyMetaDataJni : public JavaClass {
7200  public:
7201   /**
7202    * Create a new Java org.rocksdb.ColumnFamilyMetaData object.
7203    *
7204    * @param env A pointer to the Java environment
7205    * @param column_famly_meta_data A Cpp live file meta data object
7206    *
7207    * @return A reference to a Java org.rocksdb.ColumnFamilyMetaData object, or
7208    * nullptr if an an exception occurs
7209    */
7210   static jobject fromCppColumnFamilyMetaData(
7211       JNIEnv* env,
7212       const ROCKSDB_NAMESPACE::ColumnFamilyMetaData* column_famly_meta_data) {
7213     jclass jclazz = getJClass(env);
7214     if (jclazz == nullptr) {
7215       // exception occurred accessing class
7216       return nullptr;
7217     }
7218 
7219     jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJ[B[Lorg/rocksdb/LevelMetaData;)V");
7220     if (mid == nullptr) {
7221       // exception thrown: NoSuchMethodException or OutOfMemoryError
7222       return nullptr;
7223     }
7224 
7225     jbyteArray jname = ROCKSDB_NAMESPACE::JniUtil::copyBytes(
7226         env, column_famly_meta_data->name);
7227     if (jname == nullptr) {
7228       // exception occurred creating java byte array
7229       return nullptr;
7230     }
7231 
7232     const jsize jlen =
7233         static_cast<jsize>(column_famly_meta_data->levels.size());
7234     jobjectArray jlevels = env->NewObjectArray(jlen, LevelMetaDataJni::getJClass(env), nullptr);
7235     if(jlevels == nullptr) {
7236       // exception thrown: OutOfMemoryError
7237       env->DeleteLocalRef(jname);
7238       return nullptr;
7239     }
7240 
7241     jsize i = 0;
7242     for (auto it = column_famly_meta_data->levels.begin();
7243         it != column_famly_meta_data->levels.end(); ++it) {
7244       jobject jlevel = LevelMetaDataJni::fromCppLevelMetaData(env, &(*it));
7245       if (jlevel == nullptr) {
7246         // exception occurred
7247         env->DeleteLocalRef(jname);
7248         env->DeleteLocalRef(jlevels);
7249         return nullptr;
7250       }
7251       env->SetObjectArrayElement(jlevels, i++, jlevel);
7252     }
7253 
7254     jobject jcolumn_family_meta_data = env->NewObject(jclazz, mid,
7255         static_cast<jlong>(column_famly_meta_data->size),
7256         static_cast<jlong>(column_famly_meta_data->file_count),
7257         jname,
7258         jlevels
7259     );
7260 
7261     if (env->ExceptionCheck()) {
7262       env->DeleteLocalRef(jname);
7263       env->DeleteLocalRef(jlevels);
7264       return nullptr;
7265     }
7266 
7267     // cleanup
7268     env->DeleteLocalRef(jname);
7269     env->DeleteLocalRef(jlevels);
7270 
7271     return jcolumn_family_meta_data;
7272   }
7273 
7274   static jclass getJClass(JNIEnv* env) {
7275     return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyMetaData");
7276   }
7277 };
7278 
7279 // The portal class for org.rocksdb.AbstractTraceWriter
7280 class AbstractTraceWriterJni
7281     : public RocksDBNativeClass<
7282           const ROCKSDB_NAMESPACE::TraceWriterJniCallback*,
7283           AbstractTraceWriterJni> {
7284  public:
7285   /**
7286    * Get the Java Class org.rocksdb.AbstractTraceWriter
7287    *
7288    * @param env A pointer to the Java environment
7289    *
7290    * @return The Java Class or nullptr if one of the
7291    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
7292    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
7293    */
7294   static jclass getJClass(JNIEnv* env) {
7295     return RocksDBNativeClass::getJClass(env,
7296         "org/rocksdb/AbstractTraceWriter");
7297   }
7298 
7299   /**
7300    * Get the Java Method: AbstractTraceWriter#write
7301    *
7302    * @param env A pointer to the Java environment
7303    *
7304    * @return The Java Method ID or nullptr if the class or method id could not
7305    *     be retieved
7306    */
7307   static jmethodID getWriteProxyMethodId(JNIEnv* env) {
7308     jclass jclazz = getJClass(env);
7309     if(jclazz == nullptr) {
7310       // exception occurred accessing class
7311       return nullptr;
7312     }
7313 
7314     static jmethodID mid = env->GetMethodID(
7315         jclazz, "writeProxy", "(J)S");
7316     assert(mid != nullptr);
7317     return mid;
7318   }
7319 
7320   /**
7321    * Get the Java Method: AbstractTraceWriter#closeWriter
7322    *
7323    * @param env A pointer to the Java environment
7324    *
7325    * @return The Java Method ID or nullptr if the class or method id could not
7326    *     be retieved
7327    */
7328   static jmethodID getCloseWriterProxyMethodId(JNIEnv* env) {
7329     jclass jclazz = getJClass(env);
7330     if(jclazz == nullptr) {
7331       // exception occurred accessing class
7332       return nullptr;
7333     }
7334 
7335     static jmethodID mid = env->GetMethodID(
7336         jclazz, "closeWriterProxy", "()S");
7337     assert(mid != nullptr);
7338     return mid;
7339   }
7340 
7341   /**
7342    * Get the Java Method: AbstractTraceWriter#getFileSize
7343    *
7344    * @param env A pointer to the Java environment
7345    *
7346    * @return The Java Method ID or nullptr if the class or method id could not
7347    *     be retieved
7348    */
7349   static jmethodID getGetFileSizeMethodId(JNIEnv* env) {
7350     jclass jclazz = getJClass(env);
7351     if(jclazz == nullptr) {
7352       // exception occurred accessing class
7353       return nullptr;
7354     }
7355 
7356     static jmethodID mid = env->GetMethodID(
7357         jclazz, "getFileSize", "()J");
7358     assert(mid != nullptr);
7359     return mid;
7360   }
7361 };
7362 
7363 // The portal class for org.rocksdb.AbstractWalFilter
7364 class AbstractWalFilterJni
7365     : public RocksDBNativeClass<const ROCKSDB_NAMESPACE::WalFilterJniCallback*,
7366                                 AbstractWalFilterJni> {
7367  public:
7368   /**
7369    * Get the Java Class org.rocksdb.AbstractWalFilter
7370    *
7371    * @param env A pointer to the Java environment
7372    *
7373    * @return The Java Class or nullptr if one of the
7374    *     ClassFormatError, ClassCircularityError, NoClassDefFoundError,
7375    *     OutOfMemoryError or ExceptionInInitializerError exceptions is thrown
7376    */
7377   static jclass getJClass(JNIEnv* env) {
7378     return RocksDBNativeClass::getJClass(env,
7379         "org/rocksdb/AbstractWalFilter");
7380   }
7381 
7382   /**
7383    * Get the Java Method: AbstractWalFilter#columnFamilyLogNumberMap
7384    *
7385    * @param env A pointer to the Java environment
7386    *
7387    * @return The Java Method ID or nullptr if the class or method id could not
7388    *     be retieved
7389    */
7390   static jmethodID getColumnFamilyLogNumberMapMethodId(JNIEnv* env) {
7391     jclass jclazz = getJClass(env);
7392     if(jclazz == nullptr) {
7393       // exception occurred accessing class
7394       return nullptr;
7395     }
7396 
7397     static jmethodID mid = env->GetMethodID(
7398         jclazz, "columnFamilyLogNumberMap",
7399         "(Ljava/util/Map;Ljava/util/Map;)V");
7400     assert(mid != nullptr);
7401     return mid;
7402   }
7403 
7404   /**
7405    * Get the Java Method: AbstractTraceWriter#logRecordFoundProxy
7406    *
7407    * @param env A pointer to the Java environment
7408    *
7409    * @return The Java Method ID or nullptr if the class or method id could not
7410    *     be retieved
7411    */
7412   static jmethodID getLogRecordFoundProxyMethodId(JNIEnv* env) {
7413     jclass jclazz = getJClass(env);
7414     if(jclazz == nullptr) {
7415       // exception occurred accessing class
7416       return nullptr;
7417     }
7418 
7419     static jmethodID mid = env->GetMethodID(
7420         jclazz, "logRecordFoundProxy", "(JLjava/lang/String;JJ)S");
7421     assert(mid != nullptr);
7422     return mid;
7423   }
7424 
7425   /**
7426    * Get the Java Method: AbstractTraceWriter#name
7427    *
7428    * @param env A pointer to the Java environment
7429    *
7430    * @return The Java Method ID or nullptr if the class or method id could not
7431    *     be retieved
7432    */
7433   static jmethodID getNameMethodId(JNIEnv* env) {
7434     jclass jclazz = getJClass(env);
7435     if(jclazz == nullptr) {
7436       // exception occurred accessing class
7437       return nullptr;
7438     }
7439 
7440     static jmethodID mid = env->GetMethodID(
7441         jclazz, "name", "()Ljava/lang/String;");
7442     assert(mid != nullptr);
7443     return mid;
7444   }
7445 };
7446 
7447 // The portal class for org.rocksdb.WalProcessingOption
7448 class WalProcessingOptionJni {
7449  public:
7450   // Returns the equivalent org.rocksdb.WalProcessingOption for the provided
7451   // C++ ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption enum
7452   static jbyte toJavaWalProcessingOption(
7453       const ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption&
7454           wal_processing_option) {
7455     switch (wal_processing_option) {
7456       case ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7457           kContinueProcessing:
7458         return 0x0;
7459       case ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7460           kIgnoreCurrentRecord:
7461         return 0x1;
7462       case ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::kStopReplay:
7463         return 0x2;
7464       case ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::kCorruptedRecord:
7465         return 0x3;
7466       default:
7467         return 0x7F;  // undefined
7468     }
7469   }
7470 
7471   // Returns the equivalent C++
7472   // ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption enum for the provided
7473   // Java org.rocksdb.WalProcessingOption
7474   static ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption
7475   toCppWalProcessingOption(jbyte jwal_processing_option) {
7476     switch (jwal_processing_option) {
7477       case 0x0:
7478         return ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7479             kContinueProcessing;
7480       case 0x1:
7481         return ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7482             kIgnoreCurrentRecord;
7483       case 0x2:
7484         return ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::kStopReplay;
7485       case 0x3:
7486         return ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7487             kCorruptedRecord;
7488       default:
7489         // undefined/default
7490         return ROCKSDB_NAMESPACE::WalFilter::WalProcessingOption::
7491             kCorruptedRecord;
7492     }
7493   }
7494 };
7495 
7496 // The portal class for org.rocksdb.ReusedSynchronisationType
7497 class ReusedSynchronisationTypeJni {
7498  public:
7499   // Returns the equivalent org.rocksdb.ReusedSynchronisationType for the
7500   // provided C++ ROCKSDB_NAMESPACE::ReusedSynchronisationType enum
7501   static jbyte toJavaReusedSynchronisationType(
7502       const ROCKSDB_NAMESPACE::ReusedSynchronisationType&
7503           reused_synchronisation_type) {
7504     switch(reused_synchronisation_type) {
7505       case ROCKSDB_NAMESPACE::ReusedSynchronisationType::MUTEX:
7506         return 0x0;
7507       case ROCKSDB_NAMESPACE::ReusedSynchronisationType::ADAPTIVE_MUTEX:
7508         return 0x1;
7509       case ROCKSDB_NAMESPACE::ReusedSynchronisationType::THREAD_LOCAL:
7510         return 0x2;
7511       default:
7512         return 0x7F;  // undefined
7513     }
7514   }
7515 
7516   // Returns the equivalent C++ ROCKSDB_NAMESPACE::ReusedSynchronisationType
7517   // enum for the provided Java org.rocksdb.ReusedSynchronisationType
7518   static ROCKSDB_NAMESPACE::ReusedSynchronisationType
7519   toCppReusedSynchronisationType(jbyte reused_synchronisation_type) {
7520     switch(reused_synchronisation_type) {
7521       case 0x0:
7522         return ROCKSDB_NAMESPACE::ReusedSynchronisationType::MUTEX;
7523       case 0x1:
7524         return ROCKSDB_NAMESPACE::ReusedSynchronisationType::ADAPTIVE_MUTEX;
7525       case 0x2:
7526         return ROCKSDB_NAMESPACE::ReusedSynchronisationType::THREAD_LOCAL;
7527       default:
7528         // undefined/default
7529         return ROCKSDB_NAMESPACE::ReusedSynchronisationType::ADAPTIVE_MUTEX;
7530     }
7531   }
7532 };
7533 }  // namespace ROCKSDB_NAMESPACE
7534 #endif  // JAVA_ROCKSJNI_PORTAL_H_
7535