Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace ::GetJNIKey / ::GetJNIValue w/
Browse files Browse the repository at this point in the history
Use JByteArraySlice, JDirectBufferSlice for and their pinnable variants for JNI get code. Makes the changes in this PR consistent with previous re-organisation and extension of rocksjni methods and removes redundant semi-duplicate code we produced initially in this work.
alanpaxton committed Jan 15, 2024
1 parent 788b6ea commit c74c3c1
Showing 5 changed files with 102 additions and 288 deletions.
136 changes: 0 additions & 136 deletions java/rocksjni/jni_get_helpers.cc
Original file line number Diff line number Diff line change
@@ -13,142 +13,6 @@

namespace ROCKSDB_NAMESPACE {

bool GetJNIKey::fromByteArray(JNIEnv* env, jbyteArray jkey, jint jkey_off,
jint jkey_len) {
key_buf = std::make_unique<jbyte[]>(jkey_len);
env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key_buf.get());
if (env->ExceptionCheck()) {
return false;
}
slice_ = Slice(reinterpret_cast<char*>(key_buf.get()), jkey_len);

return true;
}

bool GetJNIKey::fromByteBuffer(JNIEnv* env, jobject jkey, jint jkey_off,
jint jkey_len) {
char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
if (key == nullptr) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid key argument (argument is not a valid direct ByteBuffer)");
return false;
}
if (env->GetDirectBufferCapacity(jkey) < (jkey_off + jkey_len)) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid key argument. Capacity is less than requested region (offset "
"+ length).");
return false;
}

slice_ = Slice(key + jkey_off, jkey_len);

return true;
}

jint GetJNIValue::fillByteArray(
JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& pinnable_value, jbyteArray jval,
jint jval_off, jint jval_len) {
if (s.IsNotFound()) {
return kNotFound;
} else if (!s.ok()) {
// Here since we are throwing a Java exception from c++ side.
// As a result, c++ does not know calling this function will in fact
// throwing an exception. As a result, the execution flow will
// not stop here, and codes after this throw will still be
// executed.
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);

// Return a dummy const value to avoid compilation error, although
// java side might not have a chance to get the return value :)
return kStatusError;
}

const jint pinnable_value_len = static_cast<jint>(pinnable_value.size());
const jint length = std::min(jval_len, pinnable_value_len);

env->SetByteArrayRegion(jval, jval_off, length,
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(
pinnable_value.data())));
pinnable_value.Reset();
if (env->ExceptionCheck()) {
// exception thrown: OutOfMemoryError
return kStatusError;
}

return pinnable_value_len;
}

jint GetJNIValue::fillByteBuffer(
JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& pinnable_value, jobject jval,
jint jval_off, jint jval_len) {
if (s.IsNotFound()) {
return kNotFound;
} else if (!s.ok()) {
// Here since we are throwing a Java exception from c++ side.
// As a result, c++ does not know calling this function will in fact
// throwing an exception. As a result, the execution flow will
// not stop here, and codes after this throw will still be
// executed.
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);

// Return a dummy const value to avoid compilation error, although
// java side might not have a chance to get the return value :)
return kStatusError;
}

char* value = reinterpret_cast<char*>(env->GetDirectBufferAddress(jval));
if (value == nullptr) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid value argument (argument is not a valid direct ByteBuffer)");
pinnable_value.Reset();
return kArgumentError;
}

if (env->GetDirectBufferCapacity(jval) < (jval_off + jval_len)) {
ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(
env,
"Invalid value argument. Capacity is less than requested region "
"(offset + length).");
pinnable_value.Reset();
return kArgumentError;
}

const jint pinnable_value_len = static_cast<jint>(pinnable_value.size());
const jint length = std::min(jval_len, pinnable_value_len);

memcpy(value + jval_off, pinnable_value.data(), length);
pinnable_value.Reset();

return pinnable_value_len;
}

jbyteArray GetJNIValue::byteArray(
JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& pinnable_value) {
if (s.IsNotFound()) {
return nullptr;
}

if (s.ok()) {
jbyteArray jret_value =
ROCKSDB_NAMESPACE::JniUtil::copyBytes(env, pinnable_value);
pinnable_value.Reset();
if (jret_value == nullptr) {
// exception occurred
return nullptr;
}
return jret_value;
}

ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
return nullptr;
}

