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