// 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 callback "bridge" between Java and C++ for // ROCKSDB_NAMESPACE::TraceWriter. #include "rocksjni/trace_writer_jnicallback.h" #include "rocksjni/portal.h" namespace ROCKSDB_NAMESPACE { TraceWriterJniCallback::TraceWriterJniCallback( JNIEnv* env, jobject jtrace_writer) : JniCallback(env, jtrace_writer) { m_jwrite_proxy_methodid = AbstractTraceWriterJni::getWriteProxyMethodId(env); if(m_jwrite_proxy_methodid == nullptr) { // exception thrown: NoSuchMethodException or OutOfMemoryError return; } m_jclose_writer_proxy_methodid = AbstractTraceWriterJni::getCloseWriterProxyMethodId(env); if(m_jclose_writer_proxy_methodid == nullptr) { // exception thrown: NoSuchMethodException or OutOfMemoryError return; } m_jget_file_size_methodid = AbstractTraceWriterJni::getGetFileSizeMethodId(env); if(m_jget_file_size_methodid == nullptr) { // exception thrown: NoSuchMethodException or OutOfMemoryError return; } } Status TraceWriterJniCallback::Write(const Slice& data) { jboolean attached_thread = JNI_FALSE; JNIEnv* env = getJniEnv(&attached_thread); if (env == nullptr) { return Status::IOError("Unable to attach JNI Environment"); } jshort jstatus = env->CallShortMethod(m_jcallback_obj, m_jwrite_proxy_methodid, &data); if(env->ExceptionCheck()) { // exception thrown from CallShortMethod env->ExceptionDescribe(); // print out exception to stderr releaseJniEnv(attached_thread); return Status::IOError("Unable to call AbstractTraceWriter#writeProxy(long)"); } // unpack status code and status sub-code from jstatus jbyte jcode_value = (jstatus >> 8) & 0xFF; jbyte jsub_code_value = jstatus & 0xFF; std::unique_ptr s = StatusJni::toCppStatus(jcode_value, jsub_code_value); releaseJniEnv(attached_thread); return Status(*s); } Status TraceWriterJniCallback::Close() { jboolean attached_thread = JNI_FALSE; JNIEnv* env = getJniEnv(&attached_thread); if (env == nullptr) { return Status::IOError("Unable to attach JNI Environment"); } jshort jstatus = env->CallShortMethod(m_jcallback_obj, m_jclose_writer_proxy_methodid); if(env->ExceptionCheck()) { // exception thrown from CallShortMethod env->ExceptionDescribe(); // print out exception to stderr releaseJniEnv(attached_thread); return Status::IOError("Unable to call AbstractTraceWriter#closeWriterProxy()"); } // unpack status code and status sub-code from jstatus jbyte code_value = (jstatus >> 8) & 0xFF; jbyte sub_code_value = jstatus & 0xFF; std::unique_ptr s = StatusJni::toCppStatus(code_value, sub_code_value); releaseJniEnv(attached_thread); return Status(*s); } uint64_t TraceWriterJniCallback::GetFileSize() { jboolean attached_thread = JNI_FALSE; JNIEnv* env = getJniEnv(&attached_thread); if (env == nullptr) { return 0; } jlong jfile_size = env->CallLongMethod(m_jcallback_obj, m_jget_file_size_methodid); if(env->ExceptionCheck()) { // exception thrown from CallLongMethod env->ExceptionDescribe(); // print out exception to stderr releaseJniEnv(attached_thread); return 0; } releaseJniEnv(attached_thread); return static_cast(jfile_size); } } // namespace ROCKSDB_NAMESPACE