2016-02-10 00:12:00 +01:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2017-07-16 01:03:42 +02:00
|
|
|
// 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).
|
2014-10-23 17:19:38 +02:00
|
|
|
//
|
|
|
|
// This file implements the callback "bridge" between Java and C++ for
|
|
|
|
// rocksdb::Comparator.
|
|
|
|
|
|
|
|
#include "rocksjni/writebatchhandlerjnicallback.h"
|
|
|
|
#include "rocksjni/portal.h"
|
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
|
2014-11-05 19:56:45 +01:00
|
|
|
JNIEnv* env, jobject jWriteBatchHandler)
|
|
|
|
: m_env(env) {
|
2014-10-23 17:19:38 +02:00
|
|
|
|
|
|
|
// Note: we want to access the Java WriteBatchHandler instance
|
|
|
|
// across multiple method calls, so we create a global ref
|
2017-02-28 01:26:12 +01:00
|
|
|
assert(jWriteBatchHandler != nullptr);
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler = env->NewGlobalRef(jWriteBatchHandler);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jWriteBatchHandler == nullptr) {
|
|
|
|
// exception thrown: OutOfMemoryError
|
|
|
|
return;
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
|
|
|
|
m_jPutMethodId = WriteBatchHandlerJni::getPutMethodId(env);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jPutMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jMergeMethodId = WriteBatchHandlerJni::getMergeMethodId(env);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jMergeMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jDeleteMethodId = WriteBatchHandlerJni::getDeleteMethodId(env);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jDeleteMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-07 07:13:53 +01:00
|
|
|
m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env);
|
|
|
|
if (m_jDeleteRangeMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jLogDataMethodId = WriteBatchHandlerJni::getLogDataMethodId(env);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jLogDataMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jContinueMethodId == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
return;
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) {
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_key = sliceToJArray(key);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_key == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_value = sliceToJArray(value);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_value == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
|
|
|
m_env->CallVoidMethod(
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler,
|
|
|
|
m_jPutMethodId,
|
2014-11-05 19:56:45 +01:00
|
|
|
j_key,
|
|
|
|
j_value);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
if(j_value != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_value);
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_value != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_value);
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) {
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_key = sliceToJArray(key);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_key == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_value = sliceToJArray(value);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_value == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
|
|
|
m_env->CallVoidMethod(
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler,
|
|
|
|
m_jMergeMethodId,
|
2014-11-05 19:56:45 +01:00
|
|
|
j_key,
|
|
|
|
j_value);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
if(j_value != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_value);
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_value != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_value);
|
|
|
|
}
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBatchHandlerJniCallback::Delete(const Slice& key) {
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_key = sliceToJArray(key);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_key == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
|
|
|
m_env->CallVoidMethod(
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler,
|
|
|
|
m_jDeleteMethodId,
|
2014-11-05 19:56:45 +01:00
|
|
|
j_key);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_key != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_key);
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
|
2017-03-07 07:13:53 +01:00
|
|
|
void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey,
|
|
|
|
const Slice& endKey) {
|
|
|
|
const jbyteArray j_beginKey = sliceToJArray(beginKey);
|
|
|
|
if (j_beginKey == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if (m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const jbyteArray j_endKey = sliceToJArray(beginKey);
|
|
|
|
if (j_endKey == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if (m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_env->CallVoidMethod(m_jWriteBatchHandler, m_jDeleteRangeMethodId,
|
|
|
|
j_beginKey, j_endKey);
|
|
|
|
if (m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
if (j_beginKey != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_beginKey);
|
|
|
|
}
|
|
|
|
if (j_endKey != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_endKey);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j_beginKey != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_beginKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j_endKey != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_endKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
void WriteBatchHandlerJniCallback::LogData(const Slice& blob) {
|
2014-11-05 19:56:45 +01:00
|
|
|
const jbyteArray j_blob = sliceToJArray(blob);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_blob == nullptr) {
|
|
|
|
// exception thrown
|
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
|
|
|
m_env->CallVoidMethod(
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler,
|
|
|
|
m_jLogDataMethodId,
|
2014-11-05 19:56:45 +01:00
|
|
|
j_blob);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
if(j_blob != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_blob);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-11-05 19:56:45 +01:00
|
|
|
|
2017-02-28 01:26:12 +01:00
|
|
|
if(j_blob != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(j_blob);
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WriteBatchHandlerJniCallback::Continue() {
|
2014-11-05 19:56:45 +01:00
|
|
|
jboolean jContinue = m_env->CallBooleanMethod(
|
2014-10-23 17:19:38 +02:00
|
|
|
m_jWriteBatchHandler,
|
|
|
|
m_jContinueMethodId);
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
// exception thrown
|
|
|
|
m_env->ExceptionDescribe();
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
|
|
|
|
return static_cast<bool>(jContinue == JNI_TRUE);
|
|
|
|
}
|
|
|
|
|
2014-11-05 19:56:45 +01:00
|
|
|
/*
|
|
|
|
* Creates a Java Byte Array from the data in a Slice
|
|
|
|
*
|
|
|
|
* When calling this function
|
|
|
|
* you must remember to call env->DeleteLocalRef
|
|
|
|
* on the result after you have finished with it
|
2017-02-28 01:26:12 +01:00
|
|
|
*
|
|
|
|
* @param s A Slice to convery to a Java byte array
|
|
|
|
*
|
|
|
|
* @return A reference to a Java byte array, or a nullptr if an
|
|
|
|
* exception occurs
|
2014-11-05 19:56:45 +01:00
|
|
|
*/
|
2014-10-23 17:19:38 +02:00
|
|
|
jbyteArray WriteBatchHandlerJniCallback::sliceToJArray(const Slice& s) {
|
2014-11-13 20:39:30 +01:00
|
|
|
jbyteArray ja = m_env->NewByteArray(static_cast<jsize>(s.size()));
|
2017-02-28 01:26:12 +01:00
|
|
|
if(ja == nullptr) {
|
|
|
|
// exception thrown: OutOfMemoryError
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-11-05 19:56:45 +01:00
|
|
|
m_env->SetByteArrayRegion(
|
2014-11-13 20:39:30 +01:00
|
|
|
ja, 0, static_cast<jsize>(s.size()),
|
2017-03-23 02:05:39 +01:00
|
|
|
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(s.data())));
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_env->ExceptionCheck()) {
|
|
|
|
if(ja != nullptr) {
|
|
|
|
m_env->DeleteLocalRef(ja);
|
|
|
|
}
|
|
|
|
// exception thrown: ArrayIndexOutOfBoundsException
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:19:38 +02:00
|
|
|
return ja;
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteBatchHandlerJniCallback::~WriteBatchHandlerJniCallback() {
|
2017-02-28 01:26:12 +01:00
|
|
|
if(m_jWriteBatchHandler != nullptr) {
|
|
|
|
m_env->DeleteGlobalRef(m_jWriteBatchHandler);
|
|
|
|
}
|
2014-10-23 17:19:38 +02:00
|
|
|
}
|
|
|
|
} // namespace rocksdb
|