| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- // 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::Logger.
- #include "include/org_rocksdb_Logger.h"
- #include <cstdarg>
- #include <cstdio>
- #include "rocksjni/loggerjnicallback.h"
- #include "rocksjni/portal.h"
- namespace ROCKSDB_NAMESPACE {
- LoggerJniCallback::LoggerJniCallback(JNIEnv* env, jobject jlogger)
- : JniCallback(env, jlogger) {
- m_jLogMethodId = LoggerJni::getLogMethodId(env);
- if (m_jLogMethodId == nullptr) {
- // exception thrown: NoSuchMethodException or OutOfMemoryError
- return;
- }
- jobject jdebug_level = InfoLogLevelJni::DEBUG_LEVEL(env);
- if (jdebug_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jdebug_level = env->NewGlobalRef(jdebug_level);
- if (m_jdebug_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- jobject jinfo_level = InfoLogLevelJni::INFO_LEVEL(env);
- if (jinfo_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jinfo_level = env->NewGlobalRef(jinfo_level);
- if (m_jinfo_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- jobject jwarn_level = InfoLogLevelJni::WARN_LEVEL(env);
- if (jwarn_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jwarn_level = env->NewGlobalRef(jwarn_level);
- if (m_jwarn_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- jobject jerror_level = InfoLogLevelJni::ERROR_LEVEL(env);
- if (jerror_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jerror_level = env->NewGlobalRef(jerror_level);
- if (m_jerror_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- jobject jfatal_level = InfoLogLevelJni::FATAL_LEVEL(env);
- if (jfatal_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jfatal_level = env->NewGlobalRef(jfatal_level);
- if (m_jfatal_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- jobject jheader_level = InfoLogLevelJni::HEADER_LEVEL(env);
- if (jheader_level == nullptr) {
- // exception thrown: NoSuchFieldError, ExceptionInInitializerError
- // or OutOfMemoryError
- return;
- }
- m_jheader_level = env->NewGlobalRef(jheader_level);
- if (m_jheader_level == nullptr) {
- // exception thrown: OutOfMemoryError
- return;
- }
- }
- void LoggerJniCallback::Logv(const char* /*format*/, va_list /*ap*/) {
- // We implement this method because it is virtual but we don't
- // use it because we need to know about the log level.
- }
- void LoggerJniCallback::Logv(const InfoLogLevel log_level, const char* format,
- va_list ap) {
- if (GetInfoLogLevel() <= log_level) {
- // determine InfoLogLevel java enum instance
- jobject jlog_level;
- switch (log_level) {
- case ROCKSDB_NAMESPACE::InfoLogLevel::DEBUG_LEVEL:
- jlog_level = m_jdebug_level;
- break;
- case ROCKSDB_NAMESPACE::InfoLogLevel::INFO_LEVEL:
- jlog_level = m_jinfo_level;
- break;
- case ROCKSDB_NAMESPACE::InfoLogLevel::WARN_LEVEL:
- jlog_level = m_jwarn_level;
- break;
- case ROCKSDB_NAMESPACE::InfoLogLevel::ERROR_LEVEL:
- jlog_level = m_jerror_level;
- break;
- case ROCKSDB_NAMESPACE::InfoLogLevel::FATAL_LEVEL:
- jlog_level = m_jfatal_level;
- break;
- case ROCKSDB_NAMESPACE::InfoLogLevel::HEADER_LEVEL:
- jlog_level = m_jheader_level;
- break;
- default:
- jlog_level = m_jfatal_level;
- break;
- }
- assert(format != nullptr);
- const std::unique_ptr<char[]> msg = format_str(format, ap);
- // pass msg to java callback handler
- jboolean attached_thread = JNI_FALSE;
- JNIEnv* env = getJniEnv(&attached_thread);
- assert(env != nullptr);
- jstring jmsg = env->NewStringUTF(msg.get());
- if (jmsg == nullptr) {
- // unable to construct string
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe(); // print out exception to stderr
- }
- releaseJniEnv(attached_thread);
- return;
- }
- if (env->ExceptionCheck()) {
- // exception thrown: OutOfMemoryError
- env->ExceptionDescribe(); // print out exception to stderr
- env->DeleteLocalRef(jmsg);
- releaseJniEnv(attached_thread);
- return;
- }
- env->CallVoidMethod(m_jcallback_obj, m_jLogMethodId, jlog_level, jmsg);
- if (env->ExceptionCheck()) {
- // exception thrown
- env->ExceptionDescribe(); // print out exception to stderr
- env->DeleteLocalRef(jmsg);
- releaseJniEnv(attached_thread);
- return;
- }
- env->DeleteLocalRef(jmsg);
- releaseJniEnv(attached_thread);
- }
- }
- std::unique_ptr<char[]> LoggerJniCallback::format_str(const char* format,
- va_list ap) const {
- va_list ap_copy;
- va_copy(ap_copy, ap);
- const size_t required =
- vsnprintf(nullptr, 0, format, ap_copy) + 1; // Extra space for '\0'
- va_end(ap_copy);
- std::unique_ptr<char[]> buf(new char[required]);
- va_copy(ap_copy, ap);
- vsnprintf(buf.get(), required, format, ap_copy);
- va_end(ap_copy);
- return buf;
- }
- LoggerJniCallback::~LoggerJniCallback() {
- jboolean attached_thread = JNI_FALSE;
- JNIEnv* env = getJniEnv(&attached_thread);
- assert(env != nullptr);
- if (m_jdebug_level != nullptr) {
- env->DeleteGlobalRef(m_jdebug_level);
- }
- if (m_jinfo_level != nullptr) {
- env->DeleteGlobalRef(m_jinfo_level);
- }
- if (m_jwarn_level != nullptr) {
- env->DeleteGlobalRef(m_jwarn_level);
- }
- if (m_jerror_level != nullptr) {
- env->DeleteGlobalRef(m_jerror_level);
- }
- if (m_jfatal_level != nullptr) {
- env->DeleteGlobalRef(m_jfatal_level);
- }
- if (m_jheader_level != nullptr) {
- env->DeleteGlobalRef(m_jheader_level);
- }
- releaseJniEnv(attached_thread);
- }
- } // namespace ROCKSDB_NAMESPACE
- /*
- * Class: org_rocksdb_Logger
- * Method: createNewLoggerOptions
- * Signature: (J)J
- */
- jlong Java_org_rocksdb_Logger_createNewLoggerOptions(JNIEnv* env, jobject jobj,
- jlong joptions) {
- auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
- new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));
- // set log level
- auto* options = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions);
- sptr_logger->get()->SetInfoLogLevel(options->info_log_level);
- return reinterpret_cast<jlong>(sptr_logger);
- }
- /*
- * Class: org_rocksdb_Logger
- * Method: createNewLoggerDbOptions
- * Signature: (J)J
- */
- jlong Java_org_rocksdb_Logger_createNewLoggerDbOptions(JNIEnv* env,
- jobject jobj,
- jlong jdb_options) {
- auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
- new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));
- // set log level
- auto* db_options =
- reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_options);
- sptr_logger->get()->SetInfoLogLevel(db_options->info_log_level);
- return reinterpret_cast<jlong>(sptr_logger);
- }
- /*
- * Class: org_rocksdb_Logger
- * Method: setInfoLogLevel
- * Signature: (JB)V
- */
- void Java_org_rocksdb_Logger_setInfoLogLevel(JNIEnv* /*env*/, jobject /*jobj*/,
- jlong jhandle, jbyte jlog_level) {
- auto* handle =
- reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
- jhandle);
- handle->get()->SetInfoLogLevel(
- static_cast<ROCKSDB_NAMESPACE::InfoLogLevel>(jlog_level));
- }
- /*
- * Class: org_rocksdb_Logger
- * Method: infoLogLevel
- * Signature: (J)B
- */
- jbyte Java_org_rocksdb_Logger_infoLogLevel(JNIEnv* /*env*/, jobject /*jobj*/,
- jlong jhandle) {
- auto* handle =
- reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
- jhandle);
- return static_cast<jbyte>(handle->get()->GetInfoLogLevel());
- }
- /*
- * Class: org_rocksdb_Logger
- * Method: disposeInternal
- * Signature: (J)V
- */
- void Java_org_rocksdb_Logger_disposeInternal(JNIEnv* /*env*/, jobject /*jobj*/,
- jlong jhandle) {
- auto* handle =
- reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
- jhandle);
- delete handle; // delete std::shared_ptr
- }
|