|
|
|
@ -7,14 +7,15 @@ |
|
|
|
|
// rocksdb::Comparator.
|
|
|
|
|
|
|
|
|
|
#include "rocksjni/comparatorjnicallback.h" |
|
|
|
|
#include "portal.h" |
|
|
|
|
#include "rocksjni/portal.h" |
|
|
|
|
|
|
|
|
|
namespace rocksdb { |
|
|
|
|
BaseComparatorJniCallback::BaseComparatorJniCallback( |
|
|
|
|
JNIEnv* env, jobject jComparator, const ComparatorJniCallbackOptions* copt) { |
|
|
|
|
JNIEnv* env, jobject jComparator, |
|
|
|
|
const ComparatorJniCallbackOptions* copt) { |
|
|
|
|
|
|
|
|
|
//mutex is used for synchronisation when we are re-using
|
|
|
|
|
//the global java slice objects
|
|
|
|
|
// mutex is used for synchronisation when we are re-using
|
|
|
|
|
// the global java slice objects
|
|
|
|
|
mutex_ = new port::Mutex(copt->use_adaptive_mutex); |
|
|
|
|
|
|
|
|
|
// Note: Comparator methods may be accessed by multiple threads,
|
|
|
|
@ -30,11 +31,13 @@ BaseComparatorJniCallback::BaseComparatorJniCallback( |
|
|
|
|
// so we cache it in a global var
|
|
|
|
|
jmethodID jNameMethodId = AbstractComparatorJni::getNameMethodId(env); |
|
|
|
|
jstring jsName = (jstring)env->CallObjectMethod(m_jComparator, jNameMethodId); |
|
|
|
|
m_name = JniUtil::copyString(env, jsName); //also releases jsName
|
|
|
|
|
m_name = JniUtil::copyString(env, jsName); // also releases jsName
|
|
|
|
|
|
|
|
|
|
m_jCompareMethodId = AbstractComparatorJni::getCompareMethodId(env); |
|
|
|
|
m_jFindShortestSeparatorMethodId = AbstractComparatorJni::getFindShortestSeparatorMethodId(env); |
|
|
|
|
m_jFindShortSuccessorMethodId = AbstractComparatorJni::getFindShortSuccessorMethodId(env); |
|
|
|
|
m_jFindShortestSeparatorMethodId = |
|
|
|
|
AbstractComparatorJni::getFindShortestSeparatorMethodId(env); |
|
|
|
|
m_jFindShortSuccessorMethodId = |
|
|
|
|
AbstractComparatorJni::getFindShortSuccessorMethodId(env); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -42,24 +45,25 @@ BaseComparatorJniCallback::BaseComparatorJniCallback( |
|
|
|
|
*/ |
|
|
|
|
JNIEnv* BaseComparatorJniCallback::getJniEnv() const { |
|
|
|
|
JNIEnv *env; |
|
|
|
|
jint rs = m_jvm->AttachCurrentThread((void **)&env, NULL); |
|
|
|
|
jint rs = m_jvm->AttachCurrentThread(reinterpret_cast<void **>(&env), NULL); |
|
|
|
|
assert(rs == JNI_OK); |
|
|
|
|
return env; |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char* BaseComparatorJniCallback::Name() const { |
|
|
|
|
return m_name.c_str(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int BaseComparatorJniCallback::Compare(const Slice& a, const Slice& b) const { |
|
|
|
|
|
|
|
|
|
JNIEnv* m_env = getJniEnv(); |
|
|
|
|
|
|
|
|
|
mutex_->Lock(); |
|
|
|
|
|
|
|
|
|
AbstractSliceJni::setHandle(m_env, m_jSliceA, &a); |
|
|
|
|
AbstractSliceJni::setHandle(m_env, m_jSliceB, &b); |
|
|
|
|
jint result = m_env->CallIntMethod(m_jComparator, m_jCompareMethodId, m_jSliceA, m_jSliceB); |
|
|
|
|
jint result = |
|
|
|
|
m_env->CallIntMethod(m_jComparator, m_jCompareMethodId, m_jSliceA, |
|
|
|
|
m_jSliceB); |
|
|
|
|
|
|
|
|
|
mutex_->Unlock(); |
|
|
|
|
|
|
|
|
@ -68,8 +72,8 @@ int BaseComparatorJniCallback::Compare(const Slice& a, const Slice& b) const { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void BaseComparatorJniCallback::FindShortestSeparator(std::string* start, const Slice& limit) const { |
|
|
|
|
|
|
|
|
|
void BaseComparatorJniCallback::FindShortestSeparator( |
|
|
|
|
std::string* start, const Slice& limit) const { |
|
|
|
|
if (start == nullptr) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -82,22 +86,24 @@ void BaseComparatorJniCallback::FindShortestSeparator(std::string* start, const |
|
|
|
|
mutex_->Lock(); |
|
|
|
|
|
|
|
|
|
AbstractSliceJni::setHandle(m_env, m_jSliceLimit, &limit); |
|
|
|
|
jstring jsResultStart = (jstring)m_env->CallObjectMethod(m_jComparator, m_jFindShortestSeparatorMethodId, jsStart, m_jSliceLimit); |
|
|
|
|
jstring jsResultStart = |
|
|
|
|
(jstring)m_env->CallObjectMethod(m_jComparator, |
|
|
|
|
m_jFindShortestSeparatorMethodId, jsStart, m_jSliceLimit); |
|
|
|
|
|
|
|
|
|
mutex_->Unlock(); |
|
|
|
|
|
|
|
|
|
m_env->DeleteLocalRef(jsStart); |
|
|
|
|
|
|
|
|
|
if(jsResultStart != nullptr) { |
|
|
|
|
//update start with result
|
|
|
|
|
*start = JniUtil::copyString(m_env, jsResultStart); //also releases jsResultStart
|
|
|
|
|
if (jsResultStart != nullptr) { |
|
|
|
|
// update start with result
|
|
|
|
|
*start = |
|
|
|
|
JniUtil::copyString(m_env, jsResultStart); // also releases jsResultStart
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m_jvm->DetachCurrentThread(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void BaseComparatorJniCallback::FindShortSuccessor(std::string* key) const { |
|
|
|
|
|
|
|
|
|
if (key == nullptr) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -107,13 +113,16 @@ void BaseComparatorJniCallback::FindShortSuccessor(std::string* key) const { |
|
|
|
|
const char* keyUtf = key->c_str(); |
|
|
|
|
jstring jsKey = m_env->NewStringUTF(keyUtf); |
|
|
|
|
|
|
|
|
|
jstring jsResultKey = (jstring)m_env->CallObjectMethod(m_jComparator, m_jFindShortSuccessorMethodId, jsKey); |
|
|
|
|
jstring jsResultKey = |
|
|
|
|
(jstring)m_env->CallObjectMethod(m_jComparator, |
|
|
|
|
m_jFindShortSuccessorMethodId, jsKey); |
|
|
|
|
|
|
|
|
|
m_env->DeleteLocalRef(jsKey); |
|
|
|
|
|
|
|
|
|
if(jsResultKey != nullptr) { |
|
|
|
|
//update key with result
|
|
|
|
|
*key = JniUtil::copyString(m_env, jsResultKey); //also releases jsResultKey
|
|
|
|
|
if (jsResultKey != nullptr) { |
|
|
|
|
// update key with result
|
|
|
|
|
*key = |
|
|
|
|
JniUtil::copyString(m_env, jsResultKey); // also releases jsResultKey
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m_jvm->DetachCurrentThread(); |
|
|
|
@ -121,7 +130,7 @@ void BaseComparatorJniCallback::FindShortSuccessor(std::string* key) const { |
|
|
|
|
|
|
|
|
|
BaseComparatorJniCallback::~BaseComparatorJniCallback() { |
|
|
|
|
JNIEnv* m_env = getJniEnv(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_env->DeleteGlobalRef(m_jComparator); |
|
|
|
|
m_env->DeleteGlobalRef(m_jSliceA); |
|
|
|
|
m_env->DeleteGlobalRef(m_jSliceB); |
|
|
|
@ -129,21 +138,23 @@ BaseComparatorJniCallback::~BaseComparatorJniCallback() { |
|
|
|
|
|
|
|
|
|
// Note: do not need to explicitly detach, as this function is effectively
|
|
|
|
|
// called from the Java class's disposeInternal method, and so already
|
|
|
|
|
// has an attached thread, getJniEnv above is just a no-op Attach to get the env
|
|
|
|
|
//jvm->DetachCurrentThread();
|
|
|
|
|
// has an attached thread, getJniEnv above is just a no-op Attach to get
|
|
|
|
|
// the env jvm->DetachCurrentThread();
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ComparatorJniCallback::ComparatorJniCallback( |
|
|
|
|
JNIEnv* env, jobject jComparator, const ComparatorJniCallbackOptions* copt) : BaseComparatorJniCallback(env, jComparator, copt) { |
|
|
|
|
|
|
|
|
|
JNIEnv* env, jobject jComparator, |
|
|
|
|
const ComparatorJniCallbackOptions* copt) : |
|
|
|
|
BaseComparatorJniCallback(env, jComparator, copt) { |
|
|
|
|
m_jSliceA = env->NewGlobalRef(SliceJni::construct0(env)); |
|
|
|
|
m_jSliceB = env->NewGlobalRef(SliceJni::construct0(env)); |
|
|
|
|
m_jSliceLimit = env->NewGlobalRef(SliceJni::construct0(env)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DirectComparatorJniCallback::DirectComparatorJniCallback( |
|
|
|
|
JNIEnv* env, jobject jComparator, const ComparatorJniCallbackOptions* copt) : BaseComparatorJniCallback(env, jComparator, copt) { |
|
|
|
|
|
|
|
|
|
JNIEnv* env, jobject jComparator, |
|
|
|
|
const ComparatorJniCallbackOptions* copt) : |
|
|
|
|
BaseComparatorJniCallback(env, jComparator, copt) { |
|
|
|
|
m_jSliceA = env->NewGlobalRef(DirectSliceJni::construct0(env)); |
|
|
|
|
m_jSliceB = env->NewGlobalRef(DirectSliceJni::construct0(env)); |
|
|
|
|
m_jSliceLimit = env->NewGlobalRef(DirectSliceJni::construct0(env)); |
|
|
|
|