203136e793
Summary: PR to fix this issue -> https://github.com/facebook/rocksdb/issues/1926 Closes https://github.com/facebook/rocksdb/pull/1965 Differential Revision: D4682411 Pulled By: siying fbshipit-source-id: a519be1
350 lines
9.8 KiB
C++
350 lines
9.8 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under the BSD-style license found in the
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
//
|
|
// This file implements the "bridge" between Java and C++ for
|
|
// rocksdb::Slice.
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <jni.h>
|
|
#include <string>
|
|
|
|
#include "include/org_rocksdb_AbstractSlice.h"
|
|
#include "include/org_rocksdb_Slice.h"
|
|
#include "include/org_rocksdb_DirectSlice.h"
|
|
#include "rocksdb/slice.h"
|
|
#include "rocksjni/portal.h"
|
|
|
|
// <editor-fold desc="org.rocksdb.AbstractSlice>
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: createNewSliceFromString
|
|
* Signature: (Ljava/lang/String;)J
|
|
*/
|
|
jlong Java_org_rocksdb_AbstractSlice_createNewSliceFromString(
|
|
JNIEnv * env, jclass jcls, jstring jstr) {
|
|
const auto* str = env->GetStringUTFChars(jstr, nullptr);
|
|
if(str == nullptr) {
|
|
// exception thrown: OutOfMemoryError
|
|
return 0;
|
|
}
|
|
|
|
const size_t len = strlen(str);
|
|
|
|
// NOTE: buf will be deleted in the
|
|
// Java_org_rocksdb_Slice_disposeInternalBuf or
|
|
// or Java_org_rocksdb_DirectSlice_disposeInternalBuf methods
|
|
char* buf = new char[len + 1];
|
|
memcpy(buf, str, len);
|
|
buf[len] = 0;
|
|
env->ReleaseStringUTFChars(jstr, str);
|
|
|
|
const auto* slice = new rocksdb::Slice(buf);
|
|
return reinterpret_cast<jlong>(slice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: size0
|
|
* Signature: (J)I
|
|
*/
|
|
jint Java_org_rocksdb_AbstractSlice_size0(
|
|
JNIEnv* env, jobject jobj, jlong handle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
return static_cast<jint>(slice->size());
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: empty0
|
|
* Signature: (J)Z
|
|
*/
|
|
jboolean Java_org_rocksdb_AbstractSlice_empty0(
|
|
JNIEnv* env, jobject jobj, jlong handle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
return slice->empty();
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: toString0
|
|
* Signature: (JZ)Ljava/lang/String;
|
|
*/
|
|
jstring Java_org_rocksdb_AbstractSlice_toString0(
|
|
JNIEnv* env, jobject jobj, jlong handle, jboolean hex) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const std::string s = slice->ToString(hex);
|
|
return env->NewStringUTF(s.c_str());
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: compare0
|
|
* Signature: (JJ)I;
|
|
*/
|
|
jint Java_org_rocksdb_AbstractSlice_compare0(
|
|
JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const auto* otherSlice =
|
|
reinterpret_cast<rocksdb::Slice*>(otherHandle);
|
|
return slice->compare(*otherSlice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: startsWith0
|
|
* Signature: (JJ)Z;
|
|
*/
|
|
jboolean Java_org_rocksdb_AbstractSlice_startsWith0(
|
|
JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const auto* otherSlice =
|
|
reinterpret_cast<rocksdb::Slice*>(otherHandle);
|
|
return slice->starts_with(*otherSlice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_AbstractSlice
|
|
* Method: disposeInternal
|
|
* Signature: (J)V
|
|
*/
|
|
void Java_org_rocksdb_AbstractSlice_disposeInternal(
|
|
JNIEnv* env, jobject jobj, jlong handle) {
|
|
delete reinterpret_cast<rocksdb::Slice*>(handle);
|
|
}
|
|
|
|
// </editor-fold>
|
|
|
|
// <editor-fold desc="org.rocksdb.Slice>
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: createNewSlice0
|
|
* Signature: ([BI)J
|
|
*/
|
|
jlong Java_org_rocksdb_Slice_createNewSlice0(
|
|
JNIEnv * env, jclass jcls, jbyteArray data, jint offset) {
|
|
const jsize dataSize = env->GetArrayLength(data);
|
|
const int len = dataSize - offset;
|
|
|
|
// NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf method
|
|
jbyte* buf = new jbyte[len];
|
|
env->GetByteArrayRegion(data, offset, len, buf);
|
|
if(env->ExceptionCheck()) {
|
|
// exception thrown: ArrayIndexOutOfBoundsException
|
|
return 0;
|
|
}
|
|
|
|
const auto* slice = new rocksdb::Slice((const char*)buf, len);
|
|
return reinterpret_cast<jlong>(slice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: createNewSlice1
|
|
* Signature: ([B)J
|
|
*/
|
|
jlong Java_org_rocksdb_Slice_createNewSlice1(
|
|
JNIEnv * env, jclass jcls, jbyteArray data) {
|
|
jbyte* ptrData = env->GetByteArrayElements(data, nullptr);
|
|
if(ptrData == nullptr) {
|
|
// exception thrown: OutOfMemoryError
|
|
return 0;
|
|
}
|
|
const int len = env->GetArrayLength(data) + 1;
|
|
|
|
// NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf method
|
|
char* buf = new char[len];
|
|
memcpy(buf, ptrData, len - 1);
|
|
buf[len-1] = '\0';
|
|
|
|
const auto* slice =
|
|
new rocksdb::Slice(buf, len - 1);
|
|
|
|
env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT);
|
|
|
|
return reinterpret_cast<jlong>(slice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: data0
|
|
* Signature: (J)[B
|
|
*/
|
|
jbyteArray Java_org_rocksdb_Slice_data0(
|
|
JNIEnv* env, jobject jobj, jlong handle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const jsize len = static_cast<jsize>(slice->size());
|
|
const jbyteArray data = env->NewByteArray(len);
|
|
if(data == nullptr) {
|
|
// exception thrown: OutOfMemoryError
|
|
return nullptr;
|
|
}
|
|
|
|
env->SetByteArrayRegion(data, 0, len,
|
|
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(slice->data())));
|
|
if(env->ExceptionCheck()) {
|
|
// exception thrown: ArrayIndexOutOfBoundsException
|
|
env->DeleteLocalRef(data);
|
|
return nullptr;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: clear0
|
|
* Signature: (JZJ)V
|
|
*/
|
|
void Java_org_rocksdb_Slice_clear0(
|
|
JNIEnv * env, jobject jobj, jlong handle, jboolean shouldRelease,
|
|
jlong internalBufferOffset) {
|
|
auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
if(shouldRelease == JNI_TRUE) {
|
|
const char* buf = slice->data_ - internalBufferOffset;
|
|
delete [] buf;
|
|
}
|
|
slice->clear();
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: removePrefix0
|
|
* Signature: (JI)V
|
|
*/
|
|
void Java_org_rocksdb_Slice_removePrefix0(
|
|
JNIEnv * env, jobject jobj, jlong handle, jint length) {
|
|
auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
slice->remove_prefix(length);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_Slice
|
|
* Method: disposeInternalBuf
|
|
* Signature: (JJ)V
|
|
*/
|
|
void Java_org_rocksdb_Slice_disposeInternalBuf(
|
|
JNIEnv * env, jobject jobj, jlong handle, jlong internalBufferOffset) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const char* buf = slice->data_ - internalBufferOffset;
|
|
delete [] buf;
|
|
}
|
|
|
|
// </editor-fold>
|
|
|
|
// <editor-fold desc="org.rocksdb.DirectSlice>
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: createNewDirectSlice0
|
|
* Signature: (Ljava/nio/ByteBuffer;I)J
|
|
*/
|
|
jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(
|
|
JNIEnv* env, jclass jcls, jobject data, jint length) {
|
|
assert(data != nullptr);
|
|
void* data_addr = env->GetDirectBufferAddress(data);
|
|
if(data_addr == nullptr) {
|
|
// error: memory region is undefined, given object is not a direct
|
|
// java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
|
|
rocksdb::IllegalArgumentExceptionJni::ThrowNew(env,
|
|
rocksdb::Status::InvalidArgument(
|
|
"Could not access DirectBuffer"));
|
|
return 0;
|
|
}
|
|
|
|
const auto* ptrData =
|
|
reinterpret_cast<char*>(data_addr);
|
|
const auto* slice = new rocksdb::Slice(ptrData, length);
|
|
return reinterpret_cast<jlong>(slice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: createNewDirectSlice1
|
|
* Signature: (Ljava/nio/ByteBuffer;)J
|
|
*/
|
|
jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(
|
|
JNIEnv* env, jclass jcls, jobject data) {
|
|
void* data_addr = env->GetDirectBufferAddress(data);
|
|
if(data_addr == nullptr) {
|
|
// error: memory region is undefined, given object is not a direct
|
|
// java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
|
|
rocksdb::IllegalArgumentExceptionJni::ThrowNew(env,
|
|
rocksdb::Status::InvalidArgument(
|
|
"Could not access DirectBuffer"));
|
|
return 0;
|
|
}
|
|
|
|
const auto* ptrData = reinterpret_cast<char*>(data_addr);
|
|
const auto* slice = new rocksdb::Slice(ptrData);
|
|
return reinterpret_cast<jlong>(slice);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: data0
|
|
* Signature: (J)Ljava/lang/Object;
|
|
*/
|
|
jobject Java_org_rocksdb_DirectSlice_data0(
|
|
JNIEnv* env, jobject jobj, jlong handle) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
|
|
slice->size());
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: get0
|
|
* Signature: (JI)B
|
|
*/
|
|
jbyte Java_org_rocksdb_DirectSlice_get0(
|
|
JNIEnv* env, jobject jobj, jlong handle, jint offset) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
return (*slice)[offset];
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: clear0
|
|
* Signature: (JZJ)V
|
|
*/
|
|
void Java_org_rocksdb_DirectSlice_clear0(
|
|
JNIEnv* env, jobject jobj, jlong handle,
|
|
jboolean shouldRelease, jlong internalBufferOffset) {
|
|
auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
if(shouldRelease == JNI_TRUE) {
|
|
const char* buf = slice->data_ - internalBufferOffset;
|
|
delete [] buf;
|
|
}
|
|
slice->clear();
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: removePrefix0
|
|
* Signature: (JI)V
|
|
*/
|
|
void Java_org_rocksdb_DirectSlice_removePrefix0(
|
|
JNIEnv* env, jobject jobj, jlong handle, jint length) {
|
|
auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
slice->remove_prefix(length);
|
|
}
|
|
|
|
/*
|
|
* Class: org_rocksdb_DirectSlice
|
|
* Method: disposeInternalBuf
|
|
* Signature: (JJ)V
|
|
*/
|
|
void Java_org_rocksdb_DirectSlice_disposeInternalBuf(
|
|
JNIEnv* env, jobject jobj, jlong handle, jlong internalBufferOffset) {
|
|
const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
|
|
const char* buf = slice->data_ - internalBufferOffset;
|
|
delete [] buf;
|
|
}
|
|
|
|
// </editor-fold>
|