rocksdb/java/rocksjni/slice.cc
Tomas Kolda 1001bc01c9 Read Options to support direct slice (#7132)
Summary:
This request is adding support for using DirectSlice in ReadOptions lower/upper bounds.

To be more efficient I have added setLength to DirectSlice so I can just update the length to be used by slice from direct buffer. It is also needed, because when one creates iterator it keep pointer to original slice so setting new slice in options does not help (it needs to reuse existing one). Using this approach one can modify the slice any time during operations with iterator.

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

Reviewed By: zhichao-cao

Differential Revision: D25840092

Pulled By: jay-zhuang

fbshipit-source-id: 760167baf61568c9a35138145c4bf9b06824cb71
2021-01-15 17:05:18 -08:00

372 lines
12 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).
//
// This file implements the "bridge" between Java and C++ for
// ROCKSDB_NAMESPACE::Slice.
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "include/org_rocksdb_AbstractSlice.h"
#include "include/org_rocksdb_DirectSlice.h"
#include "include/org_rocksdb_Slice.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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::Slice*>(handle);
const auto* otherSlice =
reinterpret_cast<ROCKSDB_NAMESPACE::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_NAMESPACE::Slice*>(handle);
const auto* otherSlice =
reinterpret_cast<ROCKSDB_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::Slice*>(handle);
slice->remove_prefix(length);
}
/*
* Class: org_rocksdb_DirectSlice
* Method: setLength0
* Signature: (JI)V
*/
void Java_org_rocksdb_DirectSlice_setLength0(JNIEnv* /*env*/, jobject /*jobj*/,
jlong handle, jint length) {
auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
slice->size_ = 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_NAMESPACE::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_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
"Could not access DirectBuffer"));
return 0;
}
const auto* ptrData = reinterpret_cast<char*>(data_addr);
const auto* slice = new ROCKSDB_NAMESPACE::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_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
"Could not access DirectBuffer"));
return 0;
}
const auto* ptrData = reinterpret_cast<char*>(data_addr);
const auto* slice = new ROCKSDB_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::Slice*>(handle);
const char* buf = slice->data_ - internalBufferOffset;
delete[] buf;
}
// </editor-fold>