bool MultiGetJNIKeys::fromByteArrays(JNIEnv* env, jobjectArray jkeys) {
const jsize num_keys = env->GetArrayLength(jkeys);

73 changes: 0 additions & 73 deletions java/rocksjni/jni_get_helpers.h
Original file line number Diff line number Diff line change
@@ -17,20 +17,6 @@

namespace ROCKSDB_NAMESPACE {

class GetJNIKey {
private:
ROCKSDB_NAMESPACE::Slice slice_;
std::unique_ptr<jbyte[]> key_buf;

public:
bool fromByteArray(JNIEnv* env, jbyteArray jkey, jint jkey_off,
jint jkey_len);

bool fromByteBuffer(JNIEnv* env, jobject jkey, jint jkey_off, jint jkey_len);

inline ROCKSDB_NAMESPACE::Slice slice() { return slice_; }
};

/**
* @brief Encapsulate keys and key conversions from Java/JNI objects for
* MultiGet
@@ -109,65 +95,6 @@ class MultiGetJNIKeys {
std::vector<ROCKSDB_NAMESPACE::Slice>::size_type size();
};

/**
* @brief Class with static helpers for returning java objects from RocksDB data
*
*/
class GetJNIValue {
public:
static const int kNotFound = -1;
static const int kStatusError = -2;
static const int kArgumentError = -3;

/**
* @brief allocate and fill a byte array from the value in a pinnable slice
* If the supplied status is faulty, raise an exception instead
*
* @param env JNI environment in which to raise any exception
* @param s status to check before copying the result
* @param value pinnable slice containing a value
* @return jbyteArray
*/
static jbyteArray byteArray(JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& value);

/**
* @brief fill an existing byte array from the value in a pinnable slice
*
* If the supplied status is faulty, raise an exception instead
*
* @param env JNI environment in which to raise any exception
* @param s status to check before copying the result
* @param value pinnable slice containing a value
* @param jval byte array target for value
* @param jval_off offset in the array at which to place the value
* @param jval_len length of byte array into which to copy
* @return jint length copied, or a -ve status code
*/
static jint fillByteArray(JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& value,
jbyteArray jval, jint jval_off, jint jval_len);

/**
* @brief fill an existing direct ByteBuffer from the value in a pinnable
* slice
*
* If the supplied status is faulty, raise an exception instead
*
* @param env JNI environment in which to raise any exception
* @param s status to check before copying the result
* @param value pinnable slice containing a value
* @param jval ByteBuffer target for value
* @param jval_off offset in the array at which to place the value
* @param jval_len length of byte array into which to copy
* @return jint length copied, or a -ve status code
*/

static jint fillByteBuffer(JNIEnv* env, ROCKSDB_NAMESPACE::Status& s,
ROCKSDB_NAMESPACE::PinnableSlice& value,
jobject jval, jint jval_off, jint jval_len);
};

/**
* @brief Class with static helpers for returning java objects from RocksDB data
* returned by MultiGet
9 changes: 3 additions & 6 deletions java/rocksjni/kv_helper.h
Original file line number Diff line number Diff line change
@@ -213,14 +213,11 @@ class JByteArrayPinnableSlice {
*/
jbyteArray NewByteArray() {
const jint pinnable_len = static_cast<jint>(pinnable_slice_.size());
jbyteArray jbuffer = env_->NewByteArray(static_cast<jsize>(pinnable_len));
jbyteArray jbuffer =
ROCKSDB_NAMESPACE::JniUtil::createJavaByteArrayWithSizeCheck(
env_, pinnable_slice_.data(), pinnable_len);
KVException::ThrowOnError(env_); // OutOfMemoryError

env_->SetByteArrayRegion(
jbuffer, 0, pinnable_len,
reinterpret_cast<const jbyte*>(pinnable_slice_.data()));
KVException::ThrowOnError(env_); // ArrayIndexOutOfBoundsException

return jbuffer;
}

Loading

0 comments on commit c74c3c1

Please sign in to comment.