rocksdb/java/rocksjni/jni_multiget_helpers.cc
Alan Paxton d9a441113e JNI get_helper code sharing / multiGet() use efficient batch C++ support (#12344)
Summary:
Implement RAII-based helpers for JNIGet() and multiGet()

Replace JNI C++ helpers `rocksdb_get_helper, rocksdb_get_helper_direct`, `multi_get_helper`, `multi_get_helper_direct`, `multi_get_helper_release_keys`, `txn_get_helper`, and `txn_multi_get_helper`.

The model is to entirely do away with a single helper, instead a number of utility methods allow each separate
JNI `Get()` and `MultiGet()` method to organise their parameters efficiently, then call the underlying C++ `db->Get()`,
`db->MultiGet()`, `txn->Get()`, or `txn->MultiGet()` method itself, and use further utilities to retrieve results.

Roughly speaking:

* get keys into C++ form
* Call C++ Get()
* get results and status into Java form

We achieve a useful performance gain as part of this work; by using the updated C++ multiGet we immediately pick up its performance gains (batch improvements to multiGet C++ were previously implemented, but not until now used by Java/JNI). multiGetBB already uses the batched C++ multiGet(), and all other benchmarks show consistent improvement after the changes:

## Before:
```
Benchmark (columnFamilyTestType) (keyCount) (keySize) (multiGetSize) (valueSize) Mode Cnt Score Error Units
MultiGetNewBenchmarks.multiGetBB200 no_column_family 10000 1024 100 256 thrpt 25 5315.459 ± 20.465 ops/s
MultiGetNewBenchmarks.multiGetBB200 no_column_family 10000 1024 100 1024 thrpt 25 5673.115 ± 78.299 ops/s
MultiGetNewBenchmarks.multiGetBB200 no_column_family 10000 1024 100 4096 thrpt 25 2616.860 ± 46.994 ops/s
MultiGetNewBenchmarks.multiGetBB200 no_column_family 10000 1024 100 16384 thrpt 25 1700.058 ± 24.034 ops/s
MultiGetNewBenchmarks.multiGetBB200 no_column_family 10000 1024 100 65536 thrpt 25 791.171 ± 13.955 ops/s
MultiGetNewBenchmarks.multiGetList10 no_column_family 10000 1024 100 256 thrpt 25 6129.929 ± 94.200 ops/s
MultiGetNewBenchmarks.multiGetList10 no_column_family 10000 1024 100 1024 thrpt 25 7012.405 ± 97.886 ops/s
MultiGetNewBenchmarks.multiGetList10 no_column_family 10000 1024 100 4096 thrpt 25 2799.014 ± 39.352 ops/s
MultiGetNewBenchmarks.multiGetList10 no_column_family 10000 1024 100 16384 thrpt 25 1417.205 ± 22.272 ops/s
MultiGetNewBenchmarks.multiGetList10 no_column_family 10000 1024 100 65536 thrpt 25 655.594 ± 13.050 ops/s
MultiGetNewBenchmarks.multiGetListExplicitCF20 no_column_family 10000 1024 100 256 thrpt 25 6147.247 ± 82.711 ops/s
MultiGetNewBenchmarks.multiGetListExplicitCF20 no_column_family 10000 1024 100 1024 thrpt 25 7004.213 ± 79.251 ops/s
MultiGetNewBenchmarks.multiGetListExplicitCF20 no_column_family 10000 1024 100 4096 thrpt 25 2715.154 ± 110.017 ops/s
MultiGetNewBenchmarks.multiGetListExplicitCF20 no_column_family 10000 1024 100 16384 thrpt 25 1408.070 ± 31.714 ops/s
MultiGetNewBenchmarks.multiGetListExplicitCF20 no_column_family 10000 1024 100 65536 thrpt 25 623.829 ± 57.374 ops/s
MultiGetNewBenchmarks.multiGetListRandomCF30 no_column_family 10000 1024 100 256 thrpt 25 6119.243 ± 116.313 ops/s
MultiGetNewBenchmarks.multiGetListRandomCF30 no_column_family 10000 1024 100 1024 thrpt 25 6931.873 ± 128.094 ops/s
MultiGetNewBenchmarks.multiGetListRandomCF30 no_column_family 10000 1024 100 4096 thrpt 25 2678.253 ± 39.113 ops/s
MultiGetNewBenchmarks.multiGetListRandomCF30 no_column_family 10000 1024 100 16384 thrpt 25 1337.384 ± 19.500 ops/s
MultiGetNewBenchmarks.multiGetListRandomCF30 no_column_family 10000 1024 100 65536 thrpt 25 625.596 ± 14.525 ops/s
```

## After:
```
Benchmark                                    (columnFamilyTestType)  (keyCount)  (keySize)  (multiGetSize)  (valueSize)   Mode  Cnt     Score     Error  Units
MultiGetBenchmarks.multiGetBB200                   no_column_family       10000       1024             100          256  thrpt   25  5191.074 ±  78.250  ops/s
MultiGetBenchmarks.multiGetBB200                   no_column_family       10000       1024             100         1024  thrpt   25  5378.692 ± 260.682  ops/s
MultiGetBenchmarks.multiGetBB200                   no_column_family       10000       1024             100         4096  thrpt   25  2590.183 ±  34.844  ops/s
MultiGetBenchmarks.multiGetBB200                   no_column_family       10000       1024             100        16384  thrpt   25  1634.793 ±  34.022  ops/s
MultiGetBenchmarks.multiGetBB200                   no_column_family       10000       1024             100        65536  thrpt   25   786.455 ±   8.462  ops/s
MultiGetBenchmarks.multiGetBB200                    1_column_family       10000       1024             100          256  thrpt   25  5285.055 ±  11.676  ops/s
MultiGetBenchmarks.multiGetBB200                    1_column_family       10000       1024             100         1024  thrpt   25  5586.758 ± 213.008  ops/s
MultiGetBenchmarks.multiGetBB200                    1_column_family       10000       1024             100         4096  thrpt   25  2527.172 ±  17.106  ops/s
MultiGetBenchmarks.multiGetBB200                    1_column_family       10000       1024             100        16384  thrpt   25  1819.547 ±  12.958  ops/s
MultiGetBenchmarks.multiGetBB200                    1_column_family       10000       1024             100        65536  thrpt   25   803.861 ±   9.963  ops/s
MultiGetBenchmarks.multiGetBB200                 20_column_families       10000       1024             100          256  thrpt   25  5253.793 ±  28.020  ops/s
MultiGetBenchmarks.multiGetBB200                 20_column_families       10000       1024             100         1024  thrpt   25  5705.591 ±  20.556  ops/s
MultiGetBenchmarks.multiGetBB200                 20_column_families       10000       1024             100         4096  thrpt   25  2523.377 ±  15.415  ops/s
MultiGetBenchmarks.multiGetBB200                 20_column_families       10000       1024             100        16384  thrpt   25  1815.344 ±  11.309  ops/s
MultiGetBenchmarks.multiGetBB200                 20_column_families       10000       1024             100        65536  thrpt   25   820.792 ±   3.192  ops/s
MultiGetBenchmarks.multiGetBB200                100_column_families       10000       1024             100          256  thrpt   25  5262.184 ±  20.477  ops/s
MultiGetBenchmarks.multiGetBB200                100_column_families       10000       1024             100         1024  thrpt   25  5706.959 ±  23.123  ops/s
MultiGetBenchmarks.multiGetBB200                100_column_families       10000       1024             100         4096  thrpt   25  2520.362 ±   9.170  ops/s
MultiGetBenchmarks.multiGetBB200                100_column_families       10000       1024             100        16384  thrpt   25  1789.185 ±  14.239  ops/s
MultiGetBenchmarks.multiGetBB200                100_column_families       10000       1024             100        65536  thrpt   25   818.401 ±  12.132  ops/s
MultiGetBenchmarks.multiGetList10                  no_column_family       10000       1024             100          256  thrpt   25  6978.310 ±  14.084  ops/s
MultiGetBenchmarks.multiGetList10                  no_column_family       10000       1024             100         1024  thrpt   25  7664.242 ±  22.304  ops/s
MultiGetBenchmarks.multiGetList10                  no_column_family       10000       1024             100         4096  thrpt   25  2881.778 ±  81.054  ops/s
MultiGetBenchmarks.multiGetList10                  no_column_family       10000       1024             100        16384  thrpt   25  1599.826 ±   7.190  ops/s
MultiGetBenchmarks.multiGetList10                  no_column_family       10000       1024             100        65536  thrpt   25   737.520 ±   6.809  ops/s
MultiGetBenchmarks.multiGetList10                   1_column_family       10000       1024             100          256  thrpt   25  6974.376 ±  10.716  ops/s
MultiGetBenchmarks.multiGetList10                   1_column_family       10000       1024             100         1024  thrpt   25  7637.440 ±  45.877  ops/s
MultiGetBenchmarks.multiGetList10                   1_column_family       10000       1024             100         4096  thrpt   25  2820.472 ±  42.231  ops/s
MultiGetBenchmarks.multiGetList10                   1_column_family       10000       1024             100        16384  thrpt   25  1716.663 ±   8.527  ops/s
MultiGetBenchmarks.multiGetList10                   1_column_family       10000       1024             100        65536  thrpt   25   755.848 ±   7.514  ops/s
MultiGetBenchmarks.multiGetList10                20_column_families       10000       1024             100          256  thrpt   25  6943.651 ±  20.040  ops/s
MultiGetBenchmarks.multiGetList10                20_column_families       10000       1024             100         1024  thrpt   25  7679.415 ±   9.114  ops/s
MultiGetBenchmarks.multiGetList10                20_column_families       10000       1024             100         4096  thrpt   25  2844.564 ±  13.388  ops/s
MultiGetBenchmarks.multiGetList10                20_column_families       10000       1024             100        16384  thrpt   25  1729.545 ±   5.983  ops/s
MultiGetBenchmarks.multiGetList10                20_column_families       10000       1024             100        65536  thrpt   25   783.218 ±   1.530  ops/s
MultiGetBenchmarks.multiGetList10               100_column_families       10000       1024             100          256  thrpt   25  6944.276 ±  29.995  ops/s
MultiGetBenchmarks.multiGetList10               100_column_families       10000       1024             100         1024  thrpt   25  7670.301 ±   8.986  ops/s
MultiGetBenchmarks.multiGetList10               100_column_families       10000       1024             100         4096  thrpt   25  2839.828 ±  12.421  ops/s
MultiGetBenchmarks.multiGetList10               100_column_families       10000       1024             100        16384  thrpt   25  1730.005 ±   9.209  ops/s
MultiGetBenchmarks.multiGetList10               100_column_families       10000       1024             100        65536  thrpt   25   787.096 ±   1.977  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20        no_column_family       10000       1024             100          256  thrpt   25  6896.944 ±  21.530  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20        no_column_family       10000       1024             100         1024  thrpt   25  7622.407 ±  12.824  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20        no_column_family       10000       1024             100         4096  thrpt   25  2927.538 ±  19.792  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20        no_column_family       10000       1024             100        16384  thrpt   25  1598.041 ±   4.312  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20        no_column_family       10000       1024             100        65536  thrpt   25   744.564 ±   9.236  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20         1_column_family       10000       1024             100          256  thrpt   25  6853.760 ±  78.041  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20         1_column_family       10000       1024             100         1024  thrpt   25  7360.917 ± 355.365  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20         1_column_family       10000       1024             100         4096  thrpt   25  2848.774 ±  13.409  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20         1_column_family       10000       1024             100        16384  thrpt   25  1727.688 ±   3.329  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20         1_column_family       10000       1024             100        65536  thrpt   25   776.088 ±   7.517  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20      20_column_families       10000       1024             100          256  thrpt   25  6910.339 ±  14.366  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20      20_column_families       10000       1024             100         1024  thrpt   25  7633.660 ±  10.830  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20      20_column_families       10000       1024             100         4096  thrpt   25  2787.799 ±  81.775  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20      20_column_families       10000       1024             100        16384  thrpt   25  1726.517 ±   6.830  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20      20_column_families       10000       1024             100        65536  thrpt   25   787.597 ±   3.362  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20     100_column_families       10000       1024             100          256  thrpt   25  6922.445 ±  10.493  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20     100_column_families       10000       1024             100         1024  thrpt   25  7604.710 ±  48.043  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20     100_column_families       10000       1024             100         4096  thrpt   25  2848.788 ±  15.783  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20     100_column_families       10000       1024             100        16384  thrpt   25  1730.837 ±   6.497  ops/s
MultiGetBenchmarks.multiGetListExplicitCF20     100_column_families       10000       1024             100        65536  thrpt   25   794.557 ±   1.869  ops/s
MultiGetBenchmarks.multiGetListRandomCF30          no_column_family       10000       1024             100          256  thrpt   25  6918.716 ±  15.766  ops/s
MultiGetBenchmarks.multiGetListRandomCF30          no_column_family       10000       1024             100         1024  thrpt   25  7626.692 ±   9.394  ops/s
MultiGetBenchmarks.multiGetListRandomCF30          no_column_family       10000       1024             100         4096  thrpt   25  2871.382 ±  72.155  ops/s
MultiGetBenchmarks.multiGetListRandomCF30          no_column_family       10000       1024             100        16384  thrpt   25  1598.786 ±   4.819  ops/s
MultiGetBenchmarks.multiGetListRandomCF30          no_column_family       10000       1024             100        65536  thrpt   25   748.469 ±   7.234  ops/s
MultiGetBenchmarks.multiGetListRandomCF30           1_column_family       10000       1024             100          256  thrpt   25  6922.666 ±  17.131  ops/s
MultiGetBenchmarks.multiGetListRandomCF30           1_column_family       10000       1024             100         1024  thrpt   25  7623.890 ±   8.805  ops/s
MultiGetBenchmarks.multiGetListRandomCF30           1_column_family       10000       1024             100         4096  thrpt   25  2850.698 ±  18.004  ops/s
MultiGetBenchmarks.multiGetListRandomCF30           1_column_family       10000       1024             100        16384  thrpt   25  1727.623 ±   4.868  ops/s
MultiGetBenchmarks.multiGetListRandomCF30           1_column_family       10000       1024             100        65536  thrpt   25   774.534 ±  10.025  ops/s
MultiGetBenchmarks.multiGetListRandomCF30        20_column_families       10000       1024             100          256  thrpt   25  5486.251 ±  13.582  ops/s
MultiGetBenchmarks.multiGetListRandomCF30        20_column_families       10000       1024             100         1024  thrpt   25  4920.656 ±  44.557  ops/s
MultiGetBenchmarks.multiGetListRandomCF30        20_column_families       10000       1024             100         4096  thrpt   25  3922.913 ±  25.686  ops/s
MultiGetBenchmarks.multiGetListRandomCF30        20_column_families       10000       1024             100        16384  thrpt   25  2873.106 ±   4.336  ops/s
MultiGetBenchmarks.multiGetListRandomCF30        20_column_families       10000       1024             100        65536  thrpt   25   802.404 ±   8.967  ops/s
MultiGetBenchmarks.multiGetListRandomCF30       100_column_families       10000       1024             100          256  thrpt   25  4817.996 ±  18.042  ops/s
MultiGetBenchmarks.multiGetListRandomCF30       100_column_families       10000       1024             100         1024  thrpt   25  4243.922 ±  13.929  ops/s
MultiGetBenchmarks.multiGetListRandomCF30       100_column_families       10000       1024             100         4096  thrpt   25  3175.998 ±   7.773  ops/s
MultiGetBenchmarks.multiGetListRandomCF30       100_column_families       10000       1024             100        16384  thrpt   25  2321.990 ±  12.501  ops/s
MultiGetBenchmarks.multiGetListRandomCF30       100_column_families       10000       1024             100        65536  thrpt   25  1753.028 ±   7.130  ops/s
```

Closes https://github.com/facebook/rocksdb/issues/11518

Pull Request resolved: https://github.com/facebook/rocksdb/pull/12344

Reviewed By: cbi42

Differential Revision: D54809714

Pulled By: pdillinger

fbshipit-source-id: bee3b949720abac073bce043b59ce976a11e99eb
2024-03-12 12:42:08 -07:00

291 lines
11 KiB
C++

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "rocksjni/jni_multiget_helpers.h"
#include "jni_multiget_helpers.h"
#include "rocksjni/portal.h"
namespace ROCKSDB_NAMESPACE {
bool MultiGetJNIKeys::fromByteArrays(JNIEnv* env, jobjectArray jkeys) {
const jsize num_keys = env->GetArrayLength(jkeys);
for (jsize i = 0; i < num_keys; i++) {
jobject jkey = env->GetObjectArrayElement(jkeys, i);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
return false;
}
jbyteArray jkey_ba = reinterpret_cast<jbyteArray>(jkey);
const jsize len_key = env->GetArrayLength(jkey_ba);
std::unique_ptr<jbyte[]> key = std::make_unique<jbyte[]>(len_key);
jbyte* raw_key = reinterpret_cast<jbyte*>(key.get());
key_bufs.push_back(std::move(key));
env->GetByteArrayRegion(jkey_ba, 0, len_key, raw_key);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->DeleteLocalRef(jkey);
return false;
}
slices_.push_back(
ROCKSDB_NAMESPACE::Slice(reinterpret_cast<char*>(raw_key), len_key));
env->DeleteLocalRef(jkey);
}
return true;
}
bool MultiGetJNIKeys::fromByteArrays(JNIEnv* env, jobjectArray jkeys,
jintArray jkey_offs, jintArray jkey_lens) {
const jsize num_keys = env->GetArrayLength(jkeys);
std::unique_ptr<jint[]> key_offs = std::make_unique<jint[]>(num_keys);
env->GetIntArrayRegion(jkey_offs, 0, num_keys, key_offs.get());
if (env->ExceptionCheck()) {
return false; // exception thrown: ArrayIndexOutOfBoundsException
}
std::unique_ptr<jint[]> key_lens = std::make_unique<jint[]>(num_keys);
env->GetIntArrayRegion(jkey_lens, 0, num_keys, key_lens.get());
if (env->ExceptionCheck()) {
return false; // exception thrown: ArrayIndexOutOfBoundsException
}
for (jsize i = 0; i < num_keys; i++) {
jobject jkey = env->GetObjectArrayElement(jkeys, i);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
return false;
}
jbyteArray jkey_ba = reinterpret_cast<jbyteArray>(jkey);
const jint len_key = key_lens[i];
std::unique_ptr<jbyte[]> key = std::make_unique<jbyte[]>(len_key);
jbyte* raw_key = reinterpret_cast<jbyte*>(key.get());
key_bufs.push_back(std::move(key));
env->GetByteArrayRegion(jkey_ba, key_offs[i], len_key, raw_key);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->DeleteLocalRef(jkey);
return false;
}
slices_.push_back(
ROCKSDB_NAMESPACE::Slice(reinterpret_cast<char*>(raw_key), len_key));
env->DeleteLocalRef(jkey);
}
return true;
}
bool MultiGetJNIKeys::fromByteBuffers(JNIEnv* env, jobjectArray jkeys,
jintArray jkey_offs,
jintArray jkey_lens) {
const jsize num_keys = env->GetArrayLength(jkeys);
std::unique_ptr<jint[]> key_offs = std::make_unique<jint[]>(num_keys);
env->GetIntArrayRegion(jkey_offs, 0, num_keys, key_offs.get());
if (env->ExceptionCheck()) {
return false; // exception thrown: ArrayIndexOutOfBoundsException
}
std::unique_ptr<jint[]> key_lens = std::make_unique<jint[]>(num_keys);
env->GetIntArrayRegion(jkey_lens, 0, num_keys, key_lens.get());
if (env->ExceptionCheck()) {
return false; // exception thrown: ArrayIndexOutOfBoundsException
}
for (jsize i = 0; i < num_keys; i++) {
jobject jkey = env->GetObjectArrayElement(jkeys, i);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
return false;
}
char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
ROCKSDB_NAMESPACE::Slice key_slice(key + key_offs[i], key_lens[i]);
slices_.push_back(key_slice);
env->DeleteLocalRef(jkey);
}
return true;
}
ROCKSDB_NAMESPACE::Slice* MultiGetJNIKeys::data() { return slices_.data(); }
std::vector<ROCKSDB_NAMESPACE::Slice>::size_type MultiGetJNIKeys::size() {
return slices_.size();
}
template <class TValue>
jobjectArray MultiGetJNIValues::byteArrays(
JNIEnv* env, std::vector<TValue>& values,
std::vector<ROCKSDB_NAMESPACE::Status>& s) {
jobjectArray jresults = ROCKSDB_NAMESPACE::ByteJni::new2dByteArray(
env, static_cast<jsize>(s.size()));
if (jresults == nullptr) {
// exception occurred
OutOfMemoryErrorJni::ThrowNew(env, "Insufficient Memory for results.");
return nullptr;
}
// add to the jresults
for (std::vector<ROCKSDB_NAMESPACE::Status>::size_type i = 0; i != s.size();
i++) {
if (s[i].ok()) {
TValue* value = &values[i];
jbyteArray jentry_value =
ROCKSDB_NAMESPACE::JniUtil::createJavaByteArrayWithSizeCheck(
env, value->data(), value->size());
if (jentry_value == nullptr) {
// exception set
return nullptr;
}
env->SetObjectArrayElement(jresults, static_cast<jsize>(i), jentry_value);
if (env->ExceptionCheck()) {
// exception thrown:
// ArrayIndexOutOfBoundsException
env->DeleteLocalRef(jentry_value);
return nullptr;
}
env->DeleteLocalRef(jentry_value);
} else if (s[i].code() != ROCKSDB_NAMESPACE::Status::Code::kNotFound) {
// The only way to return an error for a single key is to exception the
// entire multiGet() Previous behaviour was to return a nullptr value for
// this case and potentially succesfully return values for other keys; we
// retain this behaviour. To change it, we need to do the following:
// ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s[i]);
// return nullptr;
}
}
return jresults;
}
template jobjectArray MultiGetJNIValues::byteArrays<std::string>(
JNIEnv* env, std::vector<std::string>& values,
std::vector<ROCKSDB_NAMESPACE::Status>& s);
template jobjectArray
MultiGetJNIValues::byteArrays<ROCKSDB_NAMESPACE::PinnableSlice>(
JNIEnv* env, std::vector<ROCKSDB_NAMESPACE::PinnableSlice>& values,
std::vector<ROCKSDB_NAMESPACE::Status>& s);
template <class TValue>
void MultiGetJNIValues::fillByteBuffersAndStatusObjects(
JNIEnv* env, std::vector<TValue>& values,
std::vector<ROCKSDB_NAMESPACE::Status>& s, jobjectArray jvalues,
jintArray jvalue_sizes, jobjectArray jstatuses) {
std::vector<jint> value_size;
for (int i = 0; i < static_cast<jint>(values.size()); i++) {
auto jstatus = ROCKSDB_NAMESPACE::StatusJni::construct(env, s[i]);
if (jstatus == nullptr) {
// exception in context
return;
}
env->SetObjectArrayElement(jstatuses, i, jstatus);
if (s[i].ok()) {
jobject jvalue_bytebuf = env->GetObjectArrayElement(jvalues, i);
if (env->ExceptionCheck()) {
// ArrayIndexOutOfBoundsException is thrown
return;
}
jlong jvalue_capacity = env->GetDirectBufferCapacity(jvalue_bytebuf);
if (jvalue_capacity == -1) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid value(s) argument (argument is not a valid direct "
"ByteBuffer)");
return;
}
void* jvalue_address = env->GetDirectBufferAddress(jvalue_bytebuf);
if (jvalue_address == nullptr) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid value(s) argument (argument is not a valid direct "
"ByteBuffer)");
return;
}
// record num returned, push back that number, which may be bigger then
// the ByteBuffer supplied. then copy as much as fits in the ByteBuffer.
static const size_t INTEGER_MAX_VALUE =
((static_cast<size_t>(1)) << 31) - 1;
if (values[i].size() > INTEGER_MAX_VALUE) {
// Indicate that the result size is bigger than can be represented in a
// java integer by setting the status to incomplete and the size to -1
env->SetObjectArrayElement(
jstatuses, i,
ROCKSDB_NAMESPACE::StatusJni::construct(
env, Status::Incomplete("result too large to represent")));
value_size.push_back(-1);
} else {
value_size.push_back(static_cast<jint>(values[i].size()));
}
auto copy_bytes =
std::min(static_cast<jlong>(values[i].size()), jvalue_capacity);
memcpy(jvalue_address, values[i].data(), copy_bytes);
} else {
// bad status for this
value_size.push_back(0);
}
}
env->SetIntArrayRegion(jvalue_sizes, 0, static_cast<jint>(values.size()),
value_size.data());
}
template void MultiGetJNIValues::fillByteBuffersAndStatusObjects<
ROCKSDB_NAMESPACE::PinnableSlice>(
JNIEnv* env, std::vector<ROCKSDB_NAMESPACE::PinnableSlice>& values,
std::vector<ROCKSDB_NAMESPACE::Status>& s, jobjectArray jvalues,
jintArray jvalue_sizes, jobjectArray jstatuses);
std::unique_ptr<std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>>
ColumnFamilyJNIHelpers::handlesFromJLongArray(
JNIEnv* env, jlongArray jcolumn_family_handles) {
if (jcolumn_family_handles == nullptr) return nullptr;
const jsize num_cols = env->GetArrayLength(jcolumn_family_handles);
std::unique_ptr<jlong[]> jcf_handles = std::make_unique<jlong[]>(num_cols);
env->GetLongArrayRegion(jcolumn_family_handles, 0, num_cols,
jcf_handles.get());
if (env->ExceptionCheck())
// ArrayIndexOutOfBoundsException
return nullptr;
auto cf_handles =
std::make_unique<std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>>();
for (jsize i = 0; i < num_cols; i++) {
auto* cf_handle = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(
jcf_handles.get()[i]);
cf_handles->push_back(cf_handle);
}
return cf_handles;
}
ROCKSDB_NAMESPACE::ColumnFamilyHandle* ColumnFamilyJNIHelpers::handleFromJLong(
JNIEnv* env, jlong jcolumn_family_handle) {
auto cf_handle = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(
jcolumn_family_handle);
if (cf_handle == nullptr) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
"Invalid ColumnFamilyHandle."));
return nullptr;
}
return cf_handle;
};
}; // namespace ROCKSDB_NAMESPACE