]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/rocksjni/loggerjnicallback.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / java / rocksjni / loggerjnicallback.cc
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::Logger.
8
9 #include "rocksjni/loggerjnicallback.h"
10
11 #include <cstdarg>
12 #include <cstdio>
13
14 #include "include/org_rocksdb_Logger.h"
15 #include "rocksjni/cplusplus_to_java_convert.h"
16 #include "rocksjni/portal.h"
17
18 namespace ROCKSDB_NAMESPACE {
19
20 LoggerJniCallback::LoggerJniCallback(JNIEnv* env, jobject jlogger)
21 : JniCallback(env, jlogger) {
22 m_jLogMethodId = LoggerJni::getLogMethodId(env);
23 if (m_jLogMethodId == nullptr) {
24 // exception thrown: NoSuchMethodException or OutOfMemoryError
25 return;
26 }
27
28 jobject jdebug_level = InfoLogLevelJni::DEBUG_LEVEL(env);
29 if (jdebug_level == nullptr) {
30 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
31 // or OutOfMemoryError
32 return;
33 }
34 m_jdebug_level = env->NewGlobalRef(jdebug_level);
35 if (m_jdebug_level == nullptr) {
36 // exception thrown: OutOfMemoryError
37 return;
38 }
39
40 jobject jinfo_level = InfoLogLevelJni::INFO_LEVEL(env);
41 if (jinfo_level == nullptr) {
42 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
43 // or OutOfMemoryError
44 return;
45 }
46 m_jinfo_level = env->NewGlobalRef(jinfo_level);
47 if (m_jinfo_level == nullptr) {
48 // exception thrown: OutOfMemoryError
49 return;
50 }
51
52 jobject jwarn_level = InfoLogLevelJni::WARN_LEVEL(env);
53 if (jwarn_level == nullptr) {
54 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
55 // or OutOfMemoryError
56 return;
57 }
58 m_jwarn_level = env->NewGlobalRef(jwarn_level);
59 if (m_jwarn_level == nullptr) {
60 // exception thrown: OutOfMemoryError
61 return;
62 }
63
64 jobject jerror_level = InfoLogLevelJni::ERROR_LEVEL(env);
65 if (jerror_level == nullptr) {
66 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
67 // or OutOfMemoryError
68 return;
69 }
70 m_jerror_level = env->NewGlobalRef(jerror_level);
71 if (m_jerror_level == nullptr) {
72 // exception thrown: OutOfMemoryError
73 return;
74 }
75
76 jobject jfatal_level = InfoLogLevelJni::FATAL_LEVEL(env);
77 if (jfatal_level == nullptr) {
78 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
79 // or OutOfMemoryError
80 return;
81 }
82 m_jfatal_level = env->NewGlobalRef(jfatal_level);
83 if (m_jfatal_level == nullptr) {
84 // exception thrown: OutOfMemoryError
85 return;
86 }
87
88 jobject jheader_level = InfoLogLevelJni::HEADER_LEVEL(env);
89 if (jheader_level == nullptr) {
90 // exception thrown: NoSuchFieldError, ExceptionInInitializerError
91 // or OutOfMemoryError
92 return;
93 }
94 m_jheader_level = env->NewGlobalRef(jheader_level);
95 if (m_jheader_level == nullptr) {
96 // exception thrown: OutOfMemoryError
97 return;
98 }
99 }
100
101 void LoggerJniCallback::Logv(const char* /*format*/, va_list /*ap*/) {
102 // We implement this method because it is virtual but we don't
103 // use it because we need to know about the log level.
104 }
105
106 void LoggerJniCallback::Logv(const InfoLogLevel log_level, const char* format,
107 va_list ap) {
108 if (GetInfoLogLevel() <= log_level) {
109 // determine InfoLogLevel java enum instance
110 jobject jlog_level;
111 switch (log_level) {
112 case ROCKSDB_NAMESPACE::InfoLogLevel::DEBUG_LEVEL:
113 jlog_level = m_jdebug_level;
114 break;
115 case ROCKSDB_NAMESPACE::InfoLogLevel::INFO_LEVEL:
116 jlog_level = m_jinfo_level;
117 break;
118 case ROCKSDB_NAMESPACE::InfoLogLevel::WARN_LEVEL:
119 jlog_level = m_jwarn_level;
120 break;
121 case ROCKSDB_NAMESPACE::InfoLogLevel::ERROR_LEVEL:
122 jlog_level = m_jerror_level;
123 break;
124 case ROCKSDB_NAMESPACE::InfoLogLevel::FATAL_LEVEL:
125 jlog_level = m_jfatal_level;
126 break;
127 case ROCKSDB_NAMESPACE::InfoLogLevel::HEADER_LEVEL:
128 jlog_level = m_jheader_level;
129 break;
130 default:
131 jlog_level = m_jfatal_level;
132 break;
133 }
134
135 assert(format != nullptr);
136 const std::unique_ptr<char[]> msg = format_str(format, ap);
137
138 // pass msg to java callback handler
139 jboolean attached_thread = JNI_FALSE;
140 JNIEnv* env = getJniEnv(&attached_thread);
141 assert(env != nullptr);
142
143 jstring jmsg = env->NewStringUTF(msg.get());
144 if (jmsg == nullptr) {
145 // unable to construct string
146 if (env->ExceptionCheck()) {
147 env->ExceptionDescribe(); // print out exception to stderr
148 }
149 releaseJniEnv(attached_thread);
150 return;
151 }
152 if (env->ExceptionCheck()) {
153 // exception thrown: OutOfMemoryError
154 env->ExceptionDescribe(); // print out exception to stderr
155 env->DeleteLocalRef(jmsg);
156 releaseJniEnv(attached_thread);
157 return;
158 }
159
160 env->CallVoidMethod(m_jcallback_obj, m_jLogMethodId, jlog_level, jmsg);
161 if (env->ExceptionCheck()) {
162 // exception thrown
163 env->ExceptionDescribe(); // print out exception to stderr
164 env->DeleteLocalRef(jmsg);
165 releaseJniEnv(attached_thread);
166 return;
167 }
168
169 env->DeleteLocalRef(jmsg);
170 releaseJniEnv(attached_thread);
171 }
172 }
173
174 std::unique_ptr<char[]> LoggerJniCallback::format_str(const char* format,
175 va_list ap) const {
176 va_list ap_copy;
177
178 va_copy(ap_copy, ap);
179 const size_t required =
180 vsnprintf(nullptr, 0, format, ap_copy) + 1; // Extra space for '\0'
181 va_end(ap_copy);
182
183 std::unique_ptr<char[]> buf(new char[required]);
184
185 va_copy(ap_copy, ap);
186 vsnprintf(buf.get(), required, format, ap_copy);
187 va_end(ap_copy);
188
189 return buf;
190 }
191 LoggerJniCallback::~LoggerJniCallback() {
192 jboolean attached_thread = JNI_FALSE;
193 JNIEnv* env = getJniEnv(&attached_thread);
194 assert(env != nullptr);
195
196 if (m_jdebug_level != nullptr) {
197 env->DeleteGlobalRef(m_jdebug_level);
198 }
199
200 if (m_jinfo_level != nullptr) {
201 env->DeleteGlobalRef(m_jinfo_level);
202 }
203
204 if (m_jwarn_level != nullptr) {
205 env->DeleteGlobalRef(m_jwarn_level);
206 }
207
208 if (m_jerror_level != nullptr) {
209 env->DeleteGlobalRef(m_jerror_level);
210 }
211
212 if (m_jfatal_level != nullptr) {
213 env->DeleteGlobalRef(m_jfatal_level);
214 }
215
216 if (m_jheader_level != nullptr) {
217 env->DeleteGlobalRef(m_jheader_level);
218 }
219
220 releaseJniEnv(attached_thread);
221 }
222
223 } // namespace ROCKSDB_NAMESPACE
224
225 /*
226 * Class: org_rocksdb_Logger
227 * Method: createNewLoggerOptions
228 * Signature: (J)J
229 */
230 jlong Java_org_rocksdb_Logger_createNewLoggerOptions(JNIEnv* env, jobject jobj,
231 jlong joptions) {
232 auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
233 new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));
234
235 // set log level
236 auto* options = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions);
237 sptr_logger->get()->SetInfoLogLevel(options->info_log_level);
238
239 return GET_CPLUSPLUS_POINTER(sptr_logger);
240 }
241
242 /*
243 * Class: org_rocksdb_Logger
244 * Method: createNewLoggerDbOptions
245 * Signature: (J)J
246 */
247 jlong Java_org_rocksdb_Logger_createNewLoggerDbOptions(JNIEnv* env,
248 jobject jobj,
249 jlong jdb_options) {
250 auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
251 new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));
252
253 // set log level
254 auto* db_options =
255 reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_options);
256 sptr_logger->get()->SetInfoLogLevel(db_options->info_log_level);
257
258 return GET_CPLUSPLUS_POINTER(sptr_logger);
259 }
260
261 /*
262 * Class: org_rocksdb_Logger
263 * Method: setInfoLogLevel
264 * Signature: (JB)V
265 */
266 void Java_org_rocksdb_Logger_setInfoLogLevel(JNIEnv* /*env*/, jobject /*jobj*/,
267 jlong jhandle, jbyte jlog_level) {
268 auto* handle =
269 reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
270 jhandle);
271 handle->get()->SetInfoLogLevel(
272 static_cast<ROCKSDB_NAMESPACE::InfoLogLevel>(jlog_level));
273 }
274
275 /*
276 * Class: org_rocksdb_Logger
277 * Method: infoLogLevel
278 * Signature: (J)B
279 */
280 jbyte Java_org_rocksdb_Logger_infoLogLevel(JNIEnv* /*env*/, jobject /*jobj*/,
281 jlong jhandle) {
282 auto* handle =
283 reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
284 jhandle);
285 return static_cast<jbyte>(handle->get()->GetInfoLogLevel());
286 }
287
288 /*
289 * Class: org_rocksdb_Logger
290 * Method: disposeInternal
291 * Signature: (J)V
292 */
293 void Java_org_rocksdb_Logger_disposeInternal(JNIEnv* /*env*/, jobject /*jobj*/,
294 jlong jhandle) {
295 auto* handle =
296 reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
297 jhandle);
298 delete handle; // delete std::shared_ptr
299 }