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