From 811ee2111287fda605e14d73bc747512316fac6e Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Fri, 29 Jul 2016 00:54:06 +0100 Subject: [PATCH] Bugfix to ensure that logging can be achieved from threads that are not known to the JVM (#1106) --- java/rocksjni/loggerjnicallback.cc | 51 ++++++++++++++++++++++++++---- java/rocksjni/loggerjnicallback.h | 6 ++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/java/rocksjni/loggerjnicallback.cc b/java/rocksjni/loggerjnicallback.cc index 1da873d2f..5040177e1 100644 --- a/java/rocksjni/loggerjnicallback.cc +++ b/java/rocksjni/loggerjnicallback.cc @@ -22,6 +22,30 @@ LoggerJniCallback::LoggerJniCallback( // across multiple method calls, so we create a global ref m_jLogger = env->NewGlobalRef(jlogger); m_jLogMethodId = LoggerJni::getLogMethodId(env); + + jobject jdebug_level = InfoLogLevelJni::DEBUG_LEVEL(env); + assert(jdebug_level != nullptr); + m_jdebug_level = env->NewGlobalRef(jdebug_level); + + jobject jinfo_level = InfoLogLevelJni::INFO_LEVEL(env); + assert(jinfo_level != nullptr); + m_jinfo_level = env->NewGlobalRef(jinfo_level); + + jobject jwarn_level = InfoLogLevelJni::WARN_LEVEL(env); + assert(jwarn_level != nullptr); + m_jwarn_level = env->NewGlobalRef(jwarn_level); + + jobject jerror_level = InfoLogLevelJni::ERROR_LEVEL(env); + assert(jerror_level != nullptr); + m_jerror_level = env->NewGlobalRef(jerror_level); + + jobject jfatal_level = InfoLogLevelJni::FATAL_LEVEL(env); + assert(jfatal_level != nullptr); + m_jfatal_level = env->NewGlobalRef(jfatal_level); + + jobject jheader_level = InfoLogLevelJni::HEADER_LEVEL(env); + assert(jheader_level != nullptr); + m_jheader_level = env->NewGlobalRef(jheader_level); } /** @@ -43,31 +67,36 @@ void LoggerJniCallback::Logv(const char* format, va_list ap) { void LoggerJniCallback::Logv(const InfoLogLevel log_level, const char* format, va_list ap) { if (GetInfoLogLevel() <= log_level) { - JNIEnv* env = getJniEnv(); // determine InfoLogLevel java enum instance jobject jlog_level; switch (log_level) { case rocksdb::InfoLogLevel::DEBUG_LEVEL: - jlog_level = InfoLogLevelJni::DEBUG_LEVEL(env); + jlog_level = m_jdebug_level; break; case rocksdb::InfoLogLevel::INFO_LEVEL: - jlog_level = InfoLogLevelJni::INFO_LEVEL(env); + jlog_level = m_jinfo_level; + break; + case rocksdb::InfoLogLevel::WARN_LEVEL: + jlog_level = m_jwarn_level; break; case rocksdb::InfoLogLevel::WARN_LEVEL: jlog_level = InfoLogLevelJni::WARN_LEVEL(env); break; case rocksdb::InfoLogLevel::ERROR_LEVEL: - jlog_level = InfoLogLevelJni::ERROR_LEVEL(env); + jlog_level = m_jerror_level; break; case rocksdb::InfoLogLevel::FATAL_LEVEL: - jlog_level = InfoLogLevelJni::FATAL_LEVEL(env); + jlog_level = m_jfatal_level; + break; + case rocksdb::InfoLogLevel::HEADER_LEVEL: + jlog_level = m_jheader_level; break; case rocksdb::InfoLogLevel::HEADER_LEVEL: jlog_level = InfoLogLevelJni::HEADER_LEVEL(env); break; default: - jlog_level = InfoLogLevelJni::FATAL_LEVEL(env); + jlog_level = m_jfatal_level; break; } @@ -104,6 +133,8 @@ void LoggerJniCallback::Logv(const InfoLogLevel log_level, assert(p < limit); *p++ = '\0'; + JNIEnv* env = getJniEnv(); + // pass java string to callback handler env->CallVoidMethod( m_jLogger, @@ -123,6 +154,14 @@ void LoggerJniCallback::Logv(const InfoLogLevel log_level, LoggerJniCallback::~LoggerJniCallback() { JNIEnv* env = getJniEnv(); env->DeleteGlobalRef(m_jLogger); + + env->DeleteGlobalRef(m_jdebug_level); + env->DeleteGlobalRef(m_jinfo_level); + env->DeleteGlobalRef(m_jwarn_level); + env->DeleteGlobalRef(m_jerror_level); + env->DeleteGlobalRef(m_jfatal_level); + env->DeleteGlobalRef(m_jheader_level); + m_jvm->DetachCurrentThread(); } diff --git a/java/rocksjni/loggerjnicallback.h b/java/rocksjni/loggerjnicallback.h index 2355a3985..9a7605d24 100644 --- a/java/rocksjni/loggerjnicallback.h +++ b/java/rocksjni/loggerjnicallback.h @@ -38,6 +38,12 @@ namespace rocksdb { JavaVM* m_jvm; jobject m_jLogger; jmethodID m_jLogMethodId; + jobject m_jdebug_level; + jobject m_jinfo_level; + jobject m_jwarn_level; + jobject m_jerror_level; + jobject m_jfatal_level; + jobject m_jheader_level; }; } // namespace rocksdb