fork of https://github.com/oxigraph/rocksdb and https://github.com/facebook/rocksdb for nextgraph and oxigraph
				
			
			
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							297 lines
						
					
					
						
							8.8 KiB
						
					
					
				
			
		
		
	
	
							297 lines
						
					
					
						
							8.8 KiB
						
					
					
				| // 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
 | |
| }
 | |
| 
 |