1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 //
6 // This file implements the callback "bridge" between Java and C++ for
7 // ROCKSDB_NAMESPACE::TraceWriter.
8
9 #include "rocksjni/trace_writer_jnicallback.h"
10 #include "rocksjni/portal.h"
11
12 namespace ROCKSDB_NAMESPACE {
TraceWriterJniCallback(JNIEnv * env,jobject jtrace_writer)13 TraceWriterJniCallback::TraceWriterJniCallback(
14 JNIEnv* env, jobject jtrace_writer)
15 : JniCallback(env, jtrace_writer) {
16 m_jwrite_proxy_methodid =
17 AbstractTraceWriterJni::getWriteProxyMethodId(env);
18 if(m_jwrite_proxy_methodid == nullptr) {
19 // exception thrown: NoSuchMethodException or OutOfMemoryError
20 return;
21 }
22
23 m_jclose_writer_proxy_methodid =
24 AbstractTraceWriterJni::getCloseWriterProxyMethodId(env);
25 if(m_jclose_writer_proxy_methodid == nullptr) {
26 // exception thrown: NoSuchMethodException or OutOfMemoryError
27 return;
28 }
29
30 m_jget_file_size_methodid =
31 AbstractTraceWriterJni::getGetFileSizeMethodId(env);
32 if(m_jget_file_size_methodid == nullptr) {
33 // exception thrown: NoSuchMethodException or OutOfMemoryError
34 return;
35 }
36 }
37
Write(const Slice & data)38 Status TraceWriterJniCallback::Write(const Slice& data) {
39 jboolean attached_thread = JNI_FALSE;
40 JNIEnv* env = getJniEnv(&attached_thread);
41 if (env == nullptr) {
42 return Status::IOError("Unable to attach JNI Environment");
43 }
44
45 jshort jstatus = env->CallShortMethod(m_jcallback_obj,
46 m_jwrite_proxy_methodid,
47 &data);
48
49 if(env->ExceptionCheck()) {
50 // exception thrown from CallShortMethod
51 env->ExceptionDescribe(); // print out exception to stderr
52 releaseJniEnv(attached_thread);
53 return Status::IOError("Unable to call AbstractTraceWriter#writeProxy(long)");
54 }
55
56 // unpack status code and status sub-code from jstatus
57 jbyte jcode_value = (jstatus >> 8) & 0xFF;
58 jbyte jsub_code_value = jstatus & 0xFF;
59 std::unique_ptr<Status> s = StatusJni::toCppStatus(jcode_value, jsub_code_value);
60
61 releaseJniEnv(attached_thread);
62
63 return Status(*s);
64 }
65
Close()66 Status TraceWriterJniCallback::Close() {
67 jboolean attached_thread = JNI_FALSE;
68 JNIEnv* env = getJniEnv(&attached_thread);
69 if (env == nullptr) {
70 return Status::IOError("Unable to attach JNI Environment");
71 }
72
73 jshort jstatus = env->CallShortMethod(m_jcallback_obj,
74 m_jclose_writer_proxy_methodid);
75
76 if(env->ExceptionCheck()) {
77 // exception thrown from CallShortMethod
78 env->ExceptionDescribe(); // print out exception to stderr
79 releaseJniEnv(attached_thread);
80 return Status::IOError("Unable to call AbstractTraceWriter#closeWriterProxy()");
81 }
82
83 // unpack status code and status sub-code from jstatus
84 jbyte code_value = (jstatus >> 8) & 0xFF;
85 jbyte sub_code_value = jstatus & 0xFF;
86 std::unique_ptr<Status> s = StatusJni::toCppStatus(code_value, sub_code_value);
87
88 releaseJniEnv(attached_thread);
89
90 return Status(*s);
91 }
92
GetFileSize()93 uint64_t TraceWriterJniCallback::GetFileSize() {
94 jboolean attached_thread = JNI_FALSE;
95 JNIEnv* env = getJniEnv(&attached_thread);
96 if (env == nullptr) {
97 return 0;
98 }
99
100 jlong jfile_size = env->CallLongMethod(m_jcallback_obj,
101 m_jget_file_size_methodid);
102
103 if(env->ExceptionCheck()) {
104 // exception thrown from CallLongMethod
105 env->ExceptionDescribe(); // print out exception to stderr
106 releaseJniEnv(attached_thread);
107 return 0;
108 }
109
110 releaseJniEnv(attached_thread);
111
112 return static_cast<uint64_t>(jfile_size);
113 }
114
115 } // namespace ROCKSDB_NAMESPACE
116