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 implements the "bridge" between Java and C++ and enables
7 // calling c++ ROCKSDB_NAMESPACE::DB methods from Java side.
8 
9 #include <jni.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <algorithm>
13 #include <functional>
14 #include <memory>
15 #include <string>
16 #include <tuple>
17 #include <vector>
18 
19 #include "include/org_rocksdb_RocksDB.h"
20 #include "rocksdb/cache.h"
21 #include "rocksdb/convenience.h"
22 #include "rocksdb/db.h"
23 #include "rocksdb/options.h"
24 #include "rocksdb/types.h"
25 #include "rocksjni/portal.h"
26 
27 #ifdef min
28 #undef min
29 #endif
30 
rocksdb_open_helper(JNIEnv * env,jlong jopt_handle,jstring jdb_path,std::function<ROCKSDB_NAMESPACE::Status (const ROCKSDB_NAMESPACE::Options &,const std::string &,ROCKSDB_NAMESPACE::DB **)> open_fn)31 jlong rocksdb_open_helper(JNIEnv* env, jlong jopt_handle, jstring jdb_path,
32                           std::function<ROCKSDB_NAMESPACE::Status(
33                               const ROCKSDB_NAMESPACE::Options&,
34                               const std::string&, ROCKSDB_NAMESPACE::DB**)>
35                               open_fn) {
36   const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
37   if (db_path == nullptr) {
38     // exception thrown: OutOfMemoryError
39     return 0;
40   }
41 
42   auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(jopt_handle);
43   ROCKSDB_NAMESPACE::DB* db = nullptr;
44   ROCKSDB_NAMESPACE::Status s = open_fn(*opt, db_path, &db);
45 
46   env->ReleaseStringUTFChars(jdb_path, db_path);
47 
48   if (s.ok()) {
49     return reinterpret_cast<jlong>(db);
50   } else {
51     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
52     return 0;
53   }
54 }
55 
56 /*
57  * Class:     org_rocksdb_RocksDB
58  * Method:    open
59  * Signature: (JLjava/lang/String;)J
60  */
Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2(JNIEnv * env,jclass,jlong jopt_handle,jstring jdb_path)61 jlong Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2(
62     JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) {
63   return rocksdb_open_helper(env, jopt_handle, jdb_path,
64                              (ROCKSDB_NAMESPACE::Status(*)(
65                                  const ROCKSDB_NAMESPACE::Options&,
66                                  const std::string&, ROCKSDB_NAMESPACE::DB**)) &
67                                  ROCKSDB_NAMESPACE::DB::Open);
68 }
69 
70 /*
71  * Class:     org_rocksdb_RocksDB
72  * Method:    openROnly
73  * Signature: (JLjava/lang/String;)J
74  */
Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2(JNIEnv * env,jclass,jlong jopt_handle,jstring jdb_path)75 jlong Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2(
76     JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) {
77   return rocksdb_open_helper(
78       env, jopt_handle, jdb_path,
79       [](const ROCKSDB_NAMESPACE::Options& options, const std::string& db_path,
80          ROCKSDB_NAMESPACE::DB** db) {
81         return ROCKSDB_NAMESPACE::DB::OpenForReadOnly(options, db_path, db);
82       });
83 }
84 
rocksdb_open_helper(JNIEnv * env,jlong jopt_handle,jstring jdb_path,jobjectArray jcolumn_names,jlongArray jcolumn_options,std::function<ROCKSDB_NAMESPACE::Status (const ROCKSDB_NAMESPACE::DBOptions &,const std::string &,const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> &,std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle * > *,ROCKSDB_NAMESPACE::DB **)> open_fn)85 jlongArray rocksdb_open_helper(
86     JNIEnv* env, jlong jopt_handle, jstring jdb_path,
87     jobjectArray jcolumn_names, jlongArray jcolumn_options,
88     std::function<ROCKSDB_NAMESPACE::Status(
89         const ROCKSDB_NAMESPACE::DBOptions&, const std::string&,
90         const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>&,
91         std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>*,
92         ROCKSDB_NAMESPACE::DB**)>
93         open_fn) {
94   const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
95   if (db_path == nullptr) {
96     // exception thrown: OutOfMemoryError
97     return nullptr;
98   }
99 
100   const jsize len_cols = env->GetArrayLength(jcolumn_names);
101   jlong* jco = env->GetLongArrayElements(jcolumn_options, nullptr);
102   if (jco == nullptr) {
103     // exception thrown: OutOfMemoryError
104     env->ReleaseStringUTFChars(jdb_path, db_path);
105     return nullptr;
106   }
107 
108   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> column_families;
109   jboolean has_exception = JNI_FALSE;
110   ROCKSDB_NAMESPACE::JniUtil::byteStrings<std::string>(
111       env, jcolumn_names,
112       [](const char* str_data, const size_t str_len) {
113         return std::string(str_data, str_len);
114       },
115       [&jco, &column_families](size_t idx, std::string cf_name) {
116         ROCKSDB_NAMESPACE::ColumnFamilyOptions* cf_options =
117             reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(jco[idx]);
118         column_families.push_back(
119             ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));
120       },
121       &has_exception);
122 
123   env->ReleaseLongArrayElements(jcolumn_options, jco, JNI_ABORT);
124 
125   if (has_exception == JNI_TRUE) {
126     // exception occurred
127     env->ReleaseStringUTFChars(jdb_path, db_path);
128     return nullptr;
129   }
130 
131   auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jopt_handle);
132   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
133   ROCKSDB_NAMESPACE::DB* db = nullptr;
134   ROCKSDB_NAMESPACE::Status s =
135       open_fn(*opt, db_path, column_families, &cf_handles, &db);
136 
137   // we have now finished with db_path
138   env->ReleaseStringUTFChars(jdb_path, db_path);
139 
140   // check if open operation was successful
141   if (!s.ok()) {
142     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
143     return nullptr;
144   }
145 
146   const jsize resultsLen = 1 + len_cols;  // db handle + column family handles
147   std::unique_ptr<jlong[]> results =
148       std::unique_ptr<jlong[]>(new jlong[resultsLen]);
149   results[0] = reinterpret_cast<jlong>(db);
150   for (int i = 1; i <= len_cols; i++) {
151     results[i] = reinterpret_cast<jlong>(cf_handles[i - 1]);
152   }
153 
154   jlongArray jresults = env->NewLongArray(resultsLen);
155   if (jresults == nullptr) {
156     // exception thrown: OutOfMemoryError
157     return nullptr;
158   }
159 
160   env->SetLongArrayRegion(jresults, 0, resultsLen, results.get());
161   if (env->ExceptionCheck()) {
162     // exception thrown: ArrayIndexOutOfBoundsException
163     env->DeleteLocalRef(jresults);
164     return nullptr;
165   }
166 
167   return jresults;
168 }
169 
170 /*
171  * Class:     org_rocksdb_RocksDB
172  * Method:    openROnly
173  * Signature: (JLjava/lang/String;[[B[J)[J
174  */
Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3_3B_3J(JNIEnv * env,jclass,jlong jopt_handle,jstring jdb_path,jobjectArray jcolumn_names,jlongArray jcolumn_options)175 jlongArray Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3_3B_3J(
176     JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path,
177     jobjectArray jcolumn_names, jlongArray jcolumn_options) {
178   return rocksdb_open_helper(
179       env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options,
180       [](const ROCKSDB_NAMESPACE::DBOptions& options,
181          const std::string& db_path,
182          const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>&
183              column_families,
184          std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>* handles,
185          ROCKSDB_NAMESPACE::DB** db) {
186         return ROCKSDB_NAMESPACE::DB::OpenForReadOnly(
187             options, db_path, column_families, handles, db);
188       });
189 }
190 
191 /*
192  * Class:     org_rocksdb_RocksDB
193  * Method:    open
194  * Signature: (JLjava/lang/String;[[B[J)[J
195  */
Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2_3_3B_3J(JNIEnv * env,jclass,jlong jopt_handle,jstring jdb_path,jobjectArray jcolumn_names,jlongArray jcolumn_options)196 jlongArray Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2_3_3B_3J(
197     JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path,
198     jobjectArray jcolumn_names, jlongArray jcolumn_options) {
199   return rocksdb_open_helper(
200       env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options,
201       (ROCKSDB_NAMESPACE::Status(*)(
202           const ROCKSDB_NAMESPACE::DBOptions&, const std::string&,
203           const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>&,
204           std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>*,
205           ROCKSDB_NAMESPACE::DB**)) &
206           ROCKSDB_NAMESPACE::DB::Open);
207 }
208 
209 /*
210  * Class:     org_rocksdb_RocksDB
211  * Method:    disposeInternal
212  * Signature: (J)V
213  */
Java_org_rocksdb_RocksDB_disposeInternal(JNIEnv *,jobject,jlong jhandle)214 void Java_org_rocksdb_RocksDB_disposeInternal(
215     JNIEnv*, jobject, jlong jhandle) {
216   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
217   assert(db != nullptr);
218   delete db;
219 }
220 
221 /*
222  * Class:     org_rocksdb_RocksDB
223  * Method:    closeDatabase
224  * Signature: (J)V
225  */
Java_org_rocksdb_RocksDB_closeDatabase(JNIEnv * env,jclass,jlong jhandle)226 void Java_org_rocksdb_RocksDB_closeDatabase(
227     JNIEnv* env, jclass, jlong jhandle) {
228   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
229   assert(db != nullptr);
230   ROCKSDB_NAMESPACE::Status s = db->Close();
231   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
232 }
233 
234 /*
235  * Class:     org_rocksdb_RocksDB
236  * Method:    listColumnFamilies
237  * Signature: (JLjava/lang/String;)[[B
238  */
Java_org_rocksdb_RocksDB_listColumnFamilies(JNIEnv * env,jclass,jlong jopt_handle,jstring jdb_path)239 jobjectArray Java_org_rocksdb_RocksDB_listColumnFamilies(
240     JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) {
241   std::vector<std::string> column_family_names;
242   const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
243   if (db_path == nullptr) {
244     // exception thrown: OutOfMemoryError
245     return nullptr;
246   }
247 
248   auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(jopt_handle);
249   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::DB::ListColumnFamilies(
250       *opt, db_path, &column_family_names);
251 
252   env->ReleaseStringUTFChars(jdb_path, db_path);
253 
254   jobjectArray jcolumn_family_names =
255       ROCKSDB_NAMESPACE::JniUtil::stringsBytes(env, column_family_names);
256 
257   return jcolumn_family_names;
258 }
259 
260 /*
261  * Class:     org_rocksdb_RocksDB
262  * Method:    createColumnFamily
263  * Signature: (J[BIJ)J
264  */
Java_org_rocksdb_RocksDB_createColumnFamily(JNIEnv * env,jobject,jlong jhandle,jbyteArray jcf_name,jint jcf_name_len,jlong jcf_options_handle)265 jlong Java_org_rocksdb_RocksDB_createColumnFamily(
266     JNIEnv* env, jobject, jlong jhandle, jbyteArray jcf_name,
267     jint jcf_name_len, jlong jcf_options_handle) {
268   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
269   jboolean has_exception = JNI_FALSE;
270   const std::string cf_name =
271       ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
272           env, jcf_name, jcf_name_len,
273           [](const char* str, const size_t len) {
274             return std::string(str, len);
275           },
276           &has_exception);
277   if (has_exception == JNI_TRUE) {
278     // exception occurred
279     return 0;
280   }
281   auto* cf_options = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
282       jcf_options_handle);
283   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
284   ROCKSDB_NAMESPACE::Status s =
285       db->CreateColumnFamily(*cf_options, cf_name, &cf_handle);
286   if (!s.ok()) {
287     // error occurred
288     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
289     return 0;
290   }
291   return reinterpret_cast<jlong>(cf_handle);
292 }
293 
294 /*
295  * Class:     org_rocksdb_RocksDB
296  * Method:    createColumnFamilies
297  * Signature: (JJ[[B)[J
298  */
Java_org_rocksdb_RocksDB_createColumnFamilies__JJ_3_3B(JNIEnv * env,jobject,jlong jhandle,jlong jcf_options_handle,jobjectArray jcf_names)299 jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__JJ_3_3B(
300     JNIEnv* env, jobject, jlong jhandle, jlong jcf_options_handle,
301     jobjectArray jcf_names) {
302   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
303   auto* cf_options = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
304       jcf_options_handle);
305   jboolean has_exception = JNI_FALSE;
306   std::vector<std::string> cf_names;
307   ROCKSDB_NAMESPACE::JniUtil::byteStrings<std::string>(
308       env, jcf_names,
309       [](const char* str, const size_t len) { return std::string(str, len); },
310       [&cf_names](const size_t, std::string str) { cf_names.push_back(str); },
311       &has_exception);
312   if (has_exception == JNI_TRUE) {
313     // exception occurred
314     return nullptr;
315   }
316 
317   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
318   ROCKSDB_NAMESPACE::Status s =
319       db->CreateColumnFamilies(*cf_options, cf_names, &cf_handles);
320   if (!s.ok()) {
321     // error occurred
322     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
323     return nullptr;
324   }
325 
326   jlongArray jcf_handles = ROCKSDB_NAMESPACE::JniUtil::toJPointers<
327       ROCKSDB_NAMESPACE::ColumnFamilyHandle>(env, cf_handles, &has_exception);
328   if (has_exception == JNI_TRUE) {
329     // exception occurred
330     return nullptr;
331   }
332   return jcf_handles;
333 }
334 
335 /*
336  * Class:     org_rocksdb_RocksDB
337  * Method:    createColumnFamilies
338  * Signature: (J[J[[B)[J
339  */
Java_org_rocksdb_RocksDB_createColumnFamilies__J_3J_3_3B(JNIEnv * env,jobject,jlong jhandle,jlongArray jcf_options_handles,jobjectArray jcf_names)340 jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__J_3J_3_3B(
341     JNIEnv* env, jobject, jlong jhandle, jlongArray jcf_options_handles,
342     jobjectArray jcf_names) {
343   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jhandle);
344   const jsize jlen = env->GetArrayLength(jcf_options_handles);
345   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descriptors;
346   cf_descriptors.reserve(jlen);
347 
348   jboolean jcf_options_handles_is_copy = JNI_FALSE;
349   jlong *jcf_options_handles_elems = env->GetLongArrayElements(jcf_options_handles, &jcf_options_handles_is_copy);
350   if(jcf_options_handles_elems == nullptr) {
351       // exception thrown: OutOfMemoryError
352       return nullptr;
353   }
354 
355   // extract the column family descriptors
356   jboolean has_exception = JNI_FALSE;
357   for (jsize i = 0; i < jlen; i++) {
358     auto* cf_options =
359         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
360             jcf_options_handles_elems[i]);
361     jbyteArray jcf_name = static_cast<jbyteArray>(
362         env->GetObjectArrayElement(jcf_names, i));
363     if (env->ExceptionCheck()) {
364       // exception thrown: ArrayIndexOutOfBoundsException
365       env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT);
366       return nullptr;
367     }
368     const std::string cf_name =
369         ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
370             env, jcf_name,
371             [](const char* str, const size_t len) {
372               return std::string(str, len);
373             },
374             &has_exception);
375     if (has_exception == JNI_TRUE) {
376       // exception occurred
377       env->DeleteLocalRef(jcf_name);
378       env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT);
379       return nullptr;
380     }
381 
382     cf_descriptors.push_back(
383         ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));
384 
385     env->DeleteLocalRef(jcf_name);
386   }
387 
388   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
389   ROCKSDB_NAMESPACE::Status s =
390       db->CreateColumnFamilies(cf_descriptors, &cf_handles);
391 
392   env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT);
393 
394   if (!s.ok()) {
395     // error occurred
396     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
397     return nullptr;
398   }
399 
400   jlongArray jcf_handles = ROCKSDB_NAMESPACE::JniUtil::toJPointers<
401       ROCKSDB_NAMESPACE::ColumnFamilyHandle>(env, cf_handles, &has_exception);
402   if (has_exception == JNI_TRUE) {
403     // exception occurred
404     return nullptr;
405   }
406   return jcf_handles;
407 }
408 
409 /*
410  * Class:     org_rocksdb_RocksDB
411  * Method:    dropColumnFamily
412  * Signature: (JJ)V;
413  */
Java_org_rocksdb_RocksDB_dropColumnFamily(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle)414 void Java_org_rocksdb_RocksDB_dropColumnFamily(
415     JNIEnv* env, jobject, jlong jdb_handle,
416     jlong jcf_handle) {
417   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
418   auto* cf_handle =
419       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
420   ROCKSDB_NAMESPACE::Status s = db_handle->DropColumnFamily(cf_handle);
421   if (!s.ok()) {
422     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
423   }
424 }
425 
426 /*
427  * Class:     org_rocksdb_RocksDB
428  * Method:    dropColumnFamilies
429  * Signature: (J[J)V
430  */
Java_org_rocksdb_RocksDB_dropColumnFamilies(JNIEnv * env,jobject,jlong jdb_handle,jlongArray jcolumn_family_handles)431 void Java_org_rocksdb_RocksDB_dropColumnFamilies(
432     JNIEnv* env, jobject, jlong jdb_handle,
433     jlongArray jcolumn_family_handles) {
434   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
435 
436   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
437   if (jcolumn_family_handles != nullptr) {
438     const jsize len_cols = env->GetArrayLength(jcolumn_family_handles);
439 
440     jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr);
441     if (jcfh == nullptr) {
442       // exception thrown: OutOfMemoryError
443       return;
444     }
445 
446     for (jsize i = 0; i < len_cols; i++) {
447       auto* cf_handle =
448           reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcfh[i]);
449       cf_handles.push_back(cf_handle);
450     }
451     env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT);
452   }
453 
454   ROCKSDB_NAMESPACE::Status s = db_handle->DropColumnFamilies(cf_handles);
455   if (!s.ok()) {
456     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
457   }
458 }
459 
460 //////////////////////////////////////////////////////////////////////////////
461 // ROCKSDB_NAMESPACE::DB::Put
462 
463 /**
464  * @return true if the put succeeded, false if a Java Exception was thrown
465  */
rocksdb_put_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::WriteOptions & write_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)466 bool rocksdb_put_helper(JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
467                         const ROCKSDB_NAMESPACE::WriteOptions& write_options,
468                         ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle,
469                         jbyteArray jkey, jint jkey_off, jint jkey_len,
470                         jbyteArray jval, jint jval_off, jint jval_len) {
471   jbyte* key = new jbyte[jkey_len];
472   env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key);
473   if (env->ExceptionCheck()) {
474     // exception thrown: ArrayIndexOutOfBoundsException
475     delete[] key;
476     return false;
477   }
478 
479   jbyte* value = new jbyte[jval_len];
480   env->GetByteArrayRegion(jval, jval_off, jval_len, value);
481   if (env->ExceptionCheck()) {
482     // exception thrown: ArrayIndexOutOfBoundsException
483     delete[] value;
484     delete[] key;
485     return false;
486   }
487 
488   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
489   ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char*>(value),
490                                        jval_len);
491 
492   ROCKSDB_NAMESPACE::Status s;
493   if (cf_handle != nullptr) {
494     s = db->Put(write_options, cf_handle, key_slice, value_slice);
495   } else {
496     // backwards compatibility
497     s = db->Put(write_options, key_slice, value_slice);
498   }
499 
500   // cleanup
501   delete[] value;
502   delete[] key;
503 
504   if (s.ok()) {
505     return true;
506   } else {
507     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
508     return false;
509   }
510 }
511 
512 /*
513  * Class:     org_rocksdb_RocksDB
514  * Method:    put
515  * Signature: (J[BII[BII)V
516  */
Java_org_rocksdb_RocksDB_put__J_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)517 void Java_org_rocksdb_RocksDB_put__J_3BII_3BII(
518     JNIEnv* env, jobject, jlong jdb_handle,
519     jbyteArray jkey, jint jkey_off, jint jkey_len,
520     jbyteArray jval, jint jval_off, jint jval_len) {
521   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
522   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
523       ROCKSDB_NAMESPACE::WriteOptions();
524   rocksdb_put_helper(env, db, default_write_options, nullptr, jkey, jkey_off,
525       jkey_len, jval, jval_off, jval_len);
526 }
527 
528 /*
529  * Class:     org_rocksdb_RocksDB
530  * Method:    put
531  * Signature: (J[BII[BIIJ)V
532  */
Java_org_rocksdb_RocksDB_put__J_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)533 void Java_org_rocksdb_RocksDB_put__J_3BII_3BIIJ(
534     JNIEnv* env, jobject, jlong jdb_handle,
535     jbyteArray jkey, jint jkey_off, jint jkey_len,
536     jbyteArray jval, jint jval_off, jint jval_len,
537     jlong jcf_handle) {
538   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
539   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
540       ROCKSDB_NAMESPACE::WriteOptions();
541   auto* cf_handle =
542       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
543   if (cf_handle != nullptr) {
544     rocksdb_put_helper(env, db, default_write_options, cf_handle, jkey,
545         jkey_off, jkey_len, jval, jval_off, jval_len);
546   } else {
547     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
548         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
549                  "Invalid ColumnFamilyHandle."));
550   }
551 }
552 
553 /*
554  * Class:     org_rocksdb_RocksDB
555  * Method:    put
556  * Signature: (JJ[BII[BII)V
557  */
Java_org_rocksdb_RocksDB_put__JJ_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)558 void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BII(
559     JNIEnv* env, jobject, jlong jdb_handle,
560     jlong jwrite_options_handle,
561     jbyteArray jkey, jint jkey_off, jint jkey_len,
562     jbyteArray jval, jint jval_off, jint jval_len) {
563   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
564   auto* write_options =
565       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
566   rocksdb_put_helper(env, db, *write_options, nullptr, jkey, jkey_off, jkey_len,
567       jval, jval_off, jval_len);
568 }
569 
570 /*
571  * Class:     org_rocksdb_RocksDB
572  * Method:    put
573  * Signature: (JJ[BII[BIIJ)V
574  */
Java_org_rocksdb_RocksDB_put__JJ_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)575 void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BIIJ(
576     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle,
577     jbyteArray jkey, jint jkey_off, jint jkey_len,
578     jbyteArray jval, jint jval_off, jint jval_len,
579     jlong jcf_handle) {
580   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
581   auto* write_options =
582       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
583   auto* cf_handle =
584       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
585   if (cf_handle != nullptr) {
586     rocksdb_put_helper(env, db, *write_options, cf_handle, jkey, jkey_off,
587         jkey_len, jval, jval_off, jval_len);
588   } else {
589     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
590         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
591                  "Invalid ColumnFamilyHandle."));
592   }
593 }
594 
595 /*
596  * Class:     org_rocksdb_RocksDB
597  * Method:    putDirect
598  * Signature: (JJLjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IIJ)V
599  */
Java_org_rocksdb_RocksDB_putDirect(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jobject jkey,jint jkey_off,jint jkey_len,jobject jval,jint jval_off,jint jval_len,jlong jcf_handle)600 void Java_org_rocksdb_RocksDB_putDirect(
601     JNIEnv* env, jobject /*jdb*/, jlong jdb_handle, jlong jwrite_options_handle,
602     jobject jkey, jint jkey_off, jint jkey_len, jobject jval, jint jval_off,
603     jint jval_len, jlong jcf_handle) {
604   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
605   auto* write_options =
606       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
607   auto* cf_handle =
608       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
609   auto put = [&env, &db, &cf_handle, &write_options](
610                  ROCKSDB_NAMESPACE::Slice& key,
611                  ROCKSDB_NAMESPACE::Slice& value) {
612     ROCKSDB_NAMESPACE::Status s;
613     if (cf_handle == nullptr) {
614       s = db->Put(*write_options, key, value);
615     } else {
616       s = db->Put(*write_options, cf_handle, key, value);
617     }
618     if (s.ok()) {
619       return;
620     }
621     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
622   };
623   ROCKSDB_NAMESPACE::JniUtil::kv_op_direct(put, env, jkey, jkey_off, jkey_len,
624                                            jval, jval_off, jval_len);
625 }
626 
627 //////////////////////////////////////////////////////////////////////////////
628 // ROCKSDB_NAMESPACE::DB::Delete()
629 
630 /**
631  * @return true if the delete succeeded, false if a Java Exception was thrown
632  */
rocksdb_delete_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::WriteOptions & write_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle,jbyteArray jkey,jint jkey_off,jint jkey_len)633 bool rocksdb_delete_helper(JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
634                            const ROCKSDB_NAMESPACE::WriteOptions& write_options,
635                            ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle,
636                            jbyteArray jkey, jint jkey_off, jint jkey_len) {
637   jbyte* key = new jbyte[jkey_len];
638   env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key);
639   if (env->ExceptionCheck()) {
640     // exception thrown: ArrayIndexOutOfBoundsException
641     delete[] key;
642     return false;
643   }
644   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
645 
646   ROCKSDB_NAMESPACE::Status s;
647   if (cf_handle != nullptr) {
648     s = db->Delete(write_options, cf_handle, key_slice);
649   } else {
650     // backwards compatibility
651     s = db->Delete(write_options, key_slice);
652   }
653 
654   // cleanup
655   delete[] key;
656 
657   if (s.ok()) {
658     return true;
659   }
660 
661   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
662   return false;
663 }
664 
665 /*
666  * Class:     org_rocksdb_RocksDB
667  * Method:    delete
668  * Signature: (J[BII)V
669  */
Java_org_rocksdb_RocksDB_delete__J_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len)670 void Java_org_rocksdb_RocksDB_delete__J_3BII(
671     JNIEnv* env, jobject, jlong jdb_handle,
672     jbyteArray jkey, jint jkey_off, jint jkey_len) {
673   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
674   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
675       ROCKSDB_NAMESPACE::WriteOptions();
676   rocksdb_delete_helper(env, db, default_write_options, nullptr, jkey, jkey_off,
677       jkey_len);
678 }
679 
680 /*
681  * Class:     org_rocksdb_RocksDB
682  * Method:    delete
683  * Signature: (J[BIIJ)V
684  */
Java_org_rocksdb_RocksDB_delete__J_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jlong jcf_handle)685 void Java_org_rocksdb_RocksDB_delete__J_3BIIJ(
686     JNIEnv* env, jobject, jlong jdb_handle,
687     jbyteArray jkey, jint jkey_off, jint jkey_len,
688     jlong jcf_handle) {
689   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
690   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
691       ROCKSDB_NAMESPACE::WriteOptions();
692   auto* cf_handle =
693       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
694   if (cf_handle != nullptr) {
695     rocksdb_delete_helper(env, db, default_write_options, cf_handle, jkey,
696         jkey_off, jkey_len);
697   } else {
698     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
699         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
700                  "Invalid ColumnFamilyHandle."));
701   }
702 }
703 
704 /*
705  * Class:     org_rocksdb_RocksDB
706  * Method:    delete
707  * Signature: (JJ[BII)V
708  */
Java_org_rocksdb_RocksDB_delete__JJ_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jkey,jint jkey_off,jint jkey_len)709 void Java_org_rocksdb_RocksDB_delete__JJ_3BII(
710     JNIEnv* env, jobject,
711     jlong jdb_handle,
712     jlong jwrite_options,
713     jbyteArray jkey, jint jkey_off, jint jkey_len) {
714   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
715   auto* write_options =
716       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
717   rocksdb_delete_helper(env, db, *write_options, nullptr, jkey, jkey_off,
718       jkey_len);
719 }
720 
721 /*
722  * Class:     org_rocksdb_RocksDB
723  * Method:    delete
724  * Signature: (JJ[BIIJ)V
725  */
Java_org_rocksdb_RocksDB_delete__JJ_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jkey,jint jkey_off,jint jkey_len,jlong jcf_handle)726 void Java_org_rocksdb_RocksDB_delete__JJ_3BIIJ(
727     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options,
728     jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) {
729   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
730   auto* write_options =
731       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
732   auto* cf_handle =
733       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
734   if (cf_handle != nullptr) {
735     rocksdb_delete_helper(env, db, *write_options, cf_handle, jkey, jkey_off,
736         jkey_len);
737   } else {
738     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
739         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
740                  "Invalid ColumnFamilyHandle."));
741   }
742 }
743 
744 //////////////////////////////////////////////////////////////////////////////
745 // ROCKSDB_NAMESPACE::DB::SingleDelete()
746 /**
747  * @return true if the single delete succeeded, false if a Java Exception
748  *     was thrown
749  */
rocksdb_single_delete_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::WriteOptions & write_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle,jbyteArray jkey,jint jkey_len)750 bool rocksdb_single_delete_helper(
751     JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
752     const ROCKSDB_NAMESPACE::WriteOptions& write_options,
753     ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle, jbyteArray jkey,
754     jint jkey_len) {
755   jbyte* key = env->GetByteArrayElements(jkey, nullptr);
756   if (key == nullptr) {
757     // exception thrown: OutOfMemoryError
758     return false;
759   }
760   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
761 
762   ROCKSDB_NAMESPACE::Status s;
763   if (cf_handle != nullptr) {
764     s = db->SingleDelete(write_options, cf_handle, key_slice);
765   } else {
766     // backwards compatibility
767     s = db->SingleDelete(write_options, key_slice);
768   }
769 
770   // trigger java unref on key and value.
771   // by passing JNI_ABORT, it will simply release the reference without
772   // copying the result back to the java byte array.
773   env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
774 
775   if (s.ok()) {
776     return true;
777   }
778 
779   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
780   return false;
781 }
782 
783 /*
784  * Class:     org_rocksdb_RocksDB
785  * Method:    singleDelete
786  * Signature: (J[BI)V
787  */
Java_org_rocksdb_RocksDB_singleDelete__J_3BI(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_len)788 void Java_org_rocksdb_RocksDB_singleDelete__J_3BI(
789     JNIEnv* env, jobject,
790     jlong jdb_handle,
791     jbyteArray jkey,
792     jint jkey_len) {
793   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
794   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
795       ROCKSDB_NAMESPACE::WriteOptions();
796   rocksdb_single_delete_helper(env, db, default_write_options, nullptr,
797       jkey, jkey_len);
798 }
799 
800 /*
801  * Class:     org_rocksdb_RocksDB
802  * Method:    singleDelete
803  * Signature: (J[BIJ)V
804  */
Java_org_rocksdb_RocksDB_singleDelete__J_3BIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_len,jlong jcf_handle)805 void Java_org_rocksdb_RocksDB_singleDelete__J_3BIJ(
806     JNIEnv* env, jobject, jlong jdb_handle,
807     jbyteArray jkey, jint jkey_len, jlong jcf_handle) {
808   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
809   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
810       ROCKSDB_NAMESPACE::WriteOptions();
811   auto* cf_handle =
812       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
813   if (cf_handle != nullptr) {
814     rocksdb_single_delete_helper(env, db, default_write_options, cf_handle,
815         jkey, jkey_len);
816   } else {
817     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
818         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
819                  "Invalid ColumnFamilyHandle."));
820   }
821 }
822 
823 /*
824  * Class:     org_rocksdb_RocksDB
825  * Method:    singleDelete
826  * Signature: (JJ[BIJ)V
827  */
Java_org_rocksdb_RocksDB_singleDelete__JJ_3BI(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jkey,jint jkey_len)828 void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BI(
829     JNIEnv* env, jobject, jlong jdb_handle,
830     jlong jwrite_options,
831     jbyteArray jkey,
832     jint jkey_len) {
833   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
834   auto* write_options =
835       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
836   rocksdb_single_delete_helper(env, db, *write_options, nullptr, jkey,
837       jkey_len);
838 }
839 
840 /*
841  * Class:     org_rocksdb_RocksDB
842  * Method:    singleDelete
843  * Signature: (JJ[BIJ)V
844  */
Java_org_rocksdb_RocksDB_singleDelete__JJ_3BIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jkey,jint jkey_len,jlong jcf_handle)845 void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BIJ(
846     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options,
847     jbyteArray jkey, jint jkey_len, jlong jcf_handle) {
848   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
849   auto* write_options =
850       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
851   auto* cf_handle =
852       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
853   if (cf_handle != nullptr) {
854     rocksdb_single_delete_helper(env, db, *write_options, cf_handle, jkey,
855         jkey_len);
856   } else {
857     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
858         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
859                  "Invalid ColumnFamilyHandle."));
860   }
861 }
862 
863 //////////////////////////////////////////////////////////////////////////////
864 // ROCKSDB_NAMESPACE::DB::DeleteRange()
865 /**
866  * @return true if the delete range succeeded, false if a Java Exception
867  *     was thrown
868  */
rocksdb_delete_range_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::WriteOptions & write_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle,jbyteArray jbegin_key,jint jbegin_key_off,jint jbegin_key_len,jbyteArray jend_key,jint jend_key_off,jint jend_key_len)869 bool rocksdb_delete_range_helper(
870     JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
871     const ROCKSDB_NAMESPACE::WriteOptions& write_options,
872     ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle, jbyteArray jbegin_key,
873     jint jbegin_key_off, jint jbegin_key_len, jbyteArray jend_key,
874     jint jend_key_off, jint jend_key_len) {
875   jbyte* begin_key = new jbyte[jbegin_key_len];
876   env->GetByteArrayRegion(jbegin_key, jbegin_key_off, jbegin_key_len,
877       begin_key);
878   if (env->ExceptionCheck()) {
879     // exception thrown: ArrayIndexOutOfBoundsException
880     delete[] begin_key;
881     return false;
882   }
883   ROCKSDB_NAMESPACE::Slice begin_key_slice(reinterpret_cast<char*>(begin_key),
884                                            jbegin_key_len);
885 
886   jbyte* end_key = new jbyte[jend_key_len];
887   env->GetByteArrayRegion(jend_key, jend_key_off, jend_key_len, end_key);
888   if (env->ExceptionCheck()) {
889     // exception thrown: ArrayIndexOutOfBoundsException
890     delete[] begin_key;
891     delete[] end_key;
892     return false;
893   }
894   ROCKSDB_NAMESPACE::Slice end_key_slice(reinterpret_cast<char*>(end_key),
895                                          jend_key_len);
896 
897   ROCKSDB_NAMESPACE::Status s =
898       db->DeleteRange(write_options, cf_handle, begin_key_slice, end_key_slice);
899 
900   // cleanup
901   delete[] begin_key;
902   delete[] end_key;
903 
904   if (s.ok()) {
905     return true;
906   }
907 
908   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
909   return false;
910 }
911 
912 /*
913  * Class:     org_rocksdb_RocksDB
914  * Method:    deleteRange
915  * Signature: (J[BII[BII)V
916  */
Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jbegin_key,jint jbegin_key_off,jint jbegin_key_len,jbyteArray jend_key,jint jend_key_off,jint jend_key_len)917 void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BII(
918     JNIEnv* env, jobject, jlong jdb_handle,
919     jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
920     jbyteArray jend_key, jint jend_key_off, jint jend_key_len) {
921   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
922   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
923       ROCKSDB_NAMESPACE::WriteOptions();
924   rocksdb_delete_range_helper(env, db, default_write_options, nullptr,
925       jbegin_key, jbegin_key_off, jbegin_key_len,
926       jend_key, jend_key_off, jend_key_len);
927 }
928 
rocksdb_get_helper_direct(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::ReadOptions & read_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * column_family_handle,jobject jkey,jint jkey_off,jint jkey_len,jobject jval,jint jval_off,jint jval_len,bool * has_exception)929 jint rocksdb_get_helper_direct(
930     JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
931     const ROCKSDB_NAMESPACE::ReadOptions& read_options,
932     ROCKSDB_NAMESPACE::ColumnFamilyHandle* column_family_handle, jobject jkey,
933     jint jkey_off, jint jkey_len, jobject jval, jint jval_off, jint jval_len,
934     bool* has_exception) {
935   static const int kNotFound = -1;
936   static const int kStatusError = -2;
937   static const int kArgumentError = -3;
938 
939   char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
940   if (key == nullptr) {
941     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
942         env,
943         "Invalid key argument (argument is not a valid direct ByteBuffer)");
944     *has_exception = true;
945     return kArgumentError;
946   }
947   if (env->GetDirectBufferCapacity(jkey) < (jkey_off + jkey_len)) {
948     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
949         env,
950         "Invalid key argument. Capacity is less than requested region (offset "
951         "+ length).");
952     *has_exception = true;
953     return kArgumentError;
954   }
955 
956   char* value = reinterpret_cast<char*>(env->GetDirectBufferAddress(jval));
957   if (value == nullptr) {
958     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
959         env,
960         "Invalid value argument (argument is not a valid direct ByteBuffer)");
961     *has_exception = true;
962     return kArgumentError;
963   }
964 
965   if (env->GetDirectBufferCapacity(jval) < (jval_off + jval_len)) {
966     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
967         env,
968         "Invalid value argument. Capacity is less than requested region "
969         "(offset + length).");
970     *has_exception = true;
971     return kArgumentError;
972   }
973 
974   key += jkey_off;
975   value += jval_off;
976 
977   ROCKSDB_NAMESPACE::Slice key_slice(key, jkey_len);
978 
979   // TODO(yhchiang): we might save one memory allocation here by adding
980   // a DB::Get() function which takes preallocated jbyte* as input.
981   std::string cvalue;
982   ROCKSDB_NAMESPACE::Status s;
983   if (column_family_handle != nullptr) {
984     s = db->Get(read_options, column_family_handle, key_slice, &cvalue);
985   } else {
986     // backwards compatibility
987     s = db->Get(read_options, key_slice, &cvalue);
988   }
989 
990   if (s.IsNotFound()) {
991     *has_exception = false;
992     return kNotFound;
993   } else if (!s.ok()) {
994     *has_exception = true;
995     // Here since we are throwing a Java exception from c++ side.
996     // As a result, c++ does not know calling this function will in fact
997     // throwing an exception.  As a result, the execution flow will
998     // not stop here, and codes after this throw will still be
999     // executed.
1000     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1001 
1002     // Return a dummy const value to avoid compilation error, although
1003     // java side might not have a chance to get the return value :)
1004     return kStatusError;
1005   }
1006 
1007   const jint cvalue_len = static_cast<jint>(cvalue.size());
1008   const jint length = std::min(jval_len, cvalue_len);
1009 
1010   memcpy(value, cvalue.c_str(), length);
1011 
1012   *has_exception = false;
1013   return cvalue_len;
1014 }
1015 
1016 /*
1017  * Class:     org_rocksdb_RocksDB
1018  * Method:    deleteRange
1019  * Signature: (J[BII[BIIJ)V
1020  */
Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jbegin_key,jint jbegin_key_off,jint jbegin_key_len,jbyteArray jend_key,jint jend_key_off,jint jend_key_len,jlong jcf_handle)1021 void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BIIJ(
1022     JNIEnv* env, jobject, jlong jdb_handle,
1023     jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
1024     jbyteArray jend_key, jint jend_key_off, jint jend_key_len,
1025     jlong jcf_handle) {
1026   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1027   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
1028       ROCKSDB_NAMESPACE::WriteOptions();
1029   auto* cf_handle =
1030       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1031   if (cf_handle != nullptr) {
1032     rocksdb_delete_range_helper(env, db, default_write_options, cf_handle,
1033         jbegin_key, jbegin_key_off, jbegin_key_len,
1034         jend_key, jend_key_off, jend_key_len);
1035   } else {
1036     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1037         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1038                  "Invalid ColumnFamilyHandle."));
1039   }
1040 }
1041 
1042 /*
1043  * Class:     org_rocksdb_RocksDB
1044  * Method:    deleteRange
1045  * Signature: (JJ[BII[BII)V
1046  */
Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jbegin_key,jint jbegin_key_off,jint jbegin_key_len,jbyteArray jend_key,jint jend_key_off,jint jend_key_len)1047 void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BII(
1048     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options,
1049     jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
1050     jbyteArray jend_key, jint jend_key_off, jint jend_key_len) {
1051   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1052   auto* write_options =
1053       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
1054   rocksdb_delete_range_helper(env, db, *write_options, nullptr, jbegin_key,
1055       jbegin_key_off, jbegin_key_len, jend_key,
1056       jend_key_off, jend_key_len);
1057 }
1058 
1059 /*
1060  * Class:     org_rocksdb_RocksDB
1061  * Method:    deleteRange
1062  * Signature: (JJ[BII[BIIJ)V
1063  */
Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jbyteArray jbegin_key,jint jbegin_key_off,jint jbegin_key_len,jbyteArray jend_key,jint jend_key_off,jint jend_key_len,jlong jcf_handle)1064 void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BIIJ(
1065     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options,
1066     jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
1067     jbyteArray jend_key, jint jend_key_off, jint jend_key_len,
1068     jlong jcf_handle) {
1069   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1070   auto* write_options =
1071       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
1072   auto* cf_handle =
1073       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1074   if (cf_handle != nullptr) {
1075     rocksdb_delete_range_helper(env, db, *write_options, cf_handle,
1076         jbegin_key, jbegin_key_off, jbegin_key_len,
1077         jend_key, jend_key_off, jend_key_len);
1078   } else {
1079     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1080         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1081                  "Invalid ColumnFamilyHandle."));
1082   }
1083 }
1084 
1085 /*
1086  * Class:     org_rocksdb_RocksDB
1087  * Method:    getDirect
1088  * Signature: (JJLjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IIJ)I
1089  */
Java_org_rocksdb_RocksDB_getDirect(JNIEnv * env,jobject,jlong jdb_handle,jlong jropt_handle,jobject jkey,jint jkey_off,jint jkey_len,jobject jval,jint jval_off,jint jval_len,jlong jcf_handle)1090 jint Java_org_rocksdb_RocksDB_getDirect(JNIEnv* env, jobject /*jdb*/,
1091                                         jlong jdb_handle, jlong jropt_handle,
1092                                         jobject jkey, jint jkey_off,
1093                                         jint jkey_len, jobject jval,
1094                                         jint jval_off, jint jval_len,
1095                                         jlong jcf_handle) {
1096   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1097   auto* ro_opt =
1098       reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle);
1099   auto* cf_handle =
1100       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1101   bool has_exception = false;
1102   return rocksdb_get_helper_direct(
1103       env, db_handle,
1104       ro_opt == nullptr ? ROCKSDB_NAMESPACE::ReadOptions() : *ro_opt, cf_handle,
1105       jkey, jkey_off, jkey_len, jval, jval_off, jval_len, &has_exception);
1106 }
1107 
1108 //////////////////////////////////////////////////////////////////////////////
1109 // ROCKSDB_NAMESPACE::DB::Merge
1110 
1111 /**
1112  * @return true if the merge succeeded, false if a Java Exception was thrown
1113  */
rocksdb_merge_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::WriteOptions & write_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)1114 bool rocksdb_merge_helper(JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
1115                           const ROCKSDB_NAMESPACE::WriteOptions& write_options,
1116                           ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle,
1117                           jbyteArray jkey, jint jkey_off, jint jkey_len,
1118                           jbyteArray jval, jint jval_off, jint jval_len) {
1119   jbyte* key = new jbyte[jkey_len];
1120   env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key);
1121   if (env->ExceptionCheck()) {
1122     // exception thrown: ArrayIndexOutOfBoundsException
1123     delete[] key;
1124     return false;
1125   }
1126   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
1127 
1128   jbyte* value = new jbyte[jval_len];
1129   env->GetByteArrayRegion(jval, jval_off, jval_len, value);
1130   if (env->ExceptionCheck()) {
1131     // exception thrown: ArrayIndexOutOfBoundsException
1132     delete[] value;
1133     delete[] key;
1134     return false;
1135   }
1136   ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char*>(value),
1137                                        jval_len);
1138 
1139   ROCKSDB_NAMESPACE::Status s;
1140   if (cf_handle != nullptr) {
1141     s = db->Merge(write_options, cf_handle, key_slice, value_slice);
1142   } else {
1143     s = db->Merge(write_options, key_slice, value_slice);
1144   }
1145 
1146   // cleanup
1147   delete[] value;
1148   delete[] key;
1149 
1150   if (s.ok()) {
1151     return true;
1152   }
1153 
1154   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1155   return false;
1156 }
1157 
1158 /*
1159  * Class:     org_rocksdb_RocksDB
1160  * Method:    merge
1161  * Signature: (J[BII[BII)V
1162  */
Java_org_rocksdb_RocksDB_merge__J_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)1163 void Java_org_rocksdb_RocksDB_merge__J_3BII_3BII(
1164     JNIEnv* env, jobject, jlong jdb_handle,
1165     jbyteArray jkey, jint jkey_off, jint jkey_len,
1166     jbyteArray jval, jint jval_off, jint jval_len) {
1167   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1168   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
1169       ROCKSDB_NAMESPACE::WriteOptions();
1170   rocksdb_merge_helper(env, db, default_write_options, nullptr, jkey, jkey_off,
1171       jkey_len, jval, jval_off, jval_len);
1172 }
1173 
1174 /*
1175  * Class:     org_rocksdb_RocksDB
1176  * Method:    merge
1177  * Signature: (J[BII[BIIJ)V
1178  */
Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)1179 void Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ(
1180     JNIEnv* env, jobject, jlong jdb_handle,
1181     jbyteArray jkey, jint jkey_off, jint jkey_len,
1182     jbyteArray jval, jint jval_off, jint jval_len,
1183     jlong jcf_handle) {
1184   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1185   static const ROCKSDB_NAMESPACE::WriteOptions default_write_options =
1186       ROCKSDB_NAMESPACE::WriteOptions();
1187   auto* cf_handle =
1188       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1189   if (cf_handle != nullptr) {
1190     rocksdb_merge_helper(env, db, default_write_options, cf_handle, jkey,
1191         jkey_off, jkey_len, jval, jval_off, jval_len);
1192   } else {
1193     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1194         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1195                  "Invalid ColumnFamilyHandle."));
1196   }
1197 }
1198 
1199 /*
1200  * Class:     org_rocksdb_RocksDB
1201  * Method:    merge
1202  * Signature: (JJ[BII[BII)V
1203  */
Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)1204 void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII(
1205     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle,
1206     jbyteArray jkey, jint jkey_off, jint jkey_len,
1207     jbyteArray jval, jint jval_off, jint jval_len) {
1208   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1209   auto* write_options =
1210       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
1211   rocksdb_merge_helper(env, db, *write_options, nullptr, jkey, jkey_off,
1212       jkey_len, jval, jval_off, jval_len);
1213 }
1214 
1215 /*
1216  * Class:     org_rocksdb_RocksDB
1217  * Method:    merge
1218  * Signature: (JJ[BII[BIIJ)V
1219  */
Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)1220 void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ(
1221     JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle,
1222     jbyteArray jkey, jint jkey_off, jint jkey_len,
1223     jbyteArray jval, jint jval_off, jint jval_len, jlong jcf_handle) {
1224   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1225   auto* write_options =
1226       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
1227   auto* cf_handle =
1228       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1229   if (cf_handle != nullptr) {
1230     rocksdb_merge_helper(env, db, *write_options, cf_handle, jkey, jkey_off,
1231         jkey_len, jval, jval_off, jval_len);
1232   } else {
1233     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1234         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1235                  "Invalid ColumnFamilyHandle."));
1236   }
1237 }
1238 
rocksdb_iterator_helper(ROCKSDB_NAMESPACE::DB * db,ROCKSDB_NAMESPACE::ReadOptions read_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * cf_handle)1239 jlong rocksdb_iterator_helper(
1240     ROCKSDB_NAMESPACE::DB* db, ROCKSDB_NAMESPACE::ReadOptions read_options,
1241     ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle) {
1242   ROCKSDB_NAMESPACE::Iterator* iterator = nullptr;
1243   if (cf_handle != nullptr) {
1244     iterator = db->NewIterator(read_options, cf_handle);
1245   } else {
1246     iterator = db->NewIterator(read_options);
1247   }
1248   return reinterpret_cast<jlong>(iterator);
1249 }
1250 
1251 /*
1252  * Class:     org_rocksdb_RocksDB
1253  * Method:    deleteDirect
1254  * Signature: (JJLjava/nio/ByteBuffer;IIJ)V
1255  */
Java_org_rocksdb_RocksDB_deleteDirect(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options,jobject jkey,jint jkey_offset,jint jkey_len,jlong jcf_handle)1256 void Java_org_rocksdb_RocksDB_deleteDirect(JNIEnv* env, jobject /*jdb*/,
1257                                            jlong jdb_handle,
1258                                            jlong jwrite_options, jobject jkey,
1259                                            jint jkey_offset, jint jkey_len,
1260                                            jlong jcf_handle) {
1261   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1262   auto* write_options =
1263       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options);
1264   auto* cf_handle =
1265       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1266   auto remove = [&env, &db, &write_options,
1267                  &cf_handle](ROCKSDB_NAMESPACE::Slice& key) {
1268     ROCKSDB_NAMESPACE::Status s;
1269     if (cf_handle == nullptr) {
1270       s = db->Delete(*write_options, key);
1271     } else {
1272       s = db->Delete(*write_options, cf_handle, key);
1273     }
1274     if (s.ok()) {
1275       return;
1276     }
1277     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1278   };
1279   ROCKSDB_NAMESPACE::JniUtil::k_op_direct(remove, env, jkey, jkey_offset,
1280                                           jkey_len);
1281 }
1282 
1283 //////////////////////////////////////////////////////////////////////////////
1284 // ROCKSDB_NAMESPACE::DB::Write
1285 /*
1286  * Class:     org_rocksdb_RocksDB
1287  * Method:    write0
1288  * Signature: (JJJ)V
1289  */
Java_org_rocksdb_RocksDB_write0(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jlong jwb_handle)1290 void Java_org_rocksdb_RocksDB_write0(
1291     JNIEnv* env, jobject, jlong jdb_handle,
1292     jlong jwrite_options_handle, jlong jwb_handle) {
1293   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1294   auto* write_options =
1295       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
1296   auto* wb = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
1297 
1298   ROCKSDB_NAMESPACE::Status s = db->Write(*write_options, wb);
1299 
1300   if (!s.ok()) {
1301     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1302   }
1303 }
1304 
1305 /*
1306  * Class:     org_rocksdb_RocksDB
1307  * Method:    write1
1308  * Signature: (JJJ)V
1309  */
Java_org_rocksdb_RocksDB_write1(JNIEnv * env,jobject,jlong jdb_handle,jlong jwrite_options_handle,jlong jwbwi_handle)1310 void Java_org_rocksdb_RocksDB_write1(
1311     JNIEnv* env, jobject, jlong jdb_handle,
1312     jlong jwrite_options_handle, jlong jwbwi_handle) {
1313   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1314   auto* write_options =
1315       reinterpret_cast<ROCKSDB_NAMESPACE::WriteOptions*>(jwrite_options_handle);
1316   auto* wbwi =
1317       reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatchWithIndex*>(jwbwi_handle);
1318   auto* wb = wbwi->GetWriteBatch();
1319 
1320   ROCKSDB_NAMESPACE::Status s = db->Write(*write_options, wb);
1321 
1322   if (!s.ok()) {
1323     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1324   }
1325 }
1326 
1327 //////////////////////////////////////////////////////////////////////////////
1328 // ROCKSDB_NAMESPACE::DB::Get
1329 
rocksdb_get_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::ReadOptions & read_opt,ROCKSDB_NAMESPACE::ColumnFamilyHandle * column_family_handle,jbyteArray jkey,jint jkey_off,jint jkey_len)1330 jbyteArray rocksdb_get_helper(
1331     JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
1332     const ROCKSDB_NAMESPACE::ReadOptions& read_opt,
1333     ROCKSDB_NAMESPACE::ColumnFamilyHandle* column_family_handle,
1334     jbyteArray jkey, jint jkey_off, jint jkey_len) {
1335   jbyte* key = new jbyte[jkey_len];
1336   env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key);
1337   if (env->ExceptionCheck()) {
1338     // exception thrown: ArrayIndexOutOfBoundsException
1339     delete[] key;
1340     return nullptr;
1341   }
1342 
1343   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
1344 
1345   std::string value;
1346   ROCKSDB_NAMESPACE::Status s;
1347   if (column_family_handle != nullptr) {
1348     s = db->Get(read_opt, column_family_handle, key_slice, &value);
1349   } else {
1350     // backwards compatibility
1351     s = db->Get(read_opt, key_slice, &value);
1352   }
1353 
1354   // cleanup
1355   delete[] key;
1356 
1357   if (s.IsNotFound()) {
1358     return nullptr;
1359   }
1360 
1361   if (s.ok()) {
1362     jbyteArray jret_value = ROCKSDB_NAMESPACE::JniUtil::copyBytes(env, value);
1363     if (jret_value == nullptr) {
1364       // exception occurred
1365       return nullptr;
1366     }
1367     return jret_value;
1368   }
1369 
1370   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1371   return nullptr;
1372 }
1373 
1374 /*
1375  * Class:     org_rocksdb_RocksDB
1376  * Method:    get
1377  * Signature: (J[BII)[B
1378  */
Java_org_rocksdb_RocksDB_get__J_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len)1379 jbyteArray Java_org_rocksdb_RocksDB_get__J_3BII(
1380     JNIEnv* env, jobject, jlong jdb_handle,
1381     jbyteArray jkey, jint jkey_off, jint jkey_len) {
1382   return rocksdb_get_helper(
1383       env, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1384       ROCKSDB_NAMESPACE::ReadOptions(), nullptr, jkey, jkey_off, jkey_len);
1385 }
1386 
1387 /*
1388  * Class:     org_rocksdb_RocksDB
1389  * Method:    get
1390  * Signature: (J[BIIJ)[B
1391  */
Java_org_rocksdb_RocksDB_get__J_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jlong jcf_handle)1392 jbyteArray Java_org_rocksdb_RocksDB_get__J_3BIIJ(
1393     JNIEnv* env, jobject, jlong jdb_handle,
1394     jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) {
1395   auto db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1396   auto cf_handle =
1397       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1398   if (cf_handle != nullptr) {
1399     return rocksdb_get_helper(env, db_handle, ROCKSDB_NAMESPACE::ReadOptions(),
1400                               cf_handle, jkey, jkey_off, jkey_len);
1401   } else {
1402     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1403         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1404                  "Invalid ColumnFamilyHandle."));
1405     return nullptr;
1406   }
1407 }
1408 
1409 /*
1410  * Class:     org_rocksdb_RocksDB
1411  * Method:    get
1412  * Signature: (JJ[BII)[B
1413  */
Java_org_rocksdb_RocksDB_get__JJ_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jropt_handle,jbyteArray jkey,jint jkey_off,jint jkey_len)1414 jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BII(
1415     JNIEnv* env, jobject,
1416     jlong jdb_handle, jlong jropt_handle,
1417     jbyteArray jkey, jint jkey_off, jint jkey_len) {
1418   return rocksdb_get_helper(
1419       env, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1420       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle), nullptr,
1421       jkey, jkey_off, jkey_len);
1422 }
1423 
1424 /*
1425  * Class:     org_rocksdb_RocksDB
1426  * Method:    get
1427  * Signature: (JJ[BIIJ)[B
1428  */
Java_org_rocksdb_RocksDB_get__JJ_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jropt_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jlong jcf_handle)1429 jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BIIJ(
1430     JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle,
1431     jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) {
1432   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1433   auto& ro_opt =
1434       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle);
1435   auto* cf_handle =
1436       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1437   if (cf_handle != nullptr) {
1438     return rocksdb_get_helper(
1439         env, db_handle, ro_opt, cf_handle, jkey, jkey_off, jkey_len);
1440   } else {
1441     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1442         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1443                  "Invalid ColumnFamilyHandle."));
1444     return nullptr;
1445   }
1446 }
1447 
rocksdb_get_helper(JNIEnv * env,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::ReadOptions & read_options,ROCKSDB_NAMESPACE::ColumnFamilyHandle * column_family_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,bool * has_exception)1448 jint rocksdb_get_helper(
1449     JNIEnv* env, ROCKSDB_NAMESPACE::DB* db,
1450     const ROCKSDB_NAMESPACE::ReadOptions& read_options,
1451     ROCKSDB_NAMESPACE::ColumnFamilyHandle* column_family_handle,
1452     jbyteArray jkey, jint jkey_off, jint jkey_len, jbyteArray jval,
1453     jint jval_off, jint jval_len, bool* has_exception) {
1454   static const int kNotFound = -1;
1455   static const int kStatusError = -2;
1456 
1457   jbyte* key = new jbyte[jkey_len];
1458   env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key);
1459   if (env->ExceptionCheck()) {
1460     // exception thrown: OutOfMemoryError
1461     delete[] key;
1462     *has_exception = true;
1463     return kStatusError;
1464   }
1465   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
1466 
1467   // TODO(yhchiang): we might save one memory allocation here by adding
1468   // a DB::Get() function which takes preallocated jbyte* as input.
1469   std::string cvalue;
1470   ROCKSDB_NAMESPACE::Status s;
1471   if (column_family_handle != nullptr) {
1472     s = db->Get(read_options, column_family_handle, key_slice, &cvalue);
1473   } else {
1474     // backwards compatibility
1475     s = db->Get(read_options, key_slice, &cvalue);
1476   }
1477 
1478   // cleanup
1479   delete[] key;
1480 
1481   if (s.IsNotFound()) {
1482     *has_exception = false;
1483     return kNotFound;
1484   } else if (!s.ok()) {
1485     *has_exception = true;
1486     // Here since we are throwing a Java exception from c++ side.
1487     // As a result, c++ does not know calling this function will in fact
1488     // throwing an exception.  As a result, the execution flow will
1489     // not stop here, and codes after this throw will still be
1490     // executed.
1491     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
1492 
1493     // Return a dummy const value to avoid compilation error, although
1494     // java side might not have a chance to get the return value :)
1495     return kStatusError;
1496   }
1497 
1498   const jint cvalue_len = static_cast<jint>(cvalue.size());
1499   const jint length = std::min(jval_len, cvalue_len);
1500 
1501   env->SetByteArrayRegion(
1502       jval, jval_off, length,
1503       const_cast<jbyte*>(reinterpret_cast<const jbyte*>(cvalue.c_str())));
1504   if (env->ExceptionCheck()) {
1505     // exception thrown: OutOfMemoryError
1506     *has_exception = true;
1507     return kStatusError;
1508   }
1509 
1510   *has_exception = false;
1511   return cvalue_len;
1512 }
1513 
1514 /*
1515  * Class:     org_rocksdb_RocksDB
1516  * Method:    get
1517  * Signature: (J[BII[BII)I
1518  */
Java_org_rocksdb_RocksDB_get__J_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)1519 jint Java_org_rocksdb_RocksDB_get__J_3BII_3BII(
1520     JNIEnv* env, jobject, jlong jdb_handle,
1521     jbyteArray jkey, jint jkey_off, jint jkey_len,
1522     jbyteArray jval, jint jval_off, jint jval_len) {
1523   bool has_exception = false;
1524   return rocksdb_get_helper(
1525       env, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1526       ROCKSDB_NAMESPACE::ReadOptions(), nullptr, jkey, jkey_off, jkey_len, jval,
1527       jval_off, jval_len, &has_exception);
1528 }
1529 
1530 /*
1531  * Class:     org_rocksdb_RocksDB
1532  * Method:    get
1533  * Signature: (J[BII[BIIJ)I
1534  */
Java_org_rocksdb_RocksDB_get__J_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)1535 jint Java_org_rocksdb_RocksDB_get__J_3BII_3BIIJ(
1536     JNIEnv* env, jobject, jlong jdb_handle,
1537     jbyteArray jkey, jint jkey_off, jint jkey_len,
1538     jbyteArray jval, jint jval_off, jint jval_len,
1539     jlong jcf_handle) {
1540   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1541   auto* cf_handle =
1542       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1543   if (cf_handle != nullptr) {
1544     bool has_exception = false;
1545     return rocksdb_get_helper(env, db_handle, ROCKSDB_NAMESPACE::ReadOptions(),
1546                               cf_handle, jkey, jkey_off, jkey_len, jval,
1547                               jval_off, jval_len, &has_exception);
1548   } else {
1549     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1550         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1551                  "Invalid ColumnFamilyHandle."));
1552     // will never be evaluated
1553     return 0;
1554   }
1555 }
1556 
1557 /*
1558  * Class:     org_rocksdb_RocksDB
1559  * Method:    get
1560  * Signature: (JJ[BII[BII)I
1561  */
Java_org_rocksdb_RocksDB_get__JJ_3BII_3BII(JNIEnv * env,jobject,jlong jdb_handle,jlong jropt_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len)1562 jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BII(
1563     JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle,
1564     jbyteArray jkey, jint jkey_off, jint jkey_len,
1565     jbyteArray jval, jint jval_off, jint jval_len) {
1566   bool has_exception = false;
1567   return rocksdb_get_helper(
1568       env, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1569       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle), nullptr,
1570       jkey, jkey_off, jkey_len, jval, jval_off, jval_len, &has_exception);
1571 }
1572 
1573 /*
1574  * Class:     org_rocksdb_RocksDB
1575  * Method:    get
1576  * Signature: (JJ[BII[BIIJ)I
1577  */
Java_org_rocksdb_RocksDB_get__JJ_3BII_3BIIJ(JNIEnv * env,jobject,jlong jdb_handle,jlong jropt_handle,jbyteArray jkey,jint jkey_off,jint jkey_len,jbyteArray jval,jint jval_off,jint jval_len,jlong jcf_handle)1578 jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BIIJ(
1579     JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle,
1580     jbyteArray jkey, jint jkey_off, jint jkey_len,
1581     jbyteArray jval, jint jval_off, jint jval_len,
1582     jlong jcf_handle) {
1583   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1584   auto& ro_opt =
1585       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle);
1586   auto* cf_handle =
1587       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1588   if (cf_handle != nullptr) {
1589     bool has_exception = false;
1590     return rocksdb_get_helper(env, db_handle, ro_opt, cf_handle,
1591         jkey, jkey_off, jkey_len,
1592         jval, jval_off, jval_len,
1593         &has_exception);
1594   } else {
1595     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
1596         env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
1597                  "Invalid ColumnFamilyHandle."));
1598     // will never be evaluated
1599     return 0;
1600   }
1601 }
1602 
multi_get_helper_release_keys(JNIEnv * env,std::vector<std::pair<jbyte *,jobject>> & keys_to_free)1603 inline void multi_get_helper_release_keys(
1604     JNIEnv* env, std::vector<std::pair<jbyte*, jobject>>& keys_to_free) {
1605   auto end = keys_to_free.end();
1606   for (auto it = keys_to_free.begin(); it != end; ++it) {
1607     delete[] it->first;
1608     env->DeleteLocalRef(it->second);
1609   }
1610   keys_to_free.clear();
1611 }
1612 
1613 /**
1614  * cf multi get
1615  *
1616  * @return byte[][] of values or nullptr if an exception occurs
1617  */
multi_get_helper(JNIEnv * env,jobject,ROCKSDB_NAMESPACE::DB * db,const ROCKSDB_NAMESPACE::ReadOptions & rOpt,jobjectArray jkeys,jintArray jkey_offs,jintArray jkey_lens,jlongArray jcolumn_family_handles)1618 jobjectArray multi_get_helper(JNIEnv* env, jobject, ROCKSDB_NAMESPACE::DB* db,
1619                               const ROCKSDB_NAMESPACE::ReadOptions& rOpt,
1620                               jobjectArray jkeys, jintArray jkey_offs,
1621                               jintArray jkey_lens,
1622                               jlongArray jcolumn_family_handles) {
1623   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
1624   if (jcolumn_family_handles != nullptr) {
1625     const jsize len_cols = env->GetArrayLength(jcolumn_family_handles);
1626 
1627     jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr);
1628     if (jcfh == nullptr) {
1629       // exception thrown: OutOfMemoryError
1630       return nullptr;
1631     }
1632 
1633     for (jsize i = 0; i < len_cols; i++) {
1634       auto* cf_handle =
1635           reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcfh[i]);
1636       cf_handles.push_back(cf_handle);
1637     }
1638     env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT);
1639   }
1640 
1641   const jsize len_keys = env->GetArrayLength(jkeys);
1642   if (env->EnsureLocalCapacity(len_keys) != 0) {
1643     // exception thrown: OutOfMemoryError
1644     return nullptr;
1645   }
1646 
1647   jint* jkey_off = env->GetIntArrayElements(jkey_offs, nullptr);
1648   if (jkey_off == nullptr) {
1649     // exception thrown: OutOfMemoryError
1650     return nullptr;
1651   }
1652 
1653   jint* jkey_len = env->GetIntArrayElements(jkey_lens, nullptr);
1654   if (jkey_len == nullptr) {
1655     // exception thrown: OutOfMemoryError
1656     env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
1657     return nullptr;
1658   }
1659 
1660   std::vector<ROCKSDB_NAMESPACE::Slice> keys;
1661   std::vector<std::pair<jbyte*, jobject>> keys_to_free;
1662   for (jsize i = 0; i < len_keys; i++) {
1663     jobject jkey = env->GetObjectArrayElement(jkeys, i);
1664     if (env->ExceptionCheck()) {
1665       // exception thrown: ArrayIndexOutOfBoundsException
1666       env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT);
1667       env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
1668       multi_get_helper_release_keys(env, keys_to_free);
1669       return nullptr;
1670     }
1671 
1672     jbyteArray jkey_ba = reinterpret_cast<jbyteArray>(jkey);
1673 
1674     const jint len_key = jkey_len[i];
1675     jbyte* key = new jbyte[len_key];
1676     env->GetByteArrayRegion(jkey_ba, jkey_off[i], len_key, key);
1677     if (env->ExceptionCheck()) {
1678       // exception thrown: ArrayIndexOutOfBoundsException
1679       delete[] key;
1680       env->DeleteLocalRef(jkey);
1681       env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT);
1682       env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
1683       multi_get_helper_release_keys(env, keys_to_free);
1684       return nullptr;
1685     }
1686 
1687     ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), len_key);
1688     keys.push_back(key_slice);
1689 
1690     keys_to_free.push_back(std::pair<jbyte*, jobject>(key, jkey));
1691   }
1692 
1693   // cleanup jkey_off and jken_len
1694   env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT);
1695   env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
1696 
1697   std::vector<std::string> values;
1698   std::vector<ROCKSDB_NAMESPACE::Status> s;
1699   if (cf_handles.size() == 0) {
1700     s = db->MultiGet(rOpt, keys, &values);
1701   } else {
1702     s = db->MultiGet(rOpt, cf_handles, keys, &values);
1703   }
1704 
1705   // free up allocated byte arrays
1706   multi_get_helper_release_keys(env, keys_to_free);
1707 
1708   // prepare the results
1709   jobjectArray jresults = ROCKSDB_NAMESPACE::ByteJni::new2dByteArray(
1710       env, static_cast<jsize>(s.size()));
1711   if (jresults == nullptr) {
1712     // exception occurred
1713     return nullptr;
1714   }
1715 
1716   // TODO(AR) it is not clear to me why EnsureLocalCapacity is needed for the
1717   //     loop as we cleanup references with env->DeleteLocalRef(jentry_value);
1718   if (env->EnsureLocalCapacity(static_cast<jint>(s.size())) != 0) {
1719     // exception thrown: OutOfMemoryError
1720     return nullptr;
1721   }
1722   // add to the jresults
1723   for (std::vector<ROCKSDB_NAMESPACE::Status>::size_type i = 0; i != s.size();
1724        i++) {
1725     if (s[i].ok()) {
1726       std::string* value = &values[i];
1727       const jsize jvalue_len = static_cast<jsize>(value->size());
1728       jbyteArray jentry_value = env->NewByteArray(jvalue_len);
1729       if (jentry_value == nullptr) {
1730         // exception thrown: OutOfMemoryError
1731         return nullptr;
1732       }
1733 
1734       env->SetByteArrayRegion(
1735           jentry_value, 0, static_cast<jsize>(jvalue_len),
1736           const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value->c_str())));
1737       if (env->ExceptionCheck()) {
1738         // exception thrown: ArrayIndexOutOfBoundsException
1739         env->DeleteLocalRef(jentry_value);
1740         return nullptr;
1741       }
1742 
1743       env->SetObjectArrayElement(jresults, static_cast<jsize>(i), jentry_value);
1744       if (env->ExceptionCheck()) {
1745         // exception thrown: ArrayIndexOutOfBoundsException
1746         env->DeleteLocalRef(jentry_value);
1747         return nullptr;
1748       }
1749 
1750       env->DeleteLocalRef(jentry_value);
1751     }
1752   }
1753 
1754   return jresults;
1755 }
1756 
1757 /*
1758  * Class:     org_rocksdb_RocksDB
1759  * Method:    multiGet
1760  * Signature: (J[[B[I[I)[[B
1761  */
Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I(JNIEnv * env,jobject jdb,jlong jdb_handle,jobjectArray jkeys,jintArray jkey_offs,jintArray jkey_lens)1762 jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I(
1763     JNIEnv* env, jobject jdb, jlong jdb_handle,
1764     jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens) {
1765   return multi_get_helper(
1766       env, jdb, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1767       ROCKSDB_NAMESPACE::ReadOptions(), jkeys, jkey_offs, jkey_lens, nullptr);
1768 }
1769 
1770 /*
1771  * Class:     org_rocksdb_RocksDB
1772  * Method:    multiGet
1773  * Signature: (J[[B[I[I[J)[[B
1774  */
Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I_3J(JNIEnv * env,jobject jdb,jlong jdb_handle,jobjectArray jkeys,jintArray jkey_offs,jintArray jkey_lens,jlongArray jcolumn_family_handles)1775 jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I_3J(
1776     JNIEnv* env, jobject jdb, jlong jdb_handle,
1777     jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens,
1778     jlongArray jcolumn_family_handles) {
1779   return multi_get_helper(env, jdb,
1780                           reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1781                           ROCKSDB_NAMESPACE::ReadOptions(), jkeys, jkey_offs,
1782                           jkey_lens, jcolumn_family_handles);
1783 }
1784 
1785 /*
1786  * Class:     org_rocksdb_RocksDB
1787  * Method:    multiGet
1788  * Signature: (JJ[[B[I[I)[[B
1789  */
Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I(JNIEnv * env,jobject jdb,jlong jdb_handle,jlong jropt_handle,jobjectArray jkeys,jintArray jkey_offs,jintArray jkey_lens)1790 jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I(
1791     JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle,
1792     jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens) {
1793   return multi_get_helper(
1794       env, jdb, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1795       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle), jkeys,
1796       jkey_offs, jkey_lens, nullptr);
1797 }
1798 
1799 /*
1800  * Class:     org_rocksdb_RocksDB
1801  * Method:    multiGet
1802  * Signature: (JJ[[B[I[I[J)[[B
1803  */
Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I_3J(JNIEnv * env,jobject jdb,jlong jdb_handle,jlong jropt_handle,jobjectArray jkeys,jintArray jkey_offs,jintArray jkey_lens,jlongArray jcolumn_family_handles)1804 jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I_3J(
1805     JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle,
1806     jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens,
1807     jlongArray jcolumn_family_handles) {
1808   return multi_get_helper(
1809       env, jdb, reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle),
1810       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jropt_handle), jkeys,
1811       jkey_offs, jkey_lens, jcolumn_family_handles);
1812 }
1813 
1814 //////////////////////////////////////////////////////////////////////////////
1815 // ROCKSDB_NAMESPACE::DB::KeyMayExist
key_may_exist_helper(JNIEnv * env,jlong jdb_handle,jlong jcf_handle,jlong jread_opts_handle,jbyteArray jkey,jint jkey_offset,jint jkey_len,bool * has_exception,std::string * value,bool * value_found)1816 bool key_may_exist_helper(JNIEnv* env, jlong jdb_handle, jlong jcf_handle,
1817   jlong jread_opts_handle,
1818   jbyteArray jkey, jint jkey_offset, jint jkey_len,
1819   bool* has_exception, std::string* value, bool* value_found) {
1820   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
1821   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
1822   if (jcf_handle == 0) {
1823     cf_handle = db->DefaultColumnFamily();
1824  } else {
1825    cf_handle =
1826        reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
1827  }
1828  ROCKSDB_NAMESPACE::ReadOptions read_opts =
1829      jread_opts_handle == 0
1830          ? ROCKSDB_NAMESPACE::ReadOptions()
1831          : *(reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(
1832                jread_opts_handle));
1833 
1834  jbyte* key = new jbyte[jkey_len];
1835  env->GetByteArrayRegion(jkey, jkey_offset, jkey_len, key);
1836  if (env->ExceptionCheck()) {
1837    // exception thrown: ArrayIndexOutOfBoundsException
1838    delete[] key;
1839    *has_exception = true;
1840    return false;
1841   }
1842   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char*>(key), jkey_len);
1843 
1844   const bool exists = db->KeyMayExist(
1845       read_opts, cf_handle, key_slice, value, value_found);
1846 
1847   // cleanup
1848   delete[] key;
1849 
1850   return exists;
1851 }
1852 
1853 
1854 /*
1855  * Class:     org_rocksdb_RocksDB
1856  * Method:    keyMayExist
1857  * Signature: (JJJ[BII)Z
1858  */
Java_org_rocksdb_RocksDB_keyMayExist(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jlong jread_opts_handle,jbyteArray jkey,jint jkey_offset,jint jkey_len)1859 jboolean Java_org_rocksdb_RocksDB_keyMayExist(
1860     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
1861     jlong jread_opts_handle,
1862     jbyteArray jkey, jint jkey_offset, jint jkey_len) {
1863 
1864   bool has_exception = false;
1865   std::string value;
1866   bool value_found = false;
1867 
1868   const bool exists = key_may_exist_helper(
1869       env, jdb_handle, jcf_handle, jread_opts_handle,
1870       jkey, jkey_offset, jkey_len,
1871       &has_exception, &value, &value_found);
1872 
1873   if (has_exception) {
1874     // java exception already raised
1875     return false;
1876   }
1877 
1878   return static_cast<jboolean>(exists);
1879 }
1880 
1881 /*
1882  * Class:     org_rocksdb_RocksDB
1883  * Method:    keyMayExistFoundValue
1884  * Signature: (JJJ[BII)[[B
1885  */
Java_org_rocksdb_RocksDB_keyMayExistFoundValue(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jlong jread_opts_handle,jbyteArray jkey,jint jkey_offset,jint jkey_len)1886 jobjectArray Java_org_rocksdb_RocksDB_keyMayExistFoundValue(
1887     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
1888     jlong jread_opts_handle,
1889     jbyteArray jkey, jint jkey_offset, jint jkey_len) {
1890 
1891   bool has_exception = false;
1892   std::string value;
1893   bool value_found = false;
1894 
1895   const bool exists = key_may_exist_helper(
1896       env, jdb_handle, jcf_handle, jread_opts_handle,
1897       jkey, jkey_offset, jkey_len,
1898       &has_exception, &value, &value_found);
1899 
1900   if (has_exception) {
1901     // java exception already raised
1902     return nullptr;
1903   }
1904 
1905   jbyte result_flags[1];
1906   if (!exists) {
1907     result_flags[0] = 0;
1908   } else if (!value_found) {
1909     result_flags[0] = 1;
1910   } else {
1911     // found
1912     result_flags[0] = 2;
1913   }
1914 
1915   jobjectArray jresults = ROCKSDB_NAMESPACE::ByteJni::new2dByteArray(env, 2);
1916   if (jresults == nullptr) {
1917     // exception occurred
1918     return nullptr;
1919   }
1920 
1921   // prepare the result flag
1922   jbyteArray jresult_flags = env->NewByteArray(1);
1923   if (jresult_flags == nullptr) {
1924     // exception thrown: OutOfMemoryError
1925     return nullptr;
1926   }
1927   env->SetByteArrayRegion(jresult_flags, 0, 1, result_flags);
1928   if (env->ExceptionCheck()) {
1929     // exception thrown: ArrayIndexOutOfBoundsException
1930     env->DeleteLocalRef(jresult_flags);
1931     return nullptr;
1932   }
1933 
1934   env->SetObjectArrayElement(jresults, 0, jresult_flags);
1935   if (env->ExceptionCheck()) {
1936       // exception thrown: ArrayIndexOutOfBoundsException
1937       env->DeleteLocalRef(jresult_flags);
1938       return nullptr;
1939   }
1940 
1941   env->DeleteLocalRef(jresult_flags);
1942 
1943   if (result_flags[0] == 2) {
1944     // set the value
1945     const jsize jvalue_len = static_cast<jsize>(value.size());
1946     jbyteArray jresult_value = env->NewByteArray(jvalue_len);
1947     if (jresult_value == nullptr) {
1948       // exception thrown: OutOfMemoryError
1949       return nullptr;
1950     }
1951     env->SetByteArrayRegion(jresult_value, 0, jvalue_len,
1952         const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value.data())));
1953     if (env->ExceptionCheck()) {
1954       // exception thrown: ArrayIndexOutOfBoundsException
1955       env->DeleteLocalRef(jresult_value);
1956       return nullptr;
1957     }
1958     env->SetObjectArrayElement(jresults, 1, jresult_value);
1959     if (env->ExceptionCheck()) {
1960       // exception thrown: ArrayIndexOutOfBoundsException
1961       env->DeleteLocalRef(jresult_value);
1962       return nullptr;
1963     }
1964 
1965     env->DeleteLocalRef(jresult_value);
1966   }
1967 
1968   return jresults;
1969 }
1970 
1971 /*
1972  * Class:     org_rocksdb_RocksDB
1973  * Method:    iterator
1974  * Signature: (J)J
1975  */
Java_org_rocksdb_RocksDB_iterator__J(JNIEnv *,jobject,jlong db_handle)1976 jlong Java_org_rocksdb_RocksDB_iterator__J(
1977       JNIEnv*, jobject, jlong db_handle) {
1978   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
1979   return rocksdb_iterator_helper(db, ROCKSDB_NAMESPACE::ReadOptions(), nullptr);
1980 }
1981 
1982 /*
1983  * Class:     org_rocksdb_RocksDB
1984  * Method:    iterator
1985  * Signature: (JJ)J
1986  */
Java_org_rocksdb_RocksDB_iterator__JJ(JNIEnv *,jobject,jlong db_handle,jlong jread_options_handle)1987 jlong Java_org_rocksdb_RocksDB_iterator__JJ(
1988     JNIEnv*, jobject, jlong db_handle, jlong jread_options_handle) {
1989   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
1990   auto& read_options =
1991       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle);
1992   return rocksdb_iterator_helper(db, read_options, nullptr);
1993 }
1994 
1995 /*
1996  * Class:     org_rocksdb_RocksDB
1997  * Method:    iteratorCF
1998  * Signature: (JJ)J
1999  */
Java_org_rocksdb_RocksDB_iteratorCF__JJ(JNIEnv *,jobject,jlong db_handle,jlong jcf_handle)2000 jlong Java_org_rocksdb_RocksDB_iteratorCF__JJ(
2001     JNIEnv*, jobject, jlong db_handle, jlong jcf_handle) {
2002   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2003   auto* cf_handle =
2004       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2005   return rocksdb_iterator_helper(db, ROCKSDB_NAMESPACE::ReadOptions(),
2006                                  cf_handle);
2007 }
2008 
2009 /*
2010  * Class:     org_rocksdb_RocksDB
2011  * Method:    iteratorCF
2012  * Signature: (JJJ)J
2013  */
Java_org_rocksdb_RocksDB_iteratorCF__JJJ(JNIEnv *,jobject,jlong db_handle,jlong jcf_handle,jlong jread_options_handle)2014 jlong Java_org_rocksdb_RocksDB_iteratorCF__JJJ(
2015     JNIEnv*, jobject,
2016     jlong db_handle, jlong jcf_handle, jlong jread_options_handle) {
2017   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2018   auto* cf_handle =
2019       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2020   auto& read_options =
2021       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle);
2022   return rocksdb_iterator_helper(db, read_options, cf_handle);
2023 }
2024 
2025 /*
2026  * Class:     org_rocksdb_RocksDB
2027  * Method:    iterators
2028  * Signature: (J[JJ)[J
2029  */
Java_org_rocksdb_RocksDB_iterators(JNIEnv * env,jobject,jlong db_handle,jlongArray jcolumn_family_handles,jlong jread_options_handle)2030 jlongArray Java_org_rocksdb_RocksDB_iterators(
2031     JNIEnv* env, jobject, jlong db_handle,
2032     jlongArray jcolumn_family_handles,
2033     jlong jread_options_handle) {
2034   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2035   auto& read_options =
2036       *reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle);
2037 
2038   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
2039   if (jcolumn_family_handles != nullptr) {
2040     const jsize len_cols = env->GetArrayLength(jcolumn_family_handles);
2041     jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr);
2042     if (jcfh == nullptr) {
2043       // exception thrown: OutOfMemoryError
2044       return nullptr;
2045     }
2046 
2047     for (jsize i = 0; i < len_cols; i++) {
2048       auto* cf_handle =
2049           reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcfh[i]);
2050       cf_handles.push_back(cf_handle);
2051     }
2052 
2053     env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT);
2054   }
2055 
2056   std::vector<ROCKSDB_NAMESPACE::Iterator*> iterators;
2057   ROCKSDB_NAMESPACE::Status s =
2058       db->NewIterators(read_options, cf_handles, &iterators);
2059   if (s.ok()) {
2060     jlongArray jLongArray =
2061         env->NewLongArray(static_cast<jsize>(iterators.size()));
2062     if (jLongArray == nullptr) {
2063       // exception thrown: OutOfMemoryError
2064       return nullptr;
2065     }
2066 
2067     for (std::vector<ROCKSDB_NAMESPACE::Iterator*>::size_type i = 0;
2068          i < iterators.size(); i++) {
2069       env->SetLongArrayRegion(
2070           jLongArray, static_cast<jsize>(i), 1,
2071           const_cast<jlong*>(reinterpret_cast<const jlong*>(&iterators[i])));
2072       if (env->ExceptionCheck()) {
2073         // exception thrown: ArrayIndexOutOfBoundsException
2074         env->DeleteLocalRef(jLongArray);
2075         return nullptr;
2076       }
2077     }
2078 
2079     return jLongArray;
2080   } else {
2081     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2082     return nullptr;
2083   }
2084 }
2085 
2086 /*
2087  * Method:    getSnapshot
2088  * Signature: (J)J
2089  */
Java_org_rocksdb_RocksDB_getSnapshot(JNIEnv *,jobject,jlong db_handle)2090 jlong Java_org_rocksdb_RocksDB_getSnapshot(
2091     JNIEnv*, jobject, jlong db_handle) {
2092   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2093   const ROCKSDB_NAMESPACE::Snapshot* snapshot = db->GetSnapshot();
2094   return reinterpret_cast<jlong>(snapshot);
2095 }
2096 
2097 /*
2098  * Method:    releaseSnapshot
2099  * Signature: (JJ)V
2100  */
Java_org_rocksdb_RocksDB_releaseSnapshot(JNIEnv *,jobject,jlong db_handle,jlong snapshot_handle)2101 void Java_org_rocksdb_RocksDB_releaseSnapshot(
2102     JNIEnv*, jobject, jlong db_handle,
2103     jlong snapshot_handle) {
2104   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2105   auto* snapshot =
2106       reinterpret_cast<ROCKSDB_NAMESPACE::Snapshot*>(snapshot_handle);
2107   db->ReleaseSnapshot(snapshot);
2108 }
2109 
2110 /*
2111  * Class:     org_rocksdb_RocksDB
2112  * Method:    getProperty
2113  * Signature: (JJLjava/lang/String;I)Ljava/lang/String;
2114  */
Java_org_rocksdb_RocksDB_getProperty(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jstring jproperty,jint jproperty_len)2115 jstring Java_org_rocksdb_RocksDB_getProperty(
2116     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2117     jstring jproperty, jint jproperty_len) {
2118   const char* property = env->GetStringUTFChars(jproperty, nullptr);
2119   if (property == nullptr) {
2120     // exception thrown: OutOfMemoryError
2121     return nullptr;
2122   }
2123   ROCKSDB_NAMESPACE::Slice property_name(property, jproperty_len);
2124 
2125   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2126   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2127   if (jcf_handle == 0) {
2128     cf_handle = db->DefaultColumnFamily();
2129   } else {
2130     cf_handle =
2131         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2132   }
2133 
2134   std::string property_value;
2135   bool retCode = db->GetProperty(cf_handle, property_name, &property_value);
2136   env->ReleaseStringUTFChars(jproperty, property);
2137 
2138   if (retCode) {
2139     return env->NewStringUTF(property_value.c_str());
2140   }
2141 
2142   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2143       env, ROCKSDB_NAMESPACE::Status::NotFound());
2144   return nullptr;
2145 }
2146 
2147 /*
2148  * Class:     org_rocksdb_RocksDB
2149  * Method:    getMapProperty
2150  * Signature: (JJLjava/lang/String;I)Ljava/util/Map;
2151  */
Java_org_rocksdb_RocksDB_getMapProperty(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jstring jproperty,jint jproperty_len)2152 jobject Java_org_rocksdb_RocksDB_getMapProperty(
2153     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2154     jstring jproperty, jint jproperty_len) {
2155     const char* property = env->GetStringUTFChars(jproperty, nullptr);
2156   if (property == nullptr) {
2157     // exception thrown: OutOfMemoryError
2158     return nullptr;
2159   }
2160   ROCKSDB_NAMESPACE::Slice property_name(property, jproperty_len);
2161 
2162   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2163   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2164   if (jcf_handle == 0) {
2165     cf_handle = db->DefaultColumnFamily();
2166   } else {
2167     cf_handle =
2168         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2169   }
2170 
2171   std::map<std::string, std::string> property_value;
2172   bool retCode = db->GetMapProperty(cf_handle, property_name, &property_value);
2173   env->ReleaseStringUTFChars(jproperty, property);
2174 
2175   if (retCode) {
2176     return ROCKSDB_NAMESPACE::HashMapJni::fromCppMap(env, &property_value);
2177   }
2178 
2179   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2180       env, ROCKSDB_NAMESPACE::Status::NotFound());
2181   return nullptr;
2182 }
2183 
2184 /*
2185  * Class:     org_rocksdb_RocksDB
2186  * Method:    getLongProperty
2187  * Signature: (JJLjava/lang/String;I)J
2188  */
Java_org_rocksdb_RocksDB_getLongProperty(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jstring jproperty,jint jproperty_len)2189 jlong Java_org_rocksdb_RocksDB_getLongProperty(
2190     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2191     jstring jproperty, jint jproperty_len) {
2192   const char* property = env->GetStringUTFChars(jproperty, nullptr);
2193   if (property == nullptr) {
2194     // exception thrown: OutOfMemoryError
2195     return 0;
2196   }
2197   ROCKSDB_NAMESPACE::Slice property_name(property, jproperty_len);
2198 
2199   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2200   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2201   if (jcf_handle == 0) {
2202     cf_handle = db->DefaultColumnFamily();
2203   } else {
2204     cf_handle =
2205         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2206   }
2207 
2208   uint64_t property_value;
2209   bool retCode = db->GetIntProperty(cf_handle, property_name, &property_value);
2210   env->ReleaseStringUTFChars(jproperty, property);
2211 
2212   if (retCode) {
2213     return property_value;
2214   }
2215 
2216   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2217       env, ROCKSDB_NAMESPACE::Status::NotFound());
2218   return 0;
2219 }
2220 
2221 /*
2222  * Class:     org_rocksdb_RocksDB
2223  * Method:    resetStats
2224  * Signature: (J)V
2225  */
Java_org_rocksdb_RocksDB_resetStats(JNIEnv *,jobject,jlong jdb_handle)2226 void Java_org_rocksdb_RocksDB_resetStats(
2227     JNIEnv *, jobject, jlong jdb_handle) {
2228   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2229   db->ResetStats();
2230 }
2231 
2232 /*
2233  * Class:     org_rocksdb_RocksDB
2234  * Method:    getAggregatedLongProperty
2235  * Signature: (JLjava/lang/String;I)J
2236  */
Java_org_rocksdb_RocksDB_getAggregatedLongProperty(JNIEnv * env,jobject,jlong db_handle,jstring jproperty,jint jproperty_len)2237 jlong Java_org_rocksdb_RocksDB_getAggregatedLongProperty(
2238     JNIEnv* env, jobject, jlong db_handle,
2239     jstring jproperty, jint jproperty_len) {
2240   const char* property = env->GetStringUTFChars(jproperty, nullptr);
2241   if (property == nullptr) {
2242     return 0;
2243   }
2244   ROCKSDB_NAMESPACE::Slice property_name(property, jproperty_len);
2245   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(db_handle);
2246   uint64_t property_value = 0;
2247   bool retCode = db->GetAggregatedIntProperty(property_name, &property_value);
2248   env->ReleaseStringUTFChars(jproperty, property);
2249 
2250   if (retCode) {
2251     return property_value;
2252   }
2253 
2254   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
2255       env, ROCKSDB_NAMESPACE::Status::NotFound());
2256   return 0;
2257 }
2258 
2259 /*
2260  * Class:     org_rocksdb_RocksDB
2261  * Method:    getApproximateSizes
2262  * Signature: (JJ[JB)[J
2263  */
Java_org_rocksdb_RocksDB_getApproximateSizes(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jlongArray jrange_slice_handles,jbyte jinclude_flags)2264 jlongArray Java_org_rocksdb_RocksDB_getApproximateSizes(
2265     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2266     jlongArray jrange_slice_handles, jbyte jinclude_flags) {
2267   const jsize jlen = env->GetArrayLength(jrange_slice_handles);
2268   const size_t range_count = jlen / 2;
2269 
2270   jboolean jranges_is_copy = JNI_FALSE;
2271   jlong* jranges = env->GetLongArrayElements(jrange_slice_handles,
2272       &jranges_is_copy);
2273   if (jranges == nullptr) {
2274     // exception thrown: OutOfMemoryError
2275     return nullptr;
2276   }
2277 
2278   auto ranges = std::unique_ptr<ROCKSDB_NAMESPACE::Range[]>(
2279       new ROCKSDB_NAMESPACE::Range[range_count]);
2280   for (jsize i = 0; i < jlen; ++i) {
2281     auto* start = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jranges[i]);
2282     auto* limit = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jranges[++i]);
2283     ranges.get()[i] = ROCKSDB_NAMESPACE::Range(*start, *limit);
2284   }
2285 
2286   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2287   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2288   if (jcf_handle == 0) {
2289     cf_handle = db->DefaultColumnFamily();
2290   } else {
2291     cf_handle =
2292         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2293   }
2294 
2295   auto sizes = std::unique_ptr<uint64_t[]>(new uint64_t[range_count]);
2296   db->GetApproximateSizes(cf_handle, ranges.get(),
2297       static_cast<int>(range_count), sizes.get(),
2298       static_cast<uint8_t>(jinclude_flags));
2299 
2300   // release LongArrayElements
2301   env->ReleaseLongArrayElements(jrange_slice_handles, jranges, JNI_ABORT);
2302 
2303   // prepare results
2304   auto results = std::unique_ptr<jlong[]>(new jlong[range_count]);
2305   for (size_t i = 0; i < range_count; ++i) {
2306     results.get()[i] = static_cast<jlong>(sizes.get()[i]);
2307   }
2308 
2309   const jsize jrange_count = jlen / 2;
2310   jlongArray jresults = env->NewLongArray(jrange_count);
2311   if (jresults == nullptr) {
2312     // exception thrown: OutOfMemoryError
2313     return nullptr;
2314   }
2315 
2316   env->SetLongArrayRegion(jresults, 0, jrange_count, results.get());
2317   if (env->ExceptionCheck()) {
2318     // exception thrown: ArrayIndexOutOfBoundsException
2319     env->DeleteLocalRef(jresults);
2320     return nullptr;
2321   }
2322 
2323   return jresults;
2324 }
2325 
2326 /*
2327  * Class:     org_rocksdb_RocksDB
2328  * Method:    getApproximateMemTableStats
2329  * Signature: (JJJJ)[J
2330  */
Java_org_rocksdb_RocksDB_getApproximateMemTableStats(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jlong jstartHandle,jlong jlimitHandle)2331 jlongArray Java_org_rocksdb_RocksDB_getApproximateMemTableStats(
2332     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2333     jlong jstartHandle, jlong jlimitHandle) {
2334   auto* start = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jstartHandle);
2335   auto* limit = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jlimitHandle);
2336   const ROCKSDB_NAMESPACE::Range range(*start, *limit);
2337 
2338   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2339   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2340   if (jcf_handle == 0) {
2341     cf_handle = db->DefaultColumnFamily();
2342   } else {
2343     cf_handle =
2344         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2345   }
2346 
2347   uint64_t count = 0;
2348   uint64_t sizes = 0;
2349   db->GetApproximateMemTableStats(cf_handle, range, &count, &sizes);
2350 
2351   // prepare results
2352   jlong results[2] = {
2353       static_cast<jlong>(count),
2354       static_cast<jlong>(sizes)};
2355 
2356   const jsize jcount = static_cast<jsize>(count);
2357   jlongArray jsizes = env->NewLongArray(jcount);
2358   if (jsizes == nullptr) {
2359     // exception thrown: OutOfMemoryError
2360     return nullptr;
2361   }
2362 
2363   env->SetLongArrayRegion(jsizes, 0, jcount, results);
2364   if (env->ExceptionCheck()) {
2365     // exception thrown: ArrayIndexOutOfBoundsException
2366     env->DeleteLocalRef(jsizes);
2367     return nullptr;
2368   }
2369 
2370   return jsizes;
2371 }
2372 
2373 /*
2374  * Class:     org_rocksdb_RocksDB
2375  * Method:    compactRange
2376  * Signature: (J[BI[BIJJ)V
2377  */
Java_org_rocksdb_RocksDB_compactRange(JNIEnv * env,jobject,jlong jdb_handle,jbyteArray jbegin,jint jbegin_len,jbyteArray jend,jint jend_len,jlong jcompact_range_opts_handle,jlong jcf_handle)2378 void Java_org_rocksdb_RocksDB_compactRange(
2379     JNIEnv* env, jobject, jlong jdb_handle,
2380     jbyteArray jbegin, jint jbegin_len,
2381     jbyteArray jend, jint jend_len,
2382     jlong jcompact_range_opts_handle,
2383     jlong jcf_handle) {
2384   jboolean has_exception = JNI_FALSE;
2385 
2386   std::string str_begin;
2387   if (jbegin_len > 0) {
2388     str_begin = ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
2389         env, jbegin, jbegin_len,
2390         [](const char* str, const size_t len) { return std::string(str, len); },
2391         &has_exception);
2392     if (has_exception == JNI_TRUE) {
2393       // exception occurred
2394       return;
2395     }
2396   }
2397 
2398   std::string str_end;
2399   if (jend_len > 0) {
2400     str_end = ROCKSDB_NAMESPACE::JniUtil::byteString<std::string>(
2401         env, jend, jend_len,
2402         [](const char* str, const size_t len) { return std::string(str, len); },
2403         &has_exception);
2404     if (has_exception == JNI_TRUE) {
2405       // exception occurred
2406       return;
2407     }
2408   }
2409 
2410   ROCKSDB_NAMESPACE::CompactRangeOptions* compact_range_opts = nullptr;
2411   if (jcompact_range_opts_handle == 0) {
2412     // NOTE: we DO own the pointer!
2413     compact_range_opts = new ROCKSDB_NAMESPACE::CompactRangeOptions();
2414   } else {
2415     // NOTE: we do NOT own the pointer!
2416     compact_range_opts =
2417         reinterpret_cast<ROCKSDB_NAMESPACE::CompactRangeOptions*>(
2418             jcompact_range_opts_handle);
2419   }
2420 
2421   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2422 
2423   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2424   if (jcf_handle == 0) {
2425     cf_handle = db->DefaultColumnFamily();
2426   } else {
2427     cf_handle =
2428         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2429   }
2430 
2431   ROCKSDB_NAMESPACE::Status s;
2432   if (jbegin_len > 0 || jend_len > 0) {
2433     const ROCKSDB_NAMESPACE::Slice begin(str_begin);
2434     const ROCKSDB_NAMESPACE::Slice end(str_end);
2435     s = db->CompactRange(*compact_range_opts, cf_handle, &begin, &end);
2436   } else {
2437     s = db->CompactRange(*compact_range_opts, cf_handle, nullptr, nullptr);
2438   }
2439 
2440   if (jcompact_range_opts_handle == 0) {
2441     delete compact_range_opts;
2442   }
2443   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2444 }
2445 
2446 /*
2447  * Class:     org_rocksdb_RocksDB
2448  * Method:    setOptions
2449  * Signature: (JJ[Ljava/lang/String;[Ljava/lang/String;)V
2450  */
Java_org_rocksdb_RocksDB_setOptions(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jobjectArray jkeys,jobjectArray jvalues)2451 void Java_org_rocksdb_RocksDB_setOptions(
2452     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
2453     jobjectArray jkeys, jobjectArray jvalues) {
2454   const jsize len = env->GetArrayLength(jkeys);
2455   assert(len == env->GetArrayLength(jvalues));
2456 
2457   std::unordered_map<std::string, std::string> options_map;
2458   for (jsize i = 0; i < len; i++) {
2459     jobject jobj_key = env->GetObjectArrayElement(jkeys, i);
2460     if (env->ExceptionCheck()) {
2461       // exception thrown: ArrayIndexOutOfBoundsException
2462       return;
2463     }
2464 
2465     jobject jobj_value = env->GetObjectArrayElement(jvalues, i);
2466     if (env->ExceptionCheck()) {
2467       // exception thrown: ArrayIndexOutOfBoundsException
2468       env->DeleteLocalRef(jobj_key);
2469       return;
2470     }
2471 
2472     jboolean has_exception = JNI_FALSE;
2473     std::string s_key = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
2474         env, reinterpret_cast<jstring>(jobj_key), &has_exception);
2475     if (has_exception == JNI_TRUE) {
2476       // exception occurred
2477       env->DeleteLocalRef(jobj_value);
2478       env->DeleteLocalRef(jobj_key);
2479       return;
2480     }
2481 
2482     std::string s_value = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
2483         env, reinterpret_cast<jstring>(jobj_value), &has_exception);
2484     if (has_exception == JNI_TRUE) {
2485       // exception occurred
2486       env->DeleteLocalRef(jobj_value);
2487       env->DeleteLocalRef(jobj_key);
2488       return;
2489     }
2490 
2491     options_map[s_key] = s_value;
2492 
2493     env->DeleteLocalRef(jobj_key);
2494     env->DeleteLocalRef(jobj_value);
2495   }
2496 
2497   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2498   auto* cf_handle =
2499       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2500   auto s = db->SetOptions(cf_handle, options_map);
2501   if (!s.ok()) {
2502     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2503   }
2504 }
2505 
2506 /*
2507  * Class:     org_rocksdb_RocksDB
2508  * Method:    setDBOptions
2509  * Signature: (J[Ljava/lang/String;[Ljava/lang/String;)V
2510  */
Java_org_rocksdb_RocksDB_setDBOptions(JNIEnv * env,jobject,jlong jdb_handle,jobjectArray jkeys,jobjectArray jvalues)2511 void Java_org_rocksdb_RocksDB_setDBOptions(
2512     JNIEnv* env, jobject, jlong jdb_handle,
2513     jobjectArray jkeys, jobjectArray jvalues) {
2514   const jsize len = env->GetArrayLength(jkeys);
2515   assert(len == env->GetArrayLength(jvalues));
2516 
2517   std::unordered_map<std::string, std::string> options_map;
2518     for (jsize i = 0; i < len; i++) {
2519     jobject jobj_key = env->GetObjectArrayElement(jkeys, i);
2520     if (env->ExceptionCheck()) {
2521       // exception thrown: ArrayIndexOutOfBoundsException
2522       return;
2523     }
2524 
2525     jobject jobj_value = env->GetObjectArrayElement(jvalues, i);
2526     if (env->ExceptionCheck()) {
2527       // exception thrown: ArrayIndexOutOfBoundsException
2528       env->DeleteLocalRef(jobj_key);
2529       return;
2530     }
2531 
2532     jboolean has_exception = JNI_FALSE;
2533     std::string s_key = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
2534         env, reinterpret_cast<jstring>(jobj_key), &has_exception);
2535     if (has_exception == JNI_TRUE) {
2536       // exception occurred
2537       env->DeleteLocalRef(jobj_value);
2538       env->DeleteLocalRef(jobj_key);
2539       return;
2540     }
2541 
2542     std::string s_value = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
2543         env, reinterpret_cast<jstring>(jobj_value), &has_exception);
2544     if (has_exception == JNI_TRUE) {
2545       // exception occurred
2546       env->DeleteLocalRef(jobj_value);
2547       env->DeleteLocalRef(jobj_key);
2548       return;
2549     }
2550 
2551     options_map[s_key] = s_value;
2552 
2553     env->DeleteLocalRef(jobj_key);
2554     env->DeleteLocalRef(jobj_value);
2555   }
2556 
2557   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2558   auto s = db->SetDBOptions(options_map);
2559   if (!s.ok()) {
2560     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2561   }
2562 }
2563 
2564 /*
2565  * Class:     org_rocksdb_RocksDB
2566  * Method:    compactFiles
2567  * Signature: (JJJ[Ljava/lang/String;IIJ)[Ljava/lang/String;
2568  */
Java_org_rocksdb_RocksDB_compactFiles(JNIEnv * env,jobject,jlong jdb_handle,jlong jcompaction_opts_handle,jlong jcf_handle,jobjectArray jinput_file_names,jint joutput_level,jint joutput_path_id,jlong jcompaction_job_info_handle)2569 jobjectArray Java_org_rocksdb_RocksDB_compactFiles(
2570     JNIEnv* env, jobject, jlong jdb_handle, jlong jcompaction_opts_handle,
2571     jlong jcf_handle, jobjectArray jinput_file_names, jint joutput_level,
2572     jint joutput_path_id, jlong jcompaction_job_info_handle) {
2573   jboolean has_exception = JNI_FALSE;
2574   const std::vector<std::string> input_file_names =
2575       ROCKSDB_NAMESPACE::JniUtil::copyStrings(env, jinput_file_names,
2576                                               &has_exception);
2577   if (has_exception == JNI_TRUE) {
2578     // exception occurred
2579     return nullptr;
2580   }
2581 
2582   auto* compaction_opts =
2583       reinterpret_cast<ROCKSDB_NAMESPACE::CompactionOptions*>(
2584           jcompaction_opts_handle);
2585   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2586   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2587   if (jcf_handle == 0) {
2588     cf_handle = db->DefaultColumnFamily();
2589   } else {
2590     cf_handle =
2591         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2592   }
2593 
2594   ROCKSDB_NAMESPACE::CompactionJobInfo* compaction_job_info = nullptr;
2595   if (jcompaction_job_info_handle != 0) {
2596     compaction_job_info =
2597         reinterpret_cast<ROCKSDB_NAMESPACE::CompactionJobInfo*>(
2598             jcompaction_job_info_handle);
2599   }
2600 
2601   std::vector<std::string> output_file_names;
2602   auto s = db->CompactFiles(*compaction_opts, cf_handle, input_file_names,
2603       static_cast<int>(joutput_level), static_cast<int>(joutput_path_id),
2604       &output_file_names, compaction_job_info);
2605   if (!s.ok()) {
2606     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2607     return nullptr;
2608   }
2609 
2610   return ROCKSDB_NAMESPACE::JniUtil::toJavaStrings(env, &output_file_names);
2611 }
2612 
2613 /*
2614  * Class:     org_rocksdb_RocksDB
2615  * Method:    pauseBackgroundWork
2616  * Signature: (J)V
2617  */
Java_org_rocksdb_RocksDB_pauseBackgroundWork(JNIEnv * env,jobject,jlong jdb_handle)2618 void Java_org_rocksdb_RocksDB_pauseBackgroundWork(
2619     JNIEnv* env, jobject, jlong jdb_handle) {
2620   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2621   auto s = db->PauseBackgroundWork();
2622   if (!s.ok()) {
2623     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2624   }
2625 }
2626 
2627 /*
2628  * Class:     org_rocksdb_RocksDB
2629  * Method:    continueBackgroundWork
2630  * Signature: (J)V
2631  */
Java_org_rocksdb_RocksDB_continueBackgroundWork(JNIEnv * env,jobject,jlong jdb_handle)2632 void Java_org_rocksdb_RocksDB_continueBackgroundWork(
2633     JNIEnv* env, jobject, jlong jdb_handle) {
2634   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2635   auto s = db->ContinueBackgroundWork();
2636   if (!s.ok()) {
2637     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2638   }
2639 }
2640 
2641 /*
2642  * Class:     org_rocksdb_RocksDB
2643  * Method:    enableAutoCompaction
2644  * Signature: (J[J)V
2645  */
Java_org_rocksdb_RocksDB_enableAutoCompaction(JNIEnv * env,jobject,jlong jdb_handle,jlongArray jcf_handles)2646 void Java_org_rocksdb_RocksDB_enableAutoCompaction(
2647     JNIEnv* env, jobject, jlong jdb_handle, jlongArray jcf_handles) {
2648   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2649   jboolean has_exception = JNI_FALSE;
2650   const std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles =
2651       ROCKSDB_NAMESPACE::JniUtil::fromJPointers<
2652           ROCKSDB_NAMESPACE::ColumnFamilyHandle>(env, jcf_handles,
2653                                                  &has_exception);
2654   if (has_exception == JNI_TRUE) {
2655     // exception occurred
2656     return;
2657   }
2658   db->EnableAutoCompaction(cf_handles);
2659 }
2660 
2661 /*
2662  * Class:     org_rocksdb_RocksDB
2663  * Method:    numberLevels
2664  * Signature: (JJ)I
2665  */
Java_org_rocksdb_RocksDB_numberLevels(JNIEnv *,jobject,jlong jdb_handle,jlong jcf_handle)2666 jint Java_org_rocksdb_RocksDB_numberLevels(
2667     JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) {
2668   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2669   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2670   if (jcf_handle == 0) {
2671     cf_handle = db->DefaultColumnFamily();
2672   } else {
2673     cf_handle =
2674         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2675   }
2676   return static_cast<jint>(db->NumberLevels(cf_handle));
2677 }
2678 
2679 /*
2680  * Class:     org_rocksdb_RocksDB
2681  * Method:    maxMemCompactionLevel
2682  * Signature: (JJ)I
2683  */
Java_org_rocksdb_RocksDB_maxMemCompactionLevel(JNIEnv *,jobject,jlong jdb_handle,jlong jcf_handle)2684 jint Java_org_rocksdb_RocksDB_maxMemCompactionLevel(
2685     JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) {
2686   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2687   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2688   if (jcf_handle == 0) {
2689     cf_handle = db->DefaultColumnFamily();
2690   } else {
2691     cf_handle =
2692         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2693   }
2694   return static_cast<jint>(db->MaxMemCompactionLevel(cf_handle));
2695 }
2696 
2697 /*
2698  * Class:     org_rocksdb_RocksDB
2699  * Method:    level0StopWriteTrigger
2700  * Signature: (JJ)I
2701  */
Java_org_rocksdb_RocksDB_level0StopWriteTrigger(JNIEnv *,jobject,jlong jdb_handle,jlong jcf_handle)2702 jint Java_org_rocksdb_RocksDB_level0StopWriteTrigger(
2703     JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) {
2704   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2705   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
2706   if (jcf_handle == 0) {
2707     cf_handle = db->DefaultColumnFamily();
2708   } else {
2709     cf_handle =
2710         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
2711   }
2712   return static_cast<jint>(db->Level0StopWriteTrigger(cf_handle));
2713 }
2714 
2715 /*
2716  * Class:     org_rocksdb_RocksDB
2717  * Method:    getName
2718  * Signature: (J)Ljava/lang/String;
2719  */
Java_org_rocksdb_RocksDB_getName(JNIEnv * env,jobject,jlong jdb_handle)2720 jstring Java_org_rocksdb_RocksDB_getName(
2721     JNIEnv* env, jobject, jlong jdb_handle) {
2722   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2723   std::string name = db->GetName();
2724   return ROCKSDB_NAMESPACE::JniUtil::toJavaString(env, &name, false);
2725 }
2726 
2727 /*
2728  * Class:     org_rocksdb_RocksDB
2729  * Method:    getEnv
2730  * Signature: (J)J
2731  */
Java_org_rocksdb_RocksDB_getEnv(JNIEnv *,jobject,jlong jdb_handle)2732 jlong Java_org_rocksdb_RocksDB_getEnv(
2733     JNIEnv*, jobject, jlong jdb_handle) {
2734   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2735   return reinterpret_cast<jlong>(db->GetEnv());
2736 }
2737 
2738 /*
2739  * Class:     org_rocksdb_RocksDB
2740  * Method:    flush
2741  * Signature: (JJ[J)V
2742  */
Java_org_rocksdb_RocksDB_flush(JNIEnv * env,jobject,jlong jdb_handle,jlong jflush_opts_handle,jlongArray jcf_handles)2743 void Java_org_rocksdb_RocksDB_flush(
2744     JNIEnv* env, jobject, jlong jdb_handle, jlong jflush_opts_handle,
2745     jlongArray jcf_handles) {
2746   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2747   auto* flush_opts =
2748       reinterpret_cast<ROCKSDB_NAMESPACE::FlushOptions*>(jflush_opts_handle);
2749   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> cf_handles;
2750   if (jcf_handles == nullptr) {
2751       cf_handles.push_back(db->DefaultColumnFamily());
2752   } else {
2753       jboolean has_exception = JNI_FALSE;
2754       cf_handles = ROCKSDB_NAMESPACE::JniUtil::fromJPointers<
2755           ROCKSDB_NAMESPACE::ColumnFamilyHandle>(env, jcf_handles,
2756                                                  &has_exception);
2757       if (has_exception) {
2758         // exception occurred
2759         return;
2760       }
2761   }
2762   auto s = db->Flush(*flush_opts, cf_handles);
2763   if (!s.ok()) {
2764     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2765   }
2766 }
2767 
2768 /*
2769  * Class:     org_rocksdb_RocksDB
2770  * Method:    flushWal
2771  * Signature: (JZ)V
2772  */
Java_org_rocksdb_RocksDB_flushWal(JNIEnv * env,jobject,jlong jdb_handle,jboolean jsync)2773 void Java_org_rocksdb_RocksDB_flushWal(
2774     JNIEnv* env, jobject, jlong jdb_handle, jboolean jsync) {
2775   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2776   auto s = db->FlushWAL(jsync == JNI_TRUE);
2777   if (!s.ok()) {
2778     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2779   }
2780 }
2781 
2782 /*
2783  * Class:     org_rocksdb_RocksDB
2784  * Method:    syncWal
2785  * Signature: (J)V
2786  */
Java_org_rocksdb_RocksDB_syncWal(JNIEnv * env,jobject,jlong jdb_handle)2787 void Java_org_rocksdb_RocksDB_syncWal(
2788     JNIEnv* env, jobject, jlong jdb_handle) {
2789   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2790   auto s = db->SyncWAL();
2791   if (!s.ok()) {
2792     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2793   }
2794 }
2795 
2796 /*
2797  * Class:     org_rocksdb_RocksDB
2798  * Method:    getLatestSequenceNumber
2799  * Signature: (J)V
2800  */
Java_org_rocksdb_RocksDB_getLatestSequenceNumber(JNIEnv *,jobject,jlong jdb_handle)2801 jlong Java_org_rocksdb_RocksDB_getLatestSequenceNumber(
2802     JNIEnv*, jobject, jlong jdb_handle) {
2803   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2804   return db->GetLatestSequenceNumber();
2805 }
2806 
2807 /*
2808  * Class:     org_rocksdb_RocksDB
2809  * Method:    setPreserveDeletesSequenceNumber
2810  * Signature: (JJ)Z
2811  */
Java_org_rocksdb_RocksDB_setPreserveDeletesSequenceNumber(JNIEnv *,jobject,jlong jdb_handle,jlong jseq_number)2812 jboolean JNICALL Java_org_rocksdb_RocksDB_setPreserveDeletesSequenceNumber(
2813     JNIEnv*, jobject, jlong jdb_handle, jlong jseq_number) {
2814   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2815   if (db->SetPreserveDeletesSequenceNumber(
2816       static_cast<uint64_t>(jseq_number))) {
2817     return JNI_TRUE;
2818   } else {
2819     return JNI_FALSE;
2820   }
2821 }
2822 
2823 /*
2824  * Class:     org_rocksdb_RocksDB
2825  * Method:    disableFileDeletions
2826  * Signature: (J)V
2827  */
Java_org_rocksdb_RocksDB_disableFileDeletions(JNIEnv * env,jobject,jlong jdb_handle)2828 void Java_org_rocksdb_RocksDB_disableFileDeletions(
2829     JNIEnv* env, jobject, jlong jdb_handle) {
2830   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2831   ROCKSDB_NAMESPACE::Status s = db->DisableFileDeletions();
2832   if (!s.ok()) {
2833     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2834   }
2835 }
2836 
2837 /*
2838  * Class:     org_rocksdb_RocksDB
2839  * Method:    enableFileDeletions
2840  * Signature: (JZ)V
2841  */
Java_org_rocksdb_RocksDB_enableFileDeletions(JNIEnv * env,jobject,jlong jdb_handle,jboolean jforce)2842 void Java_org_rocksdb_RocksDB_enableFileDeletions(
2843     JNIEnv* env, jobject, jlong jdb_handle, jboolean jforce) {
2844   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2845   ROCKSDB_NAMESPACE::Status s = db->EnableFileDeletions(jforce);
2846   if (!s.ok()) {
2847     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2848   }
2849 }
2850 
2851 /*
2852  * Class:     org_rocksdb_RocksDB
2853  * Method:    getLiveFiles
2854  * Signature: (JZ)[Ljava/lang/String;
2855  */
Java_org_rocksdb_RocksDB_getLiveFiles(JNIEnv * env,jobject,jlong jdb_handle,jboolean jflush_memtable)2856 jobjectArray Java_org_rocksdb_RocksDB_getLiveFiles(
2857     JNIEnv* env, jobject, jlong jdb_handle, jboolean jflush_memtable) {
2858   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2859   std::vector<std::string> live_files;
2860   uint64_t manifest_file_size = 0;
2861   auto s = db->GetLiveFiles(
2862       live_files, &manifest_file_size, jflush_memtable == JNI_TRUE);
2863   if (!s.ok()) {
2864     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2865     return nullptr;
2866   }
2867 
2868   // append the manifest_file_size to the vector
2869   // for passing back to java
2870   live_files.push_back(std::to_string(manifest_file_size));
2871 
2872   return ROCKSDB_NAMESPACE::JniUtil::toJavaStrings(env, &live_files);
2873 }
2874 
2875 /*
2876  * Class:     org_rocksdb_RocksDB
2877  * Method:    getSortedWalFiles
2878  * Signature: (J)[Lorg/rocksdb/LogFile;
2879  */
Java_org_rocksdb_RocksDB_getSortedWalFiles(JNIEnv * env,jobject,jlong jdb_handle)2880 jobjectArray Java_org_rocksdb_RocksDB_getSortedWalFiles(
2881     JNIEnv* env, jobject, jlong jdb_handle) {
2882   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2883   std::vector<std::unique_ptr<ROCKSDB_NAMESPACE::LogFile>> sorted_wal_files;
2884   auto s = db->GetSortedWalFiles(sorted_wal_files);
2885   if (!s.ok()) {
2886     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2887     return nullptr;
2888   }
2889 
2890   // convert to Java type
2891   const jsize jlen = static_cast<jsize>(sorted_wal_files.size());
2892   jobjectArray jsorted_wal_files = env->NewObjectArray(
2893       jlen, ROCKSDB_NAMESPACE::LogFileJni::getJClass(env), nullptr);
2894   if(jsorted_wal_files == nullptr) {
2895     // exception thrown: OutOfMemoryError
2896     return nullptr;
2897   }
2898 
2899   jsize i = 0;
2900   for (auto it = sorted_wal_files.begin(); it != sorted_wal_files.end(); ++it) {
2901     jobject jlog_file =
2902         ROCKSDB_NAMESPACE::LogFileJni::fromCppLogFile(env, it->get());
2903     if (jlog_file == nullptr) {
2904       // exception occurred
2905       env->DeleteLocalRef(jsorted_wal_files);
2906       return nullptr;
2907     }
2908 
2909     env->SetObjectArrayElement(jsorted_wal_files, i++, jlog_file);
2910     if (env->ExceptionCheck()) {
2911       // exception occurred
2912       env->DeleteLocalRef(jlog_file);
2913       env->DeleteLocalRef(jsorted_wal_files);
2914       return nullptr;
2915     }
2916 
2917     env->DeleteLocalRef(jlog_file);
2918   }
2919 
2920   return jsorted_wal_files;
2921 }
2922 
2923 /*
2924  * Class:     org_rocksdb_RocksDB
2925  * Method:    getUpdatesSince
2926  * Signature: (JJ)J
2927  */
Java_org_rocksdb_RocksDB_getUpdatesSince(JNIEnv * env,jobject,jlong jdb_handle,jlong jsequence_number)2928 jlong Java_org_rocksdb_RocksDB_getUpdatesSince(
2929     JNIEnv* env, jobject, jlong jdb_handle, jlong jsequence_number) {
2930   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2931   ROCKSDB_NAMESPACE::SequenceNumber sequence_number =
2932       static_cast<ROCKSDB_NAMESPACE::SequenceNumber>(jsequence_number);
2933   std::unique_ptr<ROCKSDB_NAMESPACE::TransactionLogIterator> iter;
2934   ROCKSDB_NAMESPACE::Status s = db->GetUpdatesSince(sequence_number, &iter);
2935   if (s.ok()) {
2936     return reinterpret_cast<jlong>(iter.release());
2937   }
2938 
2939   ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
2940   return 0;
2941 }
2942 
2943 /*
2944  * Class:     org_rocksdb_RocksDB
2945  * Method:    deleteFile
2946  * Signature: (JLjava/lang/String;)V
2947  */
Java_org_rocksdb_RocksDB_deleteFile(JNIEnv * env,jobject,jlong jdb_handle,jstring jname)2948 void Java_org_rocksdb_RocksDB_deleteFile(
2949     JNIEnv* env, jobject, jlong jdb_handle, jstring jname) {
2950   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2951   jboolean has_exception = JNI_FALSE;
2952   std::string name =
2953       ROCKSDB_NAMESPACE::JniUtil::copyStdString(env, jname, &has_exception);
2954   if (has_exception == JNI_TRUE) {
2955     // exception occurred
2956     return;
2957   }
2958   db->DeleteFile(name);
2959 }
2960 
2961 /*
2962  * Class:     org_rocksdb_RocksDB
2963  * Method:    getLiveFilesMetaData
2964  * Signature: (J)[Lorg/rocksdb/LiveFileMetaData;
2965  */
Java_org_rocksdb_RocksDB_getLiveFilesMetaData(JNIEnv * env,jobject,jlong jdb_handle)2966 jobjectArray Java_org_rocksdb_RocksDB_getLiveFilesMetaData(
2967     JNIEnv* env, jobject, jlong jdb_handle) {
2968   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
2969   std::vector<ROCKSDB_NAMESPACE::LiveFileMetaData> live_files_meta_data;
2970   db->GetLiveFilesMetaData(&live_files_meta_data);
2971 
2972   // convert to Java type
2973   const jsize jlen = static_cast<jsize>(live_files_meta_data.size());
2974   jobjectArray jlive_files_meta_data = env->NewObjectArray(
2975       jlen, ROCKSDB_NAMESPACE::LiveFileMetaDataJni::getJClass(env), nullptr);
2976   if(jlive_files_meta_data == nullptr) {
2977     // exception thrown: OutOfMemoryError
2978     return nullptr;
2979   }
2980 
2981   jsize i = 0;
2982   for (auto it = live_files_meta_data.begin(); it != live_files_meta_data.end(); ++it) {
2983     jobject jlive_file_meta_data =
2984         ROCKSDB_NAMESPACE::LiveFileMetaDataJni::fromCppLiveFileMetaData(env,
2985                                                                         &(*it));
2986     if (jlive_file_meta_data == nullptr) {
2987       // exception occurred
2988       env->DeleteLocalRef(jlive_files_meta_data);
2989       return nullptr;
2990     }
2991 
2992     env->SetObjectArrayElement(jlive_files_meta_data, i++, jlive_file_meta_data);
2993     if (env->ExceptionCheck()) {
2994       // exception occurred
2995       env->DeleteLocalRef(jlive_file_meta_data);
2996       env->DeleteLocalRef(jlive_files_meta_data);
2997       return nullptr;
2998     }
2999 
3000     env->DeleteLocalRef(jlive_file_meta_data);
3001   }
3002 
3003   return jlive_files_meta_data;
3004 }
3005 
3006 /*
3007  * Class:     org_rocksdb_RocksDB
3008  * Method:    getColumnFamilyMetaData
3009  * Signature: (JJ)Lorg/rocksdb/ColumnFamilyMetaData;
3010  */
Java_org_rocksdb_RocksDB_getColumnFamilyMetaData(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle)3011 jobject Java_org_rocksdb_RocksDB_getColumnFamilyMetaData(
3012     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) {
3013   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3014   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
3015   if (jcf_handle == 0) {
3016     cf_handle = db->DefaultColumnFamily();
3017   } else {
3018     cf_handle =
3019         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3020   }
3021   ROCKSDB_NAMESPACE::ColumnFamilyMetaData cf_metadata;
3022   db->GetColumnFamilyMetaData(cf_handle, &cf_metadata);
3023   return ROCKSDB_NAMESPACE::ColumnFamilyMetaDataJni::
3024       fromCppColumnFamilyMetaData(env, &cf_metadata);
3025 }
3026 
3027 /*
3028  * Class:     org_rocksdb_RocksDB
3029  * Method:    ingestExternalFile
3030  * Signature: (JJ[Ljava/lang/String;IJ)V
3031  */
Java_org_rocksdb_RocksDB_ingestExternalFile(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jobjectArray jfile_path_list,jint jfile_path_list_len,jlong jingest_external_file_options_handle)3032 void Java_org_rocksdb_RocksDB_ingestExternalFile(
3033     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
3034     jobjectArray jfile_path_list, jint jfile_path_list_len,
3035     jlong jingest_external_file_options_handle) {
3036   jboolean has_exception = JNI_FALSE;
3037   std::vector<std::string> file_path_list =
3038       ROCKSDB_NAMESPACE::JniUtil::copyStrings(
3039           env, jfile_path_list, jfile_path_list_len, &has_exception);
3040   if (has_exception == JNI_TRUE) {
3041     // exception occurred
3042     return;
3043   }
3044 
3045   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3046   auto* column_family =
3047       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3048   auto* ifo = reinterpret_cast<ROCKSDB_NAMESPACE::IngestExternalFileOptions*>(
3049       jingest_external_file_options_handle);
3050   ROCKSDB_NAMESPACE::Status s =
3051       db->IngestExternalFile(column_family, file_path_list, *ifo);
3052   if (!s.ok()) {
3053     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3054   }
3055 }
3056 
3057 /*
3058  * Class:     org_rocksdb_RocksDB
3059  * Method:    verifyChecksum
3060  * Signature: (J)V
3061  */
Java_org_rocksdb_RocksDB_verifyChecksum(JNIEnv * env,jobject,jlong jdb_handle)3062 void Java_org_rocksdb_RocksDB_verifyChecksum(
3063     JNIEnv* env, jobject, jlong jdb_handle) {
3064   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3065   auto s = db->VerifyChecksum();
3066   if (!s.ok()) {
3067     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3068   }
3069 }
3070 
3071 /*
3072  * Class:     org_rocksdb_RocksDB
3073  * Method:    getDefaultColumnFamily
3074  * Signature: (J)J
3075  */
Java_org_rocksdb_RocksDB_getDefaultColumnFamily(JNIEnv *,jobject,jlong jdb_handle)3076 jlong Java_org_rocksdb_RocksDB_getDefaultColumnFamily(
3077     JNIEnv*, jobject, jlong jdb_handle) {
3078   auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3079   auto* cf_handle = db_handle->DefaultColumnFamily();
3080   return reinterpret_cast<jlong>(cf_handle);
3081 }
3082 
3083 /*
3084  * Class:     org_rocksdb_RocksDB
3085  * Method:    getPropertiesOfAllTables
3086  * Signature: (JJ)Ljava/util/Map;
3087  */
Java_org_rocksdb_RocksDB_getPropertiesOfAllTables(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle)3088 jobject Java_org_rocksdb_RocksDB_getPropertiesOfAllTables(
3089     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) {
3090   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3091   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
3092   if (jcf_handle == 0) {
3093     cf_handle = db->DefaultColumnFamily();
3094   } else {
3095     cf_handle =
3096         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3097   }
3098   ROCKSDB_NAMESPACE::TablePropertiesCollection table_properties_collection;
3099   auto s = db->GetPropertiesOfAllTables(cf_handle,
3100       &table_properties_collection);
3101   if (!s.ok()) {
3102     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3103   }
3104 
3105   // convert to Java type
3106   jobject jhash_map = ROCKSDB_NAMESPACE::HashMapJni::construct(
3107       env, static_cast<uint32_t>(table_properties_collection.size()));
3108   if (jhash_map == nullptr) {
3109     // exception occurred
3110     return nullptr;
3111   }
3112 
3113   const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
3114       const std::string,
3115       const std::shared_ptr<const ROCKSDB_NAMESPACE::TableProperties>, jobject,
3116       jobject>
3117       fn_map_kv =
3118           [env](const std::pair<const std::string,
3119                                 const std::shared_ptr<
3120                                     const ROCKSDB_NAMESPACE::TableProperties>>&
3121                     kv) {
3122             jstring jkey = ROCKSDB_NAMESPACE::JniUtil::toJavaString(
3123                 env, &(kv.first), false);
3124             if (env->ExceptionCheck()) {
3125               // an error occurred
3126               return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
3127             }
3128 
3129             jobject jtable_properties =
3130                 ROCKSDB_NAMESPACE::TablePropertiesJni::fromCppTableProperties(
3131                     env, *(kv.second.get()));
3132             if (jtable_properties == nullptr) {
3133               // an error occurred
3134               env->DeleteLocalRef(jkey);
3135               return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
3136             }
3137 
3138             return std::unique_ptr<std::pair<jobject, jobject>>(
3139                 new std::pair<jobject, jobject>(
3140                     static_cast<jobject>(jkey),
3141                     static_cast<jobject>(jtable_properties)));
3142           };
3143 
3144   if (!ROCKSDB_NAMESPACE::HashMapJni::putAll(
3145           env, jhash_map, table_properties_collection.begin(),
3146           table_properties_collection.end(), fn_map_kv)) {
3147     // exception occurred
3148     return nullptr;
3149   }
3150 
3151   return jhash_map;
3152 }
3153 
3154 /*
3155  * Class:     org_rocksdb_RocksDB
3156  * Method:    getPropertiesOfTablesInRange
3157  * Signature: (JJ[J)Ljava/util/Map;
3158  */
Java_org_rocksdb_RocksDB_getPropertiesOfTablesInRange(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jlongArray jrange_slice_handles)3159 jobject Java_org_rocksdb_RocksDB_getPropertiesOfTablesInRange(
3160     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle,
3161     jlongArray jrange_slice_handles) {
3162   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3163   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
3164   if (jcf_handle == 0) {
3165     cf_handle = db->DefaultColumnFamily();
3166   } else {
3167     cf_handle =
3168         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3169   }
3170   const jsize jlen = env->GetArrayLength(jrange_slice_handles);
3171   jboolean jrange_slice_handles_is_copy = JNI_FALSE;
3172   jlong *jrange_slice_handle = env->GetLongArrayElements(
3173       jrange_slice_handles, &jrange_slice_handles_is_copy);
3174   if (jrange_slice_handle == nullptr) {
3175     // exception occurred
3176     return nullptr;
3177   }
3178 
3179   const size_t ranges_len = static_cast<size_t>(jlen / 2);
3180   auto ranges = std::unique_ptr<ROCKSDB_NAMESPACE::Range[]>(
3181       new ROCKSDB_NAMESPACE::Range[ranges_len]);
3182   for (jsize i = 0, j = 0; i < jlen; ++i) {
3183     auto* start =
3184         reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jrange_slice_handle[i]);
3185     auto* limit =
3186         reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(jrange_slice_handle[++i]);
3187     ranges[j++] = ROCKSDB_NAMESPACE::Range(*start, *limit);
3188   }
3189 
3190   ROCKSDB_NAMESPACE::TablePropertiesCollection table_properties_collection;
3191   auto s = db->GetPropertiesOfTablesInRange(
3192       cf_handle, ranges.get(), ranges_len, &table_properties_collection);
3193   if (!s.ok()) {
3194     // error occurred
3195     env->ReleaseLongArrayElements(jrange_slice_handles, jrange_slice_handle, JNI_ABORT);
3196     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3197     return nullptr;
3198   }
3199 
3200   // cleanup
3201   env->ReleaseLongArrayElements(jrange_slice_handles, jrange_slice_handle, JNI_ABORT);
3202 
3203   return jrange_slice_handles;
3204 }
3205 
3206 /*
3207  * Class:     org_rocksdb_RocksDB
3208  * Method:    suggestCompactRange
3209  * Signature: (JJ)[J
3210  */
Java_org_rocksdb_RocksDB_suggestCompactRange(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle)3211 jlongArray Java_org_rocksdb_RocksDB_suggestCompactRange(
3212     JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) {
3213   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3214   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
3215   if (jcf_handle == 0) {
3216     cf_handle = db->DefaultColumnFamily();
3217   } else {
3218     cf_handle =
3219         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3220   }
3221   auto* begin = new ROCKSDB_NAMESPACE::Slice();
3222   auto* end = new ROCKSDB_NAMESPACE::Slice();
3223   auto s = db->SuggestCompactRange(cf_handle, begin, end);
3224   if (!s.ok()) {
3225     // error occurred
3226     delete begin;
3227     delete end;
3228     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3229     return nullptr;
3230   }
3231 
3232   jlongArray jslice_handles = env->NewLongArray(2);
3233   if (jslice_handles == nullptr) {
3234     // exception thrown: OutOfMemoryError
3235     delete begin;
3236     delete end;
3237     return nullptr;
3238   }
3239 
3240   jlong slice_handles[2];
3241   slice_handles[0] = reinterpret_cast<jlong>(begin);
3242   slice_handles[1] = reinterpret_cast<jlong>(end);
3243   env->SetLongArrayRegion(jslice_handles, 0, 2, slice_handles);
3244   if (env->ExceptionCheck()) {
3245     // exception thrown: ArrayIndexOutOfBoundsException
3246     delete begin;
3247     delete end;
3248     env->DeleteLocalRef(jslice_handles);
3249     return nullptr;
3250   }
3251 
3252   return jslice_handles;
3253 }
3254 
3255 /*
3256  * Class:     org_rocksdb_RocksDB
3257  * Method:    promoteL0
3258  * Signature: (JJI)V
3259  */
Java_org_rocksdb_RocksDB_promoteL0(JNIEnv *,jobject,jlong jdb_handle,jlong jcf_handle,jint jtarget_level)3260 void Java_org_rocksdb_RocksDB_promoteL0(
3261     JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle, jint jtarget_level) {
3262   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3263   ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf_handle;
3264   if (jcf_handle == 0) {
3265     cf_handle = db->DefaultColumnFamily();
3266   } else {
3267     cf_handle =
3268         reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3269   }
3270   db->PromoteL0(cf_handle, static_cast<int>(jtarget_level));
3271 }
3272 
3273 /*
3274  * Class:     org_rocksdb_RocksDB
3275  * Method:    startTrace
3276  * Signature: (JJJ)V
3277  */
Java_org_rocksdb_RocksDB_startTrace(JNIEnv * env,jobject,jlong jdb_handle,jlong jmax_trace_file_size,jlong jtrace_writer_jnicallback_handle)3278 void Java_org_rocksdb_RocksDB_startTrace(
3279     JNIEnv* env, jobject, jlong jdb_handle, jlong jmax_trace_file_size,
3280     jlong jtrace_writer_jnicallback_handle) {
3281   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3282   ROCKSDB_NAMESPACE::TraceOptions trace_options;
3283   trace_options.max_trace_file_size =
3284       static_cast<uint64_t>(jmax_trace_file_size);
3285   // transfer ownership of trace writer from Java to C++
3286   auto trace_writer =
3287       std::unique_ptr<ROCKSDB_NAMESPACE::TraceWriterJniCallback>(
3288           reinterpret_cast<ROCKSDB_NAMESPACE::TraceWriterJniCallback*>(
3289               jtrace_writer_jnicallback_handle));
3290   auto s = db->StartTrace(trace_options, std::move(trace_writer));
3291   if (!s.ok()) {
3292     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3293   }
3294 }
3295 
3296 /*
3297  * Class:     org_rocksdb_RocksDB
3298  * Method:    endTrace
3299  * Signature: (J)V
3300  */
Java_org_rocksdb_RocksDB_endTrace(JNIEnv * env,jobject,jlong jdb_handle)3301 JNIEXPORT void JNICALL Java_org_rocksdb_RocksDB_endTrace(
3302     JNIEnv* env, jobject, jlong jdb_handle) {
3303   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3304   auto s = db->EndTrace();
3305   if (!s.ok()) {
3306     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3307   }
3308 }
3309 
3310 /*
3311  * Class:     org_rocksdb_RocksDB
3312  * Method:    destroyDB
3313  * Signature: (Ljava/lang/String;J)V
3314  */
Java_org_rocksdb_RocksDB_destroyDB(JNIEnv * env,jclass,jstring jdb_path,jlong joptions_handle)3315 void Java_org_rocksdb_RocksDB_destroyDB(
3316     JNIEnv* env, jclass, jstring jdb_path, jlong joptions_handle) {
3317   const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
3318   if (db_path == nullptr) {
3319     // exception thrown: OutOfMemoryError
3320     return;
3321   }
3322 
3323   auto* options =
3324       reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions_handle);
3325   if (options == nullptr) {
3326     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
3327         env, ROCKSDB_NAMESPACE::Status::InvalidArgument("Invalid Options."));
3328   }
3329 
3330   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::DestroyDB(db_path, *options);
3331   env->ReleaseStringUTFChars(jdb_path, db_path);
3332 
3333   if (!s.ok()) {
3334     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3335   }
3336 }
3337 
get_slice_helper(JNIEnv * env,jobjectArray ranges,jsize index,std::unique_ptr<ROCKSDB_NAMESPACE::Slice> & slice,std::vector<std::unique_ptr<jbyte[]>> & ranges_to_free)3338 bool get_slice_helper(JNIEnv* env, jobjectArray ranges, jsize index,
3339                       std::unique_ptr<ROCKSDB_NAMESPACE::Slice>& slice,
3340                       std::vector<std::unique_ptr<jbyte[]>>& ranges_to_free) {
3341   jobject jArray = env->GetObjectArrayElement(ranges, index);
3342   if (env->ExceptionCheck()) {
3343     // exception thrown: ArrayIndexOutOfBoundsException
3344     return false;
3345   }
3346 
3347   if (jArray == nullptr) {
3348     return true;
3349   }
3350 
3351   jbyteArray jba = reinterpret_cast<jbyteArray>(jArray);
3352   jsize len_ba = env->GetArrayLength(jba);
3353   ranges_to_free.push_back(std::unique_ptr<jbyte[]>(new jbyte[len_ba]));
3354   env->GetByteArrayRegion(jba, 0, len_ba, ranges_to_free.back().get());
3355   if (env->ExceptionCheck()) {
3356     // exception thrown: ArrayIndexOutOfBoundsException
3357     env->DeleteLocalRef(jArray);
3358     return false;
3359   }
3360   env->DeleteLocalRef(jArray);
3361   slice.reset(new ROCKSDB_NAMESPACE::Slice(
3362       reinterpret_cast<char*>(ranges_to_free.back().get()), len_ba));
3363   return true;
3364 }
3365 /*
3366  * Class:     org_rocksdb_RocksDB
3367  * Method:    deleteFilesInRanges
3368  * Signature: (JJLjava/util/List;Z)V
3369  */
Java_org_rocksdb_RocksDB_deleteFilesInRanges(JNIEnv * env,jobject,jlong jdb_handle,jlong jcf_handle,jobjectArray ranges,jboolean include_end)3370 JNIEXPORT void JNICALL Java_org_rocksdb_RocksDB_deleteFilesInRanges(
3371     JNIEnv* env, jobject /*jdb*/, jlong jdb_handle, jlong jcf_handle,
3372     jobjectArray ranges, jboolean include_end) {
3373   jsize length = env->GetArrayLength(ranges);
3374 
3375   std::vector<ROCKSDB_NAMESPACE::RangePtr> rangesVector;
3376   std::vector<std::unique_ptr<ROCKSDB_NAMESPACE::Slice>> slices;
3377   std::vector<std::unique_ptr<jbyte[]>> ranges_to_free;
3378   for (jsize i = 0; (i + 1) < length; i += 2) {
3379     slices.push_back(std::unique_ptr<ROCKSDB_NAMESPACE::Slice>());
3380     if (!get_slice_helper(env, ranges, i, slices.back(), ranges_to_free)) {
3381       // exception thrown
3382       return;
3383     }
3384 
3385     slices.push_back(std::unique_ptr<ROCKSDB_NAMESPACE::Slice>());
3386     if (!get_slice_helper(env, ranges, i + 1, slices.back(), ranges_to_free)) {
3387       // exception thrown
3388       return;
3389     }
3390 
3391     rangesVector.push_back(ROCKSDB_NAMESPACE::RangePtr(
3392         slices[slices.size() - 2].get(), slices[slices.size() - 1].get()));
3393   }
3394 
3395   auto* db = reinterpret_cast<ROCKSDB_NAMESPACE::DB*>(jdb_handle);
3396   auto* column_family =
3397       reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
3398 
3399   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::DeleteFilesInRanges(
3400       db, column_family == nullptr ? db->DefaultColumnFamily() : column_family,
3401       rangesVector.data(), rangesVector.size(), include_end);
3402 
3403   if (!s.ok()) {
3404     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
3405   }
3406 }
3407