rocksdb/java/rocksjni/event_listener_jnicallback.cc
Peter Dillinger cb5b851ff8 Add (& fix) some simple source code checks (#8821)
Summary:
* Don't hardcode namespace rocksdb (use ROCKSDB_NAMESPACE)
* Don't #include <rocksdb/...> (use double quotes)
* Support putting NOCOMMIT (any case) in source code that should not be
committed/pushed in current state.

These will be run with `make check` and in GitHub actions

Pull Request resolved: https://github.com/facebook/rocksdb/pull/8821

Test Plan: existing tests, manually try out new checks

Reviewed By: zhichao-cao

Differential Revision: D30791726

Pulled By: pdillinger

fbshipit-source-id: 399c883f312be24d9e55c58951d4013e18429d92
2021-09-07 21:19:27 -07:00

503 lines
17 KiB
C++

// 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::EventListener.
#include "rocksjni/event_listener_jnicallback.h"
#include "rocksjni/portal.h"
namespace ROCKSDB_NAMESPACE {
EventListenerJniCallback::EventListenerJniCallback(
JNIEnv* env, jobject jevent_listener,
const std::set<EnabledEventCallback>& enabled_event_callbacks)
: JniCallback(env, jevent_listener),
m_enabled_event_callbacks(enabled_event_callbacks) {
InitCallbackMethodId(
m_on_flush_completed_proxy_mid, EnabledEventCallback::ON_FLUSH_COMPLETED,
env, AbstractEventListenerJni::getOnFlushCompletedProxyMethodId);
InitCallbackMethodId(m_on_flush_begin_proxy_mid,
EnabledEventCallback::ON_FLUSH_BEGIN, env,
AbstractEventListenerJni::getOnFlushBeginProxyMethodId);
InitCallbackMethodId(m_on_table_file_deleted_mid,
EnabledEventCallback::ON_TABLE_FILE_DELETED, env,
AbstractEventListenerJni::getOnTableFileDeletedMethodId);
InitCallbackMethodId(
m_on_compaction_begin_proxy_mid,
EnabledEventCallback::ON_COMPACTION_BEGIN, env,
AbstractEventListenerJni::getOnCompactionBeginProxyMethodId);
InitCallbackMethodId(
m_on_compaction_completed_proxy_mid,
EnabledEventCallback::ON_COMPACTION_COMPLETED, env,
AbstractEventListenerJni::getOnCompactionCompletedProxyMethodId);
InitCallbackMethodId(m_on_table_file_created_mid,
EnabledEventCallback::ON_TABLE_FILE_CREATED, env,
AbstractEventListenerJni::getOnTableFileCreatedMethodId);
InitCallbackMethodId(
m_on_table_file_creation_started_mid,
EnabledEventCallback::ON_TABLE_FILE_CREATION_STARTED, env,
AbstractEventListenerJni::getOnTableFileCreationStartedMethodId);
InitCallbackMethodId(m_on_mem_table_sealed_mid,
EnabledEventCallback::ON_MEMTABLE_SEALED, env,
AbstractEventListenerJni::getOnMemTableSealedMethodId);
InitCallbackMethodId(
m_on_column_family_handle_deletion_started_mid,
EnabledEventCallback::ON_COLUMN_FAMILY_HANDLE_DELETION_STARTED, env,
AbstractEventListenerJni::getOnColumnFamilyHandleDeletionStartedMethodId);
InitCallbackMethodId(
m_on_external_file_ingested_proxy_mid,
EnabledEventCallback::ON_EXTERNAL_FILE_INGESTED, env,
AbstractEventListenerJni::getOnExternalFileIngestedProxyMethodId);
InitCallbackMethodId(
m_on_background_error_proxy_mid,
EnabledEventCallback::ON_BACKGROUND_ERROR, env,
AbstractEventListenerJni::getOnBackgroundErrorProxyMethodId);
InitCallbackMethodId(
m_on_stall_conditions_changed_mid,
EnabledEventCallback::ON_STALL_CONDITIONS_CHANGED, env,
AbstractEventListenerJni::getOnStallConditionsChangedMethodId);
InitCallbackMethodId(m_on_file_read_finish_mid,
EnabledEventCallback::ON_FILE_READ_FINISH, env,
AbstractEventListenerJni::getOnFileReadFinishMethodId);
InitCallbackMethodId(m_on_file_write_finish_mid,
EnabledEventCallback::ON_FILE_WRITE_FINISH, env,
AbstractEventListenerJni::getOnFileWriteFinishMethodId);
InitCallbackMethodId(m_on_file_flush_finish_mid,
EnabledEventCallback::ON_FILE_FLUSH_FINISH, env,
AbstractEventListenerJni::getOnFileFlushFinishMethodId);
InitCallbackMethodId(m_on_file_sync_finish_mid,
EnabledEventCallback::ON_FILE_SYNC_FINISH, env,
AbstractEventListenerJni::getOnFileSyncFinishMethodId);
InitCallbackMethodId(
m_on_file_range_sync_finish_mid,
EnabledEventCallback::ON_FILE_RANGE_SYNC_FINISH, env,
AbstractEventListenerJni::getOnFileRangeSyncFinishMethodId);
InitCallbackMethodId(
m_on_file_truncate_finish_mid,
EnabledEventCallback::ON_FILE_TRUNCATE_FINISH, env,
AbstractEventListenerJni::getOnFileTruncateFinishMethodId);
InitCallbackMethodId(m_on_file_close_finish_mid,
EnabledEventCallback::ON_FILE_CLOSE_FINISH, env,
AbstractEventListenerJni::getOnFileCloseFinishMethodId);
InitCallbackMethodId(
m_should_be_notified_on_file_io,
EnabledEventCallback::SHOULD_BE_NOTIFIED_ON_FILE_IO, env,
AbstractEventListenerJni::getShouldBeNotifiedOnFileIOMethodId);
InitCallbackMethodId(
m_on_error_recovery_begin_proxy_mid,
EnabledEventCallback::ON_ERROR_RECOVERY_BEGIN, env,
AbstractEventListenerJni::getOnErrorRecoveryBeginProxyMethodId);
InitCallbackMethodId(
m_on_error_recovery_completed_mid,
EnabledEventCallback::ON_ERROR_RECOVERY_COMPLETED, env,
AbstractEventListenerJni::getOnErrorRecoveryCompletedMethodId);
}
EventListenerJniCallback::~EventListenerJniCallback() {}
void EventListenerJniCallback::OnFlushCompleted(
DB* db, const FlushJobInfo& flush_job_info) {
if (m_on_flush_completed_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jflush_job_info = SetupCallbackInvocation<FlushJobInfo>(
env, attached_thread, flush_job_info,
FlushJobInfoJni::fromCppFlushJobInfo);
if (jflush_job_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_flush_completed_proxy_mid,
reinterpret_cast<jlong>(db), jflush_job_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jflush_job_info});
}
void EventListenerJniCallback::OnFlushBegin(
DB* db, const FlushJobInfo& flush_job_info) {
if (m_on_flush_begin_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jflush_job_info = SetupCallbackInvocation<FlushJobInfo>(
env, attached_thread, flush_job_info,
FlushJobInfoJni::fromCppFlushJobInfo);
if (jflush_job_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_flush_begin_proxy_mid,
reinterpret_cast<jlong>(db), jflush_job_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jflush_job_info});
}
void EventListenerJniCallback::OnTableFileDeleted(
const TableFileDeletionInfo& info) {
if (m_on_table_file_deleted_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jdeletion_info = SetupCallbackInvocation<TableFileDeletionInfo>(
env, attached_thread, info,
TableFileDeletionInfoJni::fromCppTableFileDeletionInfo);
if (jdeletion_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_table_file_deleted_mid,
jdeletion_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jdeletion_info});
}
void EventListenerJniCallback::OnCompactionBegin(DB* db,
const CompactionJobInfo& ci) {
if (m_on_compaction_begin_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jcompaction_job_info = SetupCallbackInvocation<CompactionJobInfo>(
env, attached_thread, ci, CompactionJobInfoJni::fromCppCompactionJobInfo);
if (jcompaction_job_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_compaction_begin_proxy_mid,
reinterpret_cast<jlong>(db), jcompaction_job_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jcompaction_job_info});
}
void EventListenerJniCallback::OnCompactionCompleted(
DB* db, const CompactionJobInfo& ci) {
if (m_on_compaction_completed_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jcompaction_job_info = SetupCallbackInvocation<CompactionJobInfo>(
env, attached_thread, ci, CompactionJobInfoJni::fromCppCompactionJobInfo);
if (jcompaction_job_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_compaction_completed_proxy_mid,
reinterpret_cast<jlong>(db), jcompaction_job_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jcompaction_job_info});
}
void EventListenerJniCallback::OnTableFileCreated(
const TableFileCreationInfo& info) {
if (m_on_table_file_created_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jfile_creation_info = SetupCallbackInvocation<TableFileCreationInfo>(
env, attached_thread, info,
TableFileCreationInfoJni::fromCppTableFileCreationInfo);
if (jfile_creation_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_table_file_created_mid,
jfile_creation_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jfile_creation_info});
}
void EventListenerJniCallback::OnTableFileCreationStarted(
const TableFileCreationBriefInfo& info) {
if (m_on_table_file_creation_started_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jcreation_brief_info =
SetupCallbackInvocation<TableFileCreationBriefInfo>(
env, attached_thread, info,
TableFileCreationBriefInfoJni::fromCppTableFileCreationBriefInfo);
if (jcreation_brief_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_table_file_creation_started_mid,
jcreation_brief_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jcreation_brief_info});
}
void EventListenerJniCallback::OnMemTableSealed(const MemTableInfo& info) {
if (m_on_mem_table_sealed_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jmem_table_info = SetupCallbackInvocation<MemTableInfo>(
env, attached_thread, info, MemTableInfoJni::fromCppMemTableInfo);
if (jmem_table_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_mem_table_sealed_mid,
jmem_table_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jmem_table_info});
}
void EventListenerJniCallback::OnColumnFamilyHandleDeletionStarted(
ColumnFamilyHandle* handle) {
if (m_on_column_family_handle_deletion_started_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jcf_handle = SetupCallbackInvocation<ColumnFamilyHandle>(
env, attached_thread, *handle,
ColumnFamilyHandleJni::fromCppColumnFamilyHandle);
if (jcf_handle != nullptr) {
env->CallVoidMethod(m_jcallback_obj,
m_on_column_family_handle_deletion_started_mid,
jcf_handle);
}
CleanupCallbackInvocation(env, attached_thread, {&jcf_handle});
}
void EventListenerJniCallback::OnExternalFileIngested(
DB* db, const ExternalFileIngestionInfo& info) {
if (m_on_external_file_ingested_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jingestion_info = SetupCallbackInvocation<ExternalFileIngestionInfo>(
env, attached_thread, info,
ExternalFileIngestionInfoJni::fromCppExternalFileIngestionInfo);
if (jingestion_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_external_file_ingested_proxy_mid,
reinterpret_cast<jlong>(db), jingestion_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jingestion_info});
}
void EventListenerJniCallback::OnBackgroundError(BackgroundErrorReason reason,
Status* bg_error) {
if (m_on_background_error_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jstatus = SetupCallbackInvocation<Status>(
env, attached_thread, *bg_error, StatusJni::construct);
if (jstatus != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_background_error_proxy_mid,
static_cast<jbyte>(reason), jstatus);
}
CleanupCallbackInvocation(env, attached_thread, {&jstatus});
}
void EventListenerJniCallback::OnStallConditionsChanged(
const WriteStallInfo& info) {
if (m_on_stall_conditions_changed_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jwrite_stall_info = SetupCallbackInvocation<WriteStallInfo>(
env, attached_thread, info, WriteStallInfoJni::fromCppWriteStallInfo);
if (jwrite_stall_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_stall_conditions_changed_mid,
jwrite_stall_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jwrite_stall_info});
}
void EventListenerJniCallback::OnFileReadFinish(const FileOperationInfo& info) {
OnFileOperation(m_on_file_read_finish_mid, info);
}
void EventListenerJniCallback::OnFileWriteFinish(
const FileOperationInfo& info) {
OnFileOperation(m_on_file_write_finish_mid, info);
}
void EventListenerJniCallback::OnFileFlushFinish(
const FileOperationInfo& info) {
OnFileOperation(m_on_file_flush_finish_mid, info);
}
void EventListenerJniCallback::OnFileSyncFinish(const FileOperationInfo& info) {
OnFileOperation(m_on_file_sync_finish_mid, info);
}
void EventListenerJniCallback::OnFileRangeSyncFinish(
const FileOperationInfo& info) {
OnFileOperation(m_on_file_range_sync_finish_mid, info);
}
void EventListenerJniCallback::OnFileTruncateFinish(
const FileOperationInfo& info) {
OnFileOperation(m_on_file_truncate_finish_mid, info);
}
void EventListenerJniCallback::OnFileCloseFinish(
const FileOperationInfo& info) {
OnFileOperation(m_on_file_close_finish_mid, info);
}
bool EventListenerJniCallback::ShouldBeNotifiedOnFileIO() {
if (m_should_be_notified_on_file_io == nullptr) {
return false;
}
jboolean attached_thread = JNI_FALSE;
JNIEnv* env = getJniEnv(&attached_thread);
assert(env != nullptr);
jboolean jshould_be_notified =
env->CallBooleanMethod(m_jcallback_obj, m_should_be_notified_on_file_io);
CleanupCallbackInvocation(env, attached_thread, {});
return static_cast<bool>(jshould_be_notified);
}
void EventListenerJniCallback::OnErrorRecoveryBegin(
BackgroundErrorReason reason, Status bg_error, bool* auto_recovery) {
if (m_on_error_recovery_begin_proxy_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jbg_error = SetupCallbackInvocation<Status>(
env, attached_thread, bg_error, StatusJni::construct);
if (jbg_error != nullptr) {
jboolean jauto_recovery = env->CallBooleanMethod(
m_jcallback_obj, m_on_error_recovery_begin_proxy_mid,
static_cast<jbyte>(reason), jbg_error);
*auto_recovery = jauto_recovery == JNI_TRUE;
}
CleanupCallbackInvocation(env, attached_thread, {&jbg_error});
}
void EventListenerJniCallback::OnErrorRecoveryCompleted(Status old_bg_error) {
if (m_on_error_recovery_completed_mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jold_bg_error = SetupCallbackInvocation<Status>(
env, attached_thread, old_bg_error, StatusJni::construct);
if (jold_bg_error != nullptr) {
env->CallVoidMethod(m_jcallback_obj, m_on_error_recovery_completed_mid,
jold_bg_error);
}
CleanupCallbackInvocation(env, attached_thread, {&jold_bg_error});
}
void EventListenerJniCallback::InitCallbackMethodId(
jmethodID& mid, EnabledEventCallback eec, JNIEnv* env,
jmethodID (*get_id)(JNIEnv* env)) {
if (m_enabled_event_callbacks.count(eec) == 1) {
mid = get_id(env);
} else {
mid = nullptr;
}
}
template <class T>
jobject EventListenerJniCallback::SetupCallbackInvocation(
JNIEnv*& env, jboolean& attached_thread, const T& cpp_obj,
jobject (*convert)(JNIEnv* env, const T* cpp_obj)) {
attached_thread = JNI_FALSE;
env = getJniEnv(&attached_thread);
assert(env != nullptr);
return convert(env, &cpp_obj);
}
void EventListenerJniCallback::CleanupCallbackInvocation(
JNIEnv* env, jboolean attached_thread,
std::initializer_list<jobject*> refs) {
for (auto* ref : refs) {
if (*ref == nullptr) continue;
env->DeleteLocalRef(*ref);
}
if (env->ExceptionCheck()) {
// exception thrown from CallVoidMethod
env->ExceptionDescribe(); // print out exception to stderr
}
releaseJniEnv(attached_thread);
}
void EventListenerJniCallback::OnFileOperation(const jmethodID& mid,
const FileOperationInfo& info) {
if (mid == nullptr) {
return;
}
JNIEnv* env;
jboolean attached_thread;
jobject jop_info = SetupCallbackInvocation<FileOperationInfo>(
env, attached_thread, info,
FileOperationInfoJni::fromCppFileOperationInfo);
if (jop_info != nullptr) {
env->CallVoidMethod(m_jcallback_obj, mid, jop_info);
}
CleanupCallbackInvocation(env, attached_thread, {&jop_info});
}
} // namespace ROCKSDB_NAMESPACE