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