diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/rocksdb/java/rocksjni | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
81 files changed, 29418 insertions, 0 deletions
diff --git a/src/rocksdb/java/rocksjni.pom b/src/rocksdb/java/rocksjni.pom new file mode 100644 index 00000000..94f07551 --- /dev/null +++ b/src/rocksdb/java/rocksjni.pom @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <name>RocksDB JNI</name> + <url>http://rocksdb.org/</url> + <groupId>org.rocksdb</groupId> + <artifactId>rocksdbjni</artifactId> + <!-- Version will be automatically replaced --> + <version>-</version> + <description>RocksDB fat jar that contains .so files for linux32 and linux64, jnilib files + for Mac OSX, and a .dll for Windows x64. + </description> + <licenses> + <license> + <name>Apache License 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU General Public License, version 2</name> + <url>http://www.gnu.org/licenses/gpl-2.0.html</url> + <distribution>repo</distribution> + </license> + </licenses> + <scm> + <connection>scm:git:git://github.com/dropwizard/metrics.git</connection> + <developerConnection>scm:git:git@github.com:dropwizard/metrics.git</developerConnection> + <url>http://github.com/dropwizard/metrics/</url> + <tag>HEAD</tag> + </scm> + <developers> + <developer> + <name>Facebook</name> + <email>help@facebook.com</email> + <timezone>America/New_York</timezone> + <roles> + <role>architect</role> + </roles> + </developer> + </developers> + + <properties> + <project.build.source>1.7</project.build.source> + <project.build.target>1.7</project.build.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.2</version> + <configuration> + <source>${project.build.source}</source> + <target>${project.build.target}</target> + <encoding>${project.build.sourceEncoding}</encoding> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.18.1</version> + <configuration> + <argLine>${argLine} -ea -Xcheck:jni -Djava.library.path=${project.build.directory}</argLine> + <useManifestOnlyJar>false</useManifestOnlyJar> + <useSystemClassLoader>false</useSystemClassLoader> + <additionalClasspathElements> + <additionalClasspathElement>${project.build.directory}/*</additionalClasspathElement> + </additionalClasspathElements> + </configuration> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.2.201409121644</version> + <executions> + <execution> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>prepare-package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.gmaven</groupId> + <artifactId>groovy-maven-plugin</artifactId> + <version>2.0</version> + <executions> + <execution> + <phase>process-classes</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <defaults> + <name>Xenu</name> + </defaults> + <source> + String fileContents = new File(project.basedir.absolutePath + '/../include/rocksdb/version.h').getText('UTF-8') + matcher = (fileContents =~ /(?s).*ROCKSDB_MAJOR ([0-9]+).*?/) + String major_version = matcher.getAt(0).getAt(1) + matcher = (fileContents =~ /(?s).*ROCKSDB_MINOR ([0-9]+).*?/) + String minor_version = matcher.getAt(0).getAt(1) + matcher = (fileContents =~ /(?s).*ROCKSDB_PATCH ([0-9]+).*?/) + String patch_version = matcher.getAt(0).getAt(1) + String version = String.format('%s.%s.%s', major_version, minor_version, patch_version) + // Set version to be used in pom.properties + project.version = version + // Set version to be set as jar name + project.build.finalName = project.artifactId + "-" + version + </source> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>1.7.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.10.19</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/src/rocksdb/java/rocksjni/backupablejni.cc b/src/rocksdb/java/rocksjni/backupablejni.cc new file mode 100644 index 00000000..c5ac3037 --- /dev/null +++ b/src/rocksdb/java/rocksjni/backupablejni.cc @@ -0,0 +1,337 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::BackupEnginge and rocksdb::BackupableDBOptions methods +// from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> +#include <vector> + +#include "include/org_rocksdb_BackupableDBOptions.h" +#include "rocksdb/utilities/backupable_db.h" +#include "rocksjni/portal.h" + +/////////////////////////////////////////////////////////////////////////// +// BackupDBOptions + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: newBackupableDBOptions + * Signature: (Ljava/lang/String;)J + */ +jlong Java_org_rocksdb_BackupableDBOptions_newBackupableDBOptions( + JNIEnv* env, jclass /*jcls*/, jstring jpath) { + const char* cpath = env->GetStringUTFChars(jpath, nullptr); + if (cpath == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + auto* bopt = new rocksdb::BackupableDBOptions(cpath); + env->ReleaseStringUTFChars(jpath, cpath); + return reinterpret_cast<jlong>(bopt); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: backupDir + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_BackupableDBOptions_backupDir(JNIEnv* env, + jobject /*jopt*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return env->NewStringUTF(bopt->backup_dir.c_str()); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setBackupEnv + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setBackupEnv( + JNIEnv* /*env*/, jobject /*jopt*/, jlong jhandle, jlong jrocks_env_handle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jrocks_env_handle); + bopt->backup_env = rocks_env; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setShareTableFiles + * Signature: (JZ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setShareTableFiles(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jboolean flag) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->share_table_files = flag; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: shareTableFiles + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_BackupableDBOptions_shareTableFiles(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->share_table_files; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setInfoLog + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setInfoLog(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong /*jlogger_handle*/) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + auto* sptr_logger = + reinterpret_cast<std::shared_ptr<rocksdb::LoggerJniCallback>*>(jhandle); + bopt->info_log = sptr_logger->get(); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setSync + * Signature: (JZ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setSync(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jboolean flag) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->sync = flag; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: sync + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_BackupableDBOptions_sync(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->sync; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setDestroyOldData + * Signature: (JZ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setDestroyOldData(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jboolean flag) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->destroy_old_data = flag; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: destroyOldData + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_BackupableDBOptions_destroyOldData(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->destroy_old_data; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setBackupLogFiles + * Signature: (JZ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setBackupLogFiles(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jboolean flag) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->backup_log_files = flag; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: backupLogFiles + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_BackupableDBOptions_backupLogFiles(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->backup_log_files; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setBackupRateLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setBackupRateLimit( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jbackup_rate_limit) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->backup_rate_limit = jbackup_rate_limit; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: backupRateLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_BackupableDBOptions_backupRateLimit(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->backup_rate_limit; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setBackupRateLimiter + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setBackupRateLimiter( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jrate_limiter_handle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + auto* sptr_rate_limiter = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>( + jrate_limiter_handle); + bopt->backup_rate_limiter = *sptr_rate_limiter; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setRestoreRateLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setRestoreRateLimit( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jrestore_rate_limit) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->restore_rate_limit = jrestore_rate_limit; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: restoreRateLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_BackupableDBOptions_restoreRateLimit(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->restore_rate_limit; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setRestoreRateLimiter + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setRestoreRateLimiter( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jrate_limiter_handle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + auto* sptr_rate_limiter = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>( + jrate_limiter_handle); + bopt->restore_rate_limiter = *sptr_rate_limiter; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setShareFilesWithChecksum + * Signature: (JZ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setShareFilesWithChecksum( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean flag) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->share_files_with_checksum = flag; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: shareFilesWithChecksum + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_BackupableDBOptions_shareFilesWithChecksum( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return bopt->share_files_with_checksum; +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setMaxBackgroundOperations + * Signature: (JI)V + */ +void Java_org_rocksdb_BackupableDBOptions_setMaxBackgroundOperations( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jint max_background_operations) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->max_background_operations = static_cast<int>(max_background_operations); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: maxBackgroundOperations + * Signature: (J)I + */ +jint Java_org_rocksdb_BackupableDBOptions_maxBackgroundOperations( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return static_cast<jint>(bopt->max_background_operations); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: setCallbackTriggerIntervalSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_BackupableDBOptions_setCallbackTriggerIntervalSize( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jcallback_trigger_interval_size) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + bopt->callback_trigger_interval_size = + static_cast<uint64_t>(jcallback_trigger_interval_size); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: callbackTriggerIntervalSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_BackupableDBOptions_callbackTriggerIntervalSize( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + return static_cast<jlong>(bopt->callback_trigger_interval_size); +} + +/* + * Class: org_rocksdb_BackupableDBOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_BackupableDBOptions_disposeInternal(JNIEnv* /*env*/, + jobject /*jopt*/, + jlong jhandle) { + auto* bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle); + assert(bopt != nullptr); + delete bopt; +} diff --git a/src/rocksdb/java/rocksjni/backupenginejni.cc b/src/rocksdb/java/rocksjni/backupenginejni.cc new file mode 100644 index 00000000..e62b0b4f --- /dev/null +++ b/src/rocksdb/java/rocksjni/backupenginejni.cc @@ -0,0 +1,267 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::BackupEngine methods from the Java side. + +#include <jni.h> +#include <vector> + +#include "include/org_rocksdb_BackupEngine.h" +#include "rocksdb/utilities/backupable_db.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_BackupEngine + * Method: open + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_BackupEngine_open(JNIEnv* env, jclass /*jcls*/, + jlong env_handle, + jlong backupable_db_options_handle) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(env_handle); + auto* backupable_db_options = reinterpret_cast<rocksdb::BackupableDBOptions*>( + backupable_db_options_handle); + rocksdb::BackupEngine* backup_engine; + auto status = rocksdb::BackupEngine::Open(rocks_env, *backupable_db_options, + &backup_engine); + + if (status.ok()) { + return reinterpret_cast<jlong>(backup_engine); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + return 0; + } +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: createNewBackup + * Signature: (JJZ)V + */ +void Java_org_rocksdb_BackupEngine_createNewBackup( + JNIEnv* env, jobject /*jbe*/, jlong jbe_handle, jlong db_handle, + jboolean jflush_before_backup) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + auto status = backup_engine->CreateNewBackup( + db, static_cast<bool>(jflush_before_backup)); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: createNewBackupWithMetadata + * Signature: (JJLjava/lang/String;Z)V + */ +void Java_org_rocksdb_BackupEngine_createNewBackupWithMetadata( + JNIEnv* env, jobject /*jbe*/, jlong jbe_handle, jlong db_handle, + jstring japp_metadata, jboolean jflush_before_backup) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + + jboolean has_exception = JNI_FALSE; + std::string app_metadata = + rocksdb::JniUtil::copyStdString(env, japp_metadata, &has_exception); + if (has_exception == JNI_TRUE) { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, "Could not copy jstring to std::string"); + return; + } + + auto status = backup_engine->CreateNewBackupWithMetadata( + db, app_metadata, static_cast<bool>(jflush_before_backup)); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: getBackupInfo + * Signature: (J)Ljava/util/List; + */ +jobject Java_org_rocksdb_BackupEngine_getBackupInfo(JNIEnv* env, + jobject /*jbe*/, + jlong jbe_handle) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + std::vector<rocksdb::BackupInfo> backup_infos; + backup_engine->GetBackupInfo(&backup_infos); + return rocksdb::BackupInfoListJni::getBackupInfo(env, backup_infos); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: getCorruptedBackups + * Signature: (J)[I + */ +jintArray Java_org_rocksdb_BackupEngine_getCorruptedBackups(JNIEnv* env, + jobject /*jbe*/, + jlong jbe_handle) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + std::vector<rocksdb::BackupID> backup_ids; + backup_engine->GetCorruptedBackups(&backup_ids); + // store backupids in int array + std::vector<jint> int_backup_ids(backup_ids.begin(), backup_ids.end()); + + // Store ints in java array + // Its ok to loose precision here (64->32) + jsize ret_backup_ids_size = static_cast<jsize>(backup_ids.size()); + jintArray ret_backup_ids = env->NewIntArray(ret_backup_ids_size); + if (ret_backup_ids == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetIntArrayRegion(ret_backup_ids, 0, ret_backup_ids_size, + int_backup_ids.data()); + return ret_backup_ids; +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: garbageCollect + * Signature: (J)V + */ +void Java_org_rocksdb_BackupEngine_garbageCollect(JNIEnv* env, jobject /*jbe*/, + jlong jbe_handle) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + auto status = backup_engine->GarbageCollect(); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: purgeOldBackups + * Signature: (JI)V + */ +void Java_org_rocksdb_BackupEngine_purgeOldBackups(JNIEnv* env, jobject /*jbe*/, + jlong jbe_handle, + jint jnum_backups_to_keep) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + auto status = backup_engine->PurgeOldBackups( + static_cast<uint32_t>(jnum_backups_to_keep)); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: deleteBackup + * Signature: (JI)V + */ +void Java_org_rocksdb_BackupEngine_deleteBackup(JNIEnv* env, jobject /*jbe*/, + jlong jbe_handle, + jint jbackup_id) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + auto status = + backup_engine->DeleteBackup(static_cast<rocksdb::BackupID>(jbackup_id)); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: restoreDbFromBackup + * Signature: (JILjava/lang/String;Ljava/lang/String;J)V + */ +void Java_org_rocksdb_BackupEngine_restoreDbFromBackup( + JNIEnv* env, jobject /*jbe*/, jlong jbe_handle, jint jbackup_id, + jstring jdb_dir, jstring jwal_dir, jlong jrestore_options_handle) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + const char* db_dir = env->GetStringUTFChars(jdb_dir, nullptr); + if (db_dir == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + const char* wal_dir = env->GetStringUTFChars(jwal_dir, nullptr); + if (wal_dir == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_dir, db_dir); + return; + } + auto* restore_options = + reinterpret_cast<rocksdb::RestoreOptions*>(jrestore_options_handle); + auto status = backup_engine->RestoreDBFromBackup( + static_cast<rocksdb::BackupID>(jbackup_id), db_dir, wal_dir, + *restore_options); + + env->ReleaseStringUTFChars(jwal_dir, wal_dir); + env->ReleaseStringUTFChars(jdb_dir, db_dir); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: restoreDbFromLatestBackup + * Signature: (JLjava/lang/String;Ljava/lang/String;J)V + */ +void Java_org_rocksdb_BackupEngine_restoreDbFromLatestBackup( + JNIEnv* env, jobject /*jbe*/, jlong jbe_handle, jstring jdb_dir, + jstring jwal_dir, jlong jrestore_options_handle) { + auto* backup_engine = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + const char* db_dir = env->GetStringUTFChars(jdb_dir, nullptr); + if (db_dir == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + const char* wal_dir = env->GetStringUTFChars(jwal_dir, nullptr); + if (wal_dir == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_dir, db_dir); + return; + } + auto* restore_options = + reinterpret_cast<rocksdb::RestoreOptions*>(jrestore_options_handle); + auto status = backup_engine->RestoreDBFromLatestBackup(db_dir, wal_dir, + *restore_options); + + env->ReleaseStringUTFChars(jwal_dir, wal_dir); + env->ReleaseStringUTFChars(jdb_dir, db_dir); + + if (status.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); +} + +/* + * Class: org_rocksdb_BackupEngine + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_BackupEngine_disposeInternal(JNIEnv* /*env*/, + jobject /*jbe*/, + jlong jbe_handle) { + auto* be = reinterpret_cast<rocksdb::BackupEngine*>(jbe_handle); + assert(be != nullptr); + delete be; +} diff --git a/src/rocksdb/java/rocksjni/cassandra_compactionfilterjni.cc b/src/rocksdb/java/rocksjni/cassandra_compactionfilterjni.cc new file mode 100644 index 00000000..799e25e3 --- /dev/null +++ b/src/rocksdb/java/rocksjni/cassandra_compactionfilterjni.cc @@ -0,0 +1,23 @@ +// 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). + +#include <jni.h> + +#include "include/org_rocksdb_CassandraCompactionFilter.h" +#include "utilities/cassandra/cassandra_compaction_filter.h" + +/* + * Class: org_rocksdb_CassandraCompactionFilter + * Method: createNewCassandraCompactionFilter0 + * Signature: (ZI)J + */ +jlong Java_org_rocksdb_CassandraCompactionFilter_createNewCassandraCompactionFilter0( + JNIEnv* /*env*/, jclass /*jcls*/, jboolean purge_ttl_on_expiration, + jint gc_grace_period_in_seconds) { + auto* compaction_filter = new rocksdb::cassandra::CassandraCompactionFilter( + purge_ttl_on_expiration, gc_grace_period_in_seconds); + // set the native handle to our native compaction filter + return reinterpret_cast<jlong>(compaction_filter); +} diff --git a/src/rocksdb/java/rocksjni/cassandra_value_operator.cc b/src/rocksdb/java/rocksjni/cassandra_value_operator.cc new file mode 100644 index 00000000..73b3dcc6 --- /dev/null +++ b/src/rocksdb/java/rocksjni/cassandra_value_operator.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2017-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). + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory> +#include <string> + +#include "include/org_rocksdb_CassandraValueMergeOperator.h" +#include "rocksdb/db.h" +#include "rocksdb/memtablerep.h" +#include "rocksdb/merge_operator.h" +#include "rocksdb/options.h" +#include "rocksdb/slice_transform.h" +#include "rocksdb/statistics.h" +#include "rocksdb/table.h" +#include "rocksjni/portal.h" +#include "utilities/cassandra/merge_operator.h" + +/* + * Class: org_rocksdb_CassandraValueMergeOperator + * Method: newSharedCassandraValueMergeOperator + * Signature: (II)J + */ +jlong Java_org_rocksdb_CassandraValueMergeOperator_newSharedCassandraValueMergeOperator( + JNIEnv* /*env*/, jclass /*jclazz*/, jint gcGracePeriodInSeconds, + jint operands_limit) { + auto* op = new std::shared_ptr<rocksdb::MergeOperator>( + new rocksdb::cassandra::CassandraValueMergeOperator( + gcGracePeriodInSeconds, operands_limit)); + return reinterpret_cast<jlong>(op); +} + +/* + * Class: org_rocksdb_CassandraValueMergeOperator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CassandraValueMergeOperator_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* op = + reinterpret_cast<std::shared_ptr<rocksdb::MergeOperator>*>(jhandle); + delete op; +} diff --git a/src/rocksdb/java/rocksjni/checkpoint.cc b/src/rocksdb/java/rocksjni/checkpoint.cc new file mode 100644 index 00000000..f67f0162 --- /dev/null +++ b/src/rocksdb/java/rocksjni/checkpoint.cc @@ -0,0 +1,67 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::Checkpoint methods from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include "include/org_rocksdb_Checkpoint.h" +#include "rocksdb/db.h" +#include "rocksdb/utilities/checkpoint.h" +#include "rocksjni/portal.h" +/* + * Class: org_rocksdb_Checkpoint + * Method: newCheckpoint + * Signature: (J)J + */ +jlong Java_org_rocksdb_Checkpoint_newCheckpoint(JNIEnv* /*env*/, + jclass /*jclazz*/, + jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::Checkpoint* checkpoint; + rocksdb::Checkpoint::Create(db, &checkpoint); + return reinterpret_cast<jlong>(checkpoint); +} + +/* + * Class: org_rocksdb_Checkpoint + * Method: dispose + * Signature: (J)V + */ +void Java_org_rocksdb_Checkpoint_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* checkpoint = reinterpret_cast<rocksdb::Checkpoint*>(jhandle); + assert(checkpoint != nullptr); + delete checkpoint; +} + +/* + * Class: org_rocksdb_Checkpoint + * Method: createCheckpoint + * Signature: (JLjava/lang/String;)V + */ +void Java_org_rocksdb_Checkpoint_createCheckpoint(JNIEnv* env, jobject /*jobj*/, + jlong jcheckpoint_handle, + jstring jcheckpoint_path) { + const char* checkpoint_path = env->GetStringUTFChars(jcheckpoint_path, 0); + if (checkpoint_path == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* checkpoint = reinterpret_cast<rocksdb::Checkpoint*>(jcheckpoint_handle); + rocksdb::Status s = checkpoint->CreateCheckpoint(checkpoint_path); + + env->ReleaseStringUTFChars(jcheckpoint_path, checkpoint_path); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} diff --git a/src/rocksdb/java/rocksjni/clock_cache.cc b/src/rocksdb/java/rocksjni/clock_cache.cc new file mode 100644 index 00000000..b1cf0855 --- /dev/null +++ b/src/rocksdb/java/rocksjni/clock_cache.cc @@ -0,0 +1,40 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::ClockCache. + +#include <jni.h> + +#include "cache/clock_cache.h" +#include "include/org_rocksdb_ClockCache.h" + +/* + * Class: org_rocksdb_ClockCache + * Method: newClockCache + * Signature: (JIZ)J + */ +jlong Java_org_rocksdb_ClockCache_newClockCache( + JNIEnv* /*env*/, jclass /*jcls*/, jlong jcapacity, jint jnum_shard_bits, + jboolean jstrict_capacity_limit) { + auto* sptr_clock_cache = + new std::shared_ptr<rocksdb::Cache>(rocksdb::NewClockCache( + static_cast<size_t>(jcapacity), static_cast<int>(jnum_shard_bits), + static_cast<bool>(jstrict_capacity_limit))); + return reinterpret_cast<jlong>(sptr_clock_cache); +} + +/* + * Class: org_rocksdb_ClockCache + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_ClockCache_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_clock_cache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(jhandle); + delete sptr_clock_cache; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/columnfamilyhandle.cc b/src/rocksdb/java/rocksjni/columnfamilyhandle.cc new file mode 100644 index 00000000..ed280573 --- /dev/null +++ b/src/rocksdb/java/rocksjni/columnfamilyhandle.cc @@ -0,0 +1,72 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::ColumnFamilyHandle. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> + +#include "include/org_rocksdb_ColumnFamilyHandle.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_ColumnFamilyHandle + * Method: getName + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_ColumnFamilyHandle_getName(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle) { + auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle); + std::string cf_name = cfh->GetName(); + return rocksdb::JniUtil::copyBytes(env, cf_name); +} + +/* + * Class: org_rocksdb_ColumnFamilyHandle + * Method: getID + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyHandle_getID(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle); + const int32_t id = cfh->GetID(); + return static_cast<jint>(id); +} + +/* + * Class: org_rocksdb_ColumnFamilyHandle + * Method: getDescriptor + * Signature: (J)Lorg/rocksdb/ColumnFamilyDescriptor; + */ +jobject Java_org_rocksdb_ColumnFamilyHandle_getDescriptor(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle) { + auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle); + rocksdb::ColumnFamilyDescriptor desc; + rocksdb::Status s = cfh->GetDescriptor(&desc); + if (s.ok()) { + return rocksdb::ColumnFamilyDescriptorJni::construct(env, &desc); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } +} + +/* + * Class: org_rocksdb_ColumnFamilyHandle + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_ColumnFamilyHandle_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle); + assert(cfh != nullptr); + delete cfh; +} diff --git a/src/rocksdb/java/rocksjni/compact_range_options.cc b/src/rocksdb/java/rocksjni/compact_range_options.cc new file mode 100644 index 00000000..cc9ac859 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compact_range_options.cc @@ -0,0 +1,196 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactRangeOptions. + +#include <jni.h> + +#include "include/org_rocksdb_CompactRangeOptions.h" +#include "rocksdb/options.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: newCompactRangeOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactRangeOptions_newCompactRangeOptions( + JNIEnv* /*env*/, jclass /*jclazz*/) { + auto* options = new rocksdb::CompactRangeOptions(); + return reinterpret_cast<jlong>(options); +} + + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: exclusiveManualCompaction + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactRangeOptions_exclusiveManualCompaction( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jboolean>(options->exclusive_manual_compaction); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setExclusiveManualCompaction + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompactRangeOptions_setExclusiveManualCompaction( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean exclusive_manual_compaction) { + auto* options = + reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->exclusive_manual_compaction = static_cast<bool>(exclusive_manual_compaction); +} + + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: bottommostLevelCompaction + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactRangeOptions_bottommostLevelCompaction( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return rocksdb::BottommostLevelCompactionJni::toJavaBottommostLevelCompaction( + options->bottommost_level_compaction); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setBottommostLevelCompaction + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactRangeOptions_setBottommostLevelCompaction( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jint bottommost_level_compaction) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->bottommost_level_compaction = + rocksdb::BottommostLevelCompactionJni::toCppBottommostLevelCompaction(bottommost_level_compaction); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: changeLevel + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactRangeOptions_changeLevel + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jboolean>(options->change_level); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setChangeLevel + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompactRangeOptions_setChangeLevel + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean change_level) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->change_level = static_cast<bool>(change_level); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: targetLevel + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactRangeOptions_targetLevel + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jint>(options->target_level); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setTargetLevel + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactRangeOptions_setTargetLevel + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jint target_level) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->target_level = static_cast<int>(target_level); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: targetPathId + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactRangeOptions_targetPathId + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jint>(options->target_path_id); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setTargetPathId + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactRangeOptions_setTargetPathId + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jint target_path_id) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->target_path_id = static_cast<uint32_t>(target_path_id); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: allowWriteStall + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactRangeOptions_allowWriteStall + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jboolean>(options->allow_write_stall); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setAllowWriteStall + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompactRangeOptions_setAllowWriteStall + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean allow_write_stall) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->allow_write_stall = static_cast<bool>(allow_write_stall); +} + + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: maxSubcompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactRangeOptions_maxSubcompactions + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + return static_cast<jint>(options->max_subcompactions); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: setMaxSubcompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactRangeOptions_setMaxSubcompactions + (JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jint max_subcompactions) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + options->max_subcompactions = static_cast<uint32_t>(max_subcompactions); +} + +/* + * Class: org_rocksdb_CompactRangeOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactRangeOptions_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::CompactRangeOptions*>(jhandle); + delete options; +} diff --git a/src/rocksdb/java/rocksjni/compaction_filter.cc b/src/rocksdb/java/rocksjni/compaction_filter.cc new file mode 100644 index 00000000..263bae05 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_filter.cc @@ -0,0 +1,28 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionFilter. + +#include <jni.h> + +#include "include/org_rocksdb_AbstractCompactionFilter.h" +#include "rocksdb/compaction_filter.h" + +// <editor-fold desc="org.rocksdb.AbstractCompactionFilter"> + +/* + * Class: org_rocksdb_AbstractCompactionFilter + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_AbstractCompactionFilter_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + auto* cf = reinterpret_cast<rocksdb::CompactionFilter*>(handle); + assert(cf != nullptr); + delete cf; +} +// </editor-fold> diff --git a/src/rocksdb/java/rocksjni/compaction_filter_factory.cc b/src/rocksdb/java/rocksjni/compaction_filter_factory.cc new file mode 100644 index 00000000..2ef0a774 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_filter_factory.cc @@ -0,0 +1,38 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionFilterFactory. + +#include <jni.h> +#include <memory> + +#include "include/org_rocksdb_AbstractCompactionFilterFactory.h" +#include "rocksjni/compaction_filter_factory_jnicallback.h" + +/* + * Class: org_rocksdb_AbstractCompactionFilterFactory + * Method: createNewCompactionFilterFactory0 + * Signature: ()J + */ +jlong Java_org_rocksdb_AbstractCompactionFilterFactory_createNewCompactionFilterFactory0( + JNIEnv* env, jobject jobj) { + auto* cff = new rocksdb::CompactionFilterFactoryJniCallback(env, jobj); + auto* ptr_sptr_cff = + new std::shared_ptr<rocksdb::CompactionFilterFactoryJniCallback>(cff); + return reinterpret_cast<jlong>(ptr_sptr_cff); +} + +/* + * Class: org_rocksdb_AbstractCompactionFilterFactory + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_AbstractCompactionFilterFactory_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* ptr_sptr_cff = reinterpret_cast< + std::shared_ptr<rocksdb::CompactionFilterFactoryJniCallback>*>(jhandle); + delete ptr_sptr_cff; +} diff --git a/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.cc b/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.cc new file mode 100644 index 00000000..c727a3e0 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.cc @@ -0,0 +1,76 @@ +// 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::CompactionFilterFactory. + +#include "rocksjni/compaction_filter_factory_jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +CompactionFilterFactoryJniCallback::CompactionFilterFactoryJniCallback( + JNIEnv* env, jobject jcompaction_filter_factory) + : JniCallback(env, jcompaction_filter_factory) { + + // Note: The name of a CompactionFilterFactory will not change during + // it's lifetime, so we cache it in a global var + jmethodID jname_method_id = + AbstractCompactionFilterFactoryJni::getNameMethodId(env); + if(jname_method_id == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + jstring jname = + (jstring)env->CallObjectMethod(m_jcallback_obj, jname_method_id); + if(env->ExceptionCheck()) { + // exception thrown + return; + } + jboolean has_exception = JNI_FALSE; + m_name = JniUtil::copyString(env, jname, &has_exception); // also releases jname + if (has_exception == JNI_TRUE) { + // exception thrown + return; + } + + m_jcreate_compaction_filter_methodid = + AbstractCompactionFilterFactoryJni::getCreateCompactionFilterMethodId(env); + if(m_jcreate_compaction_filter_methodid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } +} + +const char* CompactionFilterFactoryJniCallback::Name() const { + return m_name.get(); +} + +std::unique_ptr<CompactionFilter> CompactionFilterFactoryJniCallback::CreateCompactionFilter( + const CompactionFilter::Context& context) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + jlong addr_compaction_filter = env->CallLongMethod(m_jcallback_obj, + m_jcreate_compaction_filter_methodid, + static_cast<jboolean>(context.is_full_compaction), + static_cast<jboolean>(context.is_manual_compaction)); + + if(env->ExceptionCheck()) { + // exception thrown from CallLongMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return nullptr; + } + + auto* cff = reinterpret_cast<CompactionFilter*>(addr_compaction_filter); + + releaseJniEnv(attached_thread); + + return std::unique_ptr<CompactionFilter>(cff); +} + +} // namespace rocksdb diff --git a/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.h b/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.h new file mode 100644 index 00000000..10802edf --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_filter_factory_jnicallback.h @@ -0,0 +1,35 @@ +// 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::CompactionFilterFactory. + +#ifndef JAVA_ROCKSJNI_COMPACTION_FILTER_FACTORY_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_COMPACTION_FILTER_FACTORY_JNICALLBACK_H_ + +#include <jni.h> +#include <memory> + +#include "rocksdb/compaction_filter.h" +#include "rocksjni/jnicallback.h" + +namespace rocksdb { + +class CompactionFilterFactoryJniCallback : public JniCallback, public CompactionFilterFactory { + public: + CompactionFilterFactoryJniCallback( + JNIEnv* env, jobject jcompaction_filter_factory); + virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter( + const CompactionFilter::Context& context); + virtual const char* Name() const; + + private: + std::unique_ptr<const char[]> m_name; + jmethodID m_jcreate_compaction_filter_methodid; +}; + +} //namespace rocksdb + +#endif // JAVA_ROCKSJNI_COMPACTION_FILTER_FACTORY_JNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/compaction_job_info.cc b/src/rocksdb/java/rocksjni/compaction_job_info.cc new file mode 100644 index 00000000..6af6efcb --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_job_info.cc @@ -0,0 +1,222 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionJobInfo. + +#include <jni.h> + +#include "include/org_rocksdb_CompactionJobInfo.h" +#include "rocksdb/listener.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: newCompactionJobInfo + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactionJobInfo_newCompactionJobInfo( + JNIEnv*, jclass) { + auto* compact_job_info = new rocksdb::CompactionJobInfo(); + return reinterpret_cast<jlong>(compact_job_info); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionJobInfo_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + delete compact_job_info; +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: columnFamilyName + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_CompactionJobInfo_columnFamilyName( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::JniUtil::copyBytes( + env, compact_job_info->cf_name); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: status + * Signature: (J)Lorg/rocksdb/Status; + */ +jobject Java_org_rocksdb_CompactionJobInfo_status( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::StatusJni::construct( + env, compact_job_info->status); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: threadId + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobInfo_threadId( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return static_cast<jlong>(compact_job_info->thread_id); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: jobId + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionJobInfo_jobId( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return static_cast<jint>(compact_job_info->job_id); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: baseInputLevel + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionJobInfo_baseInputLevel( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return static_cast<jint>(compact_job_info->base_input_level); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: outputLevel + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionJobInfo_outputLevel( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return static_cast<jint>(compact_job_info->output_level); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: inputFiles + * Signature: (J)[Ljava/lang/String; + */ +jobjectArray Java_org_rocksdb_CompactionJobInfo_inputFiles( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::JniUtil::toJavaStrings( + env, &compact_job_info->input_files); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: outputFiles + * Signature: (J)[Ljava/lang/String; + */ +jobjectArray Java_org_rocksdb_CompactionJobInfo_outputFiles( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::JniUtil::toJavaStrings( + env, &compact_job_info->output_files); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: tableProperties + * Signature: (J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_CompactionJobInfo_tableProperties( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + auto* map = &compact_job_info->table_properties; + + jobject jhash_map = rocksdb::HashMapJni::construct( + env, static_cast<uint32_t>(map->size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, std::shared_ptr<const rocksdb::TableProperties>, jobject, jobject> fn_map_kv = + [env](const std::pair<const std::string, std::shared_ptr<const rocksdb::TableProperties>>& kv) { + jstring jkey = rocksdb::JniUtil::toJavaString(env, &(kv.first), false); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jobject jtable_properties = rocksdb::TablePropertiesJni::fromCppTableProperties( + env, *(kv.second.get())); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>( + new std::pair<jobject, jobject>(static_cast<jobject>(jkey), jtable_properties)); + }; + + if (!rocksdb::HashMapJni::putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: compactionReason + * Signature: (J)B + */ +jbyte Java_org_rocksdb_CompactionJobInfo_compactionReason( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::CompactionReasonJni::toJavaCompactionReason( + compact_job_info->compaction_reason); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: compression + * Signature: (J)B + */ +jbyte Java_org_rocksdb_CompactionJobInfo_compression( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType( + compact_job_info->compression); +} + +/* + * Class: org_rocksdb_CompactionJobInfo + * Method: stats + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobInfo_stats( + JNIEnv *, jclass, jlong jhandle) { + auto* compact_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jhandle); + auto* stats = new rocksdb::CompactionJobStats(); + stats->Add(compact_job_info->stats); + return reinterpret_cast<jlong>(stats); +} diff --git a/src/rocksdb/java/rocksjni/compaction_job_stats.cc b/src/rocksdb/java/rocksjni/compaction_job_stats.cc new file mode 100644 index 00000000..7d13dd12 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_job_stats.cc @@ -0,0 +1,361 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionJobStats. + +#include <jni.h> + +#include "include/org_rocksdb_CompactionJobStats.h" +#include "rocksdb/compaction_job_stats.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: newCompactionJobStats + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactionJobStats_newCompactionJobStats( + JNIEnv*, jclass) { + auto* compact_job_stats = new rocksdb::CompactionJobStats(); + return reinterpret_cast<jlong>(compact_job_stats); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionJobStats_disposeInternal( + JNIEnv *, jobject, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + delete compact_job_stats; +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: reset + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionJobStats_reset( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + compact_job_stats->Reset(); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: add + * Signature: (JJ)V + */ +void Java_org_rocksdb_CompactionJobStats_add( + JNIEnv*, jclass, jlong jhandle, jlong jother_handle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + auto* other_compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jother_handle); + compact_job_stats->Add(*other_compact_job_stats); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: elapsedMicros + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_elapsedMicros( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>(compact_job_stats->elapsed_micros); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numInputRecords + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numInputRecords( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>(compact_job_stats->num_input_records); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numInputFiles + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numInputFiles( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>(compact_job_stats->num_input_files); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numInputFilesAtOutputLevel + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numInputFilesAtOutputLevel( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_input_files_at_output_level); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numOutputRecords + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numOutputRecords( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_output_records); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numOutputFiles + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numOutputFiles( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_output_files); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: isManualCompaction + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactionJobStats_isManualCompaction( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + if (compact_job_stats->is_manual_compaction) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: totalInputBytes + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_totalInputBytes( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->total_input_bytes); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: totalOutputBytes + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_totalOutputBytes( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->total_output_bytes); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numRecordsReplaced + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numRecordsReplaced( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_records_replaced); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: totalInputRawKeyBytes + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_totalInputRawKeyBytes( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->total_input_raw_key_bytes); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: totalInputRawValueBytes + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_totalInputRawValueBytes( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->total_input_raw_value_bytes); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numInputDeletionRecords + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numInputDeletionRecords( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_input_deletion_records); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numExpiredDeletionRecords + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numExpiredDeletionRecords( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_expired_deletion_records); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numCorruptKeys + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numCorruptKeys( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_corrupt_keys); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: fileWriteNanos + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_fileWriteNanos( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->file_write_nanos); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: fileRangeSyncNanos + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_fileRangeSyncNanos( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->file_range_sync_nanos); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: fileFsyncNanos + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_fileFsyncNanos( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->file_fsync_nanos); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: filePrepareWriteNanos + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_filePrepareWriteNanos( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->file_prepare_write_nanos); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: smallestOutputKeyPrefix + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_CompactionJobStats_smallestOutputKeyPrefix( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return rocksdb::JniUtil::copyBytes(env, + compact_job_stats->smallest_output_key_prefix); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: largestOutputKeyPrefix + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_CompactionJobStats_largestOutputKeyPrefix( + JNIEnv* env, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return rocksdb::JniUtil::copyBytes(env, + compact_job_stats->largest_output_key_prefix); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numSingleDelFallthru + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numSingleDelFallthru( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_single_del_fallthru); +} + +/* + * Class: org_rocksdb_CompactionJobStats + * Method: numSingleDelMismatch + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionJobStats_numSingleDelMismatch( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_job_stats = + reinterpret_cast<rocksdb::CompactionJobStats*>(jhandle); + return static_cast<jlong>( + compact_job_stats->num_single_del_mismatch); +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/compaction_options.cc b/src/rocksdb/java/rocksjni/compaction_options.cc new file mode 100644 index 00000000..6aaabea7 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_options.cc @@ -0,0 +1,116 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionOptions. + +#include <jni.h> + +#include "include/org_rocksdb_CompactionOptions.h" +#include "rocksdb/options.h" +#include "rocksjni/portal.h" + + +/* + * Class: org_rocksdb_CompactionOptions + * Method: newCompactionOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactionOptions_newCompactionOptions( + JNIEnv*, jclass) { + auto* compact_opts = new rocksdb::CompactionOptions(); + return reinterpret_cast<jlong>(compact_opts); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionOptions_disposeInternal( + JNIEnv *, jobject, jlong jhandle) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + delete compact_opts; +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: compression + * Signature: (J)B + */ +jbyte Java_org_rocksdb_CompactionOptions_compression( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType( + compact_opts->compression); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: setCompression + * Signature: (JB)V + */ +void Java_org_rocksdb_CompactionOptions_setCompression( + JNIEnv*, jclass, jlong jhandle, jbyte jcompression_type_value) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + compact_opts->compression = + rocksdb::CompressionTypeJni::toCppCompressionType( + jcompression_type_value); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: outputFileSizeLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionOptions_outputFileSizeLimit( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + return static_cast<jlong>( + compact_opts->output_file_size_limit); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: setOutputFileSizeLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_CompactionOptions_setOutputFileSizeLimit( + JNIEnv*, jclass, jlong jhandle, jlong joutput_file_size_limit) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + compact_opts->output_file_size_limit = + static_cast<uint64_t>(joutput_file_size_limit); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: maxSubcompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptions_maxSubcompactions( + JNIEnv*, jclass, jlong jhandle) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + return static_cast<jint>( + compact_opts->max_subcompactions); +} + +/* + * Class: org_rocksdb_CompactionOptions + * Method: setMaxSubcompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptions_setMaxSubcompactions( + JNIEnv*, jclass, jlong jhandle, jint jmax_subcompactions) { + auto* compact_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jhandle); + compact_opts->max_subcompactions = + static_cast<uint32_t>(jmax_subcompactions); +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/compaction_options_fifo.cc b/src/rocksdb/java/rocksjni/compaction_options_fifo.cc new file mode 100644 index 00000000..b7c445fd --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_options_fifo.cc @@ -0,0 +1,77 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionOptionsFIFO. + +#include <jni.h> + +#include "include/org_rocksdb_CompactionOptionsFIFO.h" +#include "rocksdb/advanced_options.h" + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: newCompactionOptionsFIFO + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactionOptionsFIFO_newCompactionOptionsFIFO( + JNIEnv*, jclass) { + const auto* opt = new rocksdb::CompactionOptionsFIFO(); + return reinterpret_cast<jlong>(opt); +} + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: setMaxTableFilesSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_CompactionOptionsFIFO_setMaxTableFilesSize( + JNIEnv*, jobject, jlong jhandle, jlong jmax_table_files_size) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>(jhandle); + opt->max_table_files_size = static_cast<uint64_t>(jmax_table_files_size); +} + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: maxTableFilesSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_CompactionOptionsFIFO_maxTableFilesSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>(jhandle); + return static_cast<jlong>(opt->max_table_files_size); +} + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: setAllowCompaction + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompactionOptionsFIFO_setAllowCompaction( + JNIEnv*, jobject, jlong jhandle, jboolean allow_compaction) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>(jhandle); + opt->allow_compaction = static_cast<bool>(allow_compaction); +} + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: allowCompaction + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactionOptionsFIFO_allowCompaction( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>(jhandle); + return static_cast<jboolean>(opt->allow_compaction); +} + +/* + * Class: org_rocksdb_CompactionOptionsFIFO + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionOptionsFIFO_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + delete reinterpret_cast<rocksdb::CompactionOptionsFIFO*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/compaction_options_universal.cc b/src/rocksdb/java/rocksjni/compaction_options_universal.cc new file mode 100644 index 00000000..7ca51988 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compaction_options_universal.cc @@ -0,0 +1,193 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionOptionsUniversal. + +#include <jni.h> + +#include "include/org_rocksdb_CompactionOptionsUniversal.h" +#include "rocksdb/advanced_options.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: newCompactionOptionsUniversal + * Signature: ()J + */ +jlong Java_org_rocksdb_CompactionOptionsUniversal_newCompactionOptionsUniversal( + JNIEnv*, jclass) { + const auto* opt = new rocksdb::CompactionOptionsUniversal(); + return reinterpret_cast<jlong>(opt); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setSizeRatio + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setSizeRatio( + JNIEnv*, jobject, jlong jhandle, jint jsize_ratio) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->size_ratio = static_cast<unsigned int>(jsize_ratio); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: sizeRatio + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptionsUniversal_sizeRatio( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return static_cast<jint>(opt->size_ratio); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setMinMergeWidth + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setMinMergeWidth( + JNIEnv*, jobject, jlong jhandle, jint jmin_merge_width) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->min_merge_width = static_cast<unsigned int>(jmin_merge_width); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: minMergeWidth + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptionsUniversal_minMergeWidth( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return static_cast<jint>(opt->min_merge_width); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setMaxMergeWidth + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setMaxMergeWidth( + JNIEnv*, jobject, jlong jhandle, jint jmax_merge_width) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->max_merge_width = static_cast<unsigned int>(jmax_merge_width); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: maxMergeWidth + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptionsUniversal_maxMergeWidth( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return static_cast<jint>(opt->max_merge_width); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setMaxSizeAmplificationPercent + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setMaxSizeAmplificationPercent( + JNIEnv*, jobject, jlong jhandle, jint jmax_size_amplification_percent) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->max_size_amplification_percent = + static_cast<unsigned int>(jmax_size_amplification_percent); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: maxSizeAmplificationPercent + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptionsUniversal_maxSizeAmplificationPercent( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return static_cast<jint>(opt->max_size_amplification_percent); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setCompressionSizePercent + * Signature: (JI)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setCompressionSizePercent( + JNIEnv*, jobject, jlong jhandle, + jint jcompression_size_percent) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->compression_size_percent = + static_cast<unsigned int>(jcompression_size_percent); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: compressionSizePercent + * Signature: (J)I + */ +jint Java_org_rocksdb_CompactionOptionsUniversal_compressionSizePercent( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return static_cast<jint>(opt->compression_size_percent); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setStopStyle + * Signature: (JB)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setStopStyle( + JNIEnv*, jobject, jlong jhandle, jbyte jstop_style_value) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->stop_style = rocksdb::CompactionStopStyleJni::toCppCompactionStopStyle( + jstop_style_value); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: stopStyle + * Signature: (J)B + */ +jbyte Java_org_rocksdb_CompactionOptionsUniversal_stopStyle( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return rocksdb::CompactionStopStyleJni::toJavaCompactionStopStyle( + opt->stop_style); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: setAllowTrivialMove + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_setAllowTrivialMove( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_trivial_move) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + opt->allow_trivial_move = static_cast<bool>(jallow_trivial_move); +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: allowTrivialMove + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompactionOptionsUniversal_allowTrivialMove( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); + return opt->allow_trivial_move; +} + +/* + * Class: org_rocksdb_CompactionOptionsUniversal + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompactionOptionsUniversal_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + delete reinterpret_cast<rocksdb::CompactionOptionsUniversal*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/comparator.cc b/src/rocksdb/java/rocksjni/comparator.cc new file mode 100644 index 00000000..13f8feb6 --- /dev/null +++ b/src/rocksdb/java/rocksjni/comparator.cc @@ -0,0 +1,63 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::Comparator. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <functional> +#include <string> + +#include "include/org_rocksdb_Comparator.h" +#include "include/org_rocksdb_DirectComparator.h" +#include "include/org_rocksdb_NativeComparatorWrapper.h" +#include "rocksjni/comparatorjnicallback.h" +#include "rocksjni/portal.h" + +// <editor-fold desc="org.rocksdb.Comparator> + +/* + * Class: org_rocksdb_Comparator + * Method: createNewComparator0 + * Signature: ()J + */ +jlong Java_org_rocksdb_Comparator_createNewComparator0(JNIEnv* env, + jobject jobj, + jlong copt_handle) { + auto* copt = + reinterpret_cast<rocksdb::ComparatorJniCallbackOptions*>(copt_handle); + auto* c = new rocksdb::ComparatorJniCallback(env, jobj, copt); + return reinterpret_cast<jlong>(c); +} +// </editor-fold> + +// <editor-fold desc="org.rocksdb.DirectComparator> + +/* + * Class: org_rocksdb_DirectComparator + * Method: createNewDirectComparator0 + * Signature: ()J + */ +jlong Java_org_rocksdb_DirectComparator_createNewDirectComparator0( + JNIEnv* env, jobject jobj, jlong copt_handle) { + auto* copt = + reinterpret_cast<rocksdb::ComparatorJniCallbackOptions*>(copt_handle); + auto* c = new rocksdb::DirectComparatorJniCallback(env, jobj, copt); + return reinterpret_cast<jlong>(c); +} + +/* + * Class: org_rocksdb_NativeComparatorWrapper + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_NativeComparatorWrapper_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jcomparator_handle) { + auto* comparator = reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle); + delete comparator; +} +// </editor-fold> diff --git a/src/rocksdb/java/rocksjni/comparatorjnicallback.cc b/src/rocksdb/java/rocksjni/comparatorjnicallback.cc new file mode 100644 index 00000000..5b4d11b0 --- /dev/null +++ b/src/rocksdb/java/rocksjni/comparatorjnicallback.cc @@ -0,0 +1,340 @@ +// 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::Comparator. + +#include "rocksjni/comparatorjnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +BaseComparatorJniCallback::BaseComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt) + : JniCallback(env, jComparator), + mtx_compare(new port::Mutex(copt->use_adaptive_mutex)), + mtx_findShortestSeparator(new port::Mutex(copt->use_adaptive_mutex)) { + + // Note: The name of a Comparator will not change during it's lifetime, + // so we cache it in a global var + jmethodID jNameMethodId = AbstractComparatorJni::getNameMethodId(env); + if(jNameMethodId == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + jstring jsName = (jstring)env->CallObjectMethod(m_jcallback_obj, jNameMethodId); + if(env->ExceptionCheck()) { + // exception thrown + return; + } + jboolean has_exception = JNI_FALSE; + m_name = JniUtil::copyString(env, jsName, + &has_exception); // also releases jsName + if (has_exception == JNI_TRUE) { + // exception thrown + return; + } + + m_jCompareMethodId = AbstractComparatorJni::getCompareMethodId(env); + if(m_jCompareMethodId == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + m_jFindShortestSeparatorMethodId = + AbstractComparatorJni::getFindShortestSeparatorMethodId(env); + if(m_jFindShortestSeparatorMethodId == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + m_jFindShortSuccessorMethodId = + AbstractComparatorJni::getFindShortSuccessorMethodId(env); + if(m_jFindShortSuccessorMethodId == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } +} + +const char* BaseComparatorJniCallback::Name() const { + return m_name.get(); +} + +int BaseComparatorJniCallback::Compare(const Slice& a, const Slice& b) const { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + // TODO(adamretter): slice objects can potentially be cached using thread + // local variables to avoid locking. Could make this configurable depending on + // performance. + mtx_compare.get()->Lock(); + + bool pending_exception = + AbstractSliceJni::setHandle(env, m_jSliceA, &a, JNI_FALSE); + if(pending_exception) { + if(env->ExceptionCheck()) { + // exception thrown from setHandle or descendant + env->ExceptionDescribe(); // print out exception to stderr + } + releaseJniEnv(attached_thread); + return 0; + } + + pending_exception = + AbstractSliceJni::setHandle(env, m_jSliceB, &b, JNI_FALSE); + if(pending_exception) { + if(env->ExceptionCheck()) { + // exception thrown from setHandle or descendant + env->ExceptionDescribe(); // print out exception to stderr + } + releaseJniEnv(attached_thread); + return 0; + } + + jint result = + env->CallIntMethod(m_jcallback_obj, m_jCompareMethodId, m_jSliceA, + m_jSliceB); + + mtx_compare.get()->Unlock(); + + if(env->ExceptionCheck()) { + // exception thrown from CallIntMethod + env->ExceptionDescribe(); // print out exception to stderr + result = 0; // we could not get a result from java callback so use 0 + } + + releaseJniEnv(attached_thread); + + return result; +} + +void BaseComparatorJniCallback::FindShortestSeparator( + std::string* start, const Slice& limit) const { + if (start == nullptr) { + return; + } + + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + const char* startUtf = start->c_str(); + jstring jsStart = env->NewStringUTF(startUtf); + if(jsStart == 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(jsStart); + releaseJniEnv(attached_thread); + return; + } + + // TODO(adamretter): slice object can potentially be cached using thread local + // variable to avoid locking. Could make this configurable depending on + // performance. + mtx_findShortestSeparator.get()->Lock(); + + bool pending_exception = + AbstractSliceJni::setHandle(env, m_jSliceLimit, &limit, JNI_FALSE); + if(pending_exception) { + if(env->ExceptionCheck()) { + // exception thrown from setHandle or descendant + env->ExceptionDescribe(); // print out exception to stderr + } + if(jsStart != nullptr) { + env->DeleteLocalRef(jsStart); + } + releaseJniEnv(attached_thread); + return; + } + + jstring jsResultStart = + (jstring)env->CallObjectMethod(m_jcallback_obj, + m_jFindShortestSeparatorMethodId, jsStart, m_jSliceLimit); + + mtx_findShortestSeparator.get()->Unlock(); + + if(env->ExceptionCheck()) { + // exception thrown from CallObjectMethod + env->ExceptionDescribe(); // print out exception to stderr + env->DeleteLocalRef(jsStart); + releaseJniEnv(attached_thread); + return; + } + + env->DeleteLocalRef(jsStart); + + if (jsResultStart != nullptr) { + // update start with result + jboolean has_exception = JNI_FALSE; + std::unique_ptr<const char[]> result_start = JniUtil::copyString(env, jsResultStart, + &has_exception); // also releases jsResultStart + if (has_exception == JNI_TRUE) { + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); // print out exception to stderr + } + releaseJniEnv(attached_thread); + return; + } + + start->assign(result_start.get()); + } + releaseJniEnv(attached_thread); +} + +void BaseComparatorJniCallback::FindShortSuccessor( + std::string* key) const { + if (key == nullptr) { + return; + } + + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + const char* keyUtf = key->c_str(); + jstring jsKey = env->NewStringUTF(keyUtf); + if(jsKey == nullptr) { + // unable to construct string + if(env->ExceptionCheck()) { + env->ExceptionDescribe(); // print out exception to stderr + } + releaseJniEnv(attached_thread); + return; + } else if(env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + env->ExceptionDescribe(); // print out exception to stderr + env->DeleteLocalRef(jsKey); + releaseJniEnv(attached_thread); + return; + } + + jstring jsResultKey = + (jstring)env->CallObjectMethod(m_jcallback_obj, + m_jFindShortSuccessorMethodId, jsKey); + + if(env->ExceptionCheck()) { + // exception thrown from CallObjectMethod + env->ExceptionDescribe(); // print out exception to stderr + env->DeleteLocalRef(jsKey); + releaseJniEnv(attached_thread); + return; + } + + env->DeleteLocalRef(jsKey); + + if (jsResultKey != nullptr) { + // updates key with result, also releases jsResultKey. + jboolean has_exception = JNI_FALSE; + std::unique_ptr<const char[]> result_key = JniUtil::copyString(env, jsResultKey, + &has_exception); // also releases jsResultKey + if (has_exception == JNI_TRUE) { + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); // print out exception to stderr + } + releaseJniEnv(attached_thread); + return; + } + + key->assign(result_key.get()); + } + + releaseJniEnv(attached_thread); +} + +ComparatorJniCallback::ComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt) : + BaseComparatorJniCallback(env, jComparator, copt) { + m_jSliceA = env->NewGlobalRef(SliceJni::construct0(env)); + if(m_jSliceA == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + m_jSliceB = env->NewGlobalRef(SliceJni::construct0(env)); + if(m_jSliceB == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + m_jSliceLimit = env->NewGlobalRef(SliceJni::construct0(env)); + if(m_jSliceLimit == nullptr) { + // exception thrown: OutOfMemoryError + return; + } +} + +ComparatorJniCallback::~ComparatorJniCallback() { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + if(m_jSliceA != nullptr) { + env->DeleteGlobalRef(m_jSliceA); + } + + if(m_jSliceB != nullptr) { + env->DeleteGlobalRef(m_jSliceB); + } + + if(m_jSliceLimit != nullptr) { + env->DeleteGlobalRef(m_jSliceLimit); + } + + releaseJniEnv(attached_thread); +} + +DirectComparatorJniCallback::DirectComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt) : + BaseComparatorJniCallback(env, jComparator, copt) { + m_jSliceA = env->NewGlobalRef(DirectSliceJni::construct0(env)); + if(m_jSliceA == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + m_jSliceB = env->NewGlobalRef(DirectSliceJni::construct0(env)); + if(m_jSliceB == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + m_jSliceLimit = env->NewGlobalRef(DirectSliceJni::construct0(env)); + if(m_jSliceLimit == nullptr) { + // exception thrown: OutOfMemoryError + return; + } +} + +DirectComparatorJniCallback::~DirectComparatorJniCallback() { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + if(m_jSliceA != nullptr) { + env->DeleteGlobalRef(m_jSliceA); + } + + if(m_jSliceB != nullptr) { + env->DeleteGlobalRef(m_jSliceB); + } + + if(m_jSliceLimit != nullptr) { + env->DeleteGlobalRef(m_jSliceLimit); + } + + releaseJniEnv(attached_thread); +} +} // namespace rocksdb diff --git a/src/rocksdb/java/rocksjni/comparatorjnicallback.h b/src/rocksdb/java/rocksjni/comparatorjnicallback.h new file mode 100644 index 00000000..0aa9cc0a --- /dev/null +++ b/src/rocksdb/java/rocksjni/comparatorjnicallback.h @@ -0,0 +1,93 @@ +// 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::Comparator and rocksdb::DirectComparator. + +#ifndef JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_ +#define JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_ + +#include <jni.h> +#include <memory> +#include <string> +#include "rocksjni/jnicallback.h" +#include "rocksdb/comparator.h" +#include "rocksdb/slice.h" +#include "port/port.h" + +namespace rocksdb { + +struct ComparatorJniCallbackOptions { + // Use adaptive mutex, which spins in the user space before resorting + // to kernel. This could reduce context switch when the mutex is not + // heavily contended. However, if the mutex is hot, we could end up + // wasting spin time. + // Default: false + bool use_adaptive_mutex; + + ComparatorJniCallbackOptions() : use_adaptive_mutex(false) { + } +}; + +/** + * This class acts as a bridge between C++ + * and Java. The methods in this class will be + * called back from the RocksDB storage engine (C++) + * we then callback to the appropriate Java method + * this enables Comparators to be implemented in Java. + * + * The design of this Comparator caches the Java Slice + * objects that are used in the compare and findShortestSeparator + * method callbacks. Instead of creating new objects for each callback + * of those functions, by reuse via setHandle we are a lot + * faster; Unfortunately this means that we have to + * introduce independent locking in regions of each of those methods + * via the mutexs mtx_compare and mtx_findShortestSeparator respectively + */ +class BaseComparatorJniCallback : public JniCallback, public Comparator { + public: + BaseComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt); + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator( + std::string* start, const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + private: + // used for synchronisation in compare method + std::unique_ptr<port::Mutex> mtx_compare; + // used for synchronisation in findShortestSeparator method + std::unique_ptr<port::Mutex> mtx_findShortestSeparator; + std::unique_ptr<const char[]> m_name; + jmethodID m_jCompareMethodId; + jmethodID m_jFindShortestSeparatorMethodId; + jmethodID m_jFindShortSuccessorMethodId; + + protected: + jobject m_jSliceA; + jobject m_jSliceB; + jobject m_jSliceLimit; +}; + +class ComparatorJniCallback : public BaseComparatorJniCallback { + public: + ComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt); + ~ComparatorJniCallback(); +}; + +class DirectComparatorJniCallback : public BaseComparatorJniCallback { + public: + DirectComparatorJniCallback( + JNIEnv* env, jobject jComparator, + const ComparatorJniCallbackOptions* copt); + ~DirectComparatorJniCallback(); +}; +} // namespace rocksdb + +#endif // JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/compression_options.cc b/src/rocksdb/java/rocksjni/compression_options.cc new file mode 100644 index 00000000..f0155eb3 --- /dev/null +++ b/src/rocksdb/java/rocksjni/compression_options.cc @@ -0,0 +1,164 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompressionOptions. + +#include <jni.h> + +#include "include/org_rocksdb_CompressionOptions.h" +#include "rocksdb/advanced_options.h" + +/* + * Class: org_rocksdb_CompressionOptions + * Method: newCompressionOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_CompressionOptions_newCompressionOptions( + JNIEnv*, jclass) { + const auto* opt = new rocksdb::CompressionOptions(); + return reinterpret_cast<jlong>(opt); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setWindowBits + * Signature: (JI)V + */ +void Java_org_rocksdb_CompressionOptions_setWindowBits( + JNIEnv*, jobject, jlong jhandle, jint jwindow_bits) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->window_bits = static_cast<int>(jwindow_bits); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: windowBits + * Signature: (J)I + */ +jint Java_org_rocksdb_CompressionOptions_windowBits( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<jint>(opt->window_bits); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setLevel + * Signature: (JI)V + */ +void Java_org_rocksdb_CompressionOptions_setLevel( + JNIEnv*, jobject, jlong jhandle, jint jlevel) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->level = static_cast<int>(jlevel); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: level + * Signature: (J)I + */ +jint Java_org_rocksdb_CompressionOptions_level( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<jint>(opt->level); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setStrategy + * Signature: (JI)V + */ +void Java_org_rocksdb_CompressionOptions_setStrategy( + JNIEnv*, jobject, jlong jhandle, jint jstrategy) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->strategy = static_cast<int>(jstrategy); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: strategy + * Signature: (J)I + */ +jint Java_org_rocksdb_CompressionOptions_strategy( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<jint>(opt->strategy); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setMaxDictBytes + * Signature: (JI)V + */ +void Java_org_rocksdb_CompressionOptions_setMaxDictBytes( + JNIEnv*, jobject, jlong jhandle, jint jmax_dict_bytes) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->max_dict_bytes = static_cast<uint32_t>(jmax_dict_bytes); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: maxDictBytes + * Signature: (J)I + */ +jint Java_org_rocksdb_CompressionOptions_maxDictBytes( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<jint>(opt->max_dict_bytes); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setZstdMaxTrainBytes + * Signature: (JI)V + */ +void Java_org_rocksdb_CompressionOptions_setZstdMaxTrainBytes( + JNIEnv*, jobject, jlong jhandle, jint jzstd_max_train_bytes) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->zstd_max_train_bytes = static_cast<uint32_t>(jzstd_max_train_bytes); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: zstdMaxTrainBytes + * Signature: (J)I + */ +jint Java_org_rocksdb_CompressionOptions_zstdMaxTrainBytes( + JNIEnv *, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<jint>(opt->zstd_max_train_bytes); +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: setEnabled + * Signature: (JZ)V + */ +void Java_org_rocksdb_CompressionOptions_setEnabled( + JNIEnv*, jobject, jlong jhandle, jboolean jenabled) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + opt->enabled = jenabled == JNI_TRUE; +} + +/* + * Class: org_rocksdb_CompressionOptions + * Method: enabled + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_CompressionOptions_enabled( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); + return static_cast<bool>(opt->enabled); +} +/* + * Class: org_rocksdb_CompressionOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_CompressionOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + delete reinterpret_cast<rocksdb::CompressionOptions*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/env.cc b/src/rocksdb/java/rocksjni/env.cc new file mode 100644 index 00000000..ed54bd36 --- /dev/null +++ b/src/rocksdb/java/rocksjni/env.cc @@ -0,0 +1,234 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::Env methods from Java side. + +#include <jni.h> +#include <vector> + +#include "portal.h" +#include "rocksdb/env.h" +#include "include/org_rocksdb_Env.h" +#include "include/org_rocksdb_HdfsEnv.h" +#include "include/org_rocksdb_RocksEnv.h" +#include "include/org_rocksdb_RocksMemEnv.h" +#include "include/org_rocksdb_TimedEnv.h" + +/* + * Class: org_rocksdb_Env + * Method: getDefaultEnvInternal + * Signature: ()J + */ +jlong Java_org_rocksdb_Env_getDefaultEnvInternal( + JNIEnv*, jclass) { + return reinterpret_cast<jlong>(rocksdb::Env::Default()); +} + +/* + * Class: org_rocksdb_RocksEnv + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksEnv_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* e = reinterpret_cast<rocksdb::Env*>(jhandle); + assert(e != nullptr); + delete e; +} + +/* + * Class: org_rocksdb_Env + * Method: setBackgroundThreads + * Signature: (JIB)V + */ +void Java_org_rocksdb_Env_setBackgroundThreads( + JNIEnv*, jobject, jlong jhandle, jint jnum, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + rocks_env->SetBackgroundThreads(static_cast<int>(jnum), + rocksdb::PriorityJni::toCppPriority(jpriority_value)); +} + +/* + * Class: org_rocksdb_Env + * Method: getBackgroundThreads + * Signature: (JB)I + */ +jint Java_org_rocksdb_Env_getBackgroundThreads( + JNIEnv*, jobject, jlong jhandle, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + const int num = rocks_env->GetBackgroundThreads( + rocksdb::PriorityJni::toCppPriority(jpriority_value)); + return static_cast<jint>(num); +} + +/* + * Class: org_rocksdb_Env + * Method: getThreadPoolQueueLen + * Signature: (JB)I + */ +jint Java_org_rocksdb_Env_getThreadPoolQueueLen( + JNIEnv*, jobject, jlong jhandle, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + const int queue_len = rocks_env->GetThreadPoolQueueLen( + rocksdb::PriorityJni::toCppPriority(jpriority_value)); + return static_cast<jint>(queue_len); +} + +/* + * Class: org_rocksdb_Env + * Method: incBackgroundThreadsIfNeeded + * Signature: (JIB)V + */ +void Java_org_rocksdb_Env_incBackgroundThreadsIfNeeded( + JNIEnv*, jobject, jlong jhandle, jint jnum, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + rocks_env->IncBackgroundThreadsIfNeeded(static_cast<int>(jnum), + rocksdb::PriorityJni::toCppPriority(jpriority_value)); +} + +/* + * Class: org_rocksdb_Env + * Method: lowerThreadPoolIOPriority + * Signature: (JB)V + */ +void Java_org_rocksdb_Env_lowerThreadPoolIOPriority( + JNIEnv*, jobject, jlong jhandle, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + rocks_env->LowerThreadPoolIOPriority( + rocksdb::PriorityJni::toCppPriority(jpriority_value)); +} + +/* + * Class: org_rocksdb_Env + * Method: lowerThreadPoolCPUPriority + * Signature: (JB)V + */ +void Java_org_rocksdb_Env_lowerThreadPoolCPUPriority( + JNIEnv*, jobject, jlong jhandle, jbyte jpriority_value) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + rocks_env->LowerThreadPoolCPUPriority( + rocksdb::PriorityJni::toCppPriority(jpriority_value)); +} + +/* + * Class: org_rocksdb_Env + * Method: getThreadList + * Signature: (J)[Lorg/rocksdb/ThreadStatus; + */ +jobjectArray Java_org_rocksdb_Env_getThreadList( + JNIEnv* env, jobject, jlong jhandle) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jhandle); + std::vector<rocksdb::ThreadStatus> thread_status; + rocksdb::Status s = rocks_env->GetThreadList(&thread_status); + if (!s.ok()) { + // error, throw exception + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + // object[] + const jsize len = static_cast<jsize>(thread_status.size()); + jobjectArray jthread_status = + env->NewObjectArray(len, rocksdb::ThreadStatusJni::getJClass(env), nullptr); + if (jthread_status == nullptr) { + // an exception occurred + return nullptr; + } + for (jsize i = 0; i < len; ++i) { + jobject jts = + rocksdb::ThreadStatusJni::construct(env, &(thread_status[i])); + env->SetObjectArrayElement(jthread_status, i, jts); + if (env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(jthread_status); + return nullptr; + } + } + + return jthread_status; +} + +/* + * Class: org_rocksdb_RocksMemEnv + * Method: createMemEnv + * Signature: (J)J + */ +jlong Java_org_rocksdb_RocksMemEnv_createMemEnv( + JNIEnv*, jclass, jlong jbase_env_handle) { + auto* base_env = reinterpret_cast<rocksdb::Env*>(jbase_env_handle); + return reinterpret_cast<jlong>(rocksdb::NewMemEnv(base_env)); +} + +/* + * Class: org_rocksdb_RocksMemEnv + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksMemEnv_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* e = reinterpret_cast<rocksdb::Env*>(jhandle); + assert(e != nullptr); + delete e; +} + +/* + * Class: org_rocksdb_HdfsEnv + * Method: createHdfsEnv + * Signature: (Ljava/lang/String;)J + */ +jlong Java_org_rocksdb_HdfsEnv_createHdfsEnv( + JNIEnv* env, jclass, jstring jfsname) { + jboolean has_exception = JNI_FALSE; + auto fsname = rocksdb::JniUtil::copyStdString(env, jfsname, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return 0; + } + rocksdb::Env* hdfs_env; + rocksdb::Status s = rocksdb::NewHdfsEnv(&hdfs_env, fsname); + if (!s.ok()) { + // error occurred + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } + return reinterpret_cast<jlong>(hdfs_env); +} + +/* + * Class: org_rocksdb_HdfsEnv + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_HdfsEnv_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* e = reinterpret_cast<rocksdb::Env*>(jhandle); + assert(e != nullptr); + delete e; +} + +/* + * Class: org_rocksdb_TimedEnv + * Method: createTimedEnv + * Signature: (J)J + */ +jlong Java_org_rocksdb_TimedEnv_createTimedEnv( + JNIEnv*, jclass, jlong jbase_env_handle) { + auto* base_env = reinterpret_cast<rocksdb::Env*>(jbase_env_handle); + return reinterpret_cast<jlong>(rocksdb::NewTimedEnv(base_env)); +} + +/* + * Class: org_rocksdb_TimedEnv + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TimedEnv_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* e = reinterpret_cast<rocksdb::Env*>(jhandle); + assert(e != nullptr); + delete e; +} + diff --git a/src/rocksdb/java/rocksjni/env_options.cc b/src/rocksdb/java/rocksjni/env_options.cc new file mode 100644 index 00000000..9ed33018 --- /dev/null +++ b/src/rocksdb/java/rocksjni/env_options.cc @@ -0,0 +1,297 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::EnvOptions methods +// from Java side. + +#include <jni.h> + +#include "include/org_rocksdb_EnvOptions.h" +#include "rocksdb/env.h" + +#define ENV_OPTIONS_SET_BOOL(_jhandle, _opt) \ + reinterpret_cast<rocksdb::EnvOptions *>(_jhandle)->_opt = \ + static_cast<bool>(_opt) + +#define ENV_OPTIONS_SET_SIZE_T(_jhandle, _opt) \ + reinterpret_cast<rocksdb::EnvOptions *>(_jhandle)->_opt = \ + static_cast<size_t>(_opt) + +#define ENV_OPTIONS_SET_UINT64_T(_jhandle, _opt) \ + reinterpret_cast<rocksdb::EnvOptions *>(_jhandle)->_opt = \ + static_cast<uint64_t>(_opt) + +#define ENV_OPTIONS_GET(_jhandle, _opt) \ + reinterpret_cast<rocksdb::EnvOptions *>(_jhandle)->_opt + +/* + * Class: org_rocksdb_EnvOptions + * Method: newEnvOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_EnvOptions_newEnvOptions__( + JNIEnv*, jclass) { + auto *env_opt = new rocksdb::EnvOptions(); + return reinterpret_cast<jlong>(env_opt); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: newEnvOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_EnvOptions_newEnvOptions__J( + JNIEnv*, jclass, jlong jdboptions_handle) { + auto* db_options = + reinterpret_cast<rocksdb::DBOptions*>(jdboptions_handle); + auto* env_opt = new rocksdb::EnvOptions(*db_options); + return reinterpret_cast<jlong>(env_opt); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_EnvOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto *eo = reinterpret_cast<rocksdb::EnvOptions *>(jhandle); + assert(eo != nullptr); + delete eo; +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setUseMmapReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setUseMmapReads( + JNIEnv*, jobject, jlong jhandle, jboolean use_mmap_reads) { + ENV_OPTIONS_SET_BOOL(jhandle, use_mmap_reads); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: useMmapReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_useMmapReads( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, use_mmap_reads); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setUseMmapWrites + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setUseMmapWrites( + JNIEnv*, jobject, jlong jhandle, jboolean use_mmap_writes) { + ENV_OPTIONS_SET_BOOL(jhandle, use_mmap_writes); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: useMmapWrites + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_useMmapWrites( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, use_mmap_writes); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setUseDirectReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setUseDirectReads( + JNIEnv*, jobject, jlong jhandle, jboolean use_direct_reads) { + ENV_OPTIONS_SET_BOOL(jhandle, use_direct_reads); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: useDirectReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_useDirectReads( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, use_direct_reads); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setUseDirectWrites + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setUseDirectWrites( + JNIEnv*, jobject, jlong jhandle, jboolean use_direct_writes) { + ENV_OPTIONS_SET_BOOL(jhandle, use_direct_writes); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: useDirectWrites + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_useDirectWrites( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, use_direct_writes); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setAllowFallocate + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setAllowFallocate( + JNIEnv*, jobject, jlong jhandle, jboolean allow_fallocate) { + ENV_OPTIONS_SET_BOOL(jhandle, allow_fallocate); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: allowFallocate + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_allowFallocate( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, allow_fallocate); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setSetFdCloexec + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setSetFdCloexec( + JNIEnv*, jobject, jlong jhandle, jboolean set_fd_cloexec) { + ENV_OPTIONS_SET_BOOL(jhandle, set_fd_cloexec); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setFdCloexec + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_setFdCloexec( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, set_fd_cloexec); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setBytesPerSync + * Signature: (JJ)V + */ +void Java_org_rocksdb_EnvOptions_setBytesPerSync( + JNIEnv*, jobject, jlong jhandle, jlong bytes_per_sync) { + ENV_OPTIONS_SET_UINT64_T(jhandle, bytes_per_sync); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: bytesPerSync + * Signature: (J)J + */ +jlong Java_org_rocksdb_EnvOptions_bytesPerSync( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, bytes_per_sync); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setFallocateWithKeepSize + * Signature: (JZ)V + */ +void Java_org_rocksdb_EnvOptions_setFallocateWithKeepSize( + JNIEnv*, jobject, jlong jhandle, jboolean fallocate_with_keep_size) { + ENV_OPTIONS_SET_BOOL(jhandle, fallocate_with_keep_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: fallocateWithKeepSize + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_EnvOptions_fallocateWithKeepSize( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, fallocate_with_keep_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setCompactionReadaheadSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_EnvOptions_setCompactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle, jlong compaction_readahead_size) { + ENV_OPTIONS_SET_SIZE_T(jhandle, compaction_readahead_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: compactionReadaheadSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_EnvOptions_compactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, compaction_readahead_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setRandomAccessMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_EnvOptions_setRandomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong random_access_max_buffer_size) { + ENV_OPTIONS_SET_SIZE_T(jhandle, random_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: randomAccessMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_EnvOptions_randomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, random_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setWritableFileMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_EnvOptions_setWritableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong writable_file_max_buffer_size) { + ENV_OPTIONS_SET_SIZE_T(jhandle, writable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: writableFileMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_EnvOptions_writableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + return ENV_OPTIONS_GET(jhandle, writable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_EnvOptions + * Method: setRateLimiter + * Signature: (JJ)V + */ +void Java_org_rocksdb_EnvOptions_setRateLimiter( + JNIEnv*, jobject, jlong jhandle, jlong rl_handle) { + auto *sptr_rate_limiter = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter> *>(rl_handle); + auto *env_opt = reinterpret_cast<rocksdb::EnvOptions *>(jhandle); + env_opt->rate_limiter = sptr_rate_limiter->get(); +} diff --git a/src/rocksdb/java/rocksjni/filter.cc b/src/rocksdb/java/rocksjni/filter.cc new file mode 100644 index 00000000..5e9c6364 --- /dev/null +++ b/src/rocksdb/java/rocksjni/filter.cc @@ -0,0 +1,42 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::FilterPolicy. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include "include/org_rocksdb_BloomFilter.h" +#include "include/org_rocksdb_Filter.h" +#include "rocksdb/filter_policy.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_BloomFilter + * Method: createBloomFilter + * Signature: (IZ)J + */ +jlong Java_org_rocksdb_BloomFilter_createNewBloomFilter( + JNIEnv* /*env*/, jclass /*jcls*/, jint bits_per_key, + jboolean use_block_base_builder) { + auto* sptr_filter = new std::shared_ptr<const rocksdb::FilterPolicy>( + rocksdb::NewBloomFilterPolicy(bits_per_key, use_block_base_builder)); + return reinterpret_cast<jlong>(sptr_filter); +} + +/* + * Class: org_rocksdb_Filter + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_Filter_disposeInternal(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* handle = + reinterpret_cast<std::shared_ptr<const rocksdb::FilterPolicy>*>(jhandle); + delete handle; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/ingest_external_file_options.cc b/src/rocksdb/java/rocksjni/ingest_external_file_options.cc new file mode 100644 index 00000000..e0871ff8 --- /dev/null +++ b/src/rocksdb/java/rocksjni/ingest_external_file_options.cc @@ -0,0 +1,196 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::FilterPolicy. + +#include <jni.h> + +#include "include/org_rocksdb_IngestExternalFileOptions.h" +#include "rocksdb/options.h" + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: newIngestExternalFileOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_IngestExternalFileOptions_newIngestExternalFileOptions__( + JNIEnv*, jclass) { + auto* options = new rocksdb::IngestExternalFileOptions(); + return reinterpret_cast<jlong>(options); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: newIngestExternalFileOptions + * Signature: (ZZZZ)J + */ +jlong Java_org_rocksdb_IngestExternalFileOptions_newIngestExternalFileOptions__ZZZZ( + JNIEnv*, jclass, jboolean jmove_files, + jboolean jsnapshot_consistency, jboolean jallow_global_seqno, + jboolean jallow_blocking_flush) { + auto* options = new rocksdb::IngestExternalFileOptions(); + options->move_files = static_cast<bool>(jmove_files); + options->snapshot_consistency = static_cast<bool>(jsnapshot_consistency); + options->allow_global_seqno = static_cast<bool>(jallow_global_seqno); + options->allow_blocking_flush = static_cast<bool>(jallow_blocking_flush); + return reinterpret_cast<jlong>(options); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: moveFiles + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_IngestExternalFileOptions_moveFiles( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return static_cast<jboolean>(options->move_files); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setMoveFiles + * Signature: (JZ)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_setMoveFiles( + JNIEnv*, jobject, jlong jhandle, jboolean jmove_files) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->move_files = static_cast<bool>(jmove_files); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: snapshotConsistency + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_IngestExternalFileOptions_snapshotConsistency( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return static_cast<jboolean>(options->snapshot_consistency); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setSnapshotConsistency + * Signature: (JZ)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_setSnapshotConsistency( + JNIEnv*, jobject, jlong jhandle, jboolean jsnapshot_consistency) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->snapshot_consistency = static_cast<bool>(jsnapshot_consistency); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: allowGlobalSeqNo + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_IngestExternalFileOptions_allowGlobalSeqNo( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return static_cast<jboolean>(options->allow_global_seqno); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setAllowGlobalSeqNo + * Signature: (JZ)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_setAllowGlobalSeqNo( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_global_seqno) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->allow_global_seqno = static_cast<bool>(jallow_global_seqno); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: allowBlockingFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_IngestExternalFileOptions_allowBlockingFlush( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return static_cast<jboolean>(options->allow_blocking_flush); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setAllowBlockingFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_setAllowBlockingFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_blocking_flush) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->allow_blocking_flush = static_cast<bool>(jallow_blocking_flush); +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: ingestBehind + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_IngestExternalFileOptions_ingestBehind( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return options->ingest_behind == JNI_TRUE; +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setIngestBehind + * Signature: (JZ)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_setIngestBehind( + JNIEnv*, jobject, jlong jhandle, jboolean jingest_behind) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->ingest_behind = jingest_behind == JNI_TRUE; +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: writeGlobalSeqno + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_IngestExternalFileOptions_writeGlobalSeqno( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + return options->write_global_seqno == JNI_TRUE; +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: setWriteGlobalSeqno + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL Java_org_rocksdb_IngestExternalFileOptions_setWriteGlobalSeqno( + JNIEnv*, jobject, jlong jhandle, jboolean jwrite_global_seqno) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + options->write_global_seqno = jwrite_global_seqno == JNI_TRUE; +} + +/* + * Class: org_rocksdb_IngestExternalFileOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_IngestExternalFileOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* options = + reinterpret_cast<rocksdb::IngestExternalFileOptions*>(jhandle); + delete options; +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/iterator.cc b/src/rocksdb/java/rocksjni/iterator.cc new file mode 100644 index 00000000..18daeb81 --- /dev/null +++ b/src/rocksdb/java/rocksjni/iterator.cc @@ -0,0 +1,186 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::Iterator methods from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> + +#include "include/org_rocksdb_RocksIterator.h" +#include "rocksdb/iterator.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_RocksIterator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + assert(it != nullptr); + delete it; +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: isValid0 + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_RocksIterator_isValid0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<rocksdb::Iterator*>(handle)->Valid(); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: seekToFirst0 + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_seekToFirst0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToFirst(); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: seekToLast0 + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_seekToLast0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToLast(); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: next0 + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_next0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::Iterator*>(handle)->Next(); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: prev0 + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_prev0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::Iterator*>(handle)->Prev(); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: seek0 + * Signature: (J[BI)V + */ +void Java_org_rocksdb_RocksIterator_seek0(JNIEnv* env, jobject /*jobj*/, + jlong handle, jbyteArray jtarget, + jint jtarget_len) { + jbyte* target = env->GetByteArrayElements(jtarget, nullptr); + if (target == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len); + + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + it->Seek(target_slice); + + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: seekForPrev0 + * Signature: (J[BI)V + */ +void Java_org_rocksdb_RocksIterator_seekForPrev0(JNIEnv* env, jobject /*jobj*/, + jlong handle, + jbyteArray jtarget, + jint jtarget_len) { + jbyte* target = env->GetByteArrayElements(jtarget, nullptr); + if (target == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len); + + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + it->SeekForPrev(target_slice); + + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: status0 + * Signature: (J)V + */ +void Java_org_rocksdb_RocksIterator_status0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + rocksdb::Status s = it->status(); + + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: key0 + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_RocksIterator_key0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + rocksdb::Slice key_slice = it->key(); + + jbyteArray jkey = env->NewByteArray(static_cast<jsize>(key_slice.size())); + if (jkey == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetByteArrayRegion( + jkey, 0, static_cast<jsize>(key_slice.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(key_slice.data()))); + return jkey; +} + +/* + * Class: org_rocksdb_RocksIterator + * Method: value0 + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_RocksIterator_value0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); + rocksdb::Slice value_slice = it->value(); + + jbyteArray jkeyValue = + env->NewByteArray(static_cast<jsize>(value_slice.size())); + if (jkeyValue == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetByteArrayRegion( + jkeyValue, 0, static_cast<jsize>(value_slice.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value_slice.data()))); + return jkeyValue; +} diff --git a/src/rocksdb/java/rocksjni/jnicallback.cc b/src/rocksdb/java/rocksjni/jnicallback.cc new file mode 100644 index 00000000..f72eecd4 --- /dev/null +++ b/src/rocksdb/java/rocksjni/jnicallback.cc @@ -0,0 +1,53 @@ +// 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 +// JNI Callbacks from C++ to sub-classes or org.rocksdb.RocksCallbackObject + +#include <assert.h> +#include "rocksjni/jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +JniCallback::JniCallback(JNIEnv* env, jobject jcallback_obj) { + // Note: jcallback_obj may be accessed by multiple threads, + // so we ref the jvm not the env + const jint rs = env->GetJavaVM(&m_jvm); + if(rs != JNI_OK) { + // exception thrown + return; + } + + // Note: we may want to access the Java callback object instance + // across multiple method calls, so we create a global ref + assert(jcallback_obj != nullptr); + m_jcallback_obj = env->NewGlobalRef(jcallback_obj); + if(jcallback_obj == nullptr) { + // exception thrown: OutOfMemoryError + return; + } +} + +JNIEnv* JniCallback::getJniEnv(jboolean* attached) const { + return JniUtil::getJniEnv(m_jvm, attached); +} + +void JniCallback::releaseJniEnv(jboolean& attached) const { + JniUtil::releaseJniEnv(m_jvm, attached); +} + +JniCallback::~JniCallback() { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + if(m_jcallback_obj != nullptr) { + env->DeleteGlobalRef(m_jcallback_obj); + } + + releaseJniEnv(attached_thread); +} +// @lint-ignore TXT4 T25377293 Grandfathered in +} // namespace rocksdb
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/jnicallback.h b/src/rocksdb/java/rocksjni/jnicallback.h new file mode 100644 index 00000000..940ecf06 --- /dev/null +++ b/src/rocksdb/java/rocksjni/jnicallback.h @@ -0,0 +1,29 @@ +// 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 +// JNI Callbacks from C++ to sub-classes or org.rocksdb.RocksCallbackObject + +#ifndef JAVA_ROCKSJNI_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_JNICALLBACK_H_ + +#include <jni.h> + +namespace rocksdb { + class JniCallback { + public: + JniCallback(JNIEnv* env, jobject jcallback_obj); + virtual ~JniCallback(); + + protected: + JavaVM* m_jvm; + jobject m_jcallback_obj; + JNIEnv* getJniEnv(jboolean* attached) const; + void releaseJniEnv(jboolean& attached) const; + }; +} + +// @lint-ignore TXT4 T25377293 Grandfathered in +#endif // JAVA_ROCKSJNI_JNICALLBACK_H_
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/loggerjnicallback.cc b/src/rocksdb/java/rocksjni/loggerjnicallback.cc new file mode 100644 index 00000000..61571e98 --- /dev/null +++ b/src/rocksdb/java/rocksjni/loggerjnicallback.cc @@ -0,0 +1,294 @@ +// 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::Logger. + +#include "include/org_rocksdb_Logger.h" + +#include <cstdarg> +#include <cstdio> +#include "rocksjni/loggerjnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { + +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::InfoLogLevel::DEBUG_LEVEL: + jlog_level = m_jdebug_level; + break; + case rocksdb::InfoLogLevel::INFO_LEVEL: + jlog_level = m_jinfo_level; + break; + case rocksdb::InfoLogLevel::WARN_LEVEL: + jlog_level = m_jwarn_level; + break; + case rocksdb::InfoLogLevel::ERROR_LEVEL: + jlog_level = m_jerror_level; + break; + case rocksdb::InfoLogLevel::FATAL_LEVEL: + jlog_level = m_jfatal_level; + break; + case rocksdb::InfoLogLevel::HEADER_LEVEL: + jlog_level = m_jheader_level; + break; + default: + jlog_level = m_jfatal_level; + break; + } + + assert(format != nullptr); + assert(ap != 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 + +/* + * 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::LoggerJniCallback>( + new rocksdb::LoggerJniCallback(env, jobj)); + + // set log level + auto* options = reinterpret_cast<rocksdb::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::LoggerJniCallback>( + new rocksdb::LoggerJniCallback(env, jobj)); + + // set log level + auto* db_options = reinterpret_cast<rocksdb::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::LoggerJniCallback>*>(jhandle); + handle->get()->SetInfoLogLevel( + static_cast<rocksdb::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::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::LoggerJniCallback>*>(jhandle); + delete handle; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/loggerjnicallback.h b/src/rocksdb/java/rocksjni/loggerjnicallback.h new file mode 100644 index 00000000..80c5a198 --- /dev/null +++ b/src/rocksdb/java/rocksjni/loggerjnicallback.h @@ -0,0 +1,49 @@ +// 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::Logger + +#ifndef JAVA_ROCKSJNI_LOGGERJNICALLBACK_H_ +#define JAVA_ROCKSJNI_LOGGERJNICALLBACK_H_ + +#include <jni.h> +#include <memory> +#include <string> +#include "rocksjni/jnicallback.h" +#include "port/port.h" +#include "rocksdb/env.h" + +namespace rocksdb { + + class LoggerJniCallback : public JniCallback, public Logger { + public: + LoggerJniCallback(JNIEnv* env, jobject jLogger); + ~LoggerJniCallback(); + + using Logger::SetInfoLogLevel; + using Logger::GetInfoLogLevel; + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap); + // Write an entry to the log file with the specified log level + // and format. Any log with level under the internal log level + // of *this (see @SetInfoLogLevel and @GetInfoLogLevel) will not be + // printed. + virtual void Logv(const InfoLogLevel log_level, + const char* format, va_list ap); + + private: + 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; + std::unique_ptr<char[]> format_str(const char* format, va_list ap) const; + }; +} // namespace rocksdb + +#endif // JAVA_ROCKSJNI_LOGGERJNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/lru_cache.cc b/src/rocksdb/java/rocksjni/lru_cache.cc new file mode 100644 index 00000000..2424bc8e --- /dev/null +++ b/src/rocksdb/java/rocksjni/lru_cache.cc @@ -0,0 +1,43 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::LRUCache. + +#include <jni.h> + +#include "cache/lru_cache.h" +#include "include/org_rocksdb_LRUCache.h" + +/* + * Class: org_rocksdb_LRUCache + * Method: newLRUCache + * Signature: (JIZD)J + */ +jlong Java_org_rocksdb_LRUCache_newLRUCache(JNIEnv* /*env*/, jclass /*jcls*/, + jlong jcapacity, + jint jnum_shard_bits, + jboolean jstrict_capacity_limit, + jdouble jhigh_pri_pool_ratio) { + auto* sptr_lru_cache = + new std::shared_ptr<rocksdb::Cache>(rocksdb::NewLRUCache( + static_cast<size_t>(jcapacity), static_cast<int>(jnum_shard_bits), + static_cast<bool>(jstrict_capacity_limit), + static_cast<double>(jhigh_pri_pool_ratio))); + return reinterpret_cast<jlong>(sptr_lru_cache); +} + +/* + * Class: org_rocksdb_LRUCache + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_LRUCache_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_lru_cache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(jhandle); + delete sptr_lru_cache; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/memory_util.cc b/src/rocksdb/java/rocksjni/memory_util.cc new file mode 100644 index 00000000..04385021 --- /dev/null +++ b/src/rocksdb/java/rocksjni/memory_util.cc @@ -0,0 +1,100 @@ +// 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). + +#include <jni.h> +#include <map> +#include <string> +#include <unordered_set> +#include <vector> + +#include "include/org_rocksdb_MemoryUtil.h" + +#include "rocksjni/portal.h" + +#include "rocksdb/utilities/memory_util.h" + + +/* + * Class: org_rocksdb_MemoryUtil + * Method: getApproximateMemoryUsageByType + * Signature: ([J[J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_MemoryUtil_getApproximateMemoryUsageByType( + JNIEnv *env, jclass /*jclazz*/, jlongArray jdb_handles, jlongArray jcache_handles) { + + std::vector<rocksdb::DB*> dbs; + jsize db_handle_count = env->GetArrayLength(jdb_handles); + if(db_handle_count > 0) { + jlong *ptr_jdb_handles = env->GetLongArrayElements(jdb_handles, nullptr); + if (ptr_jdb_handles == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + for (jsize i = 0; i < db_handle_count; i++) { + dbs.push_back(reinterpret_cast<rocksdb::DB *>(ptr_jdb_handles[i])); + } + env->ReleaseLongArrayElements(jdb_handles, ptr_jdb_handles, JNI_ABORT); + } + + std::unordered_set<const rocksdb::Cache*> cache_set; + jsize cache_handle_count = env->GetArrayLength(jcache_handles); + if(cache_handle_count > 0) { + jlong *ptr_jcache_handles = env->GetLongArrayElements(jcache_handles, nullptr); + if (ptr_jcache_handles == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + for (jsize i = 0; i < cache_handle_count; i++) { + auto *cache_ptr = + reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(ptr_jcache_handles[i]); + cache_set.insert(cache_ptr->get()); + } + env->ReleaseLongArrayElements(jcache_handles, ptr_jcache_handles, JNI_ABORT); + } + + std::map<rocksdb::MemoryUtil::UsageType, uint64_t> usage_by_type; + if(rocksdb::MemoryUtil::GetApproximateMemoryUsageByType(dbs, cache_set, &usage_by_type) != rocksdb::Status::OK()) { + // Non-OK status + return nullptr; + } + + jobject jusage_by_type = rocksdb::HashMapJni::construct( + env, static_cast<uint32_t>(usage_by_type.size())); + if (jusage_by_type == nullptr) { + // exception occurred + return nullptr; + } + const rocksdb::HashMapJni::FnMapKV<const rocksdb::MemoryUtil::UsageType, const uint64_t, jobject, jobject> + fn_map_kv = + [env](const std::pair<rocksdb::MemoryUtil::UsageType, uint64_t>& pair) { + // Construct key + const jobject jusage_type = + rocksdb::ByteJni::valueOf(env, rocksdb::MemoryUsageTypeJni::toJavaMemoryUsageType(pair.first)); + if (jusage_type == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + // Construct value + const jobject jusage_value = + rocksdb::LongJni::valueOf(env, pair.second); + if (jusage_value == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + // Construct and return pointer to pair of jobjects + return std::unique_ptr<std::pair<jobject, jobject>>( + new std::pair<jobject, jobject>(jusage_type, + jusage_value)); + }; + + if (!rocksdb::HashMapJni::putAll(env, jusage_by_type, usage_by_type.begin(), + usage_by_type.end(), fn_map_kv)) { + // exception occcurred + jusage_by_type = nullptr; + } + + return jusage_by_type; + +} diff --git a/src/rocksdb/java/rocksjni/memtablejni.cc b/src/rocksdb/java/rocksjni/memtablejni.cc new file mode 100644 index 00000000..ad704c3b --- /dev/null +++ b/src/rocksdb/java/rocksjni/memtablejni.cc @@ -0,0 +1,89 @@ +// 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 "bridge" between Java and C++ for MemTables. + +#include "include/org_rocksdb_HashLinkedListMemTableConfig.h" +#include "include/org_rocksdb_HashSkipListMemTableConfig.h" +#include "include/org_rocksdb_SkipListMemTableConfig.h" +#include "include/org_rocksdb_VectorMemTableConfig.h" +#include "rocksdb/memtablerep.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_HashSkipListMemTableConfig + * Method: newMemTableFactoryHandle + * Signature: (JII)J + */ +jlong Java_org_rocksdb_HashSkipListMemTableConfig_newMemTableFactoryHandle( + JNIEnv* env, jobject /*jobj*/, jlong jbucket_count, jint jheight, + jint jbranching_factor) { + rocksdb::Status s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jbucket_count); + if (s.ok()) { + return reinterpret_cast<jlong>(rocksdb::NewHashSkipListRepFactory( + static_cast<size_t>(jbucket_count), static_cast<int32_t>(jheight), + static_cast<int32_t>(jbranching_factor))); + } + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + return 0; +} + +/* + * Class: org_rocksdb_HashLinkedListMemTableConfig + * Method: newMemTableFactoryHandle + * Signature: (JJIZI)J + */ +jlong Java_org_rocksdb_HashLinkedListMemTableConfig_newMemTableFactoryHandle( + JNIEnv* env, jobject /*jobj*/, jlong jbucket_count, + jlong jhuge_page_tlb_size, jint jbucket_entries_logging_threshold, + jboolean jif_log_bucket_dist_when_flash, jint jthreshold_use_skiplist) { + rocksdb::Status statusBucketCount = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jbucket_count); + rocksdb::Status statusHugePageTlb = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jhuge_page_tlb_size); + if (statusBucketCount.ok() && statusHugePageTlb.ok()) { + return reinterpret_cast<jlong>(rocksdb::NewHashLinkListRepFactory( + static_cast<size_t>(jbucket_count), + static_cast<size_t>(jhuge_page_tlb_size), + static_cast<int32_t>(jbucket_entries_logging_threshold), + static_cast<bool>(jif_log_bucket_dist_when_flash), + static_cast<int32_t>(jthreshold_use_skiplist))); + } + rocksdb::IllegalArgumentExceptionJni::ThrowNew( + env, !statusBucketCount.ok() ? statusBucketCount : statusHugePageTlb); + return 0; +} + +/* + * Class: org_rocksdb_VectorMemTableConfig + * Method: newMemTableFactoryHandle + * Signature: (J)J + */ +jlong Java_org_rocksdb_VectorMemTableConfig_newMemTableFactoryHandle( + JNIEnv* env, jobject /*jobj*/, jlong jreserved_size) { + rocksdb::Status s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jreserved_size); + if (s.ok()) { + return reinterpret_cast<jlong>( + new rocksdb::VectorRepFactory(static_cast<size_t>(jreserved_size))); + } + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + return 0; +} + +/* + * Class: org_rocksdb_SkipListMemTableConfig + * Method: newMemTableFactoryHandle0 + * Signature: (J)J + */ +jlong Java_org_rocksdb_SkipListMemTableConfig_newMemTableFactoryHandle0( + JNIEnv* env, jobject /*jobj*/, jlong jlookahead) { + rocksdb::Status s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jlookahead); + if (s.ok()) { + return reinterpret_cast<jlong>( + new rocksdb::SkipListFactory(static_cast<size_t>(jlookahead))); + } + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + return 0; +} diff --git a/src/rocksdb/java/rocksjni/merge_operator.cc b/src/rocksdb/java/rocksjni/merge_operator.cc new file mode 100644 index 00000000..e06a06f7 --- /dev/null +++ b/src/rocksdb/java/rocksjni/merge_operator.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2014, Vlad Balan (vlad.gm@gmail.com). 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 "bridge" between Java and C++ +// for rocksdb::MergeOperator. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory> +#include <string> + +#include "include/org_rocksdb_StringAppendOperator.h" +#include "include/org_rocksdb_UInt64AddOperator.h" +#include "rocksdb/db.h" +#include "rocksdb/memtablerep.h" +#include "rocksdb/merge_operator.h" +#include "rocksdb/options.h" +#include "rocksdb/slice_transform.h" +#include "rocksdb/statistics.h" +#include "rocksdb/table.h" +#include "rocksjni/portal.h" +#include "utilities/merge_operators.h" + +/* + * Class: org_rocksdb_StringAppendOperator + * Method: newSharedStringAppendOperator + * Signature: (C)J + */ +jlong Java_org_rocksdb_StringAppendOperator_newSharedStringAppendOperator( + JNIEnv* /*env*/, jclass /*jclazz*/, jchar jdelim) { + auto* sptr_string_append_op = new std::shared_ptr<rocksdb::MergeOperator>( + rocksdb::MergeOperators::CreateStringAppendOperator((char)jdelim)); + return reinterpret_cast<jlong>(sptr_string_append_op); +} + +/* + * Class: org_rocksdb_StringAppendOperator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_StringAppendOperator_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_string_append_op = + reinterpret_cast<std::shared_ptr<rocksdb::MergeOperator>*>(jhandle); + delete sptr_string_append_op; // delete std::shared_ptr +} + +/* + * Class: org_rocksdb_UInt64AddOperator + * Method: newSharedUInt64AddOperator + * Signature: ()J + */ +jlong Java_org_rocksdb_UInt64AddOperator_newSharedUInt64AddOperator( + JNIEnv* /*env*/, jclass /*jclazz*/) { + auto* sptr_uint64_add_op = new std::shared_ptr<rocksdb::MergeOperator>( + rocksdb::MergeOperators::CreateUInt64AddOperator()); + return reinterpret_cast<jlong>(sptr_uint64_add_op); +} + +/* + * Class: org_rocksdb_UInt64AddOperator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_UInt64AddOperator_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_uint64_add_op = + reinterpret_cast<std::shared_ptr<rocksdb::MergeOperator>*>(jhandle); + delete sptr_uint64_add_op; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/native_comparator_wrapper_test.cc b/src/rocksdb/java/rocksjni/native_comparator_wrapper_test.cc new file mode 100644 index 00000000..829019f9 --- /dev/null +++ b/src/rocksdb/java/rocksjni/native_comparator_wrapper_test.cc @@ -0,0 +1,43 @@ +// 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). + +#include <jni.h> +#include <string> + +#include "rocksdb/comparator.h" +#include "rocksdb/slice.h" + +#include "include/org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper.h" + +namespace rocksdb { + +class NativeComparatorWrapperTestStringComparator : public Comparator { + const char* Name() const { + return "NativeComparatorWrapperTestStringComparator"; + } + + int Compare(const Slice& a, const Slice& b) const { + return a.ToString().compare(b.ToString()); + } + + void FindShortestSeparator(std::string* /*start*/, + const Slice& /*limit*/) const { + return; + } + + void FindShortSuccessor(std::string* /*key*/) const { return; } +}; +} // namespace rocksdb + +/* + * Class: org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper + * Method: newStringComparator + * Signature: ()J + */ +jlong Java_org_rocksdb_NativeComparatorWrapperTest_00024NativeStringComparatorWrapper_newStringComparator( + JNIEnv* /*env*/, jobject /*jobj*/) { + auto* comparator = new rocksdb::NativeComparatorWrapperTestStringComparator(); + return reinterpret_cast<jlong>(comparator); +} diff --git a/src/rocksdb/java/rocksjni/optimistic_transaction_db.cc b/src/rocksdb/java/rocksjni/optimistic_transaction_db.cc new file mode 100644 index 00000000..1505ff98 --- /dev/null +++ b/src/rocksdb/java/rocksjni/optimistic_transaction_db.cc @@ -0,0 +1,278 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::TransactionDB. + +#include <jni.h> + +#include "include/org_rocksdb_OptimisticTransactionDB.h" + +#include "rocksdb/options.h" +#include "rocksdb/utilities/optimistic_transaction_db.h" +#include "rocksdb/utilities/transaction.h" + +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: open + * Signature: (JLjava/lang/String;)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2( + JNIEnv* env, jclass, jlong joptions_handle, jstring jdb_path) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + auto* options = reinterpret_cast<rocksdb::Options*>(joptions_handle); + rocksdb::OptimisticTransactionDB* otdb = nullptr; + rocksdb::Status s = + rocksdb::OptimisticTransactionDB::Open(*options, db_path, &otdb); + env->ReleaseStringUTFChars(jdb_path, db_path); + + if (s.ok()) { + return reinterpret_cast<jlong>(otdb); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: open + * Signature: (JLjava/lang/String;[[B[J)[J + */ +jlongArray +Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2_3_3B_3J( + JNIEnv* env, jclass, jlong jdb_options_handle, jstring jdb_path, + jobjectArray jcolumn_names, jlongArray jcolumn_options_handles) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + std::vector<rocksdb::ColumnFamilyDescriptor> column_families; + const jsize len_cols = env->GetArrayLength(jcolumn_names); + if (len_cols > 0) { + if (env->EnsureLocalCapacity(len_cols) != 0) { + // out of memory + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + jlong* jco = env->GetLongArrayElements(jcolumn_options_handles, nullptr); + if (jco == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + for (int i = 0; i < len_cols; i++) { + const jobject jcn = env->GetObjectArrayElement(jcolumn_names, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + const jbyteArray jcn_ba = reinterpret_cast<jbyteArray>(jcn); + const jsize jcf_name_len = env->GetArrayLength(jcn_ba); + if (env->EnsureLocalCapacity(jcf_name_len) != 0) { + // out of memory + env->DeleteLocalRef(jcn); + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + jbyte* jcf_name = env->GetByteArrayElements(jcn_ba, nullptr); + if (jcf_name == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jcn); + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + const std::string cf_name(reinterpret_cast<char*>(jcf_name), + jcf_name_len); + const rocksdb::ColumnFamilyOptions* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[i]); + column_families.push_back( + rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options)); + + env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT); + env->DeleteLocalRef(jcn); + } + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + } + + auto* db_options = reinterpret_cast<rocksdb::DBOptions*>(jdb_options_handle); + std::vector<rocksdb::ColumnFamilyHandle*> handles; + rocksdb::OptimisticTransactionDB* otdb = nullptr; + const rocksdb::Status s = rocksdb::OptimisticTransactionDB::Open( + *db_options, db_path, column_families, &handles, &otdb); + + env->ReleaseStringUTFChars(jdb_path, db_path); + + // check if open operation was successful + if (s.ok()) { + const jsize resultsLen = 1 + len_cols; // db handle + column family handles + std::unique_ptr<jlong[]> results = + std::unique_ptr<jlong[]>(new jlong[resultsLen]); + results[0] = reinterpret_cast<jlong>(otdb); + for (int i = 1; i <= len_cols; i++) { + results[i] = reinterpret_cast<jlong>(handles[i - 1]); + } + + jlongArray jresults = env->NewLongArray(resultsLen); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetLongArrayRegion(jresults, 0, resultsLen, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return nullptr; + } + return jresults; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_OptimisticTransactionDB_disposeInternal( + JNIEnv *, jobject, jlong jhandle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + assert(optimistic_txn_db != nullptr); + delete optimistic_txn_db; +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: closeDatabase + * Signature: (J)V + */ +void Java_org_rocksdb_OptimisticTransactionDB_closeDatabase( + JNIEnv* env, jclass, jlong jhandle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + assert(optimistic_txn_db != nullptr); + rocksdb::Status s = optimistic_txn_db->Close(); + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: beginTransaction + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction__JJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + rocksdb::Transaction* txn = + optimistic_txn_db->BeginTransaction(*write_options); + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: beginTransaction + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction__JJJ( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jwrite_options_handle, jlong joptimistic_txn_options_handle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* optimistic_txn_options = + reinterpret_cast<rocksdb::OptimisticTransactionOptions*>( + joptimistic_txn_options_handle); + rocksdb::Transaction* txn = optimistic_txn_db->BeginTransaction( + *write_options, *optimistic_txn_options); + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: beginTransaction_withOld + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction_1withOld__JJJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle, + jlong jold_txn_handle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle); + rocksdb::OptimisticTransactionOptions optimistic_txn_options; + rocksdb::Transaction* txn = optimistic_txn_db->BeginTransaction( + *write_options, optimistic_txn_options, old_txn); + + // RocksJava relies on the assumption that + // we do not allocate a new Transaction object + // when providing an old_optimistic_txn + assert(txn == old_txn); + + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: beginTransaction_withOld + * Signature: (JJJJ)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction_1withOld__JJJJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle, + jlong joptimistic_txn_options_handle, jlong jold_txn_handle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* optimistic_txn_options = + reinterpret_cast<rocksdb::OptimisticTransactionOptions*>( + joptimistic_txn_options_handle); + auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle); + rocksdb::Transaction* txn = optimistic_txn_db->BeginTransaction( + *write_options, *optimistic_txn_options, old_txn); + + // RocksJava relies on the assumption that + // we do not allocate a new Transaction object + // when providing an old_optimisic_txn + assert(txn == old_txn); + + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_OptimisticTransactionDB + * Method: getBaseDB + * Signature: (J)J + */ +jlong Java_org_rocksdb_OptimisticTransactionDB_getBaseDB( + JNIEnv*, jobject, jlong jhandle) { + auto* optimistic_txn_db = + reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle); + return reinterpret_cast<jlong>(optimistic_txn_db->GetBaseDB()); +} diff --git a/src/rocksdb/java/rocksjni/optimistic_transaction_options.cc b/src/rocksdb/java/rocksjni/optimistic_transaction_options.cc new file mode 100644 index 00000000..3eee4466 --- /dev/null +++ b/src/rocksdb/java/rocksjni/optimistic_transaction_options.cc @@ -0,0 +1,73 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::OptimisticTransactionOptions. + +#include <jni.h> + +#include "include/org_rocksdb_OptimisticTransactionOptions.h" + +#include "rocksdb/comparator.h" +#include "rocksdb/utilities/optimistic_transaction_db.h" + +/* + * Class: org_rocksdb_OptimisticTransactionOptions + * Method: newOptimisticTransactionOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_OptimisticTransactionOptions_newOptimisticTransactionOptions( + JNIEnv* /*env*/, jclass /*jcls*/) { + rocksdb::OptimisticTransactionOptions* opts = + new rocksdb::OptimisticTransactionOptions(); + return reinterpret_cast<jlong>(opts); +} + +/* + * Class: org_rocksdb_OptimisticTransactionOptions + * Method: isSetSnapshot + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_OptimisticTransactionOptions_isSetSnapshot( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* opts = + reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle); + return opts->set_snapshot; +} + +/* + * Class: org_rocksdb_OptimisticTransactionOptions + * Method: setSetSnapshot + * Signature: (JZ)V + */ +void Java_org_rocksdb_OptimisticTransactionOptions_setSetSnapshot( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean jset_snapshot) { + auto* opts = + reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle); + opts->set_snapshot = jset_snapshot; +} + +/* + * Class: org_rocksdb_OptimisticTransactionOptions + * Method: setComparator + * Signature: (JJ)V + */ +void Java_org_rocksdb_OptimisticTransactionOptions_setComparator( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jcomparator_handle) { + auto* opts = + reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle); + opts->cmp = reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle); +} + +/* + * Class: org_rocksdb_OptimisticTransactionOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_OptimisticTransactionOptions_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + delete reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/options.cc b/src/rocksdb/java/rocksjni/options.cc new file mode 100644 index 00000000..12f44b5e --- /dev/null +++ b/src/rocksdb/java/rocksjni/options.cc @@ -0,0 +1,6800 @@ +// 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 "bridge" between Java and C++ for rocksdb::Options. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory> +#include <vector> + +#include "include/org_rocksdb_ColumnFamilyOptions.h" +#include "include/org_rocksdb_ComparatorOptions.h" +#include "include/org_rocksdb_DBOptions.h" +#include "include/org_rocksdb_FlushOptions.h" +#include "include/org_rocksdb_Options.h" +#include "include/org_rocksdb_ReadOptions.h" +#include "include/org_rocksdb_WriteOptions.h" + +#include "rocksjni/comparatorjnicallback.h" +#include "rocksjni/portal.h" +#include "rocksjni/statisticsjni.h" +#include "rocksjni/table_filter_jnicallback.h" + +#include "rocksdb/comparator.h" +#include "rocksdb/convenience.h" +#include "rocksdb/db.h" +#include "rocksdb/memtablerep.h" +#include "rocksdb/merge_operator.h" +#include "rocksdb/options.h" +#include "rocksdb/rate_limiter.h" +#include "rocksdb/slice_transform.h" +#include "rocksdb/statistics.h" +#include "rocksdb/table.h" +#include "utilities/merge_operators.h" + +/* + * Class: org_rocksdb_Options + * Method: newOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_Options_newOptions__( + JNIEnv*, jclass) { + auto* op = new rocksdb::Options(); + return reinterpret_cast<jlong>(op); +} + +/* + * Class: org_rocksdb_Options + * Method: newOptions + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_Options_newOptions__JJ( + JNIEnv*, jclass, jlong jdboptions, jlong jcfoptions) { + auto* dbOpt = reinterpret_cast<const rocksdb::DBOptions*>(jdboptions); + auto* cfOpt = + reinterpret_cast<const rocksdb::ColumnFamilyOptions*>(jcfoptions); + auto* op = new rocksdb::Options(*dbOpt, *cfOpt); + return reinterpret_cast<jlong>(op); +} + +/* + * Class: org_rocksdb_Options + * Method: copyOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_copyOptions( + JNIEnv*, jclass, jlong jhandle) { + auto new_opt = + new rocksdb::Options(*(reinterpret_cast<rocksdb::Options*>(jhandle))); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_Options + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_Options_disposeInternal( + JNIEnv*, jobject, jlong handle) { + auto* op = reinterpret_cast<rocksdb::Options*>(handle); + assert(op != nullptr); + delete op; +} + +/* + * Class: org_rocksdb_Options + * Method: setIncreaseParallelism + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setIncreaseParallelism( + JNIEnv*, jobject, jlong jhandle, jint totalThreads) { + reinterpret_cast<rocksdb::Options*>(jhandle)->IncreaseParallelism( + static_cast<int>(totalThreads)); +} + +/* + * Class: org_rocksdb_Options + * Method: setCreateIfMissing + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setCreateIfMissing( + JNIEnv*, jobject, jlong jhandle, jboolean flag) { + reinterpret_cast<rocksdb::Options*>(jhandle)->create_if_missing = flag; +} + +/* + * Class: org_rocksdb_Options + * Method: createIfMissing + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_createIfMissing( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->create_if_missing; +} + +/* + * Class: org_rocksdb_Options + * Method: setCreateMissingColumnFamilies + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setCreateMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle, jboolean flag) { + reinterpret_cast<rocksdb::Options*>(jhandle)->create_missing_column_families = + flag; +} + +/* + * Class: org_rocksdb_Options + * Method: createMissingColumnFamilies + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_createMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->create_missing_column_families; +} + +/* + * Class: org_rocksdb_Options + * Method: setComparatorHandle + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setComparatorHandle__JI( + JNIEnv*, jobject, jlong jhandle, jint builtinComparator) { + switch (builtinComparator) { + case 1: + reinterpret_cast<rocksdb::Options*>(jhandle)->comparator = + rocksdb::ReverseBytewiseComparator(); + break; + default: + reinterpret_cast<rocksdb::Options*>(jhandle)->comparator = + rocksdb::BytewiseComparator(); + break; + } +} + +/* + * Class: org_rocksdb_Options + * Method: setComparatorHandle + * Signature: (JJB)V + */ +void Java_org_rocksdb_Options_setComparatorHandle__JJB( + JNIEnv*, jobject, jlong jopt_handle, jlong jcomparator_handle, + jbyte jcomparator_type) { + rocksdb::Comparator* comparator = nullptr; + switch (jcomparator_type) { + // JAVA_COMPARATOR + case 0x0: + comparator = + reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle); + break; + + // JAVA_DIRECT_COMPARATOR + case 0x1: + comparator = reinterpret_cast<rocksdb::DirectComparatorJniCallback*>( + jcomparator_handle); + break; + + // JAVA_NATIVE_COMPARATOR_WRAPPER + case 0x2: + comparator = reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle); + break; + } + auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle); + opt->comparator = comparator; +} + +/* + * Class: org_rocksdb_Options + * Method: setMergeOperatorName + * Signature: (JJjava/lang/String)V + */ +void Java_org_rocksdb_Options_setMergeOperatorName( + JNIEnv* env, jobject, jlong jhandle, jstring jop_name) { + const char* op_name = env->GetStringUTFChars(jop_name, nullptr); + if (op_name == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + options->merge_operator = + rocksdb::MergeOperators::CreateFromStringId(op_name); + + env->ReleaseStringUTFChars(jop_name, op_name); +} + +/* + * Class: org_rocksdb_Options + * Method: setMergeOperator + * Signature: (JJjava/lang/String)V + */ +void Java_org_rocksdb_Options_setMergeOperator( + JNIEnv*, jobject, jlong jhandle, jlong mergeOperatorHandle) { + reinterpret_cast<rocksdb::Options*>(jhandle)->merge_operator = + *(reinterpret_cast<std::shared_ptr<rocksdb::MergeOperator>*>( + mergeOperatorHandle)); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionFilterHandle + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setCompactionFilterHandle( + JNIEnv*, jobject, jlong jopt_handle, + jlong jcompactionfilter_handle) { + reinterpret_cast<rocksdb::Options*>(jopt_handle)-> + compaction_filter = reinterpret_cast<rocksdb::CompactionFilter*> + (jcompactionfilter_handle); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionFilterFactoryHandle + * Signature: (JJ)V + */ +void JNICALL Java_org_rocksdb_Options_setCompactionFilterFactoryHandle( + JNIEnv*, jobject, jlong jopt_handle, + jlong jcompactionfilterfactory_handle) { + auto* cff_factory = + reinterpret_cast<std::shared_ptr<rocksdb::CompactionFilterFactory> *>( + jcompactionfilterfactory_handle); + reinterpret_cast<rocksdb::Options*>(jopt_handle)-> + compaction_filter_factory = *cff_factory; +} + +/* + * Class: org_rocksdb_Options + * Method: setWriteBufferSize + * Signature: (JJ)I + */ +void Java_org_rocksdb_Options_setWriteBufferSize( + JNIEnv* env, jobject, jlong jhandle, jlong jwrite_buffer_size) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jwrite_buffer_size); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->write_buffer_size = + jwrite_buffer_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: setWriteBufferManager + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWriteBufferManager( + JNIEnv*, jobject, jlong joptions_handle, + jlong jwrite_buffer_manager_handle) { + auto* write_buffer_manager = + reinterpret_cast<std::shared_ptr<rocksdb::WriteBufferManager> *>(jwrite_buffer_manager_handle); + reinterpret_cast<rocksdb::Options*>(joptions_handle)->write_buffer_manager = + *write_buffer_manager; +} + +/* + * Class: org_rocksdb_Options + * Method: writeBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_writeBufferSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->write_buffer_size; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxWriteBufferNumber + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxWriteBufferNumber( + JNIEnv*, jobject, jlong jhandle, + jint jmax_write_buffer_number) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_write_buffer_number = + jmax_write_buffer_number; +} + +/* + * Class: org_rocksdb_Options + * Method: setStatistics + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setStatistics( + JNIEnv*, jobject, jlong jhandle, jlong jstatistics_handle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* pSptr = reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>( + jstatistics_handle); + opt->statistics = *pSptr; +} + +/* + * Class: org_rocksdb_Options + * Method: statistics + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_statistics( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + std::shared_ptr<rocksdb::Statistics> sptr = opt->statistics; + if (sptr == nullptr) { + return 0; + } else { + std::shared_ptr<rocksdb::Statistics>* pSptr = + new std::shared_ptr<rocksdb::Statistics>(sptr); + return reinterpret_cast<jlong>(pSptr); + } +} + +/* + * Class: org_rocksdb_Options + * Method: maxWriteBufferNumber + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxWriteBufferNumber( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_write_buffer_number; +} + +/* + * Class: org_rocksdb_Options + * Method: errorIfExists + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_errorIfExists( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->error_if_exists; +} + +/* + * Class: org_rocksdb_Options + * Method: setErrorIfExists + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setErrorIfExists( + JNIEnv*, jobject, jlong jhandle, jboolean error_if_exists) { + reinterpret_cast<rocksdb::Options*>(jhandle)->error_if_exists = + static_cast<bool>(error_if_exists); +} + +/* + * Class: org_rocksdb_Options + * Method: paranoidChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_paranoidChecks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->paranoid_checks; +} + +/* + * Class: org_rocksdb_Options + * Method: setParanoidChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setParanoidChecks( + JNIEnv*, jobject, jlong jhandle, jboolean paranoid_checks) { + reinterpret_cast<rocksdb::Options*>(jhandle)->paranoid_checks = + static_cast<bool>(paranoid_checks); +} + +/* + * Class: org_rocksdb_Options + * Method: setEnv + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setEnv( + JNIEnv*, jobject, jlong jhandle, jlong jenv) { + reinterpret_cast<rocksdb::Options*>(jhandle)->env = + reinterpret_cast<rocksdb::Env*>(jenv); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxTotalWalSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxTotalWalSize( + JNIEnv*, jobject, jlong jhandle, jlong jmax_total_wal_size) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_total_wal_size = + static_cast<jlong>(jmax_total_wal_size); +} + +/* + * Class: org_rocksdb_Options + * Method: maxTotalWalSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxTotalWalSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_total_wal_size; +} + +/* + * Class: org_rocksdb_Options + * Method: maxOpenFiles + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxOpenFiles( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_open_files; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxOpenFiles + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxOpenFiles( + JNIEnv*, jobject, jlong jhandle, jint max_open_files) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_open_files = + static_cast<int>(max_open_files); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxFileOpeningThreads + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxFileOpeningThreads( + JNIEnv*, jobject, jlong jhandle, jint jmax_file_opening_threads) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_file_opening_threads = + static_cast<int>(jmax_file_opening_threads); +} + +/* + * Class: org_rocksdb_Options + * Method: maxFileOpeningThreads + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxFileOpeningThreads( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<int>(opt->max_file_opening_threads); +} + +/* + * Class: org_rocksdb_Options + * Method: useFsync + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_useFsync( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->use_fsync; +} + +/* + * Class: org_rocksdb_Options + * Method: setUseFsync + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setUseFsync( + JNIEnv*, jobject, jlong jhandle, jboolean use_fsync) { + reinterpret_cast<rocksdb::Options*>(jhandle)->use_fsync = + static_cast<bool>(use_fsync); +} + +/* + * Class: org_rocksdb_Options + * Method: setDbPaths + * Signature: (J[Ljava/lang/String;[J)V + */ +void Java_org_rocksdb_Options_setDbPaths( + JNIEnv* env, jobject, jlong jhandle, jobjectArray jpaths, + jlongArray jtarget_sizes) { + std::vector<rocksdb::DbPath> db_paths; + jlong* ptr_jtarget_size = env->GetLongArrayElements(jtarget_sizes, nullptr); + if (ptr_jtarget_size == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + jboolean has_exception = JNI_FALSE; + const jsize len = env->GetArrayLength(jpaths); + for (jsize i = 0; i < len; i++) { + jobject jpath = + reinterpret_cast<jstring>(env->GetObjectArrayElement(jpaths, i)); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + std::string path = rocksdb::JniUtil::copyStdString( + env, static_cast<jstring>(jpath), &has_exception); + env->DeleteLocalRef(jpath); + + if (has_exception == JNI_TRUE) { + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + + jlong jtarget_size = ptr_jtarget_size[i]; + + db_paths.push_back( + rocksdb::DbPath(path, static_cast<uint64_t>(jtarget_size))); + } + + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->db_paths = db_paths; +} + +/* + * Class: org_rocksdb_Options + * Method: dbPathsLen + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_dbPathsLen( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->db_paths.size()); +} + +/* + * Class: org_rocksdb_Options + * Method: dbPaths + * Signature: (J[Ljava/lang/String;[J)V + */ +void Java_org_rocksdb_Options_dbPaths( + JNIEnv* env, jobject, jlong jhandle, jobjectArray jpaths, + jlongArray jtarget_sizes) { + jlong* ptr_jtarget_size = env->GetLongArrayElements(jtarget_sizes, nullptr); + if (ptr_jtarget_size == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + const jsize len = env->GetArrayLength(jpaths); + for (jsize i = 0; i < len; i++) { + rocksdb::DbPath db_path = opt->db_paths[i]; + + jstring jpath = env->NewStringUTF(db_path.path.c_str()); + if (jpath == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + env->SetObjectArrayElement(jpaths, i, jpath); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jpath); + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + + ptr_jtarget_size[i] = static_cast<jint>(db_path.target_size); + } + + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_COMMIT); +} + +/* + * Class: org_rocksdb_Options + * Method: dbLogDir + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_Options_dbLogDir( + JNIEnv* env, jobject, jlong jhandle) { + return env->NewStringUTF( + reinterpret_cast<rocksdb::Options*>(jhandle)->db_log_dir.c_str()); +} + +/* + * Class: org_rocksdb_Options + * Method: setDbLogDir + * Signature: (JLjava/lang/String)V + */ +void Java_org_rocksdb_Options_setDbLogDir( + JNIEnv* env, jobject, jlong jhandle, jstring jdb_log_dir) { + const char* log_dir = env->GetStringUTFChars(jdb_log_dir, nullptr); + if (log_dir == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + reinterpret_cast<rocksdb::Options*>(jhandle)->db_log_dir.assign(log_dir); + env->ReleaseStringUTFChars(jdb_log_dir, log_dir); +} + +/* + * Class: org_rocksdb_Options + * Method: walDir + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_Options_walDir( + JNIEnv* env, jobject, jlong jhandle) { + return env->NewStringUTF( + reinterpret_cast<rocksdb::Options*>(jhandle)->wal_dir.c_str()); +} + +/* + * Class: org_rocksdb_Options + * Method: setWalDir + * Signature: (JLjava/lang/String)V + */ +void Java_org_rocksdb_Options_setWalDir( + JNIEnv* env, jobject, jlong jhandle, jstring jwal_dir) { + const char* wal_dir = env->GetStringUTFChars(jwal_dir, nullptr); + if (wal_dir == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + reinterpret_cast<rocksdb::Options*>(jhandle)->wal_dir.assign(wal_dir); + env->ReleaseStringUTFChars(jwal_dir, wal_dir); +} + +/* + * Class: org_rocksdb_Options + * Method: deleteObsoleteFilesPeriodMicros + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_deleteObsoleteFilesPeriodMicros( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->delete_obsolete_files_period_micros; +} + +/* + * Class: org_rocksdb_Options + * Method: setDeleteObsoleteFilesPeriodMicros + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setDeleteObsoleteFilesPeriodMicros( + JNIEnv*, jobject, jlong jhandle, jlong micros) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->delete_obsolete_files_period_micros = static_cast<int64_t>(micros); +} + +/* + * Class: org_rocksdb_Options + * Method: setBaseBackgroundCompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setBaseBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::Options*>(jhandle)->base_background_compactions = + static_cast<int>(max); +} + +/* + * Class: org_rocksdb_Options + * Method: baseBackgroundCompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_baseBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->base_background_compactions; +} + +/* + * Class: org_rocksdb_Options + * Method: maxBackgroundCompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_background_compactions; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBackgroundCompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_background_compactions = + static_cast<int>(max); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxSubcompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxSubcompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_subcompactions = + static_cast<int32_t>(max); +} + +/* + * Class: org_rocksdb_Options + * Method: maxSubcompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxSubcompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_subcompactions; +} + +/* + * Class: org_rocksdb_Options + * Method: maxBackgroundFlushes + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxBackgroundFlushes( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_background_flushes; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBackgroundFlushes + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxBackgroundFlushes( + JNIEnv*, jobject, jlong jhandle, jint max_background_flushes) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_background_flushes = + static_cast<int>(max_background_flushes); +} + +/* + * Class: org_rocksdb_Options + * Method: maxBackgroundJobs + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxBackgroundJobs( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_background_jobs; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBackgroundJobs + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxBackgroundJobs( + JNIEnv*, jobject, jlong jhandle, jint max_background_jobs) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_background_jobs = + static_cast<int>(max_background_jobs); +} + +/* + * Class: org_rocksdb_Options + * Method: maxLogFileSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxLogFileSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_log_file_size; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxLogFileSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxLogFileSize( + JNIEnv* env, jobject, jlong jhandle, jlong max_log_file_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(max_log_file_size); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_log_file_size = + max_log_file_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: logFileTimeToRoll + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_logFileTimeToRoll( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->log_file_time_to_roll; +} + +/* + * Class: org_rocksdb_Options + * Method: setLogFileTimeToRoll + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setLogFileTimeToRoll( + JNIEnv* env, jobject, jlong jhandle, jlong log_file_time_to_roll) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(log_file_time_to_roll); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->log_file_time_to_roll = + log_file_time_to_roll; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: keepLogFileNum + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_keepLogFileNum( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->keep_log_file_num; +} + +/* + * Class: org_rocksdb_Options + * Method: setKeepLogFileNum + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setKeepLogFileNum( + JNIEnv* env, jobject, jlong jhandle, jlong keep_log_file_num) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(keep_log_file_num); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->keep_log_file_num = + keep_log_file_num; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: recycleLogFileNum + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_recycleLogFileNum( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->recycle_log_file_num; +} + +/* + * Class: org_rocksdb_Options + * Method: setRecycleLogFileNum + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setRecycleLogFileNum( + JNIEnv* env, jobject, jlong jhandle, jlong recycle_log_file_num) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(recycle_log_file_num); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->recycle_log_file_num = + recycle_log_file_num; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: maxManifestFileSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxManifestFileSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_manifest_file_size; +} + +/* + * Method: memTableFactoryName + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_Options_memTableFactoryName( + JNIEnv* env, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + rocksdb::MemTableRepFactory* tf = opt->memtable_factory.get(); + + // Should never be nullptr. + // Default memtable factory is SkipListFactory + assert(tf); + + // temporarly fix for the historical typo + if (strcmp(tf->Name(), "HashLinkListRepFactory") == 0) { + return env->NewStringUTF("HashLinkedListRepFactory"); + } + + return env->NewStringUTF(tf->Name()); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxManifestFileSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxManifestFileSize( + JNIEnv*, jobject, jlong jhandle, jlong max_manifest_file_size) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_manifest_file_size = + static_cast<int64_t>(max_manifest_file_size); +} + +/* + * Method: setMemTableFactory + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMemTableFactory( + JNIEnv*, jobject, jlong jhandle, jlong jfactory_handle) { + reinterpret_cast<rocksdb::Options*>(jhandle)->memtable_factory.reset( + reinterpret_cast<rocksdb::MemTableRepFactory*>(jfactory_handle)); +} + +/* + * Class: org_rocksdb_Options + * Method: setRateLimiter + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setRateLimiter( + JNIEnv*, jobject, jlong jhandle, jlong jrate_limiter_handle) { + std::shared_ptr<rocksdb::RateLimiter>* pRateLimiter = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>( + jrate_limiter_handle); + reinterpret_cast<rocksdb::Options*>(jhandle)->rate_limiter = *pRateLimiter; +} + +/* + * Class: org_rocksdb_Options + * Method: setSstFileManager + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setSstFileManager( + JNIEnv*, jobject, jlong jhandle, jlong jsst_file_manager_handle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>( + jsst_file_manager_handle); + reinterpret_cast<rocksdb::Options*>(jhandle)->sst_file_manager = + *sptr_sst_file_manager; +} + +/* + * Class: org_rocksdb_Options + * Method: setLogger + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setLogger( + JNIEnv*, jobject, jlong jhandle, jlong jlogger_handle) { + std::shared_ptr<rocksdb::LoggerJniCallback>* pLogger = + reinterpret_cast<std::shared_ptr<rocksdb::LoggerJniCallback>*>( + jlogger_handle); + reinterpret_cast<rocksdb::Options*>(jhandle)->info_log = *pLogger; +} + +/* + * Class: org_rocksdb_Options + * Method: setInfoLogLevel + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setInfoLogLevel( + JNIEnv*, jobject, jlong jhandle, jbyte jlog_level) { + reinterpret_cast<rocksdb::Options*>(jhandle)->info_log_level = + static_cast<rocksdb::InfoLogLevel>(jlog_level); +} + +/* + * Class: org_rocksdb_Options + * Method: infoLogLevel + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_infoLogLevel( + JNIEnv*, jobject, jlong jhandle) { + return static_cast<jbyte>( + reinterpret_cast<rocksdb::Options*>(jhandle)->info_log_level); +} + +/* + * Class: org_rocksdb_Options + * Method: tableCacheNumshardbits + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_tableCacheNumshardbits( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->table_cache_numshardbits; +} + +/* + * Class: org_rocksdb_Options + * Method: setTableCacheNumshardbits + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setTableCacheNumshardbits( + JNIEnv*, jobject, jlong jhandle, jint table_cache_numshardbits) { + reinterpret_cast<rocksdb::Options*>(jhandle)->table_cache_numshardbits = + static_cast<int>(table_cache_numshardbits); +} + +/* + * Method: useFixedLengthPrefixExtractor + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_useFixedLengthPrefixExtractor( + JNIEnv*, jobject, jlong jhandle, jint jprefix_length) { + reinterpret_cast<rocksdb::Options*>(jhandle)->prefix_extractor.reset( + rocksdb::NewFixedPrefixTransform(static_cast<int>(jprefix_length))); +} + +/* + * Method: useCappedPrefixExtractor + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_useCappedPrefixExtractor( + JNIEnv*, jobject, jlong jhandle, jint jprefix_length) { + reinterpret_cast<rocksdb::Options*>(jhandle)->prefix_extractor.reset( + rocksdb::NewCappedPrefixTransform(static_cast<int>(jprefix_length))); +} + +/* + * Class: org_rocksdb_Options + * Method: walTtlSeconds + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_walTtlSeconds( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->WAL_ttl_seconds; +} + +/* + * Class: org_rocksdb_Options + * Method: setWalTtlSeconds + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWalTtlSeconds( + JNIEnv*, jobject, jlong jhandle, jlong WAL_ttl_seconds) { + reinterpret_cast<rocksdb::Options*>(jhandle)->WAL_ttl_seconds = + static_cast<int64_t>(WAL_ttl_seconds); +} + +/* + * Class: org_rocksdb_Options + * Method: walTtlSeconds + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_walSizeLimitMB( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->WAL_size_limit_MB; +} + +/* + * Class: org_rocksdb_Options + * Method: setWalSizeLimitMB + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWalSizeLimitMB( + JNIEnv*, jobject, jlong jhandle, jlong WAL_size_limit_MB) { + reinterpret_cast<rocksdb::Options*>(jhandle)->WAL_size_limit_MB = + static_cast<int64_t>(WAL_size_limit_MB); +} + +/* + * Class: org_rocksdb_Options + * Method: manifestPreallocationSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_manifestPreallocationSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->manifest_preallocation_size; +} + +/* + * Class: org_rocksdb_Options + * Method: setManifestPreallocationSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setManifestPreallocationSize( + JNIEnv* env, jobject, jlong jhandle, jlong preallocation_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(preallocation_size); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->manifest_preallocation_size = + preallocation_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Method: setTableFactory + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setTableFactory( + JNIEnv*, jobject, jlong jhandle, jlong jtable_factory_handle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* table_factory = + reinterpret_cast<rocksdb::TableFactory*>(jtable_factory_handle); + options->table_factory.reset(table_factory); +} + +/* + * Class: org_rocksdb_Options + * Method: allowMmapReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allowMmapReads( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->allow_mmap_reads; +} + +/* + * Class: org_rocksdb_Options + * Method: setAllowMmapReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllowMmapReads( + JNIEnv*, jobject, jlong jhandle, jboolean allow_mmap_reads) { + reinterpret_cast<rocksdb::Options*>(jhandle)->allow_mmap_reads = + static_cast<bool>(allow_mmap_reads); +} + +/* + * Class: org_rocksdb_Options + * Method: allowMmapWrites + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allowMmapWrites( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->allow_mmap_writes; +} + +/* + * Class: org_rocksdb_Options + * Method: setAllowMmapWrites + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllowMmapWrites( + JNIEnv*, jobject, jlong jhandle, jboolean allow_mmap_writes) { + reinterpret_cast<rocksdb::Options*>(jhandle)->allow_mmap_writes = + static_cast<bool>(allow_mmap_writes); +} + +/* + * Class: org_rocksdb_Options + * Method: useDirectReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_useDirectReads( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->use_direct_reads; +} + +/* + * Class: org_rocksdb_Options + * Method: setUseDirectReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setUseDirectReads( + JNIEnv*, jobject, jlong jhandle, jboolean use_direct_reads) { + reinterpret_cast<rocksdb::Options*>(jhandle)->use_direct_reads = + static_cast<bool>(use_direct_reads); +} + +/* + * Class: org_rocksdb_Options + * Method: useDirectIoForFlushAndCompaction + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_useDirectIoForFlushAndCompaction( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->use_direct_io_for_flush_and_compaction; +} + +/* + * Class: org_rocksdb_Options + * Method: setUseDirectIoForFlushAndCompaction + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setUseDirectIoForFlushAndCompaction( + JNIEnv*, jobject, jlong jhandle, + jboolean use_direct_io_for_flush_and_compaction) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->use_direct_io_for_flush_and_compaction = + static_cast<bool>(use_direct_io_for_flush_and_compaction); +} + +/* + * Class: org_rocksdb_Options + * Method: setAllowFAllocate + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllowFAllocate( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_fallocate) { + reinterpret_cast<rocksdb::Options*>(jhandle)->allow_fallocate = + static_cast<bool>(jallow_fallocate); +} + +/* + * Class: org_rocksdb_Options + * Method: allowFAllocate + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allowFAllocate( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->allow_fallocate); +} + +/* + * Class: org_rocksdb_Options + * Method: isFdCloseOnExec + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_isFdCloseOnExec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->is_fd_close_on_exec; +} + +/* + * Class: org_rocksdb_Options + * Method: setIsFdCloseOnExec + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setIsFdCloseOnExec( + JNIEnv*, jobject, jlong jhandle, jboolean is_fd_close_on_exec) { + reinterpret_cast<rocksdb::Options*>(jhandle)->is_fd_close_on_exec = + static_cast<bool>(is_fd_close_on_exec); +} + +/* + * Class: org_rocksdb_Options + * Method: statsDumpPeriodSec + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_statsDumpPeriodSec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->stats_dump_period_sec; +} + +/* + * Class: org_rocksdb_Options + * Method: setStatsDumpPeriodSec + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setStatsDumpPeriodSec( + JNIEnv*, jobject, jlong jhandle, + jint stats_dump_period_sec) { + reinterpret_cast<rocksdb::Options*>(jhandle)->stats_dump_period_sec = + static_cast<int>(stats_dump_period_sec); +} + +/* + * Class: org_rocksdb_Options + * Method: adviseRandomOnOpen + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_adviseRandomOnOpen( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->advise_random_on_open; +} + +/* + * Class: org_rocksdb_Options + * Method: setAdviseRandomOnOpen + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAdviseRandomOnOpen( + JNIEnv*, jobject, jlong jhandle, + jboolean advise_random_on_open) { + reinterpret_cast<rocksdb::Options*>(jhandle)->advise_random_on_open = + static_cast<bool>(advise_random_on_open); +} + +/* + * Class: org_rocksdb_Options + * Method: setDbWriteBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setDbWriteBufferSize( + JNIEnv*, jobject, jlong jhandle, + jlong jdb_write_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->db_write_buffer_size = static_cast<size_t>(jdb_write_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: dbWriteBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_dbWriteBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->db_write_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: setAccessHintOnCompactionStart + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setAccessHintOnCompactionStart( + JNIEnv*, jobject, jlong jhandle, + jbyte jaccess_hint_value) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->access_hint_on_compaction_start = + rocksdb::AccessHintJni::toCppAccessHint(jaccess_hint_value); +} + +/* + * Class: org_rocksdb_Options + * Method: accessHintOnCompactionStart + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_accessHintOnCompactionStart( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::AccessHintJni::toJavaAccessHint( + opt->access_hint_on_compaction_start); +} + +/* + * Class: org_rocksdb_Options + * Method: setNewTableReaderForCompactionInputs + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setNewTableReaderForCompactionInputs( + JNIEnv*, jobject, jlong jhandle, + jboolean jnew_table_reader_for_compaction_inputs) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->new_table_reader_for_compaction_inputs = + static_cast<bool>(jnew_table_reader_for_compaction_inputs); +} + +/* + * Class: org_rocksdb_Options + * Method: newTableReaderForCompactionInputs + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_newTableReaderForCompactionInputs( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<bool>(opt->new_table_reader_for_compaction_inputs); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionReadaheadSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setCompactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle, + jlong jcompaction_readahead_size) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->compaction_readahead_size = + static_cast<size_t>(jcompaction_readahead_size); +} + +/* + * Class: org_rocksdb_Options + * Method: compactionReadaheadSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_compactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->compaction_readahead_size); +} + +/* + * Class: org_rocksdb_Options + * Method: setRandomAccessMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setRandomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong jrandom_access_max_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->random_access_max_buffer_size = + static_cast<size_t>(jrandom_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: randomAccessMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_randomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->random_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: setWritableFileMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWritableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, + jlong jwritable_file_max_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->writable_file_max_buffer_size = + static_cast<size_t>(jwritable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: writableFileMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_writableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->writable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_Options + * Method: useAdaptiveMutex + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_useAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->use_adaptive_mutex; +} + +/* + * Class: org_rocksdb_Options + * Method: setUseAdaptiveMutex + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setUseAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle, jboolean use_adaptive_mutex) { + reinterpret_cast<rocksdb::Options*>(jhandle)->use_adaptive_mutex = + static_cast<bool>(use_adaptive_mutex); +} + +/* + * Class: org_rocksdb_Options + * Method: bytesPerSync + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_bytesPerSync( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->bytes_per_sync; +} + +/* + * Class: org_rocksdb_Options + * Method: setBytesPerSync + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setBytesPerSync( + JNIEnv*, jobject, jlong jhandle, jlong bytes_per_sync) { + reinterpret_cast<rocksdb::Options*>(jhandle)->bytes_per_sync = + static_cast<int64_t>(bytes_per_sync); +} + +/* + * Class: org_rocksdb_Options + * Method: setWalBytesPerSync + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWalBytesPerSync( + JNIEnv*, jobject, jlong jhandle, jlong jwal_bytes_per_sync) { + reinterpret_cast<rocksdb::Options*>(jhandle)->wal_bytes_per_sync = + static_cast<int64_t>(jwal_bytes_per_sync); +} + +/* + * Class: org_rocksdb_Options + * Method: walBytesPerSync + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_walBytesPerSync( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->wal_bytes_per_sync); +} + +/* + * Class: org_rocksdb_Options + * Method: setEnableThreadTracking + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setEnableThreadTracking( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_thread_tracking) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->enable_thread_tracking = static_cast<bool>(jenable_thread_tracking); +} + +/* + * Class: org_rocksdb_Options + * Method: enableThreadTracking + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_enableThreadTracking( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->enable_thread_tracking); +} + +/* + * Class: org_rocksdb_Options + * Method: setDelayedWriteRate + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setDelayedWriteRate( + JNIEnv*, jobject, jlong jhandle, jlong jdelayed_write_rate) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->delayed_write_rate = static_cast<uint64_t>(jdelayed_write_rate); +} + +/* + * Class: org_rocksdb_Options + * Method: delayedWriteRate + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_delayedWriteRate( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opt->delayed_write_rate); +} + +/* + * Class: org_rocksdb_Options + * Method: setEnablePipelinedWrite + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setEnablePipelinedWrite( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_pipelined_write) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->enable_pipelined_write = jenable_pipelined_write == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: enablePipelinedWrite + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_enablePipelinedWrite( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->enable_pipelined_write); +} + +/* + * Class: org_rocksdb_Options + * Method: setAllowConcurrentMemtableWrite + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllowConcurrentMemtableWrite( + JNIEnv*, jobject, jlong jhandle, jboolean allow) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->allow_concurrent_memtable_write = static_cast<bool>(allow); +} + +/* + * Class: org_rocksdb_Options + * Method: allowConcurrentMemtableWrite + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allowConcurrentMemtableWrite( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->allow_concurrent_memtable_write; +} + +/* + * Class: org_rocksdb_Options + * Method: setEnableWriteThreadAdaptiveYield + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setEnableWriteThreadAdaptiveYield( + JNIEnv*, jobject, jlong jhandle, jboolean yield) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->enable_write_thread_adaptive_yield = static_cast<bool>(yield); +} + +/* + * Class: org_rocksdb_Options + * Method: enableWriteThreadAdaptiveYield + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_enableWriteThreadAdaptiveYield( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->enable_write_thread_adaptive_yield; +} + +/* + * Class: org_rocksdb_Options + * Method: setWriteThreadMaxYieldUsec + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWriteThreadMaxYieldUsec( + JNIEnv*, jobject, jlong jhandle, jlong max) { + reinterpret_cast<rocksdb::Options*>(jhandle)->write_thread_max_yield_usec = + static_cast<int64_t>(max); +} + +/* + * Class: org_rocksdb_Options + * Method: writeThreadMaxYieldUsec + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_writeThreadMaxYieldUsec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->write_thread_max_yield_usec; +} + +/* + * Class: org_rocksdb_Options + * Method: setWriteThreadSlowYieldUsec + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWriteThreadSlowYieldUsec( + JNIEnv*, jobject, jlong jhandle, jlong slow) { + reinterpret_cast<rocksdb::Options*>(jhandle)->write_thread_slow_yield_usec = + static_cast<int64_t>(slow); +} + +/* + * Class: org_rocksdb_Options + * Method: writeThreadSlowYieldUsec + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_writeThreadSlowYieldUsec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->write_thread_slow_yield_usec; +} + +/* + * Class: org_rocksdb_Options + * Method: setSkipStatsUpdateOnDbOpen + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setSkipStatsUpdateOnDbOpen( + JNIEnv*, jobject, jlong jhandle, + jboolean jskip_stats_update_on_db_open) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->skip_stats_update_on_db_open = + static_cast<bool>(jskip_stats_update_on_db_open); +} + +/* + * Class: org_rocksdb_Options + * Method: skipStatsUpdateOnDbOpen + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_skipStatsUpdateOnDbOpen( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->skip_stats_update_on_db_open); +} + +/* + * Class: org_rocksdb_Options + * Method: setWalRecoveryMode + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setWalRecoveryMode( + JNIEnv*, jobject, jlong jhandle, + jbyte jwal_recovery_mode_value) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->wal_recovery_mode = rocksdb::WALRecoveryModeJni::toCppWALRecoveryMode( + jwal_recovery_mode_value); +} + +/* + * Class: org_rocksdb_Options + * Method: walRecoveryMode + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_walRecoveryMode( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::WALRecoveryModeJni::toJavaWALRecoveryMode( + opt->wal_recovery_mode); +} + +/* + * Class: org_rocksdb_Options + * Method: setAllow2pc + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllow2pc( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_2pc) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->allow_2pc = static_cast<bool>(jallow_2pc); +} + +/* + * Class: org_rocksdb_Options + * Method: allow2pc + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allow2pc( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->allow_2pc); +} + +/* + * Class: org_rocksdb_Options + * Method: setRowCache + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setRowCache( + JNIEnv*, jobject, jlong jhandle, jlong jrow_cache_handle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* row_cache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(jrow_cache_handle); + opt->row_cache = *row_cache; +} + + +/* + * Class: org_rocksdb_Options + * Method: setWalFilter + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setWalFilter( + JNIEnv*, jobject, jlong jhandle, jlong jwal_filter_handle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* wal_filter = + reinterpret_cast<rocksdb::WalFilterJniCallback*>(jwal_filter_handle); + opt->wal_filter = wal_filter; +} + +/* + * Class: org_rocksdb_Options + * Method: setFailIfOptionsFileError + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setFailIfOptionsFileError( + JNIEnv*, jobject, jlong jhandle, jboolean jfail_if_options_file_error) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->fail_if_options_file_error = + static_cast<bool>(jfail_if_options_file_error); +} + +/* + * Class: org_rocksdb_Options + * Method: failIfOptionsFileError + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_failIfOptionsFileError( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->fail_if_options_file_error); +} + +/* + * Class: org_rocksdb_Options + * Method: setDumpMallocStats + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setDumpMallocStats( + JNIEnv*, jobject, jlong jhandle, jboolean jdump_malloc_stats) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->dump_malloc_stats = static_cast<bool>(jdump_malloc_stats); +} + +/* + * Class: org_rocksdb_Options + * Method: dumpMallocStats + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_dumpMallocStats( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->dump_malloc_stats); +} + +/* + * Class: org_rocksdb_Options + * Method: setAvoidFlushDuringRecovery + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAvoidFlushDuringRecovery( + JNIEnv*, jobject, jlong jhandle, jboolean javoid_flush_during_recovery) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->avoid_flush_during_recovery = + static_cast<bool>(javoid_flush_during_recovery); +} + +/* + * Class: org_rocksdb_Options + * Method: avoidFlushDuringRecovery + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_avoidFlushDuringRecovery( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->avoid_flush_during_recovery); +} + +/* + * Class: org_rocksdb_Options + * Method: setAvoidFlushDuringShutdown + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAvoidFlushDuringShutdown( + JNIEnv*, jobject, jlong jhandle, jboolean javoid_flush_during_shutdown) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->avoid_flush_during_shutdown = + static_cast<bool>(javoid_flush_during_shutdown); +} + +/* + * Class: org_rocksdb_Options + * Method: avoidFlushDuringShutdown + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_avoidFlushDuringShutdown( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->avoid_flush_during_shutdown); +} + +/* + * Class: org_rocksdb_Options + * Method: setAllowIngestBehind + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAllowIngestBehind( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_ingest_behind) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->allow_ingest_behind = jallow_ingest_behind == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: allowIngestBehind + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_allowIngestBehind( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->allow_ingest_behind); +} + +/* + * Class: org_rocksdb_Options + * Method: setPreserveDeletes + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setPreserveDeletes( + JNIEnv*, jobject, jlong jhandle, jboolean jpreserve_deletes) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->preserve_deletes = jpreserve_deletes == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: preserveDeletes + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_preserveDeletes( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->preserve_deletes); +} + +/* + * Class: org_rocksdb_Options + * Method: setTwoWriteQueues + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setTwoWriteQueues( + JNIEnv*, jobject, jlong jhandle, jboolean jtwo_write_queues) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->two_write_queues = jtwo_write_queues == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: twoWriteQueues + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_twoWriteQueues( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->two_write_queues); +} + +/* + * Class: org_rocksdb_Options + * Method: setManualWalFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setManualWalFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jmanual_wal_flush) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->manual_wal_flush = jmanual_wal_flush == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: manualWalFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_manualWalFlush( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->manual_wal_flush); +} + +/* + * Class: org_rocksdb_Options + * Method: setAtomicFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setAtomicFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jatomic_flush) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->atomic_flush = jatomic_flush == JNI_TRUE; +} + +/* + * Class: org_rocksdb_Options + * Method: atomicFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_atomicFlush( + JNIEnv *, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jboolean>(opt->atomic_flush); +} + +/* + * Method: tableFactoryName + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_Options_tableFactoryName( + JNIEnv* env, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + rocksdb::TableFactory* tf = opt->table_factory.get(); + + // Should never be nullptr. + // Default memtable factory is SkipListFactory + assert(tf); + + return env->NewStringUTF(tf->Name()); +} + +/* + * Class: org_rocksdb_Options + * Method: minWriteBufferNumberToMerge + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_minWriteBufferNumberToMerge( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->min_write_buffer_number_to_merge; +} + +/* + * Class: org_rocksdb_Options + * Method: setMinWriteBufferNumberToMerge + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMinWriteBufferNumberToMerge( + JNIEnv*, jobject, jlong jhandle, jint jmin_write_buffer_number_to_merge) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->min_write_buffer_number_to_merge = + static_cast<int>(jmin_write_buffer_number_to_merge); +} +/* + * Class: org_rocksdb_Options + * Method: maxWriteBufferNumberToMaintain + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_maxWriteBufferNumberToMaintain( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_write_buffer_number_to_maintain; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxWriteBufferNumberToMaintain + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxWriteBufferNumberToMaintain( + JNIEnv*, jobject, jlong jhandle, + jint jmax_write_buffer_number_to_maintain) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_write_buffer_number_to_maintain = + static_cast<int>(jmax_write_buffer_number_to_maintain); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompressionType + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setCompressionType( + JNIEnv*, jobject, jlong jhandle, jbyte jcompression_type_value) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + opts->compression = rocksdb::CompressionTypeJni::toCppCompressionType( + jcompression_type_value); +} + +/* + * Class: org_rocksdb_Options + * Method: compressionType + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_compressionType( + JNIEnv*, jobject, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType(opts->compression); +} + +/** + * Helper method to convert a Java byte array of compression levels + * to a C++ vector of rocksdb::CompressionType + * + * @param env A pointer to the Java environment + * @param jcompression_levels A reference to a java byte array + * where each byte indicates a compression level + * + * @return A std::unique_ptr to the vector, or std::unique_ptr(nullptr) if a JNI + * exception occurs + */ +std::unique_ptr<std::vector<rocksdb::CompressionType>>rocksdb_compression_vector_helper( + JNIEnv* env, jbyteArray jcompression_levels) { + jsize len = env->GetArrayLength(jcompression_levels); + jbyte* jcompression_level = + env->GetByteArrayElements(jcompression_levels, nullptr); + if (jcompression_level == nullptr) { + // exception thrown: OutOfMemoryError + return std::unique_ptr<std::vector<rocksdb::CompressionType>>(); + } + + auto* compression_levels = new std::vector<rocksdb::CompressionType>(); + std::unique_ptr<std::vector<rocksdb::CompressionType>> + uptr_compression_levels(compression_levels); + + for (jsize i = 0; i < len; i++) { + jbyte jcl = jcompression_level[i]; + compression_levels->push_back(static_cast<rocksdb::CompressionType>(jcl)); + } + + env->ReleaseByteArrayElements(jcompression_levels, jcompression_level, + JNI_ABORT); + + return uptr_compression_levels; +} + +/** + * Helper method to convert a C++ vector of rocksdb::CompressionType + * to a Java byte array of compression levels + * + * @param env A pointer to the Java environment + * @param jcompression_levels A reference to a java byte array + * where each byte indicates a compression level + * + * @return A jbytearray or nullptr if an exception occurs + */ +jbyteArray rocksdb_compression_list_helper( + JNIEnv* env, std::vector<rocksdb::CompressionType> compression_levels) { + const size_t len = compression_levels.size(); + jbyte* jbuf = new jbyte[len]; + + for (size_t i = 0; i < len; i++) { + jbuf[i] = compression_levels[i]; + } + + // insert in java array + jbyteArray jcompression_levels = env->NewByteArray(static_cast<jsize>(len)); + if (jcompression_levels == nullptr) { + // exception thrown: OutOfMemoryError + delete[] jbuf; + return nullptr; + } + env->SetByteArrayRegion(jcompression_levels, 0, static_cast<jsize>(len), + jbuf); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jcompression_levels); + delete[] jbuf; + return nullptr; + } + + delete[] jbuf; + + return jcompression_levels; +} + +/* + * Class: org_rocksdb_Options + * Method: setCompressionPerLevel + * Signature: (J[B)V + */ +void Java_org_rocksdb_Options_setCompressionPerLevel( + JNIEnv* env, jobject, jlong jhandle, jbyteArray jcompressionLevels) { + auto uptr_compression_levels = + rocksdb_compression_vector_helper(env, jcompressionLevels); + if (!uptr_compression_levels) { + // exception occurred + return; + } + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + options->compression_per_level = *(uptr_compression_levels.get()); +} + +/* + * Class: org_rocksdb_Options + * Method: compressionPerLevel + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_Options_compressionPerLevel( + JNIEnv* env, jobject, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb_compression_list_helper(env, options->compression_per_level); +} + +/* + * Class: org_rocksdb_Options + * Method: setBottommostCompressionType + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setBottommostCompressionType( + JNIEnv*, jobject, jlong jhandle, jbyte jcompression_type_value) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + options->bottommost_compression = + rocksdb::CompressionTypeJni::toCppCompressionType( + jcompression_type_value); +} + +/* + * Class: org_rocksdb_Options + * Method: bottommostCompressionType + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_bottommostCompressionType( + JNIEnv*, jobject, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType( + options->bottommost_compression); +} + +/* + * Class: org_rocksdb_Options + * Method: setBottommostCompressionOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setBottommostCompressionOptions( + JNIEnv*, jobject, jlong jhandle, + jlong jbottommost_compression_options_handle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* bottommost_compression_options = + reinterpret_cast<rocksdb::CompressionOptions*>( + jbottommost_compression_options_handle); + options->bottommost_compression_opts = *bottommost_compression_options; +} + +/* + * Class: org_rocksdb_Options + * Method: setCompressionOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setCompressionOptions( + JNIEnv*, jobject, jlong jhandle, jlong jcompression_options_handle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* compression_options = reinterpret_cast<rocksdb::CompressionOptions*>( + jcompression_options_handle); + options->compression_opts = *compression_options; +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionStyle + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setCompactionStyle( + JNIEnv*, jobject, jlong jhandle, jbyte jcompaction_style) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + options->compaction_style = + rocksdb::CompactionStyleJni::toCppCompactionStyle( + jcompaction_style); +} + +/* + * Class: org_rocksdb_Options + * Method: compactionStyle + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_compactionStyle( + JNIEnv*, jobject, jlong jhandle) { + auto* options = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::CompactionStyleJni::toJavaCompactionStyle( + options->compaction_style); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxTableFilesSizeFIFO + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxTableFilesSizeFIFO( + JNIEnv*, jobject, jlong jhandle, jlong jmax_table_files_size) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->compaction_options_fifo.max_table_files_size = + static_cast<uint64_t>(jmax_table_files_size); +} + +/* + * Class: org_rocksdb_Options + * Method: maxTableFilesSizeFIFO + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxTableFilesSizeFIFO( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->compaction_options_fifo.max_table_files_size; +} + +/* + * Class: org_rocksdb_Options + * Method: numLevels + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_numLevels( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->num_levels; +} + +/* + * Class: org_rocksdb_Options + * Method: setNumLevels + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setNumLevels( + JNIEnv*, jobject, jlong jhandle, jint jnum_levels) { + reinterpret_cast<rocksdb::Options*>(jhandle)->num_levels = + static_cast<int>(jnum_levels); +} + +/* + * Class: org_rocksdb_Options + * Method: levelZeroFileNumCompactionTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_levelZeroFileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_file_num_compaction_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevelZeroFileNumCompactionTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevelZeroFileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle, + jint jlevel0_file_num_compaction_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_file_num_compaction_trigger = + static_cast<int>(jlevel0_file_num_compaction_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: levelZeroSlowdownWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_levelZeroSlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_slowdown_writes_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevelSlowdownWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevelZeroSlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_slowdown_writes_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle)->level0_slowdown_writes_trigger = + static_cast<int>(jlevel0_slowdown_writes_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: levelZeroStopWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_levelZeroStopWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_stop_writes_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevelStopWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevelZeroStopWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_stop_writes_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle)->level0_stop_writes_trigger = + static_cast<int>(jlevel0_stop_writes_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: targetFileSizeBase + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_targetFileSizeBase( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->target_file_size_base; +} + +/* + * Class: org_rocksdb_Options + * Method: setTargetFileSizeBase + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setTargetFileSizeBase( + JNIEnv*, jobject, jlong jhandle, jlong jtarget_file_size_base) { + reinterpret_cast<rocksdb::Options*>(jhandle)->target_file_size_base = + static_cast<uint64_t>(jtarget_file_size_base); +} + +/* + * Class: org_rocksdb_Options + * Method: targetFileSizeMultiplier + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_targetFileSizeMultiplier( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->target_file_size_multiplier; +} + +/* + * Class: org_rocksdb_Options + * Method: setTargetFileSizeMultiplier + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setTargetFileSizeMultiplier( + JNIEnv*, jobject, jlong jhandle, jint jtarget_file_size_multiplier) { + reinterpret_cast<rocksdb::Options*>(jhandle)->target_file_size_multiplier = + static_cast<int>(jtarget_file_size_multiplier); +} + +/* + * Class: org_rocksdb_Options + * Method: maxBytesForLevelBase + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxBytesForLevelBase( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_bytes_for_level_base; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBytesForLevelBase + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxBytesForLevelBase( + JNIEnv*, jobject, jlong jhandle, jlong jmax_bytes_for_level_base) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_bytes_for_level_base = + static_cast<int64_t>(jmax_bytes_for_level_base); +} + +/* + * Class: org_rocksdb_Options + * Method: levelCompactionDynamicLevelBytes + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_levelCompactionDynamicLevelBytes( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level_compaction_dynamic_level_bytes; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevelCompactionDynamicLevelBytes + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setLevelCompactionDynamicLevelBytes( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_dynamic_level_bytes) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->level_compaction_dynamic_level_bytes = (jenable_dynamic_level_bytes); +} + +/* + * Class: org_rocksdb_Options + * Method: maxBytesForLevelMultiplier + * Signature: (J)D + */ +jdouble Java_org_rocksdb_Options_maxBytesForLevelMultiplier( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_bytes_for_level_multiplier; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBytesForLevelMultiplier + * Signature: (JD)V + */ +void Java_org_rocksdb_Options_setMaxBytesForLevelMultiplier( + JNIEnv*, jobject, jlong jhandle, jdouble jmax_bytes_for_level_multiplier) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_bytes_for_level_multiplier = + static_cast<double>(jmax_bytes_for_level_multiplier); +} + +/* + * Class: org_rocksdb_Options + * Method: maxCompactionBytes + * Signature: (J)I + */ +jlong Java_org_rocksdb_Options_maxCompactionBytes( + JNIEnv*, jobject, jlong jhandle) { + return static_cast<jlong>( + reinterpret_cast<rocksdb::Options*>(jhandle)->max_compaction_bytes); +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxCompactionBytes + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMaxCompactionBytes( + JNIEnv*, jobject, jlong jhandle, jlong jmax_compaction_bytes) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_compaction_bytes = + static_cast<uint64_t>(jmax_compaction_bytes); +} + +/* + * Class: org_rocksdb_Options + * Method: arenaBlockSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_arenaBlockSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->arena_block_size; +} + +/* + * Class: org_rocksdb_Options + * Method: setArenaBlockSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setArenaBlockSize( + JNIEnv* env, jobject, jlong jhandle, jlong jarena_block_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jarena_block_size); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->arena_block_size = + jarena_block_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: disableAutoCompactions + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_disableAutoCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->disable_auto_compactions; +} + +/* + * Class: org_rocksdb_Options + * Method: setDisableAutoCompactions + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setDisableAutoCompactions( + JNIEnv*, jobject, jlong jhandle, jboolean jdisable_auto_compactions) { + reinterpret_cast<rocksdb::Options*>(jhandle)->disable_auto_compactions = + static_cast<bool>(jdisable_auto_compactions); +} + +/* + * Class: org_rocksdb_Options + * Method: maxSequentialSkipInIterations + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxSequentialSkipInIterations( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_sequential_skip_in_iterations; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxSequentialSkipInIterations + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxSequentialSkipInIterations( + JNIEnv*, jobject, jlong jhandle, + jlong jmax_sequential_skip_in_iterations) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_sequential_skip_in_iterations = + static_cast<int64_t>(jmax_sequential_skip_in_iterations); +} + +/* + * Class: org_rocksdb_Options + * Method: inplaceUpdateSupport + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_inplaceUpdateSupport( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->inplace_update_support; +} + +/* + * Class: org_rocksdb_Options + * Method: setInplaceUpdateSupport + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setInplaceUpdateSupport( + JNIEnv*, jobject, jlong jhandle, jboolean jinplace_update_support) { + reinterpret_cast<rocksdb::Options*>(jhandle)->inplace_update_support = + static_cast<bool>(jinplace_update_support); +} + +/* + * Class: org_rocksdb_Options + * Method: inplaceUpdateNumLocks + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_inplaceUpdateNumLocks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->inplace_update_num_locks; +} + +/* + * Class: org_rocksdb_Options + * Method: setInplaceUpdateNumLocks + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setInplaceUpdateNumLocks( + JNIEnv* env, jobject, jlong jhandle, jlong jinplace_update_num_locks) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jinplace_update_num_locks); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->inplace_update_num_locks = + jinplace_update_num_locks; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: memtablePrefixBloomSizeRatio + * Signature: (J)I + */ +jdouble Java_org_rocksdb_Options_memtablePrefixBloomSizeRatio( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->memtable_prefix_bloom_size_ratio; +} + +/* + * Class: org_rocksdb_Options + * Method: setMemtablePrefixBloomSizeRatio + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setMemtablePrefixBloomSizeRatio( + JNIEnv*, jobject, jlong jhandle, + jdouble jmemtable_prefix_bloom_size_ratio) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->memtable_prefix_bloom_size_ratio = + static_cast<double>(jmemtable_prefix_bloom_size_ratio); +} + +/* + * Class: org_rocksdb_Options + * Method: bloomLocality + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_bloomLocality( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->bloom_locality; +} + +/* + * Class: org_rocksdb_Options + * Method: setBloomLocality + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setBloomLocality( + JNIEnv*, jobject, jlong jhandle, jint jbloom_locality) { + reinterpret_cast<rocksdb::Options*>(jhandle)->bloom_locality = + static_cast<int32_t>(jbloom_locality); +} + +/* + * Class: org_rocksdb_Options + * Method: maxSuccessiveMerges + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_maxSuccessiveMerges( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->max_successive_merges; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxSuccessiveMerges + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMaxSuccessiveMerges( + JNIEnv* env, jobject, jlong jhandle, jlong jmax_successive_merges) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jmax_successive_merges); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->max_successive_merges = + jmax_successive_merges; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: optimizeFiltersForHits + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_optimizeFiltersForHits( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->optimize_filters_for_hits; +} + +/* + * Class: org_rocksdb_Options + * Method: setOptimizeFiltersForHits + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setOptimizeFiltersForHits( + JNIEnv*, jobject, jlong jhandle, jboolean joptimize_filters_for_hits) { + reinterpret_cast<rocksdb::Options*>(jhandle)->optimize_filters_for_hits = + static_cast<bool>(joptimize_filters_for_hits); +} + +/* + * Class: org_rocksdb_Options + * Method: optimizeForSmallDb + * Signature: (J)V + */ +void Java_org_rocksdb_Options_optimizeForSmallDb( + JNIEnv*, jobject, jlong jhandle) { + reinterpret_cast<rocksdb::Options*>(jhandle)->OptimizeForSmallDb(); +} + +/* + * Class: org_rocksdb_Options + * Method: optimizeForPointLookup + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_optimizeForPointLookup( + JNIEnv*, jobject, jlong jhandle, jlong block_cache_size_mb) { + reinterpret_cast<rocksdb::Options*>(jhandle)->OptimizeForPointLookup( + block_cache_size_mb); +} + +/* + * Class: org_rocksdb_Options + * Method: optimizeLevelStyleCompaction + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_optimizeLevelStyleCompaction( + JNIEnv*, jobject, jlong jhandle, jlong memtable_memory_budget) { + reinterpret_cast<rocksdb::Options*>(jhandle)->OptimizeLevelStyleCompaction( + memtable_memory_budget); +} + +/* + * Class: org_rocksdb_Options + * Method: optimizeUniversalStyleCompaction + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_optimizeUniversalStyleCompaction( + JNIEnv*, jobject, jlong jhandle, jlong memtable_memory_budget) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->OptimizeUniversalStyleCompaction(memtable_memory_budget); +} + +/* + * Class: org_rocksdb_Options + * Method: prepareForBulkLoad + * Signature: (J)V + */ +void Java_org_rocksdb_Options_prepareForBulkLoad( + JNIEnv*, jobject, jlong jhandle) { + reinterpret_cast<rocksdb::Options*>(jhandle)->PrepareForBulkLoad(); +} + +/* + * Class: org_rocksdb_Options + * Method: memtableHugePageSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_memtableHugePageSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->memtable_huge_page_size; +} + +/* + * Class: org_rocksdb_Options + * Method: setMemtableHugePageSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setMemtableHugePageSize( + JNIEnv* env, jobject, jlong jhandle, jlong jmemtable_huge_page_size) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jmemtable_huge_page_size); + if (s.ok()) { + reinterpret_cast<rocksdb::Options*>(jhandle)->memtable_huge_page_size = + jmemtable_huge_page_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Options + * Method: softPendingCompactionBytesLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_softPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->soft_pending_compaction_bytes_limit; +} + +/* + * Class: org_rocksdb_Options + * Method: setSoftPendingCompactionBytesLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setSoftPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle, + jlong jsoft_pending_compaction_bytes_limit) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->soft_pending_compaction_bytes_limit = + static_cast<int64_t>(jsoft_pending_compaction_bytes_limit); +} + +/* + * Class: org_rocksdb_Options + * Method: softHardCompactionBytesLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_hardPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->hard_pending_compaction_bytes_limit; +} + +/* + * Class: org_rocksdb_Options + * Method: setHardPendingCompactionBytesLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setHardPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle, + jlong jhard_pending_compaction_bytes_limit) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->hard_pending_compaction_bytes_limit = + static_cast<int64_t>(jhard_pending_compaction_bytes_limit); +} + +/* + * Class: org_rocksdb_Options + * Method: level0FileNumCompactionTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_level0FileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_file_num_compaction_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevel0FileNumCompactionTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevel0FileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle, + jint jlevel0_file_num_compaction_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_file_num_compaction_trigger = + static_cast<int32_t>(jlevel0_file_num_compaction_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: level0SlowdownWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_level0SlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_slowdown_writes_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevel0SlowdownWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevel0SlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_slowdown_writes_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle)->level0_slowdown_writes_trigger = + static_cast<int32_t>(jlevel0_slowdown_writes_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: level0StopWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_Options_level0StopWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle) + ->level0_stop_writes_trigger; +} + +/* + * Class: org_rocksdb_Options + * Method: setLevel0StopWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_Options_setLevel0StopWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_stop_writes_trigger) { + reinterpret_cast<rocksdb::Options*>(jhandle)->level0_stop_writes_trigger = + static_cast<int32_t>(jlevel0_stop_writes_trigger); +} + +/* + * Class: org_rocksdb_Options + * Method: maxBytesForLevelMultiplierAdditional + * Signature: (J)[I + */ +jintArray Java_org_rocksdb_Options_maxBytesForLevelMultiplierAdditional( + JNIEnv* env, jobject, jlong jhandle) { + auto mbflma = reinterpret_cast<rocksdb::Options*>(jhandle) + ->max_bytes_for_level_multiplier_additional; + + const size_t size = mbflma.size(); + + jint* additionals = new jint[size]; + for (size_t i = 0; i < size; i++) { + additionals[i] = static_cast<jint>(mbflma[i]); + } + + jsize jlen = static_cast<jsize>(size); + jintArray result = env->NewIntArray(jlen); + if (result == nullptr) { + // exception thrown: OutOfMemoryError + delete[] additionals; + return nullptr; + } + + env->SetIntArrayRegion(result, 0, jlen, additionals); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(result); + delete[] additionals; + return nullptr; + } + + delete[] additionals; + + return result; +} + +/* + * Class: org_rocksdb_Options + * Method: setMaxBytesForLevelMultiplierAdditional + * Signature: (J[I)V + */ +void Java_org_rocksdb_Options_setMaxBytesForLevelMultiplierAdditional( + JNIEnv* env, jobject, jlong jhandle, + jintArray jmax_bytes_for_level_multiplier_additional) { + jsize len = env->GetArrayLength(jmax_bytes_for_level_multiplier_additional); + jint* additionals = env->GetIntArrayElements( + jmax_bytes_for_level_multiplier_additional, nullptr); + if (additionals == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle); + opt->max_bytes_for_level_multiplier_additional.clear(); + for (jsize i = 0; i < len; i++) { + opt->max_bytes_for_level_multiplier_additional.push_back( + static_cast<int32_t>(additionals[i])); + } + + env->ReleaseIntArrayElements(jmax_bytes_for_level_multiplier_additional, + additionals, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Options + * Method: paranoidFileChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_paranoidFileChecks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::Options*>(jhandle)->paranoid_file_checks; +} + +/* + * Class: org_rocksdb_Options + * Method: setParanoidFileChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setParanoidFileChecks( + JNIEnv*, jobject, jlong jhandle, jboolean jparanoid_file_checks) { + reinterpret_cast<rocksdb::Options*>(jhandle)->paranoid_file_checks = + static_cast<bool>(jparanoid_file_checks); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionPriority + * Signature: (JB)V + */ +void Java_org_rocksdb_Options_setCompactionPriority( + JNIEnv*, jobject, jlong jhandle, jbyte jcompaction_priority_value) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + opts->compaction_pri = + rocksdb::CompactionPriorityJni::toCppCompactionPriority( + jcompaction_priority_value); +} + +/* + * Class: org_rocksdb_Options + * Method: compactionPriority + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Options_compactionPriority( + JNIEnv*, jobject, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + return rocksdb::CompactionPriorityJni::toJavaCompactionPriority( + opts->compaction_pri); +} + +/* + * Class: org_rocksdb_Options + * Method: setReportBgIoStats + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setReportBgIoStats( + JNIEnv*, jobject, jlong jhandle, jboolean jreport_bg_io_stats) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + opts->report_bg_io_stats = static_cast<bool>(jreport_bg_io_stats); +} + +/* + * Class: org_rocksdb_Options + * Method: reportBgIoStats + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_reportBgIoStats( + JNIEnv*, jobject, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<bool>(opts->report_bg_io_stats); +} + +/* + * Class: org_rocksdb_Options + * Method: setTtl + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setTtl( + JNIEnv*, jobject, jlong jhandle, jlong jttl) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + opts->ttl = static_cast<uint64_t>(jttl); +} + +/* + * Class: org_rocksdb_Options + * Method: ttl + * Signature: (J)J + */ +jlong Java_org_rocksdb_Options_ttl( + JNIEnv*, jobject, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<jlong>(opts->ttl); +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionOptionsUniversal + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setCompactionOptionsUniversal( + JNIEnv*, jobject, jlong jhandle, + jlong jcompaction_options_universal_handle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* opts_uni = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>( + jcompaction_options_universal_handle); + opts->compaction_options_universal = *opts_uni; +} + +/* + * Class: org_rocksdb_Options + * Method: setCompactionOptionsFIFO + * Signature: (JJ)V + */ +void Java_org_rocksdb_Options_setCompactionOptionsFIFO( + JNIEnv*, jobject, jlong jhandle, jlong jcompaction_options_fifo_handle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + auto* opts_fifo = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>( + jcompaction_options_fifo_handle); + opts->compaction_options_fifo = *opts_fifo; +} + +/* + * Class: org_rocksdb_Options + * Method: setForceConsistencyChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_Options_setForceConsistencyChecks( + JNIEnv*, jobject, jlong jhandle, jboolean jforce_consistency_checks) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + opts->force_consistency_checks = static_cast<bool>(jforce_consistency_checks); +} + +/* + * Class: org_rocksdb_Options + * Method: forceConsistencyChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Options_forceConsistencyChecks( + JNIEnv*, jobject, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::Options*>(jhandle); + return static_cast<bool>(opts->force_consistency_checks); +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::ColumnFamilyOptions + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: newColumnFamilyOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_newColumnFamilyOptions( + JNIEnv*, jclass) { + auto* op = new rocksdb::ColumnFamilyOptions(); + return reinterpret_cast<jlong>(op); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: copyColumnFamilyOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_copyColumnFamilyOptions( + JNIEnv*, jclass, jlong jhandle) { + auto new_opt = new rocksdb::ColumnFamilyOptions( + *(reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle))); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: newColumnFamilyOptionsFromOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_newColumnFamilyOptionsFromOptions( + JNIEnv*, jclass, jlong joptions_handle) { + auto new_opt = new rocksdb::ColumnFamilyOptions( + *reinterpret_cast<rocksdb::Options*>(joptions_handle)); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: getColumnFamilyOptionsFromProps + * Signature: (Ljava/util/String;)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_getColumnFamilyOptionsFromProps( + JNIEnv* env, jclass, jstring jopt_string) { + const char* opt_string = env->GetStringUTFChars(jopt_string, nullptr); + if (opt_string == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + auto* cf_options = new rocksdb::ColumnFamilyOptions(); + rocksdb::Status status = rocksdb::GetColumnFamilyOptionsFromString( + rocksdb::ColumnFamilyOptions(), opt_string, cf_options); + + env->ReleaseStringUTFChars(jopt_string, opt_string); + + // Check if ColumnFamilyOptions creation was possible. + jlong ret_value = 0; + if (status.ok()) { + ret_value = reinterpret_cast<jlong>(cf_options); + } else { + // if operation failed the ColumnFamilyOptions need to be deleted + // again to prevent a memory leak. + delete cf_options; + } + return ret_value; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_disposeInternal( + JNIEnv*, jobject, jlong handle) { + auto* cfo = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(handle); + assert(cfo != nullptr); + delete cfo; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: optimizeForSmallDb + * Signature: (J)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_optimizeForSmallDb( + JNIEnv*, jobject, jlong jhandle) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->OptimizeForSmallDb(); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: optimizeForPointLookup + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_optimizeForPointLookup( + JNIEnv*, jobject, jlong jhandle, jlong block_cache_size_mb) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->OptimizeForPointLookup(block_cache_size_mb); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: optimizeLevelStyleCompaction + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_optimizeLevelStyleCompaction( + JNIEnv*, jobject, jlong jhandle, jlong memtable_memory_budget) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->OptimizeLevelStyleCompaction(memtable_memory_budget); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: optimizeUniversalStyleCompaction + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_optimizeUniversalStyleCompaction( + JNIEnv*, jobject, jlong jhandle, jlong memtable_memory_budget) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->OptimizeUniversalStyleCompaction(memtable_memory_budget); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setComparatorHandle + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JI( + JNIEnv*, jobject, jlong jhandle, jint builtinComparator) { + switch (builtinComparator) { + case 1: + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->comparator = + rocksdb::ReverseBytewiseComparator(); + break; + default: + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->comparator = + rocksdb::BytewiseComparator(); + break; + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setComparatorHandle + * Signature: (JJB)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JJB( + JNIEnv*, jobject, jlong jopt_handle, jlong jcomparator_handle, + jbyte jcomparator_type) { + rocksdb::Comparator* comparator = nullptr; + switch (jcomparator_type) { + // JAVA_COMPARATOR + case 0x0: + comparator = + reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle); + break; + + // JAVA_DIRECT_COMPARATOR + case 0x1: + comparator = reinterpret_cast<rocksdb::DirectComparatorJniCallback*>( + jcomparator_handle); + break; + + // JAVA_NATIVE_COMPARATOR_WRAPPER + case 0x2: + comparator = reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle); + break; + } + auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle); + opt->comparator = comparator; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMergeOperatorName + * Signature: (JJjava/lang/String)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMergeOperatorName( + JNIEnv* env, jobject, jlong jhandle, jstring jop_name) { + auto* options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + const char* op_name = env->GetStringUTFChars(jop_name, nullptr); + if (op_name == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + options->merge_operator = + rocksdb::MergeOperators::CreateFromStringId(op_name); + env->ReleaseStringUTFChars(jop_name, op_name); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMergeOperator + * Signature: (JJjava/lang/String)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMergeOperator( + JNIEnv*, jobject, jlong jhandle, jlong mergeOperatorHandle) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->merge_operator = + *(reinterpret_cast<std::shared_ptr<rocksdb::MergeOperator>*>( + mergeOperatorHandle)); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionFilterHandle + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionFilterHandle( + JNIEnv*, jobject, jlong jopt_handle, jlong jcompactionfilter_handle) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle) + ->compaction_filter = + reinterpret_cast<rocksdb::CompactionFilter*>(jcompactionfilter_handle); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionFilterFactoryHandle + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionFilterFactoryHandle( + JNIEnv*, jobject, jlong jopt_handle, + jlong jcompactionfilterfactory_handle) { + auto* cff_factory = + reinterpret_cast<std::shared_ptr<rocksdb::CompactionFilterFactoryJniCallback>*>( + jcompactionfilterfactory_handle); + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle) + ->compaction_filter_factory = *cff_factory; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setWriteBufferSize + * Signature: (JJ)I + */ +void Java_org_rocksdb_ColumnFamilyOptions_setWriteBufferSize( + JNIEnv* env, jobject, jlong jhandle, jlong jwrite_buffer_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jwrite_buffer_size); + if (s.ok()) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->write_buffer_size = jwrite_buffer_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: writeBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_writeBufferSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->write_buffer_size; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxWriteBufferNumber + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxWriteBufferNumber( + JNIEnv*, jobject, jlong jhandle, jint jmax_write_buffer_number) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_write_buffer_number = jmax_write_buffer_number; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxWriteBufferNumber + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_maxWriteBufferNumber( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_write_buffer_number; +} + +/* + * Method: setMemTableFactory + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMemTableFactory( + JNIEnv*, jobject, jlong jhandle, jlong jfactory_handle) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->memtable_factory.reset( + reinterpret_cast<rocksdb::MemTableRepFactory*>(jfactory_handle)); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: memTableFactoryName + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_ColumnFamilyOptions_memTableFactoryName( + JNIEnv* env, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + rocksdb::MemTableRepFactory* tf = opt->memtable_factory.get(); + + // Should never be nullptr. + // Default memtable factory is SkipListFactory + assert(tf); + + // temporarly fix for the historical typo + if (strcmp(tf->Name(), "HashLinkListRepFactory") == 0) { + return env->NewStringUTF("HashLinkedListRepFactory"); + } + + return env->NewStringUTF(tf->Name()); +} + +/* + * Method: useFixedLengthPrefixExtractor + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_useFixedLengthPrefixExtractor( + JNIEnv*, jobject, jlong jhandle, jint jprefix_length) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->prefix_extractor.reset( + rocksdb::NewFixedPrefixTransform(static_cast<int>(jprefix_length))); +} + +/* + * Method: useCappedPrefixExtractor + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_useCappedPrefixExtractor( + JNIEnv*, jobject, jlong jhandle, jint jprefix_length) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->prefix_extractor.reset( + rocksdb::NewCappedPrefixTransform(static_cast<int>(jprefix_length))); +} + +/* + * Method: setTableFactory + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setTableFactory( + JNIEnv*, jobject, jlong jhandle, jlong jfactory_handle) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->table_factory.reset( + reinterpret_cast<rocksdb::TableFactory*>(jfactory_handle)); +} + +/* + * Method: tableFactoryName + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_ColumnFamilyOptions_tableFactoryName( + JNIEnv* env, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + rocksdb::TableFactory* tf = opt->table_factory.get(); + + // Should never be nullptr. + // Default memtable factory is SkipListFactory + assert(tf); + + return env->NewStringUTF(tf->Name()); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: minWriteBufferNumberToMerge + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_minWriteBufferNumberToMerge( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->min_write_buffer_number_to_merge; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMinWriteBufferNumberToMerge + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMinWriteBufferNumberToMerge( + JNIEnv*, jobject, jlong jhandle, jint jmin_write_buffer_number_to_merge) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->min_write_buffer_number_to_merge = + static_cast<int>(jmin_write_buffer_number_to_merge); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxWriteBufferNumberToMaintain + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_maxWriteBufferNumberToMaintain( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_write_buffer_number_to_maintain; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxWriteBufferNumberToMaintain + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxWriteBufferNumberToMaintain( + JNIEnv*, jobject, jlong jhandle, + jint jmax_write_buffer_number_to_maintain) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_write_buffer_number_to_maintain = + static_cast<int>(jmax_write_buffer_number_to_maintain); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompressionType + * Signature: (JB)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompressionType( + JNIEnv*, jobject, jlong jhandle, jbyte jcompression_type_value) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opts->compression = rocksdb::CompressionTypeJni::toCppCompressionType( + jcompression_type_value); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: compressionType + * Signature: (J)B + */ +jbyte Java_org_rocksdb_ColumnFamilyOptions_compressionType( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType( + cf_opts->compression); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompressionPerLevel + * Signature: (J[B)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompressionPerLevel( + JNIEnv* env, jobject, jlong jhandle, jbyteArray jcompressionLevels) { + auto* options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + auto uptr_compression_levels = + rocksdb_compression_vector_helper(env, jcompressionLevels); + if (!uptr_compression_levels) { + // exception occurred + return; + } + options->compression_per_level = *(uptr_compression_levels.get()); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: compressionPerLevel + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_ColumnFamilyOptions_compressionPerLevel( + JNIEnv* env, jobject, jlong jhandle) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return rocksdb_compression_list_helper(env, + cf_options->compression_per_level); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setBottommostCompressionType + * Signature: (JB)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setBottommostCompressionType( + JNIEnv*, jobject, jlong jhandle, jbyte jcompression_type_value) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_options->bottommost_compression = + rocksdb::CompressionTypeJni::toCppCompressionType( + jcompression_type_value); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: bottommostCompressionType + * Signature: (J)B + */ +jbyte Java_org_rocksdb_ColumnFamilyOptions_bottommostCompressionType( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return rocksdb::CompressionTypeJni::toJavaCompressionType( + cf_options->bottommost_compression); +} +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setBottommostCompressionOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setBottommostCompressionOptions( + JNIEnv*, jobject, jlong jhandle, + jlong jbottommost_compression_options_handle) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + auto* bottommost_compression_options = + reinterpret_cast<rocksdb::CompressionOptions*>( + jbottommost_compression_options_handle); + cf_options->bottommost_compression_opts = *bottommost_compression_options; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompressionOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompressionOptions( + JNIEnv*, jobject, jlong jhandle, jlong jcompression_options_handle) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + auto* compression_options = reinterpret_cast<rocksdb::CompressionOptions*>( + jcompression_options_handle); + cf_options->compression_opts = *compression_options; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionStyle + * Signature: (JB)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionStyle( + JNIEnv*, jobject, jlong jhandle, jbyte jcompaction_style) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_options->compaction_style = + rocksdb::CompactionStyleJni::toCppCompactionStyle(jcompaction_style); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: compactionStyle + * Signature: (J)B + */ +jbyte Java_org_rocksdb_ColumnFamilyOptions_compactionStyle( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return rocksdb::CompactionStyleJni::toJavaCompactionStyle( + cf_options->compaction_style); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxTableFilesSizeFIFO + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxTableFilesSizeFIFO( + JNIEnv*, jobject, jlong jhandle, jlong jmax_table_files_size) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->compaction_options_fifo.max_table_files_size = + static_cast<uint64_t>(jmax_table_files_size); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxTableFilesSizeFIFO + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_maxTableFilesSizeFIFO( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->compaction_options_fifo.max_table_files_size; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: numLevels + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_numLevels( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->num_levels; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setNumLevels + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setNumLevels( + JNIEnv*, jobject, jlong jhandle, jint jnum_levels) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->num_levels = + static_cast<int>(jnum_levels); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: levelZeroFileNumCompactionTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_levelZeroFileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_file_num_compaction_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevelZeroFileNumCompactionTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevelZeroFileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle, + jint jlevel0_file_num_compaction_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_file_num_compaction_trigger = + static_cast<int>(jlevel0_file_num_compaction_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: levelZeroSlowdownWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_levelZeroSlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_slowdown_writes_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevelSlowdownWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevelZeroSlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_slowdown_writes_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_slowdown_writes_trigger = + static_cast<int>(jlevel0_slowdown_writes_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: levelZeroStopWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_levelZeroStopWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_stop_writes_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevelStopWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevelZeroStopWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_stop_writes_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_stop_writes_trigger = + static_cast<int>(jlevel0_stop_writes_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: targetFileSizeBase + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_targetFileSizeBase( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->target_file_size_base; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setTargetFileSizeBase + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setTargetFileSizeBase( + JNIEnv*, jobject, jlong jhandle, jlong jtarget_file_size_base) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->target_file_size_base = static_cast<uint64_t>(jtarget_file_size_base); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: targetFileSizeMultiplier + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_targetFileSizeMultiplier( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->target_file_size_multiplier; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setTargetFileSizeMultiplier + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setTargetFileSizeMultiplier( + JNIEnv*, jobject, jlong jhandle, jint jtarget_file_size_multiplier) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->target_file_size_multiplier = + static_cast<int>(jtarget_file_size_multiplier); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxBytesForLevelBase + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_maxBytesForLevelBase( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_bytes_for_level_base; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxBytesForLevelBase + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxBytesForLevelBase( + JNIEnv*, jobject, jlong jhandle, jlong jmax_bytes_for_level_base) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_bytes_for_level_base = + static_cast<int64_t>(jmax_bytes_for_level_base); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: levelCompactionDynamicLevelBytes + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_levelCompactionDynamicLevelBytes( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level_compaction_dynamic_level_bytes; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevelCompactionDynamicLevelBytes + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevelCompactionDynamicLevelBytes( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_dynamic_level_bytes) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level_compaction_dynamic_level_bytes = (jenable_dynamic_level_bytes); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxBytesForLevelMultiplier + * Signature: (J)D + */ +jdouble Java_org_rocksdb_ColumnFamilyOptions_maxBytesForLevelMultiplier( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_bytes_for_level_multiplier; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxBytesForLevelMultiplier + * Signature: (JD)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxBytesForLevelMultiplier( + JNIEnv*, jobject, jlong jhandle, jdouble jmax_bytes_for_level_multiplier) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_bytes_for_level_multiplier = + static_cast<double>(jmax_bytes_for_level_multiplier); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxCompactionBytes + * Signature: (J)I + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_maxCompactionBytes( + JNIEnv*, jobject, jlong jhandle) { + return static_cast<jlong>( + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_compaction_bytes); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxCompactionBytes + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxCompactionBytes( + JNIEnv*, jobject, jlong jhandle, jlong jmax_compaction_bytes) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_compaction_bytes = static_cast<uint64_t>(jmax_compaction_bytes); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: arenaBlockSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_arenaBlockSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->arena_block_size; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setArenaBlockSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setArenaBlockSize( + JNIEnv* env, jobject, jlong jhandle, jlong jarena_block_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(jarena_block_size); + if (s.ok()) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->arena_block_size = + jarena_block_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: disableAutoCompactions + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_disableAutoCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->disable_auto_compactions; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setDisableAutoCompactions + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setDisableAutoCompactions( + JNIEnv*, jobject, jlong jhandle, jboolean jdisable_auto_compactions) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->disable_auto_compactions = static_cast<bool>(jdisable_auto_compactions); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxSequentialSkipInIterations + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_maxSequentialSkipInIterations( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_sequential_skip_in_iterations; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxSequentialSkipInIterations + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxSequentialSkipInIterations( + JNIEnv*, jobject, jlong jhandle, + jlong jmax_sequential_skip_in_iterations) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_sequential_skip_in_iterations = + static_cast<int64_t>(jmax_sequential_skip_in_iterations); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: inplaceUpdateSupport + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_inplaceUpdateSupport( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->inplace_update_support; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setInplaceUpdateSupport + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setInplaceUpdateSupport( + JNIEnv*, jobject, jlong jhandle, jboolean jinplace_update_support) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->inplace_update_support = static_cast<bool>(jinplace_update_support); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: inplaceUpdateNumLocks + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_inplaceUpdateNumLocks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->inplace_update_num_locks; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setInplaceUpdateNumLocks + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setInplaceUpdateNumLocks( + JNIEnv* env, jobject, jlong jhandle, jlong jinplace_update_num_locks) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jinplace_update_num_locks); + if (s.ok()) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->inplace_update_num_locks = jinplace_update_num_locks; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: memtablePrefixBloomSizeRatio + * Signature: (J)I + */ +jdouble Java_org_rocksdb_ColumnFamilyOptions_memtablePrefixBloomSizeRatio( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->memtable_prefix_bloom_size_ratio; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMemtablePrefixBloomSizeRatio + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMemtablePrefixBloomSizeRatio( + JNIEnv*, jobject, jlong jhandle, + jdouble jmemtable_prefix_bloom_size_ratio) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->memtable_prefix_bloom_size_ratio = + static_cast<double>(jmemtable_prefix_bloom_size_ratio); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: bloomLocality + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_bloomLocality( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->bloom_locality; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setBloomLocality + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setBloomLocality( + JNIEnv*, jobject, jlong jhandle, jint jbloom_locality) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->bloom_locality = + static_cast<int32_t>(jbloom_locality); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxSuccessiveMerges + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_maxSuccessiveMerges( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_successive_merges; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxSuccessiveMerges + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxSuccessiveMerges( + JNIEnv* env, jobject, jlong jhandle, jlong jmax_successive_merges) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jmax_successive_merges); + if (s.ok()) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_successive_merges = jmax_successive_merges; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: optimizeFiltersForHits + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_optimizeFiltersForHits( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->optimize_filters_for_hits; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setOptimizeFiltersForHits + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setOptimizeFiltersForHits( + JNIEnv*, jobject, jlong jhandle, jboolean joptimize_filters_for_hits) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->optimize_filters_for_hits = + static_cast<bool>(joptimize_filters_for_hits); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: memtableHugePageSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_memtableHugePageSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->memtable_huge_page_size; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMemtableHugePageSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMemtableHugePageSize( + JNIEnv* env, jobject, jlong jhandle, jlong jmemtable_huge_page_size) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(jmemtable_huge_page_size); + if (s.ok()) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->memtable_huge_page_size = jmemtable_huge_page_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: softPendingCompactionBytesLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_softPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->soft_pending_compaction_bytes_limit; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setSoftPendingCompactionBytesLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setSoftPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle, + jlong jsoft_pending_compaction_bytes_limit) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->soft_pending_compaction_bytes_limit = + static_cast<int64_t>(jsoft_pending_compaction_bytes_limit); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: softHardCompactionBytesLimit + * Signature: (J)J + */ +jlong Java_org_rocksdb_ColumnFamilyOptions_hardPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->hard_pending_compaction_bytes_limit; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setHardPendingCompactionBytesLimit + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setHardPendingCompactionBytesLimit( + JNIEnv*, jobject, jlong jhandle, + jlong jhard_pending_compaction_bytes_limit) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->hard_pending_compaction_bytes_limit = + static_cast<int64_t>(jhard_pending_compaction_bytes_limit); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: level0FileNumCompactionTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_level0FileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_file_num_compaction_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevel0FileNumCompactionTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevel0FileNumCompactionTrigger( + JNIEnv*, jobject, jlong jhandle, + jint jlevel0_file_num_compaction_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_file_num_compaction_trigger = + static_cast<int32_t>(jlevel0_file_num_compaction_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: level0SlowdownWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_level0SlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_slowdown_writes_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevel0SlowdownWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevel0SlowdownWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_slowdown_writes_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_slowdown_writes_trigger = + static_cast<int32_t>(jlevel0_slowdown_writes_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: level0StopWritesTrigger + * Signature: (J)I + */ +jint Java_org_rocksdb_ColumnFamilyOptions_level0StopWritesTrigger( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_stop_writes_trigger; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setLevel0StopWritesTrigger + * Signature: (JI)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setLevel0StopWritesTrigger( + JNIEnv*, jobject, jlong jhandle, jint jlevel0_stop_writes_trigger) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->level0_stop_writes_trigger = + static_cast<int32_t>(jlevel0_stop_writes_trigger); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: maxBytesForLevelMultiplierAdditional + * Signature: (J)[I + */ +jintArray Java_org_rocksdb_ColumnFamilyOptions_maxBytesForLevelMultiplierAdditional( + JNIEnv* env, jobject, jlong jhandle) { + auto mbflma = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->max_bytes_for_level_multiplier_additional; + + const size_t size = mbflma.size(); + + jint* additionals = new jint[size]; + for (size_t i = 0; i < size; i++) { + additionals[i] = static_cast<jint>(mbflma[i]); + } + + jsize jlen = static_cast<jsize>(size); + jintArray result = env->NewIntArray(jlen); + if (result == nullptr) { + // exception thrown: OutOfMemoryError + delete[] additionals; + return nullptr; + } + env->SetIntArrayRegion(result, 0, jlen, additionals); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(result); + delete[] additionals; + return nullptr; + } + + delete[] additionals; + + return result; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setMaxBytesForLevelMultiplierAdditional + * Signature: (J[I)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setMaxBytesForLevelMultiplierAdditional( + JNIEnv* env, jobject, jlong jhandle, + jintArray jmax_bytes_for_level_multiplier_additional) { + jsize len = env->GetArrayLength(jmax_bytes_for_level_multiplier_additional); + jint* additionals = + env->GetIntArrayElements(jmax_bytes_for_level_multiplier_additional, 0); + if (additionals == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* cf_opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opt->max_bytes_for_level_multiplier_additional.clear(); + for (jsize i = 0; i < len; i++) { + cf_opt->max_bytes_for_level_multiplier_additional.push_back( + static_cast<int32_t>(additionals[i])); + } + + env->ReleaseIntArrayElements(jmax_bytes_for_level_multiplier_additional, + additionals, JNI_ABORT); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: paranoidFileChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_paranoidFileChecks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->paranoid_file_checks; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setParanoidFileChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setParanoidFileChecks( + JNIEnv*, jobject, jlong jhandle, jboolean jparanoid_file_checks) { + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle) + ->paranoid_file_checks = static_cast<bool>(jparanoid_file_checks); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionPriority + * Signature: (JB)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionPriority( + JNIEnv*, jobject, jlong jhandle, jbyte jcompaction_priority_value) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opts->compaction_pri = + rocksdb::CompactionPriorityJni::toCppCompactionPriority( + jcompaction_priority_value); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: compactionPriority + * Signature: (J)B + */ +jbyte Java_org_rocksdb_ColumnFamilyOptions_compactionPriority( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return rocksdb::CompactionPriorityJni::toJavaCompactionPriority( + cf_opts->compaction_pri); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setReportBgIoStats + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setReportBgIoStats( + JNIEnv*, jobject, jlong jhandle, jboolean jreport_bg_io_stats) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opts->report_bg_io_stats = static_cast<bool>(jreport_bg_io_stats); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: reportBgIoStats + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_reportBgIoStats( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return static_cast<bool>(cf_opts->report_bg_io_stats); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setTtl + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setTtl( + JNIEnv*, jobject, jlong jhandle, jlong jttl) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opts->ttl = static_cast<uint64_t>(jttl); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: ttl + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_rocksdb_ColumnFamilyOptions_ttl( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return static_cast<jlong>(cf_opts->ttl); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionOptionsUniversal + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionOptionsUniversal( + JNIEnv*, jobject, jlong jhandle, + jlong jcompaction_options_universal_handle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + auto* opts_uni = reinterpret_cast<rocksdb::CompactionOptionsUniversal*>( + jcompaction_options_universal_handle); + cf_opts->compaction_options_universal = *opts_uni; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setCompactionOptionsFIFO + * Signature: (JJ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setCompactionOptionsFIFO( + JNIEnv*, jobject, jlong jhandle, jlong jcompaction_options_fifo_handle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + auto* opts_fifo = reinterpret_cast<rocksdb::CompactionOptionsFIFO*>( + jcompaction_options_fifo_handle); + cf_opts->compaction_options_fifo = *opts_fifo; +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: setForceConsistencyChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_ColumnFamilyOptions_setForceConsistencyChecks( + JNIEnv*, jobject, jlong jhandle, jboolean jforce_consistency_checks) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + cf_opts->force_consistency_checks = + static_cast<bool>(jforce_consistency_checks); +} + +/* + * Class: org_rocksdb_ColumnFamilyOptions + * Method: forceConsistencyChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ColumnFamilyOptions_forceConsistencyChecks( + JNIEnv*, jobject, jlong jhandle) { + auto* cf_opts = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle); + return static_cast<bool>(cf_opts->force_consistency_checks); +} + +///////////////////////////////////////////////////////////////////// +// rocksdb::DBOptions + +/* + * Class: org_rocksdb_DBOptions + * Method: newDBOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_DBOptions_newDBOptions( + JNIEnv*, jclass) { + auto* dbop = new rocksdb::DBOptions(); + return reinterpret_cast<jlong>(dbop); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: copyDBOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_copyDBOptions( + JNIEnv*, jclass, jlong jhandle) { + auto new_opt = + new rocksdb::DBOptions(*(reinterpret_cast<rocksdb::DBOptions*>(jhandle))); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: newDBOptionsFromOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_newDBOptionsFromOptions( + JNIEnv*, jclass, jlong joptions_handle) { + auto new_opt = + new rocksdb::DBOptions(*reinterpret_cast<rocksdb::Options*>(joptions_handle)); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: getDBOptionsFromProps + * Signature: (Ljava/util/String;)J + */ +jlong Java_org_rocksdb_DBOptions_getDBOptionsFromProps( + JNIEnv* env, jclass, jstring jopt_string) { + const char* opt_string = env->GetStringUTFChars(jopt_string, nullptr); + if (opt_string == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + auto* db_options = new rocksdb::DBOptions(); + rocksdb::Status status = rocksdb::GetDBOptionsFromString( + rocksdb::DBOptions(), opt_string, db_options); + + env->ReleaseStringUTFChars(jopt_string, opt_string); + + // Check if DBOptions creation was possible. + jlong ret_value = 0; + if (status.ok()) { + ret_value = reinterpret_cast<jlong>(db_options); + } else { + // if operation failed the DBOptions need to be deleted + // again to prevent a memory leak. + delete db_options; + } + return ret_value; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_DBOptions_disposeInternal( + JNIEnv*, jobject, jlong handle) { + auto* dbo = reinterpret_cast<rocksdb::DBOptions*>(handle); + assert(dbo != nullptr); + delete dbo; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: optimizeForSmallDb + * Signature: (J)V + */ +void Java_org_rocksdb_DBOptions_optimizeForSmallDb( + JNIEnv*, jobject, jlong jhandle) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->OptimizeForSmallDb(); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setEnv + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setEnv( + JNIEnv*, jobject, jlong jhandle, jlong jenv_handle) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->env = + reinterpret_cast<rocksdb::Env*>(jenv_handle); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setIncreaseParallelism + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setIncreaseParallelism( + JNIEnv*, jobject, jlong jhandle, jint totalThreads) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->IncreaseParallelism( + static_cast<int>(totalThreads)); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setCreateIfMissing + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setCreateIfMissing( + JNIEnv*, jobject, jlong jhandle, jboolean flag) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->create_if_missing = flag; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: createIfMissing + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_createIfMissing( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->create_if_missing; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setCreateMissingColumnFamilies + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setCreateMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle, jboolean flag) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->create_missing_column_families = flag; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: createMissingColumnFamilies + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_createMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->create_missing_column_families; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setErrorIfExists + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setErrorIfExists( + JNIEnv*, jobject, jlong jhandle, jboolean error_if_exists) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->error_if_exists = + static_cast<bool>(error_if_exists); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: errorIfExists + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_errorIfExists( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->error_if_exists; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setParanoidChecks + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setParanoidChecks( + JNIEnv*, jobject, jlong jhandle, jboolean paranoid_checks) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->paranoid_checks = + static_cast<bool>(paranoid_checks); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: paranoidChecks + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_paranoidChecks( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->paranoid_checks; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setRateLimiter + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setRateLimiter( + JNIEnv*, jobject, jlong jhandle, jlong jrate_limiter_handle) { + std::shared_ptr<rocksdb::RateLimiter>* pRateLimiter = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>( + jrate_limiter_handle); + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->rate_limiter = *pRateLimiter; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setSstFileManager + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setSstFileManager( + JNIEnv*, jobject, jlong jhandle, jlong jsst_file_manager_handle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>( + jsst_file_manager_handle); + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->sst_file_manager = + *sptr_sst_file_manager; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setLogger + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setLogger( + JNIEnv*, jobject, jlong jhandle, jlong jlogger_handle) { + std::shared_ptr<rocksdb::LoggerJniCallback>* pLogger = + reinterpret_cast<std::shared_ptr<rocksdb::LoggerJniCallback>*>( + jlogger_handle); + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->info_log = *pLogger; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setInfoLogLevel + * Signature: (JB)V + */ +void Java_org_rocksdb_DBOptions_setInfoLogLevel( + JNIEnv*, jobject, jlong jhandle, jbyte jlog_level) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->info_log_level = + static_cast<rocksdb::InfoLogLevel>(jlog_level); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: infoLogLevel + * Signature: (J)B + */ +jbyte Java_org_rocksdb_DBOptions_infoLogLevel( + JNIEnv*, jobject, jlong jhandle) { + return static_cast<jbyte>( + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->info_log_level); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxTotalWalSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setMaxTotalWalSize( + JNIEnv*, jobject, jlong jhandle, jlong jmax_total_wal_size) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_total_wal_size = + static_cast<jlong>(jmax_total_wal_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxTotalWalSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_maxTotalWalSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_total_wal_size; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxOpenFiles + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxOpenFiles( + JNIEnv*, jobject, jlong jhandle, jint max_open_files) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_open_files = + static_cast<int>(max_open_files); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxOpenFiles + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxOpenFiles( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_open_files; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxFileOpeningThreads + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxFileOpeningThreads( + JNIEnv*, jobject, jlong jhandle, jint jmax_file_opening_threads) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_file_opening_threads = + static_cast<int>(jmax_file_opening_threads); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxFileOpeningThreads + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxFileOpeningThreads( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<int>(opt->max_file_opening_threads); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setStatistics + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setStatistics( + JNIEnv*, jobject, jlong jhandle, jlong jstatistics_handle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + auto* pSptr = reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>( + jstatistics_handle); + opt->statistics = *pSptr; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: statistics + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_statistics( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + std::shared_ptr<rocksdb::Statistics> sptr = opt->statistics; + if (sptr == nullptr) { + return 0; + } else { + std::shared_ptr<rocksdb::Statistics>* pSptr = + new std::shared_ptr<rocksdb::Statistics>(sptr); + return reinterpret_cast<jlong>(pSptr); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setUseFsync + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setUseFsync( + JNIEnv*, jobject, jlong jhandle, jboolean use_fsync) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_fsync = + static_cast<bool>(use_fsync); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: useFsync + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_useFsync( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_fsync; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDbPaths + * Signature: (J[Ljava/lang/String;[J)V + */ +void Java_org_rocksdb_DBOptions_setDbPaths( + JNIEnv* env, jobject, jlong jhandle, jobjectArray jpaths, + jlongArray jtarget_sizes) { + std::vector<rocksdb::DbPath> db_paths; + jlong* ptr_jtarget_size = env->GetLongArrayElements(jtarget_sizes, nullptr); + if (ptr_jtarget_size == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + jboolean has_exception = JNI_FALSE; + const jsize len = env->GetArrayLength(jpaths); + for (jsize i = 0; i < len; i++) { + jobject jpath = + reinterpret_cast<jstring>(env->GetObjectArrayElement(jpaths, i)); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + std::string path = rocksdb::JniUtil::copyStdString( + env, static_cast<jstring>(jpath), &has_exception); + env->DeleteLocalRef(jpath); + + if (has_exception == JNI_TRUE) { + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + + jlong jtarget_size = ptr_jtarget_size[i]; + + db_paths.push_back( + rocksdb::DbPath(path, static_cast<uint64_t>(jtarget_size))); + } + + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->db_paths = db_paths; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: dbPathsLen + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_dbPathsLen( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->db_paths.size()); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: dbPaths + * Signature: (J[Ljava/lang/String;[J)V + */ +void Java_org_rocksdb_DBOptions_dbPaths( + JNIEnv* env, jobject, jlong jhandle, jobjectArray jpaths, + jlongArray jtarget_sizes) { + jlong* ptr_jtarget_size = env->GetLongArrayElements(jtarget_sizes, nullptr); + if (ptr_jtarget_size == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + const jsize len = env->GetArrayLength(jpaths); + for (jsize i = 0; i < len; i++) { + rocksdb::DbPath db_path = opt->db_paths[i]; + + jstring jpath = env->NewStringUTF(db_path.path.c_str()); + if (jpath == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + env->SetObjectArrayElement(jpaths, i, jpath); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jpath); + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_ABORT); + return; + } + + ptr_jtarget_size[i] = static_cast<jint>(db_path.target_size); + } + + env->ReleaseLongArrayElements(jtarget_sizes, ptr_jtarget_size, JNI_COMMIT); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDbLogDir + * Signature: (JLjava/lang/String)V + */ +void Java_org_rocksdb_DBOptions_setDbLogDir( + JNIEnv* env, jobject, jlong jhandle, jstring jdb_log_dir) { + const char* log_dir = env->GetStringUTFChars(jdb_log_dir, nullptr); + if (log_dir == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->db_log_dir.assign(log_dir); + env->ReleaseStringUTFChars(jdb_log_dir, log_dir); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: dbLogDir + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_DBOptions_dbLogDir( + JNIEnv* env, jobject, jlong jhandle) { + return env->NewStringUTF( + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->db_log_dir.c_str()); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalDir + * Signature: (JLjava/lang/String)V + */ +void Java_org_rocksdb_DBOptions_setWalDir( + JNIEnv* env, jobject, jlong jhandle, jstring jwal_dir) { + const char* wal_dir = env->GetStringUTFChars(jwal_dir, 0); + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->wal_dir.assign(wal_dir); + env->ReleaseStringUTFChars(jwal_dir, wal_dir); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: walDir + * Signature: (J)Ljava/lang/String + */ +jstring Java_org_rocksdb_DBOptions_walDir( + JNIEnv* env, jobject, jlong jhandle) { + return env->NewStringUTF( + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->wal_dir.c_str()); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDeleteObsoleteFilesPeriodMicros + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setDeleteObsoleteFilesPeriodMicros( + JNIEnv*, jobject, jlong jhandle, jlong micros) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->delete_obsolete_files_period_micros = static_cast<int64_t>(micros); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: deleteObsoleteFilesPeriodMicros + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_deleteObsoleteFilesPeriodMicros( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->delete_obsolete_files_period_micros; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setBaseBackgroundCompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setBaseBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->base_background_compactions = + static_cast<int>(max); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: baseBackgroundCompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_baseBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->base_background_compactions; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxBackgroundCompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_background_compactions = + static_cast<int>(max); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxBackgroundCompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxBackgroundCompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->max_background_compactions; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxSubcompactions + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxSubcompactions( + JNIEnv*, jobject, jlong jhandle, jint max) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_subcompactions = + static_cast<int32_t>(max); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxSubcompactions + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxSubcompactions( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_subcompactions; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxBackgroundFlushes + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxBackgroundFlushes( + JNIEnv*, jobject, jlong jhandle, jint max_background_flushes) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_background_flushes = + static_cast<int>(max_background_flushes); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxBackgroundFlushes + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxBackgroundFlushes( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_background_flushes; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxBackgroundJobs + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setMaxBackgroundJobs( + JNIEnv*, jobject, jlong jhandle, jint max_background_jobs) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_background_jobs = + static_cast<int>(max_background_jobs); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxBackgroundJobs + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_maxBackgroundJobs( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_background_jobs; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxLogFileSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setMaxLogFileSize( + JNIEnv* env, jobject, jlong jhandle, jlong max_log_file_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(max_log_file_size); + if (s.ok()) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_log_file_size = + max_log_file_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxLogFileSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_maxLogFileSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_log_file_size; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setLogFileTimeToRoll + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setLogFileTimeToRoll( + JNIEnv* env, jobject, jlong jhandle, jlong log_file_time_to_roll) { + auto s = + rocksdb::JniUtil::check_if_jlong_fits_size_t(log_file_time_to_roll); + if (s.ok()) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->log_file_time_to_roll = + log_file_time_to_roll; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: logFileTimeToRoll + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_logFileTimeToRoll( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->log_file_time_to_roll; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setKeepLogFileNum + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setKeepLogFileNum( + JNIEnv* env, jobject, jlong jhandle, jlong keep_log_file_num) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(keep_log_file_num); + if (s.ok()) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->keep_log_file_num = + keep_log_file_num; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: keepLogFileNum + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_keepLogFileNum( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->keep_log_file_num; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setRecycleLogFileNum + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setRecycleLogFileNum( + JNIEnv* env, jobject, jlong jhandle, jlong recycle_log_file_num) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(recycle_log_file_num); + if (s.ok()) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->recycle_log_file_num = + recycle_log_file_num; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: recycleLogFileNum + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_recycleLogFileNum( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->recycle_log_file_num; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setMaxManifestFileSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setMaxManifestFileSize( + JNIEnv*, jobject, jlong jhandle, jlong max_manifest_file_size) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_manifest_file_size = + static_cast<int64_t>(max_manifest_file_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: maxManifestFileSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_maxManifestFileSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->max_manifest_file_size; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setTableCacheNumshardbits + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setTableCacheNumshardbits( + JNIEnv*, jobject, jlong jhandle, jint table_cache_numshardbits) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->table_cache_numshardbits = + static_cast<int>(table_cache_numshardbits); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: tableCacheNumshardbits + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_tableCacheNumshardbits( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->table_cache_numshardbits; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalTtlSeconds + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWalTtlSeconds( + JNIEnv*, jobject, jlong jhandle, jlong WAL_ttl_seconds) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->WAL_ttl_seconds = + static_cast<int64_t>(WAL_ttl_seconds); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: walTtlSeconds + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_walTtlSeconds( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->WAL_ttl_seconds; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalSizeLimitMB + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWalSizeLimitMB( + JNIEnv*, jobject, jlong jhandle, jlong WAL_size_limit_MB) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->WAL_size_limit_MB = + static_cast<int64_t>(WAL_size_limit_MB); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: walTtlSeconds + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_walSizeLimitMB( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->WAL_size_limit_MB; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setManifestPreallocationSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setManifestPreallocationSize( + JNIEnv* env, jobject, jlong jhandle, jlong preallocation_size) { + auto s = rocksdb::JniUtil::check_if_jlong_fits_size_t(preallocation_size); + if (s.ok()) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->manifest_preallocation_size = preallocation_size; + } else { + rocksdb::IllegalArgumentExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_DBOptions + * Method: manifestPreallocationSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_manifestPreallocationSize( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->manifest_preallocation_size; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: useDirectReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_useDirectReads( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_direct_reads; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setUseDirectReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setUseDirectReads( + JNIEnv*, jobject, jlong jhandle, jboolean use_direct_reads) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_direct_reads = + static_cast<bool>(use_direct_reads); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: useDirectIoForFlushAndCompaction + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_useDirectIoForFlushAndCompaction( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->use_direct_io_for_flush_and_compaction; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setUseDirectReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setUseDirectIoForFlushAndCompaction( + JNIEnv*, jobject, jlong jhandle, + jboolean use_direct_io_for_flush_and_compaction) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->use_direct_io_for_flush_and_compaction = + static_cast<bool>(use_direct_io_for_flush_and_compaction); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllowFAllocate + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllowFAllocate( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_fallocate) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->allow_fallocate = + static_cast<bool>(jallow_fallocate); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allowFAllocate + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allowFAllocate( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->allow_fallocate); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllowMmapReads + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllowMmapReads( + JNIEnv*, jobject, jlong jhandle, jboolean allow_mmap_reads) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->allow_mmap_reads = + static_cast<bool>(allow_mmap_reads); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allowMmapReads + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allowMmapReads( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->allow_mmap_reads; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllowMmapWrites + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllowMmapWrites( + JNIEnv*, jobject, jlong jhandle, jboolean allow_mmap_writes) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->allow_mmap_writes = + static_cast<bool>(allow_mmap_writes); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allowMmapWrites + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allowMmapWrites( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->allow_mmap_writes; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setIsFdCloseOnExec + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setIsFdCloseOnExec( + JNIEnv*, jobject, jlong jhandle, jboolean is_fd_close_on_exec) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->is_fd_close_on_exec = + static_cast<bool>(is_fd_close_on_exec); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: isFdCloseOnExec + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_isFdCloseOnExec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->is_fd_close_on_exec; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setStatsDumpPeriodSec + * Signature: (JI)V + */ +void Java_org_rocksdb_DBOptions_setStatsDumpPeriodSec( + JNIEnv*, jobject, jlong jhandle, jint stats_dump_period_sec) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->stats_dump_period_sec = + static_cast<int>(stats_dump_period_sec); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: statsDumpPeriodSec + * Signature: (J)I + */ +jint Java_org_rocksdb_DBOptions_statsDumpPeriodSec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->stats_dump_period_sec; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAdviseRandomOnOpen + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAdviseRandomOnOpen( + JNIEnv*, jobject, jlong jhandle, jboolean advise_random_on_open) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->advise_random_on_open = + static_cast<bool>(advise_random_on_open); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: adviseRandomOnOpen + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_adviseRandomOnOpen( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->advise_random_on_open; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDbWriteBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setDbWriteBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong jdb_write_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->db_write_buffer_size = static_cast<size_t>(jdb_write_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWriteBufferManager + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWriteBufferManager( + JNIEnv*, jobject, jlong jdb_options_handle, + jlong jwrite_buffer_manager_handle) { + auto* write_buffer_manager = + reinterpret_cast<std::shared_ptr<rocksdb::WriteBufferManager> *>(jwrite_buffer_manager_handle); + reinterpret_cast<rocksdb::DBOptions*>(jdb_options_handle)->write_buffer_manager = + *write_buffer_manager; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: dbWriteBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_dbWriteBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->db_write_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAccessHintOnCompactionStart + * Signature: (JB)V + */ +void Java_org_rocksdb_DBOptions_setAccessHintOnCompactionStart( + JNIEnv*, jobject, jlong jhandle, jbyte jaccess_hint_value) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->access_hint_on_compaction_start = + rocksdb::AccessHintJni::toCppAccessHint(jaccess_hint_value); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: accessHintOnCompactionStart + * Signature: (J)B + */ +jbyte Java_org_rocksdb_DBOptions_accessHintOnCompactionStart( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return rocksdb::AccessHintJni::toJavaAccessHint( + opt->access_hint_on_compaction_start); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setNewTableReaderForCompactionInputs + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setNewTableReaderForCompactionInputs( + JNIEnv*, jobject, jlong jhandle, + jboolean jnew_table_reader_for_compaction_inputs) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->new_table_reader_for_compaction_inputs = + static_cast<bool>(jnew_table_reader_for_compaction_inputs); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: newTableReaderForCompactionInputs + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_newTableReaderForCompactionInputs( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<bool>(opt->new_table_reader_for_compaction_inputs); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setCompactionReadaheadSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setCompactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle, jlong jcompaction_readahead_size) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->compaction_readahead_size = + static_cast<size_t>(jcompaction_readahead_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: compactionReadaheadSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_compactionReadaheadSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->compaction_readahead_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setRandomAccessMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setRandomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong jrandom_access_max_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->random_access_max_buffer_size = + static_cast<size_t>(jrandom_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: randomAccessMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_randomAccessMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->random_access_max_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWritableFileMaxBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWritableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle, jlong jwritable_file_max_buffer_size) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->writable_file_max_buffer_size = + static_cast<size_t>(jwritable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: writableFileMaxBufferSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_writableFileMaxBufferSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->writable_file_max_buffer_size); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setUseAdaptiveMutex + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setUseAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle, jboolean use_adaptive_mutex) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_adaptive_mutex = + static_cast<bool>(use_adaptive_mutex); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: useAdaptiveMutex + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_useAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->use_adaptive_mutex; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setBytesPerSync + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setBytesPerSync( + JNIEnv*, jobject, jlong jhandle, jlong bytes_per_sync) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->bytes_per_sync = + static_cast<int64_t>(bytes_per_sync); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: bytesPerSync + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_bytesPerSync( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle)->bytes_per_sync; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalBytesPerSync + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWalBytesPerSync( + JNIEnv*, jobject, jlong jhandle, jlong jwal_bytes_per_sync) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->wal_bytes_per_sync = + static_cast<int64_t>(jwal_bytes_per_sync); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: walBytesPerSync + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_walBytesPerSync( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->wal_bytes_per_sync); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDelayedWriteRate + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setDelayedWriteRate( + JNIEnv*, jobject, jlong jhandle, jlong jdelayed_write_rate) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->delayed_write_rate = static_cast<uint64_t>(jdelayed_write_rate); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: delayedWriteRate + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_delayedWriteRate( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jlong>(opt->delayed_write_rate); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setEnablePipelinedWrite + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setEnablePipelinedWrite( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_pipelined_write) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->enable_pipelined_write = jenable_pipelined_write == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: enablePipelinedWrite + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_enablePipelinedWrite( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->enable_pipelined_write); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setEnableThreadTracking + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setEnableThreadTracking( + JNIEnv*, jobject, jlong jhandle, jboolean jenable_thread_tracking) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->enable_thread_tracking = jenable_thread_tracking == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: enableThreadTracking + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_enableThreadTracking( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->enable_thread_tracking); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllowConcurrentMemtableWrite + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllowConcurrentMemtableWrite( + JNIEnv*, jobject, jlong jhandle, jboolean allow) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->allow_concurrent_memtable_write = static_cast<bool>(allow); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allowConcurrentMemtableWrite + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allowConcurrentMemtableWrite( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->allow_concurrent_memtable_write; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setEnableWriteThreadAdaptiveYield + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setEnableWriteThreadAdaptiveYield( + JNIEnv*, jobject, jlong jhandle, jboolean yield) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->enable_write_thread_adaptive_yield = static_cast<bool>(yield); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: enableWriteThreadAdaptiveYield + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_enableWriteThreadAdaptiveYield( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->enable_write_thread_adaptive_yield; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWriteThreadMaxYieldUsec + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWriteThreadMaxYieldUsec( + JNIEnv*, jobject, jlong jhandle, jlong max) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->write_thread_max_yield_usec = + static_cast<int64_t>(max); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: writeThreadMaxYieldUsec + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_writeThreadMaxYieldUsec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->write_thread_max_yield_usec; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWriteThreadSlowYieldUsec + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWriteThreadSlowYieldUsec( + JNIEnv*, jobject, jlong jhandle, jlong slow) { + reinterpret_cast<rocksdb::DBOptions*>(jhandle)->write_thread_slow_yield_usec = + static_cast<int64_t>(slow); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: writeThreadSlowYieldUsec + * Signature: (J)J + */ +jlong Java_org_rocksdb_DBOptions_writeThreadSlowYieldUsec( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::DBOptions*>(jhandle) + ->write_thread_slow_yield_usec; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setSkipStatsUpdateOnDbOpen + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setSkipStatsUpdateOnDbOpen( + JNIEnv*, jobject, jlong jhandle, jboolean jskip_stats_update_on_db_open) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->skip_stats_update_on_db_open = + static_cast<bool>(jskip_stats_update_on_db_open); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: skipStatsUpdateOnDbOpen + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_skipStatsUpdateOnDbOpen( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->skip_stats_update_on_db_open); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalRecoveryMode + * Signature: (JB)V + */ +void Java_org_rocksdb_DBOptions_setWalRecoveryMode( + JNIEnv*, jobject, jlong jhandle, jbyte jwal_recovery_mode_value) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->wal_recovery_mode = rocksdb::WALRecoveryModeJni::toCppWALRecoveryMode( + jwal_recovery_mode_value); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: walRecoveryMode + * Signature: (J)B + */ +jbyte Java_org_rocksdb_DBOptions_walRecoveryMode( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return rocksdb::WALRecoveryModeJni::toJavaWALRecoveryMode( + opt->wal_recovery_mode); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllow2pc + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllow2pc( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_2pc) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->allow_2pc = static_cast<bool>(jallow_2pc); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allow2pc + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allow2pc( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->allow_2pc); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setRowCache + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setRowCache( + JNIEnv*, jobject, jlong jhandle, jlong jrow_cache_handle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + auto* row_cache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(jrow_cache_handle); + opt->row_cache = *row_cache; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setWalFilter + * Signature: (JJ)V + */ +void Java_org_rocksdb_DBOptions_setWalFilter( + JNIEnv*, jobject, jlong jhandle, jlong jwal_filter_handle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + auto* wal_filter = + reinterpret_cast<rocksdb::WalFilterJniCallback*>(jwal_filter_handle); + opt->wal_filter = wal_filter; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setFailIfOptionsFileError + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setFailIfOptionsFileError( + JNIEnv*, jobject, jlong jhandle, jboolean jfail_if_options_file_error) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->fail_if_options_file_error = + static_cast<bool>(jfail_if_options_file_error); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: failIfOptionsFileError + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_failIfOptionsFileError( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->fail_if_options_file_error); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setDumpMallocStats + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setDumpMallocStats( + JNIEnv*, jobject, jlong jhandle, jboolean jdump_malloc_stats) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->dump_malloc_stats = static_cast<bool>(jdump_malloc_stats); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: dumpMallocStats + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_dumpMallocStats( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->dump_malloc_stats); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAvoidFlushDuringRecovery + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAvoidFlushDuringRecovery( + JNIEnv*, jobject, jlong jhandle, jboolean javoid_flush_during_recovery) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->avoid_flush_during_recovery = + static_cast<bool>(javoid_flush_during_recovery); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: avoidFlushDuringRecovery + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_avoidFlushDuringRecovery( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->avoid_flush_during_recovery); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAllowIngestBehind + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAllowIngestBehind( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_ingest_behind) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->allow_ingest_behind = jallow_ingest_behind == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: allowIngestBehind + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_allowIngestBehind( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->allow_ingest_behind); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setPreserveDeletes + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setPreserveDeletes( + JNIEnv*, jobject, jlong jhandle, jboolean jpreserve_deletes) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->preserve_deletes = jpreserve_deletes == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: preserveDeletes + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_preserveDeletes( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->preserve_deletes); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setTwoWriteQueues + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setTwoWriteQueues( + JNIEnv*, jobject, jlong jhandle, jboolean jtwo_write_queues) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->two_write_queues = jtwo_write_queues == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: twoWriteQueues + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_twoWriteQueues( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->two_write_queues); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setManualWalFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setManualWalFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jmanual_wal_flush) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->manual_wal_flush = jmanual_wal_flush == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: manualWalFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_manualWalFlush( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->manual_wal_flush); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAtomicFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAtomicFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jatomic_flush) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->atomic_flush = jatomic_flush == JNI_TRUE; +} + +/* + * Class: org_rocksdb_DBOptions + * Method: atomicFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_atomicFlush( + JNIEnv *, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->atomic_flush); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: setAvoidFlushDuringShutdown + * Signature: (JZ)V + */ +void Java_org_rocksdb_DBOptions_setAvoidFlushDuringShutdown( + JNIEnv*, jobject, jlong jhandle, jboolean javoid_flush_during_shutdown) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + opt->avoid_flush_during_shutdown = + static_cast<bool>(javoid_flush_during_shutdown); +} + +/* + * Class: org_rocksdb_DBOptions + * Method: avoidFlushDuringShutdown + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_DBOptions_avoidFlushDuringShutdown( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle); + return static_cast<jboolean>(opt->avoid_flush_during_shutdown); +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::WriteOptions + +/* + * Class: org_rocksdb_WriteOptions + * Method: newWriteOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_WriteOptions_newWriteOptions( + JNIEnv*, jclass) { + auto* op = new rocksdb::WriteOptions(); + return reinterpret_cast<jlong>(op); +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: copyWriteOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_WriteOptions_copyWriteOptions( + JNIEnv*, jclass, jlong jhandle) { + auto new_opt = new rocksdb::WriteOptions( + *(reinterpret_cast<rocksdb::WriteOptions*>(jhandle))); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: disposeInternal + * Signature: ()V + */ +void Java_org_rocksdb_WriteOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* write_options = reinterpret_cast<rocksdb::WriteOptions*>(jhandle); + assert(write_options != nullptr); + delete write_options; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: setSync + * Signature: (JZ)V + */ +void Java_org_rocksdb_WriteOptions_setSync( + JNIEnv*, jobject, jlong jhandle, jboolean jflag) { + reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->sync = jflag; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: sync + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteOptions_sync( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->sync; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: setDisableWAL + * Signature: (JZ)V + */ +void Java_org_rocksdb_WriteOptions_setDisableWAL( + JNIEnv*, jobject, jlong jhandle, jboolean jflag) { + reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->disableWAL = jflag; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: disableWAL + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteOptions_disableWAL( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->disableWAL; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: setIgnoreMissingColumnFamilies + * Signature: (JZ)V + */ +void Java_org_rocksdb_WriteOptions_setIgnoreMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle, + jboolean jignore_missing_column_families) { + reinterpret_cast<rocksdb::WriteOptions*>(jhandle) + ->ignore_missing_column_families = + static_cast<bool>(jignore_missing_column_families); +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: ignoreMissingColumnFamilies + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteOptions_ignoreMissingColumnFamilies( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::WriteOptions*>(jhandle) + ->ignore_missing_column_families; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: setNoSlowdown + * Signature: (JZ)V + */ +void Java_org_rocksdb_WriteOptions_setNoSlowdown( + JNIEnv*, jobject, jlong jhandle, jboolean jno_slowdown) { + reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->no_slowdown = + static_cast<bool>(jno_slowdown); +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: noSlowdown + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteOptions_noSlowdown( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->no_slowdown; +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: setLowPri + * Signature: (JZ)V + */ +void Java_org_rocksdb_WriteOptions_setLowPri( + JNIEnv*, jobject, jlong jhandle, jboolean jlow_pri) { + reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->low_pri = + static_cast<bool>(jlow_pri); +} + +/* + * Class: org_rocksdb_WriteOptions + * Method: lowPri + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteOptions_lowPri( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::WriteOptions*>(jhandle)->low_pri; +} + +///////////////////////////////////////////////////////////////////// +// rocksdb::ReadOptions + +/* + * Class: org_rocksdb_ReadOptions + * Method: newReadOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_ReadOptions_newReadOptions__( + JNIEnv*, jclass) { + auto* read_options = new rocksdb::ReadOptions(); + return reinterpret_cast<jlong>(read_options); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: newReadOptions + * Signature: (ZZ)J + */ +jlong Java_org_rocksdb_ReadOptions_newReadOptions__ZZ( + JNIEnv*, jclass, jboolean jverify_checksums, jboolean jfill_cache) { + auto* read_options = + new rocksdb::ReadOptions(static_cast<bool>(jverify_checksums), + static_cast<bool>(jfill_cache)); + return reinterpret_cast<jlong>(read_options); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: copyReadOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_copyReadOptions( + JNIEnv*, jclass, jlong jhandle) { + auto new_opt = new rocksdb::ReadOptions( + *(reinterpret_cast<rocksdb::ReadOptions*>(jhandle))); + return reinterpret_cast<jlong>(new_opt); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_ReadOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* read_options = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + assert(read_options != nullptr); + delete read_options; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setVerifyChecksums + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setVerifyChecksums( + JNIEnv*, jobject, jlong jhandle, jboolean jverify_checksums) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->verify_checksums = + static_cast<bool>(jverify_checksums); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: verifyChecksums + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_verifyChecksums( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->verify_checksums; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setFillCache + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setFillCache( + JNIEnv*, jobject, jlong jhandle, jboolean jfill_cache) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->fill_cache = + static_cast<bool>(jfill_cache); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: fillCache + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_fillCache( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->fill_cache; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setTailing + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setTailing( + JNIEnv*, jobject, jlong jhandle, jboolean jtailing) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->tailing = + static_cast<bool>(jtailing); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: tailing + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_tailing( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->tailing; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: managed + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_managed( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->managed; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setManaged + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setManaged( + JNIEnv*, jobject, jlong jhandle, jboolean jmanaged) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->managed = + static_cast<bool>(jmanaged); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: totalOrderSeek + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_totalOrderSeek( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->total_order_seek; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setTotalOrderSeek + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setTotalOrderSeek( + JNIEnv*, jobject, jlong jhandle, jboolean jtotal_order_seek) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->total_order_seek = + static_cast<bool>(jtotal_order_seek); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: prefixSameAsStart + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_prefixSameAsStart( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->prefix_same_as_start; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setPrefixSameAsStart + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setPrefixSameAsStart( + JNIEnv*, jobject, jlong jhandle, jboolean jprefix_same_as_start) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->prefix_same_as_start = + static_cast<bool>(jprefix_same_as_start); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: pinData + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_pinData( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->pin_data; +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setPinData + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setPinData( + JNIEnv*, jobject, jlong jhandle, jboolean jpin_data) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->pin_data = + static_cast<bool>(jpin_data); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: backgroundPurgeOnIteratorCleanup + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_backgroundPurgeOnIteratorCleanup( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + return static_cast<jboolean>(opt->background_purge_on_iterator_cleanup); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setBackgroundPurgeOnIteratorCleanup + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setBackgroundPurgeOnIteratorCleanup( + JNIEnv*, jobject, jlong jhandle, + jboolean jbackground_purge_on_iterator_cleanup) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + opt->background_purge_on_iterator_cleanup = + static_cast<bool>(jbackground_purge_on_iterator_cleanup); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: readaheadSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_readaheadSize( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + return static_cast<jlong>(opt->readahead_size); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setReadaheadSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_ReadOptions_setReadaheadSize( + JNIEnv*, jobject, jlong jhandle, jlong jreadahead_size) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + opt->readahead_size = static_cast<size_t>(jreadahead_size); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: maxSkippableInternalKeys + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_maxSkippableInternalKeys( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + return static_cast<jlong>(opt->max_skippable_internal_keys); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setMaxSkippableInternalKeys + * Signature: (JJ)V + */ +void Java_org_rocksdb_ReadOptions_setMaxSkippableInternalKeys( + JNIEnv*, jobject, jlong jhandle, jlong jmax_skippable_internal_keys) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + opt->max_skippable_internal_keys = + static_cast<uint64_t>(jmax_skippable_internal_keys); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: ignoreRangeDeletions + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ReadOptions_ignoreRangeDeletions( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + return static_cast<jboolean>(opt->ignore_range_deletions); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setIgnoreRangeDeletions + * Signature: (JZ)V + */ +void Java_org_rocksdb_ReadOptions_setIgnoreRangeDeletions( + JNIEnv*, jobject, jlong jhandle, jboolean jignore_range_deletions) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + opt->ignore_range_deletions = static_cast<bool>(jignore_range_deletions); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setSnapshot + * Signature: (JJ)V + */ +void Java_org_rocksdb_ReadOptions_setSnapshot( + JNIEnv*, jobject, jlong jhandle, jlong jsnapshot) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->snapshot = + reinterpret_cast<rocksdb::Snapshot*>(jsnapshot); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: snapshot + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_snapshot( + JNIEnv*, jobject, jlong jhandle) { + auto& snapshot = reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->snapshot; + return reinterpret_cast<jlong>(snapshot); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: readTier + * Signature: (J)B + */ +jbyte Java_org_rocksdb_ReadOptions_readTier( + JNIEnv*, jobject, jlong jhandle) { + return static_cast<jbyte>( + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->read_tier); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setReadTier + * Signature: (JB)V + */ +void Java_org_rocksdb_ReadOptions_setReadTier( + JNIEnv*, jobject, jlong jhandle, jbyte jread_tier) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->read_tier = + static_cast<rocksdb::ReadTier>(jread_tier); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setIterateUpperBound + * Signature: (JJ)I + */ +void Java_org_rocksdb_ReadOptions_setIterateUpperBound( + JNIEnv*, jobject, jlong jhandle, jlong jupper_bound_slice_handle) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_upper_bound = + reinterpret_cast<rocksdb::Slice*>(jupper_bound_slice_handle); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: iterateUpperBound + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_iterateUpperBound( + JNIEnv*, jobject, jlong jhandle) { + auto& upper_bound_slice_handle = + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_upper_bound; + return reinterpret_cast<jlong>(upper_bound_slice_handle); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setIterateLowerBound + * Signature: (JJ)I + */ +void Java_org_rocksdb_ReadOptions_setIterateLowerBound( + JNIEnv*, jobject, jlong jhandle, jlong jlower_bound_slice_handle) { + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_lower_bound = + reinterpret_cast<rocksdb::Slice*>(jlower_bound_slice_handle); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: iterateLowerBound + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_iterateLowerBound( + JNIEnv*, jobject, jlong jhandle) { + auto& lower_bound_slice_handle = + reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->iterate_lower_bound; + return reinterpret_cast<jlong>(lower_bound_slice_handle); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setTableFilter + * Signature: (JJ)V + */ +void Java_org_rocksdb_ReadOptions_setTableFilter( + JNIEnv*, jobject, jlong jhandle, jlong jjni_table_filter_handle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + auto* jni_table_filter = + reinterpret_cast<rocksdb::TableFilterJniCallback*>(jjni_table_filter_handle); + opt->table_filter = jni_table_filter->GetTableFilterFunction(); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: setIterStartSeqnum + * Signature: (JJ)V + */ +void Java_org_rocksdb_ReadOptions_setIterStartSeqnum( + JNIEnv*, jobject, jlong jhandle, jlong jiter_start_seqnum) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + opt->iter_start_seqnum = static_cast<uint64_t>(jiter_start_seqnum); +} + +/* + * Class: org_rocksdb_ReadOptions + * Method: iterStartSeqnum + * Signature: (J)J + */ +jlong Java_org_rocksdb_ReadOptions_iterStartSeqnum( + JNIEnv*, jobject, jlong jhandle) { + auto* opt = reinterpret_cast<rocksdb::ReadOptions*>(jhandle); + return static_cast<jlong>(opt->iter_start_seqnum); +} + +///////////////////////////////////////////////////////////////////// +// rocksdb::ComparatorOptions + +/* + * Class: org_rocksdb_ComparatorOptions + * Method: newComparatorOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_ComparatorOptions_newComparatorOptions( + JNIEnv*, jclass) { + auto* comparator_opt = new rocksdb::ComparatorJniCallbackOptions(); + return reinterpret_cast<jlong>(comparator_opt); +} + +/* + * Class: org_rocksdb_ComparatorOptions + * Method: useAdaptiveMutex + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_ComparatorOptions_useAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::ComparatorJniCallbackOptions*>(jhandle) + ->use_adaptive_mutex; +} + +/* + * Class: org_rocksdb_ComparatorOptions + * Method: setUseAdaptiveMutex + * Signature: (JZ)V + */ +void Java_org_rocksdb_ComparatorOptions_setUseAdaptiveMutex( + JNIEnv*, jobject, jlong jhandle, jboolean juse_adaptive_mutex) { + reinterpret_cast<rocksdb::ComparatorJniCallbackOptions*>(jhandle) + ->use_adaptive_mutex = static_cast<bool>(juse_adaptive_mutex); +} + +/* + * Class: org_rocksdb_ComparatorOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_ComparatorOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* comparator_opt = + reinterpret_cast<rocksdb::ComparatorJniCallbackOptions*>(jhandle); + assert(comparator_opt != nullptr); + delete comparator_opt; +} + +///////////////////////////////////////////////////////////////////// +// rocksdb::FlushOptions + +/* + * Class: org_rocksdb_FlushOptions + * Method: newFlushOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_FlushOptions_newFlushOptions( + JNIEnv*, jclass) { + auto* flush_opt = new rocksdb::FlushOptions(); + return reinterpret_cast<jlong>(flush_opt); +} + +/* + * Class: org_rocksdb_FlushOptions + * Method: setWaitForFlush + * Signature: (JZ)V + */ +void Java_org_rocksdb_FlushOptions_setWaitForFlush( + JNIEnv*, jobject, jlong jhandle, jboolean jwait) { + reinterpret_cast<rocksdb::FlushOptions*>(jhandle)->wait = + static_cast<bool>(jwait); +} + +/* + * Class: org_rocksdb_FlushOptions + * Method: waitForFlush + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_FlushOptions_waitForFlush( + JNIEnv*, jobject, jlong jhandle) { + return reinterpret_cast<rocksdb::FlushOptions*>(jhandle)->wait; +} + +/* + * Class: org_rocksdb_FlushOptions + * Method: setAllowWriteStall + * Signature: (JZ)V + */ +void Java_org_rocksdb_FlushOptions_setAllowWriteStall( + JNIEnv*, jobject, jlong jhandle, jboolean jallow_write_stall) { + auto* flush_options = reinterpret_cast<rocksdb::FlushOptions*>(jhandle); + flush_options->allow_write_stall = jallow_write_stall == JNI_TRUE; +} + +/* + * Class: org_rocksdb_FlushOptions + * Method: allowWriteStall + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_FlushOptions_allowWriteStall( + JNIEnv*, jobject, jlong jhandle) { + auto* flush_options = reinterpret_cast<rocksdb::FlushOptions*>(jhandle); + return static_cast<jboolean>(flush_options->allow_write_stall); +} + +/* + * Class: org_rocksdb_FlushOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_FlushOptions_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* flush_opt = reinterpret_cast<rocksdb::FlushOptions*>(jhandle); + assert(flush_opt != nullptr); + delete flush_opt; +} diff --git a/src/rocksdb/java/rocksjni/options_util.cc b/src/rocksdb/java/rocksjni/options_util.cc new file mode 100644 index 00000000..7dd00784 --- /dev/null +++ b/src/rocksdb/java/rocksjni/options_util.cc @@ -0,0 +1,130 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::OptionsUtil methods from Java side. + +#include <jni.h> +#include <string> + +#include "include/org_rocksdb_OptionsUtil.h" + +#include "rocksdb/db.h" +#include "rocksdb/env.h" +#include "rocksdb/utilities/options_util.h" +#include "rocksjni/portal.h" + +void build_column_family_descriptor_list( + JNIEnv* env, jobject jcfds, + std::vector<rocksdb::ColumnFamilyDescriptor>& cf_descs) { + jmethodID add_mid = rocksdb::ListJni::getListAddMethodId(env); + if (add_mid == nullptr) { + // exception occurred accessing method + return; + } + + // Column family descriptor + for (rocksdb::ColumnFamilyDescriptor& cfd : cf_descs) { + // Construct a ColumnFamilyDescriptor java object + jobject jcfd = rocksdb::ColumnFamilyDescriptorJni::construct(env, &cfd); + if (env->ExceptionCheck()) { + // exception occurred constructing object + if (jcfd != nullptr) { + env->DeleteLocalRef(jcfd); + } + return; + } + + // Add the object to java list. + jboolean rs = env->CallBooleanMethod(jcfds, add_mid, jcfd); + if (env->ExceptionCheck() || rs == JNI_FALSE) { + // exception occurred calling method, or could not add + if (jcfd != nullptr) { + env->DeleteLocalRef(jcfd); + } + return; + } + } +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: loadLatestOptions + * Signature: (Ljava/lang/String;JLjava/util/List;Z)V + */ +void Java_org_rocksdb_OptionsUtil_loadLatestOptions( + JNIEnv* env, jclass /*jcls*/, jstring jdbpath, jlong jenv_handle, + jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) { + jboolean has_exception = JNI_FALSE; + auto db_path = rocksdb::JniUtil::copyStdString(env, jdbpath, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + std::vector<rocksdb::ColumnFamilyDescriptor> cf_descs; + rocksdb::Status s = rocksdb::LoadLatestOptions( + db_path, reinterpret_cast<rocksdb::Env*>(jenv_handle), + reinterpret_cast<rocksdb::DBOptions*>(jdb_opts_handle), &cf_descs, + ignore_unknown_options); + if (!s.ok()) { + // error, raise an exception + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } else { + build_column_family_descriptor_list(env, jcfds, cf_descs); + } +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: loadOptionsFromFile + * Signature: (Ljava/lang/String;JJLjava/util/List;Z)V + */ +void Java_org_rocksdb_OptionsUtil_loadOptionsFromFile( + JNIEnv* env, jclass /*jcls*/, jstring jopts_file_name, jlong jenv_handle, + jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) { + jboolean has_exception = JNI_FALSE; + auto opts_file_name = rocksdb::JniUtil::copyStdString(env, jopts_file_name, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + std::vector<rocksdb::ColumnFamilyDescriptor> cf_descs; + rocksdb::Status s = rocksdb::LoadOptionsFromFile( + opts_file_name, reinterpret_cast<rocksdb::Env*>(jenv_handle), + reinterpret_cast<rocksdb::DBOptions*>(jdb_opts_handle), &cf_descs, + ignore_unknown_options); + if (!s.ok()) { + // error, raise an exception + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } else { + build_column_family_descriptor_list(env, jcfds, cf_descs); + } +} + +/* + * Class: org_rocksdb_OptionsUtil + * Method: getLatestOptionsFileName + * Signature: (Ljava/lang/String;J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName( + JNIEnv* env, jclass /*jcls*/, jstring jdbpath, jlong jenv_handle) { + jboolean has_exception = JNI_FALSE; + auto db_path = rocksdb::JniUtil::copyStdString(env, jdbpath, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return nullptr; + } + std::string options_file_name; + rocksdb::Status s = rocksdb::GetLatestOptionsFileName( + db_path, reinterpret_cast<rocksdb::Env*>(jenv_handle), + &options_file_name); + if (!s.ok()) { + // error, raise an exception + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } else { + return env->NewStringUTF(options_file_name.c_str()); + } +} diff --git a/src/rocksdb/java/rocksjni/persistent_cache.cc b/src/rocksdb/java/rocksjni/persistent_cache.cc new file mode 100644 index 00000000..2b6fc60b --- /dev/null +++ b/src/rocksdb/java/rocksjni/persistent_cache.cc @@ -0,0 +1,53 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::PersistentCache. + +#include <jni.h> +#include <string> + +#include "include/org_rocksdb_PersistentCache.h" +#include "rocksdb/persistent_cache.h" +#include "loggerjnicallback.h" +#include "portal.h" + +/* + * Class: org_rocksdb_PersistentCache + * Method: newPersistentCache + * Signature: (JLjava/lang/String;JJZ)J + */ +jlong Java_org_rocksdb_PersistentCache_newPersistentCache( + JNIEnv* env, jclass, jlong jenv_handle, jstring jpath, + jlong jsz, jlong jlogger_handle, jboolean joptimized_for_nvm) { + auto* rocks_env = reinterpret_cast<rocksdb::Env*>(jenv_handle); + jboolean has_exception = JNI_FALSE; + std::string path = rocksdb::JniUtil::copyStdString(env, jpath, &has_exception); + if (has_exception == JNI_TRUE) { + return 0; + } + auto* logger = + reinterpret_cast<std::shared_ptr<rocksdb::LoggerJniCallback>*>(jlogger_handle); + auto* cache = new std::shared_ptr<rocksdb::PersistentCache>(nullptr); + rocksdb::Status s = rocksdb::NewPersistentCache( + rocks_env, path, static_cast<uint64_t>(jsz), *logger, + static_cast<bool>(joptimized_for_nvm), cache); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } + return reinterpret_cast<jlong>(cache); +} + +/* + * Class: org_rocksdb_PersistentCache + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_PersistentCache_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* cache = + reinterpret_cast<std::shared_ptr<rocksdb::PersistentCache>*>(jhandle); + delete cache; // delete std::shared_ptr +} diff --git a/src/rocksdb/java/rocksjni/portal.h b/src/rocksdb/java/rocksjni/portal.h new file mode 100644 index 00000000..70e67653 --- /dev/null +++ b/src/rocksdb/java/rocksjni/portal.h @@ -0,0 +1,7092 @@ +// 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 is designed for caching those frequently used IDs and provide +// efficient portal (i.e, a set of static functions) to access java code +// from c++. + +#ifndef JAVA_ROCKSJNI_PORTAL_H_ +#define JAVA_ROCKSJNI_PORTAL_H_ + +#include <algorithm> +#include <cstring> +#include <functional> +#include <iostream> +#include <iterator> +#include <jni.h> +#include <limits> +#include <memory> +#include <string> +#include <type_traits> +#include <vector> + +#include "rocksdb/db.h" +#include "rocksdb/filter_policy.h" +#include "rocksdb/rate_limiter.h" +#include "rocksdb/status.h" +#include "rocksdb/table.h" +#include "rocksdb/utilities/backupable_db.h" +#include "rocksdb/utilities/memory_util.h" +#include "rocksdb/utilities/transaction_db.h" +#include "rocksdb/utilities/write_batch_with_index.h" +#include "rocksjni/compaction_filter_factory_jnicallback.h" +#include "rocksjni/comparatorjnicallback.h" +#include "rocksjni/loggerjnicallback.h" +#include "rocksjni/table_filter_jnicallback.h" +#include "rocksjni/trace_writer_jnicallback.h" +#include "rocksjni/transaction_notifier_jnicallback.h" +#include "rocksjni/wal_filter_jnicallback.h" +#include "rocksjni/writebatchhandlerjnicallback.h" + +// Remove macro on windows +#ifdef DELETE +#undef DELETE +#endif + +namespace rocksdb { + +class JavaClass { + public: + /** + * Gets and initializes a Java Class + * + * @param env A pointer to the Java environment + * @param jclazz_name The fully qualified JNI name of the Java Class + * e.g. "java/lang/String" + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env, const char* jclazz_name) { + jclass jclazz = env->FindClass(jclazz_name); + assert(jclazz != nullptr); + return jclazz; + } +}; + +// Native class template +template<class PTR, class DERIVED> class RocksDBNativeClass : public JavaClass { +}; + +// Native class template for sub-classes of RocksMutableObject +template<class PTR, class DERIVED> class NativeRocksMutableObject + : public RocksDBNativeClass<PTR, DERIVED> { + public: + + /** + * Gets the Java Method ID for the + * RocksMutableObject#setNativeHandle(long, boolean) method + * + * @param env A pointer to the Java environment + * @return The Java Method ID or nullptr the RocksMutableObject class cannot + * be accessed, or if one of the NoSuchMethodError, + * ExceptionInInitializerError or OutOfMemoryError exceptions is thrown + */ + static jmethodID getSetNativeHandleMethod(JNIEnv* env) { + static jclass jclazz = DERIVED::getJClass(env); + if(jclazz == nullptr) { + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "setNativeHandle", "(JZ)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Sets the C++ object pointer handle in the Java object + * + * @param env A pointer to the Java environment + * @param jobj The Java object on which to set the pointer handle + * @param ptr The C++ object pointer + * @param java_owns_handle JNI_TRUE if ownership of the C++ object is + * managed by the Java object + * + * @return true if a Java exception is pending, false otherwise + */ + static bool setHandle(JNIEnv* env, jobject jobj, PTR ptr, + jboolean java_owns_handle) { + assert(jobj != nullptr); + static jmethodID mid = getSetNativeHandleMethod(env); + if(mid == nullptr) { + return true; // signal exception + } + + env->CallVoidMethod(jobj, mid, reinterpret_cast<jlong>(ptr), java_owns_handle); + if(env->ExceptionCheck()) { + return true; // signal exception + } + + return false; + } +}; + +// Java Exception template +template<class DERIVED> class JavaException : public JavaClass { + public: + /** + * Create and throw a java exception with the provided message + * + * @param env A pointer to the Java environment + * @param msg The message for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, const std::string& msg) { + jclass jclazz = DERIVED::getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + std::cerr << "JavaException::ThrowNew - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + const jint rs = env->ThrowNew(jclazz, msg.c_str()); + if(rs != JNI_OK) { + // exception could not be thrown + std::cerr << "JavaException::ThrowNew - Fatal: could not throw exception!" << std::endl; + return env->ExceptionCheck(); + } + + return true; + } +}; + +// The portal class for java.lang.IllegalArgumentException +class IllegalArgumentExceptionJni : + public JavaException<IllegalArgumentExceptionJni> { + public: + /** + * Get the Java Class java.lang.IllegalArgumentException + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaException::getJClass(env, "java/lang/IllegalArgumentException"); + } + + /** + * Create and throw a Java IllegalArgumentException with the provided status + * + * If s.ok() == true, then this function will not throw any exception. + * + * @param env A pointer to the Java environment + * @param s The status for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, const Status& s) { + assert(!s.ok()); + if (s.ok()) { + return false; + } + + // get the IllegalArgumentException class + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + std::cerr << "IllegalArgumentExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + return JavaException::ThrowNew(env, s.ToString()); + } +}; + +// The portal class for org.rocksdb.Status.Code +class CodeJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.Status.Code + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/Status$Code"); + } + + /** + * Get the Java Method: Status.Code#getValue + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getValueMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getValue", "()b"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.Status.SubCode +class SubCodeJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.Status.SubCode + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/Status$SubCode"); + } + + /** + * Get the Java Method: Status.SubCode#getValue + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getValueMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getValue", "()b"); + assert(mid != nullptr); + return mid; + } + + static rocksdb::Status::SubCode toCppSubCode(const jbyte jsub_code) { + switch (jsub_code) { + case 0x0: + return rocksdb::Status::SubCode::kNone; + case 0x1: + return rocksdb::Status::SubCode::kMutexTimeout; + case 0x2: + return rocksdb::Status::SubCode::kLockTimeout; + case 0x3: + return rocksdb::Status::SubCode::kLockLimit; + case 0x4: + return rocksdb::Status::SubCode::kNoSpace; + case 0x5: + return rocksdb::Status::SubCode::kDeadlock; + case 0x6: + return rocksdb::Status::SubCode::kStaleFile; + case 0x7: + return rocksdb::Status::SubCode::kMemoryLimit; + + case 0x7F: + default: + return rocksdb::Status::SubCode::kNone; + } + } +}; + +// The portal class for org.rocksdb.Status +class StatusJni : public RocksDBNativeClass<rocksdb::Status*, StatusJni> { + public: + /** + * Get the Java Class org.rocksdb.Status + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/Status"); + } + + /** + * Get the Java Method: Status#getCode + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getCodeMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getCode", "()Lorg/rocksdb/Status$Code;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Status#getSubCode + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getSubCodeMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getSubCode", "()Lorg/rocksdb/Status$SubCode;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Status#getState + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getStateMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getState", "()Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } + + /** + * Create a new Java org.rocksdb.Status object with the same properties as + * the provided C++ rocksdb::Status object + * + * @param env A pointer to the Java environment + * @param status The rocksdb::Status object + * + * @return A reference to a Java org.rocksdb.Status object, or nullptr + * if an an exception occurs + */ + static jobject construct(JNIEnv* env, const Status& status) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = + env->GetMethodID(jclazz, "<init>", "(BBLjava/lang/String;)V"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + // convert the Status state for Java + jstring jstate = nullptr; + if (status.getState() != nullptr) { + const char* const state = status.getState(); + jstate = env->NewStringUTF(state); + if(env->ExceptionCheck()) { + if(jstate != nullptr) { + env->DeleteLocalRef(jstate); + } + return nullptr; + } + } + + jobject jstatus = + env->NewObject(jclazz, mid, toJavaStatusCode(status.code()), + toJavaStatusSubCode(status.subcode()), jstate); + if(env->ExceptionCheck()) { + // exception occurred + if(jstate != nullptr) { + env->DeleteLocalRef(jstate); + } + return nullptr; + } + + if(jstate != nullptr) { + env->DeleteLocalRef(jstate); + } + + return jstatus; + } + + // Returns the equivalent org.rocksdb.Status.Code for the provided + // C++ rocksdb::Status::Code enum + static jbyte toJavaStatusCode(const rocksdb::Status::Code& code) { + switch (code) { + case rocksdb::Status::Code::kOk: + return 0x0; + case rocksdb::Status::Code::kNotFound: + return 0x1; + case rocksdb::Status::Code::kCorruption: + return 0x2; + case rocksdb::Status::Code::kNotSupported: + return 0x3; + case rocksdb::Status::Code::kInvalidArgument: + return 0x4; + case rocksdb::Status::Code::kIOError: + return 0x5; + case rocksdb::Status::Code::kMergeInProgress: + return 0x6; + case rocksdb::Status::Code::kIncomplete: + return 0x7; + case rocksdb::Status::Code::kShutdownInProgress: + return 0x8; + case rocksdb::Status::Code::kTimedOut: + return 0x9; + case rocksdb::Status::Code::kAborted: + return 0xA; + case rocksdb::Status::Code::kBusy: + return 0xB; + case rocksdb::Status::Code::kExpired: + return 0xC; + case rocksdb::Status::Code::kTryAgain: + return 0xD; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent org.rocksdb.Status.SubCode for the provided + // C++ rocksdb::Status::SubCode enum + static jbyte toJavaStatusSubCode(const rocksdb::Status::SubCode& subCode) { + switch (subCode) { + case rocksdb::Status::SubCode::kNone: + return 0x0; + case rocksdb::Status::SubCode::kMutexTimeout: + return 0x1; + case rocksdb::Status::SubCode::kLockTimeout: + return 0x2; + case rocksdb::Status::SubCode::kLockLimit: + return 0x3; + case rocksdb::Status::SubCode::kNoSpace: + return 0x4; + case rocksdb::Status::SubCode::kDeadlock: + return 0x5; + case rocksdb::Status::SubCode::kStaleFile: + return 0x6; + case rocksdb::Status::SubCode::kMemoryLimit: + return 0x7; + default: + return 0x7F; // undefined + } + } + + static std::unique_ptr<rocksdb::Status> toCppStatus( + const jbyte jcode_value, const jbyte jsub_code_value) { + std::unique_ptr<rocksdb::Status> status; + switch (jcode_value) { + case 0x0: + //Ok + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::OK())); + break; + case 0x1: + //NotFound + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::NotFound( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x2: + //Corruption + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::Corruption( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x3: + //NotSupported + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::NotSupported( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x4: + //InvalidArgument + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::InvalidArgument( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x5: + //IOError + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::IOError( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x6: + //MergeInProgress + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::MergeInProgress( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x7: + //Incomplete + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::Incomplete( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x8: + //ShutdownInProgress + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::ShutdownInProgress( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x9: + //TimedOut + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::TimedOut( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0xA: + //Aborted + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::Aborted( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0xB: + //Busy + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::Busy( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0xC: + //Expired + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::Expired( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0xD: + //TryAgain + status = std::unique_ptr<rocksdb::Status>( + new rocksdb::Status(rocksdb::Status::TryAgain( + rocksdb::SubCodeJni::toCppSubCode(jsub_code_value)))); + break; + case 0x7F: + default: + return nullptr; + } + return status; + } + + // Returns the equivalent rocksdb::Status for the Java org.rocksdb.Status + static std::unique_ptr<rocksdb::Status> toCppStatus(JNIEnv* env, const jobject jstatus) { + jmethodID mid_code = getCodeMethod(env); + if (mid_code == nullptr) { + // exception occurred + return nullptr; + } + jobject jcode = env->CallObjectMethod(jstatus, mid_code); + if (env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + jmethodID mid_code_value = rocksdb::CodeJni::getValueMethod(env); + if (mid_code_value == nullptr) { + // exception occurred + return nullptr; + } + jbyte jcode_value = env->CallByteMethod(jcode, mid_code_value); + if (env->ExceptionCheck()) { + // exception occurred + if (jcode != nullptr) { + env->DeleteLocalRef(jcode); + } + return nullptr; + } + + jmethodID mid_subCode = getSubCodeMethod(env); + if (mid_subCode == nullptr) { + // exception occurred + return nullptr; + } + jobject jsubCode = env->CallObjectMethod(jstatus, mid_subCode); + if (env->ExceptionCheck()) { + // exception occurred + if (jcode != nullptr) { + env->DeleteLocalRef(jcode); + } + return nullptr; + } + + jbyte jsub_code_value = 0x0; // None + if (jsubCode != nullptr) { + jmethodID mid_subCode_value = rocksdb::SubCodeJni::getValueMethod(env); + if (mid_subCode_value == nullptr) { + // exception occurred + return nullptr; + } + jsub_code_value = env->CallByteMethod(jsubCode, mid_subCode_value); + if (env->ExceptionCheck()) { + // exception occurred + if (jcode != nullptr) { + env->DeleteLocalRef(jcode); + } + return nullptr; + } + } + + jmethodID mid_state = getStateMethod(env); + if (mid_state == nullptr) { + // exception occurred + return nullptr; + } + jobject jstate = env->CallObjectMethod(jstatus, mid_state); + if (env->ExceptionCheck()) { + // exception occurred + if (jsubCode != nullptr) { + env->DeleteLocalRef(jsubCode); + } + if (jcode != nullptr) { + env->DeleteLocalRef(jcode); + } + return nullptr; + } + + std::unique_ptr<rocksdb::Status> status = + toCppStatus(jcode_value, jsub_code_value); + + // delete all local refs + if (jstate != nullptr) { + env->DeleteLocalRef(jstate); + } + if (jsubCode != nullptr) { + env->DeleteLocalRef(jsubCode); + } + if (jcode != nullptr) { + env->DeleteLocalRef(jcode); + } + + return status; + } +}; + +// The portal class for org.rocksdb.RocksDBException +class RocksDBExceptionJni : + public JavaException<RocksDBExceptionJni> { + public: + /** + * Get the Java Class org.rocksdb.RocksDBException + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaException::getJClass(env, "org/rocksdb/RocksDBException"); + } + + /** + * Create and throw a Java RocksDBException with the provided message + * + * @param env A pointer to the Java environment + * @param msg The message for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, const std::string& msg) { + return JavaException::ThrowNew(env, msg); + } + + /** + * Create and throw a Java RocksDBException with the provided status + * + * If s->ok() == true, then this function will not throw any exception. + * + * @param env A pointer to the Java environment + * @param s The status for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, std::unique_ptr<Status>& s) { + return rocksdb::RocksDBExceptionJni::ThrowNew(env, *(s.get())); + } + + /** + * Create and throw a Java RocksDBException with the provided status + * + * If s.ok() == true, then this function will not throw any exception. + * + * @param env A pointer to the Java environment + * @param s The status for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, const Status& s) { + if (s.ok()) { + return false; + } + + // get the RocksDBException class + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + std::cerr << "RocksDBExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + // get the constructor of org.rocksdb.RocksDBException + jmethodID mid = + env->GetMethodID(jclazz, "<init>", "(Lorg/rocksdb/Status;)V"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + std::cerr << "RocksDBExceptionJni::ThrowNew/cstr - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + // get the Java status object + jobject jstatus = StatusJni::construct(env, s); + if(jstatus == nullptr) { + // exception occcurred + std::cerr << "RocksDBExceptionJni::ThrowNew/StatusJni - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + // construct the RocksDBException + jthrowable rocksdb_exception = reinterpret_cast<jthrowable>(env->NewObject(jclazz, mid, jstatus)); + if(env->ExceptionCheck()) { + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + std::cerr << "RocksDBExceptionJni::ThrowNew/NewObject - Error: unexpected exception!" << std::endl; + return true; + } + + // throw the RocksDBException + const jint rs = env->Throw(rocksdb_exception); + if(rs != JNI_OK) { + // exception could not be thrown + std::cerr << "RocksDBExceptionJni::ThrowNew - Fatal: could not throw exception!" << std::endl; + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + return env->ExceptionCheck(); + } + + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + + return true; + } + + /** + * Create and throw a Java RocksDBException with the provided message + * and status + * + * If s.ok() == true, then this function will not throw any exception. + * + * @param env A pointer to the Java environment + * @param msg The message for the exception + * @param s The status for the exception + * + * @return true if an exception was thrown, false otherwise + */ + static bool ThrowNew(JNIEnv* env, const std::string& msg, const Status& s) { + assert(!s.ok()); + if (s.ok()) { + return false; + } + + // get the RocksDBException class + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + std::cerr << "RocksDBExceptionJni::ThrowNew/class - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + // get the constructor of org.rocksdb.RocksDBException + jmethodID mid = + env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;Lorg/rocksdb/Status;)V"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + std::cerr << "RocksDBExceptionJni::ThrowNew/cstr - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + jstring jmsg = env->NewStringUTF(msg.c_str()); + if(jmsg == nullptr) { + // exception thrown: OutOfMemoryError + std::cerr << "RocksDBExceptionJni::ThrowNew/msg - Error: unexpected exception!" << std::endl; + return env->ExceptionCheck(); + } + + // get the Java status object + jobject jstatus = StatusJni::construct(env, s); + if(jstatus == nullptr) { + // exception occcurred + std::cerr << "RocksDBExceptionJni::ThrowNew/StatusJni - Error: unexpected exception!" << std::endl; + if(jmsg != nullptr) { + env->DeleteLocalRef(jmsg); + } + return env->ExceptionCheck(); + } + + // construct the RocksDBException + jthrowable rocksdb_exception = reinterpret_cast<jthrowable>(env->NewObject(jclazz, mid, jmsg, jstatus)); + if(env->ExceptionCheck()) { + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(jmsg != nullptr) { + env->DeleteLocalRef(jmsg); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + std::cerr << "RocksDBExceptionJni::ThrowNew/NewObject - Error: unexpected exception!" << std::endl; + return true; + } + + // throw the RocksDBException + const jint rs = env->Throw(rocksdb_exception); + if(rs != JNI_OK) { + // exception could not be thrown + std::cerr << "RocksDBExceptionJni::ThrowNew - Fatal: could not throw exception!" << std::endl; + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(jmsg != nullptr) { + env->DeleteLocalRef(jmsg); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + return env->ExceptionCheck(); + } + + if(jstatus != nullptr) { + env->DeleteLocalRef(jstatus); + } + if(jmsg != nullptr) { + env->DeleteLocalRef(jmsg); + } + if(rocksdb_exception != nullptr) { + env->DeleteLocalRef(rocksdb_exception); + } + + return true; + } + + /** + * Get the Java Method: RocksDBException#getStatus + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getStatusMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "getStatus", "()Lorg/rocksdb/Status;"); + assert(mid != nullptr); + return mid; + } + + static std::unique_ptr<rocksdb::Status> toCppStatus( + JNIEnv* env, jthrowable jrocksdb_exception) { + if(!env->IsInstanceOf(jrocksdb_exception, getJClass(env))) { + // not an instance of RocksDBException + return nullptr; + } + + // get the java status object + jmethodID mid = getStatusMethod(env); + if(mid == nullptr) { + // exception occurred accessing class or method + return nullptr; + } + + jobject jstatus = env->CallObjectMethod(jrocksdb_exception, mid); + if(env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + if(jstatus == nullptr) { + return nullptr; // no status available + } + + return rocksdb::StatusJni::toCppStatus(env, jstatus); + } +}; + +// The portal class for java.util.List +class ListJni : public JavaClass { + public: + /** + * Get the Java Class java.util.List + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getListClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/util/List"); + } + + /** + * Get the Java Class java.util.ArrayList + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getArrayListClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/util/ArrayList"); + } + + /** + * Get the Java Class java.util.Iterator + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getIteratorClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/util/Iterator"); + } + + /** + * Get the Java Method: List#iterator + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getIteratorMethod(JNIEnv* env) { + jclass jlist_clazz = getListClass(env); + if(jlist_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jlist_clazz, "iterator", "()Ljava/util/Iterator;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Iterator#hasNext + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getHasNextMethod(JNIEnv* env) { + jclass jiterator_clazz = getIteratorClass(env); + if(jiterator_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jiterator_clazz, "hasNext", "()Z"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Iterator#next + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getNextMethod(JNIEnv* env) { + jclass jiterator_clazz = getIteratorClass(env); + if(jiterator_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jiterator_clazz, "next", "()Ljava/lang/Object;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: ArrayList constructor + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getArrayListConstructorMethodId(JNIEnv* env) { + jclass jarray_list_clazz = getArrayListClass(env); + if(jarray_list_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + static jmethodID mid = + env->GetMethodID(jarray_list_clazz, "<init>", "(I)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: List#add + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getListAddMethodId(JNIEnv* env) { + jclass jlist_clazz = getListClass(env); + if(jlist_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jlist_clazz, "add", "(Ljava/lang/Object;)Z"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for java.lang.Byte +class ByteJni : public JavaClass { + public: + /** + * Get the Java Class java.lang.Byte + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/lang/Byte"); + } + + /** + * Get the Java Class byte[] + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getArrayJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "[B"); + } + + /** + * Creates a new 2-dimensional Java Byte Array byte[][] + * + * @param env A pointer to the Java environment + * @param len The size of the first dimension + * + * @return A reference to the Java byte[][] or nullptr if an exception occurs + */ + static jobjectArray new2dByteArray(JNIEnv* env, const jsize len) { + jclass clazz = getArrayJClass(env); + if(clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + return env->NewObjectArray(len, clazz, nullptr); + } + + /** + * Get the Java Method: Byte#byteValue + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retrieved + */ + static jmethodID getByteValueMethod(JNIEnv* env) { + jclass clazz = getJClass(env); + if(clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(clazz, "byteValue", "()B"); + assert(mid != nullptr); + return mid; + } + + /** + * Calls the Java Method: Byte#valueOf, returning a constructed Byte jobject + * + * @param env A pointer to the Java environment + * + * @return A constructing Byte object or nullptr if the class or method id could not + * be retrieved, or an exception occurred + */ + static jobject valueOf(JNIEnv* env, jbyte jprimitive_byte) { + jclass clazz = getJClass(env); + if (clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetStaticMethodID(clazz, "valueOf", "(B)Ljava/lang/Byte;"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + const jobject jbyte_obj = + env->CallStaticObjectMethod(clazz, mid, jprimitive_byte); + if (env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + return jbyte_obj; + } + +}; + +// The portal class for java.lang.Integer +class IntegerJni : public JavaClass { + public: + /** + * Get the Java Class java.lang.Integer + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/lang/Integer"); + } + + static jobject valueOf(JNIEnv* env, jint jprimitive_int) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = + env->GetStaticMethodID(jclazz, "valueOf", "(I)Ljava/lang/Integer;"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + const jobject jinteger_obj = + env->CallStaticObjectMethod(jclazz, mid, jprimitive_int); + if (env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + return jinteger_obj; + } +}; + +// The portal class for java.lang.Long +class LongJni : public JavaClass { + public: + /** + * Get the Java Class java.lang.Long + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/lang/Long"); + } + + static jobject valueOf(JNIEnv* env, jlong jprimitive_long) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = + env->GetStaticMethodID(jclazz, "valueOf", "(J)Ljava/lang/Long;"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + const jobject jlong_obj = + env->CallStaticObjectMethod(jclazz, mid, jprimitive_long); + if (env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + return jlong_obj; + } +}; + +// The portal class for java.lang.StringBuilder +class StringBuilderJni : public JavaClass { + public: + /** + * Get the Java Class java.lang.StringBuilder + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/lang/StringBuilder"); + } + + /** + * Get the Java Method: StringBuilder#append + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getListAddMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "append", + "(Ljava/lang/String;)Ljava/lang/StringBuilder;"); + assert(mid != nullptr); + return mid; + } + + /** + * Appends a C-style string to a StringBuilder + * + * @param env A pointer to the Java environment + * @param jstring_builder Reference to a java.lang.StringBuilder + * @param c_str A C-style string to append to the StringBuilder + * + * @return A reference to the updated StringBuilder, or a nullptr if + * an exception occurs + */ + static jobject append(JNIEnv* env, jobject jstring_builder, + const char* c_str) { + jmethodID mid = getListAddMethodId(env); + if(mid == nullptr) { + // exception occurred accessing class or method + return nullptr; + } + + jstring new_value_str = env->NewStringUTF(c_str); + if(new_value_str == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jobject jresult_string_builder = + env->CallObjectMethod(jstring_builder, mid, new_value_str); + if(env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(new_value_str); + return nullptr; + } + + return jresult_string_builder; + } +}; + +// various utility functions for working with RocksDB and JNI +class JniUtil { + public: + /** + * Detect if jlong overflows size_t + * + * @param jvalue the jlong value + * + * @return + */ + inline static Status check_if_jlong_fits_size_t(const jlong& jvalue) { + Status s = Status::OK(); + if (static_cast<uint64_t>(jvalue) > std::numeric_limits<size_t>::max()) { + s = Status::InvalidArgument(Slice("jlong overflows 32 bit value.")); + } + return s; + } + + /** + * Obtains a reference to the JNIEnv from + * the JVM + * + * If the current thread is not attached to the JavaVM + * then it will be attached so as to retrieve the JNIEnv + * + * If a thread is attached, it must later be manually + * released by calling JavaVM::DetachCurrentThread. + * This can be handled by always matching calls to this + * function with calls to {@link JniUtil::releaseJniEnv(JavaVM*, jboolean)} + * + * @param jvm (IN) A pointer to the JavaVM instance + * @param attached (OUT) A pointer to a boolean which + * will be set to JNI_TRUE if we had to attach the thread + * + * @return A pointer to the JNIEnv or nullptr if a fatal error + * occurs and the JNIEnv cannot be retrieved + */ + static JNIEnv* getJniEnv(JavaVM* jvm, jboolean* attached) { + assert(jvm != nullptr); + + JNIEnv *env; + const jint env_rs = jvm->GetEnv(reinterpret_cast<void**>(&env), + JNI_VERSION_1_2); + + if(env_rs == JNI_OK) { + // current thread is already attached, return the JNIEnv + *attached = JNI_FALSE; + return env; + } else if(env_rs == JNI_EDETACHED) { + // current thread is not attached, attempt to attach + const jint rs_attach = jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL); + if(rs_attach == JNI_OK) { + *attached = JNI_TRUE; + return env; + } else { + // error, could not attach the thread + std::cerr << "JniUtil::getJniEnv - Fatal: could not attach current thread to JVM!" << std::endl; + return nullptr; + } + } else if(env_rs == JNI_EVERSION) { + // error, JDK does not support JNI_VERSION_1_2+ + std::cerr << "JniUtil::getJniEnv - Fatal: JDK does not support JNI_VERSION_1_2" << std::endl; + return nullptr; + } else { + std::cerr << "JniUtil::getJniEnv - Fatal: Unknown error: env_rs=" << env_rs << std::endl; + return nullptr; + } + } + + /** + * Counterpart to {@link JniUtil::getJniEnv(JavaVM*, jboolean*)} + * + * Detachess the current thread from the JVM if it was previously + * attached + * + * @param jvm (IN) A pointer to the JavaVM instance + * @param attached (IN) JNI_TRUE if we previously had to attach the thread + * to the JavaVM to get the JNIEnv + */ + static void releaseJniEnv(JavaVM* jvm, jboolean& attached) { + assert(jvm != nullptr); + if(attached == JNI_TRUE) { + const jint rs_detach = jvm->DetachCurrentThread(); + assert(rs_detach == JNI_OK); + if(rs_detach != JNI_OK) { + std::cerr << "JniUtil::getJniEnv - Warn: Unable to detach current thread from JVM!" << std::endl; + } + } + } + + /** + * Copies a Java String[] to a C++ std::vector<std::string> + * + * @param env (IN) A pointer to the java environment + * @param jss (IN) The Java String array to copy + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError or ArrayIndexOutOfBoundsException + * exception occurs + * + * @return A std::vector<std:string> containing copies of the Java strings + */ + static std::vector<std::string> copyStrings(JNIEnv* env, + jobjectArray jss, jboolean* has_exception) { + return rocksdb::JniUtil::copyStrings(env, jss, + env->GetArrayLength(jss), has_exception); + } + + /** + * Copies a Java String[] to a C++ std::vector<std::string> + * + * @param env (IN) A pointer to the java environment + * @param jss (IN) The Java String array to copy + * @param jss_len (IN) The length of the Java String array to copy + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError or ArrayIndexOutOfBoundsException + * exception occurs + * + * @return A std::vector<std:string> containing copies of the Java strings + */ + static std::vector<std::string> copyStrings(JNIEnv* env, + jobjectArray jss, const jsize jss_len, jboolean* has_exception) { + std::vector<std::string> strs; + strs.reserve(jss_len); + for (jsize i = 0; i < jss_len; i++) { + jobject js = env->GetObjectArrayElement(jss, i); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + *has_exception = JNI_TRUE; + return strs; + } + + jstring jstr = static_cast<jstring>(js); + const char* str = env->GetStringUTFChars(jstr, nullptr); + if(str == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(js); + *has_exception = JNI_TRUE; + return strs; + } + + strs.push_back(std::string(str)); + + env->ReleaseStringUTFChars(jstr, str); + env->DeleteLocalRef(js); + } + + *has_exception = JNI_FALSE; + return strs; + } + + /** + * Copies a jstring to a C-style null-terminated byte string + * and releases the original jstring + * + * The jstring is copied as UTF-8 + * + * If an exception occurs, then JNIEnv::ExceptionCheck() + * will have been called + * + * @param env (IN) A pointer to the java environment + * @param js (IN) The java string to copy + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError exception occurs + * + * @return A pointer to the copied string, or a + * nullptr if has_exception == JNI_TRUE + */ + static std::unique_ptr<char[]> copyString(JNIEnv* env, jstring js, + jboolean* has_exception) { + const char *utf = env->GetStringUTFChars(js, nullptr); + if(utf == nullptr) { + // exception thrown: OutOfMemoryError + env->ExceptionCheck(); + *has_exception = JNI_TRUE; + return nullptr; + } else if(env->ExceptionCheck()) { + // exception thrown + env->ReleaseStringUTFChars(js, utf); + *has_exception = JNI_TRUE; + return nullptr; + } + + const jsize utf_len = env->GetStringUTFLength(js); + std::unique_ptr<char[]> str(new char[utf_len + 1]); // Note: + 1 is needed for the c_str null terminator + std::strcpy(str.get(), utf); + env->ReleaseStringUTFChars(js, utf); + *has_exception = JNI_FALSE; + return str; + } + + /** + * Copies a jstring to a std::string + * and releases the original jstring + * + * If an exception occurs, then JNIEnv::ExceptionCheck() + * will have been called + * + * @param env (IN) A pointer to the java environment + * @param js (IN) The java string to copy + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError exception occurs + * + * @return A std:string copy of the jstring, or an + * empty std::string if has_exception == JNI_TRUE + */ + static std::string copyStdString(JNIEnv* env, jstring js, + jboolean* has_exception) { + const char *utf = env->GetStringUTFChars(js, nullptr); + if(utf == nullptr) { + // exception thrown: OutOfMemoryError + env->ExceptionCheck(); + *has_exception = JNI_TRUE; + return std::string(); + } else if(env->ExceptionCheck()) { + // exception thrown + env->ReleaseStringUTFChars(js, utf); + *has_exception = JNI_TRUE; + return std::string(); + } + + std::string name(utf); + env->ReleaseStringUTFChars(js, utf); + *has_exception = JNI_FALSE; + return name; + } + + /** + * Copies bytes from a std::string to a jByteArray + * + * @param env A pointer to the java environment + * @param bytes The bytes to copy + * + * @return the Java byte[], or nullptr if an exception occurs + * + * @throws RocksDBException thrown + * if memory size to copy exceeds general java specific array size limitation. + */ + static jbyteArray copyBytes(JNIEnv* env, std::string bytes) { + return createJavaByteArrayWithSizeCheck(env, bytes.c_str(), bytes.size()); + } + + /** + * Given a Java byte[][] which is an array of java.lang.Strings + * where each String is a byte[], the passed function `string_fn` + * will be called on each String, the result is the collected by + * calling the passed function `collector_fn` + * + * @param env (IN) A pointer to the java environment + * @param jbyte_strings (IN) A Java array of Strings expressed as bytes + * @param string_fn (IN) A transform function to call for each String + * @param collector_fn (IN) A collector which is called for the result + * of each `string_fn` + * @param has_exception (OUT) will be set to JNI_TRUE + * if an ArrayIndexOutOfBoundsException or OutOfMemoryError + * exception occurs + */ + template <typename T> static void byteStrings(JNIEnv* env, + jobjectArray jbyte_strings, + std::function<T(const char*, const size_t)> string_fn, + std::function<void(size_t, T)> collector_fn, + jboolean *has_exception) { + const jsize jlen = env->GetArrayLength(jbyte_strings); + + for(jsize i = 0; i < jlen; i++) { + jobject jbyte_string_obj = env->GetObjectArrayElement(jbyte_strings, i); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + *has_exception = JNI_TRUE; // signal error + return; + } + + jbyteArray jbyte_string_ary = + reinterpret_cast<jbyteArray>(jbyte_string_obj); + T result = byteString(env, jbyte_string_ary, string_fn, has_exception); + + env->DeleteLocalRef(jbyte_string_obj); + + if(*has_exception == JNI_TRUE) { + // exception thrown: OutOfMemoryError + return; + } + + collector_fn(i, result); + } + + *has_exception = JNI_FALSE; + } + + /** + * Given a Java String which is expressed as a Java Byte Array byte[], + * the passed function `string_fn` will be called on the String + * and the result returned + * + * @param env (IN) A pointer to the java environment + * @param jbyte_string_ary (IN) A Java String expressed in bytes + * @param string_fn (IN) A transform function to call on the String + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError exception occurs + */ + template <typename T> static T byteString(JNIEnv* env, + jbyteArray jbyte_string_ary, + std::function<T(const char*, const size_t)> string_fn, + jboolean* has_exception) { + const jsize jbyte_string_len = env->GetArrayLength(jbyte_string_ary); + return byteString<T>(env, jbyte_string_ary, jbyte_string_len, string_fn, + has_exception); + } + + /** + * Given a Java String which is expressed as a Java Byte Array byte[], + * the passed function `string_fn` will be called on the String + * and the result returned + * + * @param env (IN) A pointer to the java environment + * @param jbyte_string_ary (IN) A Java String expressed in bytes + * @param jbyte_string_len (IN) The length of the Java String + * expressed in bytes + * @param string_fn (IN) A transform function to call on the String + * @param has_exception (OUT) will be set to JNI_TRUE + * if an OutOfMemoryError exception occurs + */ + template <typename T> static T byteString(JNIEnv* env, + jbyteArray jbyte_string_ary, const jsize jbyte_string_len, + std::function<T(const char*, const size_t)> string_fn, + jboolean* has_exception) { + jbyte* jbyte_string = + env->GetByteArrayElements(jbyte_string_ary, nullptr); + if(jbyte_string == nullptr) { + // exception thrown: OutOfMemoryError + *has_exception = JNI_TRUE; + return nullptr; // signal error + } + + T result = + string_fn(reinterpret_cast<char *>(jbyte_string), jbyte_string_len); + + env->ReleaseByteArrayElements(jbyte_string_ary, jbyte_string, JNI_ABORT); + + *has_exception = JNI_FALSE; + return result; + } + + /** + * Converts a std::vector<string> to a Java byte[][] where each Java String + * is expressed as a Java Byte Array byte[]. + * + * @param env A pointer to the java environment + * @param strings A vector of Strings + * + * @return A Java array of Strings expressed as bytes, + * or nullptr if an exception is thrown + */ + static jobjectArray stringsBytes(JNIEnv* env, std::vector<std::string> strings) { + jclass jcls_ba = ByteJni::getArrayJClass(env); + if(jcls_ba == nullptr) { + // exception occurred + return nullptr; + } + + const jsize len = static_cast<jsize>(strings.size()); + + jobjectArray jbyte_strings = env->NewObjectArray(len, jcls_ba, nullptr); + if(jbyte_strings == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + for (jsize i = 0; i < len; i++) { + std::string *str = &strings[i]; + const jsize str_len = static_cast<jsize>(str->size()); + + jbyteArray jbyte_string_ary = env->NewByteArray(str_len); + if(jbyte_string_ary == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jbyte_strings); + return nullptr; + } + + env->SetByteArrayRegion( + jbyte_string_ary, 0, str_len, + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(str->c_str()))); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jbyte_string_ary); + env->DeleteLocalRef(jbyte_strings); + return nullptr; + } + + env->SetObjectArrayElement(jbyte_strings, i, jbyte_string_ary); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + // or ArrayStoreException + env->DeleteLocalRef(jbyte_string_ary); + env->DeleteLocalRef(jbyte_strings); + return nullptr; + } + + env->DeleteLocalRef(jbyte_string_ary); + } + + return jbyte_strings; + } + + /** + * Converts a std::vector<std::string> to a Java String[]. + * + * @param env A pointer to the java environment + * @param strings A vector of Strings + * + * @return A Java array of Strings, + * or nullptr if an exception is thrown + */ + static jobjectArray toJavaStrings(JNIEnv* env, + const std::vector<std::string>* strings) { + jclass jcls_str = env->FindClass("java/lang/String"); + if(jcls_str == nullptr) { + // exception occurred + return nullptr; + } + + const jsize len = static_cast<jsize>(strings->size()); + + jobjectArray jstrings = env->NewObjectArray(len, jcls_str, nullptr); + if(jstrings == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + for (jsize i = 0; i < len; i++) { + const std::string *str = &((*strings)[i]); + jstring js = rocksdb::JniUtil::toJavaString(env, str); + if (js == nullptr) { + env->DeleteLocalRef(jstrings); + return nullptr; + } + + env->SetObjectArrayElement(jstrings, i, js); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + // or ArrayStoreException + env->DeleteLocalRef(js); + env->DeleteLocalRef(jstrings); + return nullptr; + } + } + + return jstrings; + } + + /** + * Creates a Java UTF String from a C++ std::string + * + * @param env A pointer to the java environment + * @param string the C++ std::string + * @param treat_empty_as_null true if empty strings should be treated as null + * + * @return the Java UTF string, or nullptr if the provided string + * is null (or empty and treat_empty_as_null is set), or if an + * exception occurs allocating the Java String. + */ + static jstring toJavaString(JNIEnv* env, const std::string* string, + const bool treat_empty_as_null = false) { + if (string == nullptr) { + return nullptr; + } + + if (treat_empty_as_null && string->empty()) { + return nullptr; + } + + return env->NewStringUTF(string->c_str()); + } + + /** + * Copies bytes to a new jByteArray with the check of java array size limitation. + * + * @param bytes pointer to memory to copy to a new jByteArray + * @param size number of bytes to copy + * + * @return the Java byte[], or nullptr if an exception occurs + * + * @throws RocksDBException thrown + * if memory size to copy exceeds general java array size limitation to avoid overflow. + */ + static jbyteArray createJavaByteArrayWithSizeCheck(JNIEnv* env, const char* bytes, const size_t size) { + // Limitation for java array size is vm specific + // In general it cannot exceed Integer.MAX_VALUE (2^31 - 1) + // Current HotSpot VM limitation for array size is Integer.MAX_VALUE - 5 (2^31 - 1 - 5) + // It means that the next call to env->NewByteArray can still end with + // OutOfMemoryError("Requested array size exceeds VM limit") coming from VM + static const size_t MAX_JARRAY_SIZE = (static_cast<size_t>(1)) << 31; + if(size > MAX_JARRAY_SIZE) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, "Requested array size exceeds VM limit"); + return nullptr; + } + + const jsize jlen = static_cast<jsize>(size); + jbyteArray jbytes = env->NewByteArray(jlen); + if(jbytes == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion(jbytes, 0, jlen, + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(bytes))); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jbytes); + return nullptr; + } + + return jbytes; + } + + /** + * Copies bytes from a rocksdb::Slice to a jByteArray + * + * @param env A pointer to the java environment + * @param bytes The bytes to copy + * + * @return the Java byte[] or nullptr if an exception occurs + * + * @throws RocksDBException thrown + * if memory size to copy exceeds general java specific array size limitation. + */ + static jbyteArray copyBytes(JNIEnv* env, const Slice& bytes) { + return createJavaByteArrayWithSizeCheck(env, bytes.data(), bytes.size()); + } + + /* + * Helper for operations on a key and value + * for example WriteBatch->Put + * + * TODO(AR) could be used for RocksDB->Put etc. + */ + static std::unique_ptr<rocksdb::Status> kv_op( + std::function<rocksdb::Status(rocksdb::Slice, rocksdb::Slice)> op, + JNIEnv* env, jobject /*jobj*/, + jbyteArray jkey, jint jkey_len, + jbyteArray jvalue, jint jvalue_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if(env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jbyte* value = env->GetByteArrayElements(jvalue, nullptr); + if(env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + if(key != nullptr) { + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + } + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + rocksdb::Slice value_slice(reinterpret_cast<char*>(value), + jvalue_len); + + auto status = op(key_slice, value_slice); + + if(value != nullptr) { + env->ReleaseByteArrayElements(jvalue, value, JNI_ABORT); + } + if(key != nullptr) { + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + } + + return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(status)); + } + + /* + * Helper for operations on a key + * for example WriteBatch->Delete + * + * TODO(AR) could be used for RocksDB->Delete etc. + */ + static std::unique_ptr<rocksdb::Status> k_op( + std::function<rocksdb::Status(rocksdb::Slice)> op, + JNIEnv* env, jobject /*jobj*/, + jbyteArray jkey, jint jkey_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if(env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + auto status = op(key_slice); + + if(key != nullptr) { + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + } + + return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(status)); + } + + /* + * Helper for operations on a value + * for example WriteBatchWithIndex->GetFromBatch + */ + static jbyteArray v_op( + std::function<rocksdb::Status(rocksdb::Slice, std::string*)> op, + JNIEnv* env, jbyteArray jkey, jint jkey_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if(env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + std::string value; + rocksdb::Status s = op(key_slice, &value); + + if(key != nullptr) { + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + } + + if (s.IsNotFound()) { + return nullptr; + } + + if (s.ok()) { + jbyteArray jret_value = + env->NewByteArray(static_cast<jsize>(value.size())); + if(jret_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion(jret_value, 0, static_cast<jsize>(value.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value.c_str()))); + if(env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + if(jret_value != nullptr) { + env->DeleteLocalRef(jret_value); + } + return nullptr; + } + + return jret_value; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + /** + * Creates a vector<T*> of C++ pointers from + * a Java array of C++ pointer addresses. + * + * @param env (IN) A pointer to the java environment + * @param pointers (IN) A Java array of C++ pointer addresses + * @param has_exception (OUT) will be set to JNI_TRUE + * if an ArrayIndexOutOfBoundsException or OutOfMemoryError + * exception occurs. + * + * @return A vector of C++ pointers. + */ + template<typename T> static std::vector<T*> fromJPointers( + JNIEnv* env, jlongArray jptrs, jboolean *has_exception) { + const jsize jptrs_len = env->GetArrayLength(jptrs); + std::vector<T*> ptrs; + jlong* jptr = env->GetLongArrayElements(jptrs, nullptr); + if (jptr == nullptr) { + // exception thrown: OutOfMemoryError + *has_exception = JNI_TRUE; + return ptrs; + } + ptrs.reserve(jptrs_len); + for (jsize i = 0; i < jptrs_len; i++) { + ptrs.push_back(reinterpret_cast<T*>(jptr[i])); + } + env->ReleaseLongArrayElements(jptrs, jptr, JNI_ABORT); + return ptrs; + } + + /** + * Creates a Java array of C++ pointer addresses + * from a vector of C++ pointers. + * + * @param env (IN) A pointer to the java environment + * @param pointers (IN) A vector of C++ pointers + * @param has_exception (OUT) will be set to JNI_TRUE + * if an ArrayIndexOutOfBoundsException or OutOfMemoryError + * exception occurs + * + * @return Java array of C++ pointer addresses. + */ + template<typename T> static jlongArray toJPointers(JNIEnv* env, + const std::vector<T*> &pointers, + jboolean *has_exception) { + const jsize len = static_cast<jsize>(pointers.size()); + std::unique_ptr<jlong[]> results(new jlong[len]); + std::transform(pointers.begin(), pointers.end(), results.get(), [](T* pointer) -> jlong { + return reinterpret_cast<jlong>(pointer); + }); + + jlongArray jpointers = env->NewLongArray(len); + if (jpointers == nullptr) { + // exception thrown: OutOfMemoryError + *has_exception = JNI_TRUE; + return nullptr; + } + + env->SetLongArrayRegion(jpointers, 0, len, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + *has_exception = JNI_TRUE; + env->DeleteLocalRef(jpointers); + return nullptr; + } + + *has_exception = JNI_FALSE; + + return jpointers; + } +}; + +class MapJni : public JavaClass { + public: + /** + * Get the Java Class java.util.Map + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/util/Map"); + } + + /** + * Get the Java Method: Map#put + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMapPutMethodId(JNIEnv* env) { + jclass jlist_clazz = getJClass(env); + if(jlist_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jlist_clazz, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + assert(mid != nullptr); + return mid; + } +}; + +class HashMapJni : public JavaClass { + public: + /** + * Get the Java Class java.util.HashMap + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "java/util/HashMap"); + } + + /** + * Create a new Java java.util.HashMap object. + * + * @param env A pointer to the Java environment + * + * @return A reference to a Java java.util.HashMap object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, const uint32_t initial_capacity = 16) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(I)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jhash_map = env->NewObject(jclazz, mid, static_cast<jint>(initial_capacity)); + if (env->ExceptionCheck()) { + return nullptr; + } + + return jhash_map; + } + + /** + * A function which maps a std::pair<K,V> to a std::pair<JK, JV> + * + * @return Either a pointer to a std::pair<jobject, jobject>, or nullptr + * if an error occurs during the mapping + */ + template <typename K, typename V, typename JK, typename JV> + using FnMapKV = std::function<std::unique_ptr<std::pair<JK, JV>> (const std::pair<K, V>&)>; + + // template <class I, typename K, typename V, typename K1, typename V1, typename std::enable_if<std::is_same<typename std::iterator_traits<I>::value_type, std::pair<const K,V>>::value, int32_t>::type = 0> + // static void putAll(JNIEnv* env, const jobject jhash_map, I iterator, const FnMapKV<const K,V,K1,V1> &fn_map_kv) { + /** + * Returns true if it succeeds, false if an error occurs + */ + template<class iterator_type, typename K, typename V> + static bool putAll(JNIEnv* env, const jobject jhash_map, iterator_type iterator, iterator_type end, const FnMapKV<K, V, jobject, jobject> &fn_map_kv) { + const jmethodID jmid_put = rocksdb::MapJni::getMapPutMethodId(env); + if (jmid_put == nullptr) { + return false; + } + + for (auto it = iterator; it != end; ++it) { + const std::unique_ptr<std::pair<jobject, jobject>> result = fn_map_kv(*it); + if (result == nullptr) { + // an error occurred during fn_map_kv + return false; + } + env->CallObjectMethod(jhash_map, jmid_put, result->first, result->second); + if (env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(result->second); + env->DeleteLocalRef(result->first); + return false; + } + + // release local references + env->DeleteLocalRef(result->second); + env->DeleteLocalRef(result->first); + } + + return true; + } + + /** + * Creates a java.util.Map<String, String> from a std::map<std::string, std::string> + * + * @param env A pointer to the Java environment + * @param map the Cpp map + * + * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred + */ + static jobject fromCppMap(JNIEnv* env, const std::map<std::string, std::string>* map) { + if (map == nullptr) { + return nullptr; + } + + jobject jhash_map = construct(env, static_cast<uint32_t>(map->size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, const std::string, jobject, jobject> fn_map_kv = + [env](const std::pair<const std::string, const std::string>& kv) { + jstring jkey = rocksdb::JniUtil::toJavaString(env, &(kv.first), false); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jstring jvalue = rocksdb::JniUtil::toJavaString(env, &(kv.second), true); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(static_cast<jobject>(jkey), static_cast<jobject>(jvalue))); + }; + + if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; + } + + /** + * Creates a java.util.Map<String, Long> from a std::map<std::string, uint32_t> + * + * @param env A pointer to the Java environment + * @param map the Cpp map + * + * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred + */ + static jobject fromCppMap(JNIEnv* env, const std::map<std::string, uint32_t>* map) { + if (map == nullptr) { + return nullptr; + } + + if (map == nullptr) { + return nullptr; + } + + jobject jhash_map = construct(env, static_cast<uint32_t>(map->size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, const uint32_t, jobject, jobject> fn_map_kv = + [env](const std::pair<const std::string, const uint32_t>& kv) { + jstring jkey = rocksdb::JniUtil::toJavaString(env, &(kv.first), false); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jobject jvalue = rocksdb::IntegerJni::valueOf(env, static_cast<jint>(kv.second)); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(static_cast<jobject>(jkey), jvalue)); + }; + + if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; + } + + /** + * Creates a java.util.Map<String, Long> from a std::map<std::string, uint64_t> + * + * @param env A pointer to the Java environment + * @param map the Cpp map + * + * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred + */ + static jobject fromCppMap(JNIEnv* env, const std::map<std::string, uint64_t>* map) { + if (map == nullptr) { + return nullptr; + } + + jobject jhash_map = construct(env, static_cast<uint32_t>(map->size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, const uint64_t, jobject, jobject> fn_map_kv = + [env](const std::pair<const std::string, const uint64_t>& kv) { + jstring jkey = rocksdb::JniUtil::toJavaString(env, &(kv.first), false); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jobject jvalue = rocksdb::LongJni::valueOf(env, static_cast<jlong>(kv.second)); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(static_cast<jobject>(jkey), jvalue)); + }; + + if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; + } + + /** + * Creates a java.util.Map<String, Long> from a std::map<uint32_t, uint64_t> + * + * @param env A pointer to the Java environment + * @param map the Cpp map + * + * @return a reference to the Java java.util.Map object, or nullptr if an exception occcurred + */ + static jobject fromCppMap(JNIEnv* env, const std::map<uint32_t, uint64_t>* map) { + if (map == nullptr) { + return nullptr; + } + + jobject jhash_map = construct(env, static_cast<uint32_t>(map->size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const uint32_t, const uint64_t, jobject, jobject> fn_map_kv = + [env](const std::pair<const uint32_t, const uint64_t>& kv) { + jobject jkey = rocksdb::IntegerJni::valueOf(env, static_cast<jint>(kv.first)); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jobject jvalue = rocksdb::LongJni::valueOf(env, static_cast<jlong>(kv.second)); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(static_cast<jobject>(jkey), jvalue)); + }; + + if (!putAll(env, jhash_map, map->begin(), map->end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; + } +}; + +// The portal class for org.rocksdb.RocksDB +class RocksDBJni : public RocksDBNativeClass<rocksdb::DB*, RocksDBJni> { + public: + /** + * Get the Java Class org.rocksdb.RocksDB + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/RocksDB"); + } +}; + +// The portal class for org.rocksdb.Options +class OptionsJni : public RocksDBNativeClass< + rocksdb::Options*, OptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.Options + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/Options"); + } +}; + +// The portal class for org.rocksdb.DBOptions +class DBOptionsJni : public RocksDBNativeClass< + rocksdb::DBOptions*, DBOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.DBOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/DBOptions"); + } +}; + +// The portal class for org.rocksdb.ColumnFamilyOptions +class ColumnFamilyOptionsJni + : public RocksDBNativeClass<rocksdb::ColumnFamilyOptions*, + ColumnFamilyOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.ColumnFamilyOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/ColumnFamilyOptions"); + } + + /** + * Create a new Java org.rocksdb.ColumnFamilyOptions object with the same + * properties as the provided C++ rocksdb::ColumnFamilyOptions object + * + * @param env A pointer to the Java environment + * @param cfoptions A pointer to rocksdb::ColumnFamilyOptions object + * + * @return A reference to a Java org.rocksdb.ColumnFamilyOptions object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, const ColumnFamilyOptions* cfoptions) { + auto* cfo = new rocksdb::ColumnFamilyOptions(*cfoptions); + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(J)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jcfd = env->NewObject(jclazz, mid, reinterpret_cast<jlong>(cfo)); + if (env->ExceptionCheck()) { + return nullptr; + } + + return jcfd; + } +}; + +// The portal class for org.rocksdb.WriteOptions +class WriteOptionsJni : public RocksDBNativeClass< + rocksdb::WriteOptions*, WriteOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.WriteOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/WriteOptions"); + } +}; + +// The portal class for org.rocksdb.ReadOptions +class ReadOptionsJni : public RocksDBNativeClass< + rocksdb::ReadOptions*, ReadOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.ReadOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/ReadOptions"); + } +}; + +// The portal class for org.rocksdb.WriteBatch +class WriteBatchJni : public RocksDBNativeClass< + rocksdb::WriteBatch*, WriteBatchJni> { + public: + /** + * Get the Java Class org.rocksdb.WriteBatch + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/WriteBatch"); + } + + /** + * Create a new Java org.rocksdb.WriteBatch object + * + * @param env A pointer to the Java environment + * @param wb A pointer to rocksdb::WriteBatch object + * + * @return A reference to a Java org.rocksdb.WriteBatch object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, const WriteBatch* wb) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(J)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jwb = env->NewObject(jclazz, mid, reinterpret_cast<jlong>(wb)); + if (env->ExceptionCheck()) { + return nullptr; + } + + return jwb; + } +}; + +// The portal class for org.rocksdb.WriteBatch.Handler +class WriteBatchHandlerJni : public RocksDBNativeClass< + const rocksdb::WriteBatchHandlerJniCallback*, + WriteBatchHandlerJni> { + public: + /** + * Get the Java Class org.rocksdb.WriteBatch.Handler + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/WriteBatch$Handler"); + } + + /** + * Get the Java Method: WriteBatch.Handler#put + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getPutCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "put", "(I[B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#put + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getPutMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "put", "([B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#merge + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMergeCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "merge", "(I[B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#merge + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMergeMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "merge", "([B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#delete + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getDeleteCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "delete", "(I[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#delete + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getDeleteMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "delete", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#singleDelete + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getSingleDeleteCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "singleDelete", "(I[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#singleDelete + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getSingleDeleteMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "singleDelete", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#deleteRange + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getDeleteRangeCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "deleteRange", "(I[B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#deleteRange + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getDeleteRangeMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "deleteRange", "([B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#logData + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getLogDataMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "logData", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#putBlobIndex + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getPutBlobIndexCfMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "putBlobIndex", "(I[B[B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#markBeginPrepare + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMarkBeginPrepareMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "markBeginPrepare", "()V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#markEndPrepare + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMarkEndPrepareMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "markEndPrepare", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#markNoop + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMarkNoopMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "markNoop", "(Z)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#markRollback + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMarkRollbackMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "markRollback", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#markCommit + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getMarkCommitMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "markCommit", "([B)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: WriteBatch.Handler#shouldContinue + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getContinueMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "shouldContinue", "()Z"); + assert(mid != nullptr); + return mid; + } +}; + +class WriteBatchSavePointJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.WriteBatch.SavePoint + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/WriteBatch$SavePoint"); + } + + /** + * Get the Java Method: HistogramData constructor + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getConstructorMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJJ)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Create a new Java org.rocksdb.WriteBatch.SavePoint object + * + * @param env A pointer to the Java environment + * @param savePoint A pointer to rocksdb::WriteBatch::SavePoint object + * + * @return A reference to a Java org.rocksdb.WriteBatch.SavePoint object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, const SavePoint &save_point) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = getConstructorMethodId(env); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jsave_point = env->NewObject(jclazz, mid, + static_cast<jlong>(save_point.size), + static_cast<jlong>(save_point.count), + static_cast<jlong>(save_point.content_flags)); + if (env->ExceptionCheck()) { + return nullptr; + } + + return jsave_point; + } +}; + +// The portal class for org.rocksdb.WriteBatchWithIndex +class WriteBatchWithIndexJni : public RocksDBNativeClass< + rocksdb::WriteBatchWithIndex*, WriteBatchWithIndexJni> { + public: + /** + * Get the Java Class org.rocksdb.WriteBatchWithIndex + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/WriteBatchWithIndex"); + } +}; + +// The portal class for org.rocksdb.HistogramData +class HistogramDataJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.HistogramData + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/HistogramData"); + } + + /** + * Get the Java Method: HistogramData constructor + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getConstructorMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "<init>", "(DDDDDDJJD)V"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.BackupableDBOptions +class BackupableDBOptionsJni : public RocksDBNativeClass< + rocksdb::BackupableDBOptions*, BackupableDBOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.BackupableDBOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/BackupableDBOptions"); + } +}; + +// The portal class for org.rocksdb.BackupEngine +class BackupEngineJni : public RocksDBNativeClass< + rocksdb::BackupEngine*, BackupEngineJni> { + public: + /** + * Get the Java Class org.rocksdb.BackupableEngine + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/BackupEngine"); + } +}; + +// The portal class for org.rocksdb.RocksIterator +class IteratorJni : public RocksDBNativeClass< + rocksdb::Iterator*, IteratorJni> { + public: + /** + * Get the Java Class org.rocksdb.RocksIterator + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/RocksIterator"); + } +}; + +// The portal class for org.rocksdb.Filter +class FilterJni : public RocksDBNativeClass< + std::shared_ptr<rocksdb::FilterPolicy>*, FilterJni> { + public: + /** + * Get the Java Class org.rocksdb.Filter + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/Filter"); + } +}; + +// The portal class for org.rocksdb.ColumnFamilyHandle +class ColumnFamilyHandleJni : public RocksDBNativeClass< + rocksdb::ColumnFamilyHandle*, ColumnFamilyHandleJni> { + public: + /** + * Get the Java Class org.rocksdb.ColumnFamilyHandle + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/ColumnFamilyHandle"); + } +}; + +// The portal class for org.rocksdb.FlushOptions +class FlushOptionsJni : public RocksDBNativeClass< + rocksdb::FlushOptions*, FlushOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.FlushOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/FlushOptions"); + } +}; + +// The portal class for org.rocksdb.ComparatorOptions +class ComparatorOptionsJni : public RocksDBNativeClass< + rocksdb::ComparatorJniCallbackOptions*, ComparatorOptionsJni> { + public: + /** + * Get the Java Class org.rocksdb.ComparatorOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/ComparatorOptions"); + } +}; + +// The portal class for org.rocksdb.AbstractCompactionFilterFactory +class AbstractCompactionFilterFactoryJni : public RocksDBNativeClass< + const rocksdb::CompactionFilterFactoryJniCallback*, + AbstractCompactionFilterFactoryJni> { + public: + /** + * Get the Java Class org.rocksdb.AbstractCompactionFilterFactory + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/AbstractCompactionFilterFactory"); + } + + /** + * Get the Java Method: AbstractCompactionFilterFactory#name + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getNameMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "name", "()Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: AbstractCompactionFilterFactory#createCompactionFilter + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getCreateCompactionFilterMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, + "createCompactionFilter", + "(ZZ)J"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.AbstractTransactionNotifier +class AbstractTransactionNotifierJni : public RocksDBNativeClass< + const rocksdb::TransactionNotifierJniCallback*, + AbstractTransactionNotifierJni> { + public: + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/AbstractTransactionNotifier"); + } + + // Get the java method `snapshotCreated` + // of org.rocksdb.AbstractTransactionNotifier. + static jmethodID getSnapshotCreatedMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "snapshotCreated", "(J)V"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.AbstractComparator +class AbstractComparatorJni : public RocksDBNativeClass< + const rocksdb::BaseComparatorJniCallback*, + AbstractComparatorJni> { + public: + /** + * Get the Java Class org.rocksdb.AbstractComparator + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/AbstractComparator"); + } + + /** + * Get the Java Method: Comparator#name + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getNameMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "name", "()Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Comparator#compare + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getCompareMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "compare", + "(Lorg/rocksdb/AbstractSlice;Lorg/rocksdb/AbstractSlice;)I"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Comparator#findShortestSeparator + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getFindShortestSeparatorMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "findShortestSeparator", + "(Ljava/lang/String;Lorg/rocksdb/AbstractSlice;)Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: Comparator#findShortSuccessor + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getFindShortSuccessorMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "findShortSuccessor", + "(Ljava/lang/String;)Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.AbstractSlice +class AbstractSliceJni : public NativeRocksMutableObject< + const rocksdb::Slice*, AbstractSliceJni> { + public: + /** + * Get the Java Class org.rocksdb.AbstractSlice + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/AbstractSlice"); + } +}; + +// The portal class for org.rocksdb.Slice +class SliceJni : public NativeRocksMutableObject< + const rocksdb::Slice*, AbstractSliceJni> { + public: + /** + * Get the Java Class org.rocksdb.Slice + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/Slice"); + } + + /** + * Constructs a Slice object + * + * @param env A pointer to the Java environment + * + * @return A reference to a Java Slice object, or a nullptr if an + * exception occurs + */ + static jobject construct0(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "<init>", "()V"); + if(mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + jobject jslice = env->NewObject(jclazz, mid); + if(env->ExceptionCheck()) { + return nullptr; + } + + return jslice; + } +}; + +// The portal class for org.rocksdb.DirectSlice +class DirectSliceJni : public NativeRocksMutableObject< + const rocksdb::Slice*, AbstractSliceJni> { + public: + /** + * Get the Java Class org.rocksdb.DirectSlice + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/DirectSlice"); + } + + /** + * Constructs a DirectSlice object + * + * @param env A pointer to the Java environment + * + * @return A reference to a Java DirectSlice object, or a nullptr if an + * exception occurs + */ + static jobject construct0(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "<init>", "()V"); + if(mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + jobject jdirect_slice = env->NewObject(jclazz, mid); + if(env->ExceptionCheck()) { + return nullptr; + } + + return jdirect_slice; + } +}; + +// The portal class for org.rocksdb.BackupInfo +class BackupInfoJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.BackupInfo + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/BackupInfo"); + } + + /** + * Constructs a BackupInfo object + * + * @param env A pointer to the Java environment + * @param backup_id id of the backup + * @param timestamp timestamp of the backup + * @param size size of the backup + * @param number_files number of files related to the backup + * @param app_metadata application specific metadata + * + * @return A reference to a Java BackupInfo object, or a nullptr if an + * exception occurs + */ + static jobject construct0(JNIEnv* env, uint32_t backup_id, int64_t timestamp, + uint64_t size, uint32_t number_files, + const std::string& app_metadata) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "<init>", "(IJJILjava/lang/String;)V"); + if(mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + jstring japp_metadata = nullptr; + if (app_metadata != nullptr) { + japp_metadata = env->NewStringUTF(app_metadata.c_str()); + if (japp_metadata == nullptr) { + // exception occurred creating java string + return nullptr; + } + } + + jobject jbackup_info = env->NewObject(jclazz, mid, backup_id, timestamp, + size, number_files, japp_metadata); + if(env->ExceptionCheck()) { + env->DeleteLocalRef(japp_metadata); + return nullptr; + } + + return jbackup_info; + } +}; + +class BackupInfoListJni { + public: + /** + * Converts a C++ std::vector<BackupInfo> object to + * a Java ArrayList<org.rocksdb.BackupInfo> object + * + * @param env A pointer to the Java environment + * @param backup_infos A vector of BackupInfo + * + * @return Either a reference to a Java ArrayList object, or a nullptr + * if an exception occurs + */ + static jobject getBackupInfo(JNIEnv* env, + std::vector<BackupInfo> backup_infos) { + jclass jarray_list_clazz = rocksdb::ListJni::getArrayListClass(env); + if(jarray_list_clazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID cstr_mid = rocksdb::ListJni::getArrayListConstructorMethodId(env); + if(cstr_mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + jmethodID add_mid = rocksdb::ListJni::getListAddMethodId(env); + if(add_mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + // create java list + jobject jbackup_info_handle_list = + env->NewObject(jarray_list_clazz, cstr_mid, backup_infos.size()); + if(env->ExceptionCheck()) { + // exception occurred constructing object + return nullptr; + } + + // insert in java list + auto end = backup_infos.end(); + for (auto it = backup_infos.begin(); it != end; ++it) { + auto backup_info = *it; + + jobject obj = rocksdb::BackupInfoJni::construct0( + env, backup_info.backup_id, backup_info.timestamp, backup_info.size, + backup_info.number_files, backup_info.app_metadata); + if(env->ExceptionCheck()) { + // exception occurred constructing object + if(obj != nullptr) { + env->DeleteLocalRef(obj); + } + if(jbackup_info_handle_list != nullptr) { + env->DeleteLocalRef(jbackup_info_handle_list); + } + return nullptr; + } + + jboolean rs = + env->CallBooleanMethod(jbackup_info_handle_list, add_mid, obj); + if(env->ExceptionCheck() || rs == JNI_FALSE) { + // exception occurred calling method, or could not add + if(obj != nullptr) { + env->DeleteLocalRef(obj); + } + if(jbackup_info_handle_list != nullptr) { + env->DeleteLocalRef(jbackup_info_handle_list); + } + return nullptr; + } + } + + return jbackup_info_handle_list; + } +}; + +// The portal class for org.rocksdb.WBWIRocksIterator +class WBWIRocksIteratorJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.WBWIRocksIterator + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator"); + } + + /** + * Get the Java Field: WBWIRocksIterator#entry + * + * @param env A pointer to the Java environment + * + * @return The Java Field ID or nullptr if the class or field id could not + * be retieved + */ + static jfieldID getWriteEntryField(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jfieldID fid = + env->GetFieldID(jclazz, "entry", + "Lorg/rocksdb/WBWIRocksIterator$WriteEntry;"); + assert(fid != nullptr); + return fid; + } + + /** + * Gets the value of the WBWIRocksIterator#entry + * + * @param env A pointer to the Java environment + * @param jwbwi_rocks_iterator A reference to a WBWIIterator + * + * @return A reference to a Java WBWIRocksIterator.WriteEntry object, or + * a nullptr if an exception occurs + */ + static jobject getWriteEntry(JNIEnv* env, jobject jwbwi_rocks_iterator) { + assert(jwbwi_rocks_iterator != nullptr); + + jfieldID jwrite_entry_field = getWriteEntryField(env); + if(jwrite_entry_field == nullptr) { + // exception occurred accessing the field + return nullptr; + } + + jobject jwe = env->GetObjectField(jwbwi_rocks_iterator, jwrite_entry_field); + assert(jwe != nullptr); + return jwe; + } +}; + +// The portal class for org.rocksdb.WBWIRocksIterator.WriteType +class WriteTypeJni : public JavaClass { + public: + /** + * Get the PUT enum field value of WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject PUT(JNIEnv* env) { + return getEnum(env, "PUT"); + } + + /** + * Get the MERGE enum field value of WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject MERGE(JNIEnv* env) { + return getEnum(env, "MERGE"); + } + + /** + * Get the DELETE enum field value of WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject DELETE(JNIEnv* env) { + return getEnum(env, "DELETE"); + } + + /** + * Get the LOG enum field value of WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject LOG(JNIEnv* env) { + return getEnum(env, "LOG"); + } + + // Returns the equivalent org.rocksdb.WBWIRocksIterator.WriteType for the + // provided C++ rocksdb::WriteType enum + static jbyte toJavaWriteType(const rocksdb::WriteType& writeType) { + switch (writeType) { + case rocksdb::WriteType::kPutRecord: + return 0x0; + case rocksdb::WriteType::kMergeRecord: + return 0x1; + case rocksdb::WriteType::kDeleteRecord: + return 0x2; + case rocksdb::WriteType::kSingleDeleteRecord: + return 0x3; + case rocksdb::WriteType::kDeleteRangeRecord: + return 0x4; + case rocksdb::WriteType::kLogDataRecord: + return 0x5; + case rocksdb::WriteType::kXIDRecord: + return 0x6; + default: + return 0x7F; // undefined + } + } + + private: + /** + * Get the Java Class org.rocksdb.WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator$WriteType"); + } + + /** + * Get an enum field of org.rocksdb.WBWIRocksIterator.WriteType + * + * @param env A pointer to the Java environment + * @param name The name of the enum field + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject getEnum(JNIEnv* env, const char name[]) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jfieldID jfid = + env->GetStaticFieldID(jclazz, name, + "Lorg/rocksdb/WBWIRocksIterator$WriteType;"); + if(env->ExceptionCheck()) { + // exception occurred while getting field + return nullptr; + } else if(jfid == nullptr) { + return nullptr; + } + + jobject jwrite_type = env->GetStaticObjectField(jclazz, jfid); + assert(jwrite_type != nullptr); + return jwrite_type; + } +}; + +// The portal class for org.rocksdb.WBWIRocksIterator.WriteEntry +class WriteEntryJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.WBWIRocksIterator.WriteEntry + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/WBWIRocksIterator$WriteEntry"); + } +}; + +// The portal class for org.rocksdb.InfoLogLevel +class InfoLogLevelJni : public JavaClass { + public: + /** + * Get the DEBUG_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject DEBUG_LEVEL(JNIEnv* env) { + return getEnum(env, "DEBUG_LEVEL"); + } + + /** + * Get the INFO_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject INFO_LEVEL(JNIEnv* env) { + return getEnum(env, "INFO_LEVEL"); + } + + /** + * Get the WARN_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject WARN_LEVEL(JNIEnv* env) { + return getEnum(env, "WARN_LEVEL"); + } + + /** + * Get the ERROR_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject ERROR_LEVEL(JNIEnv* env) { + return getEnum(env, "ERROR_LEVEL"); + } + + /** + * Get the FATAL_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject FATAL_LEVEL(JNIEnv* env) { + return getEnum(env, "FATAL_LEVEL"); + } + + /** + * Get the HEADER_LEVEL enum field value of InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject HEADER_LEVEL(JNIEnv* env) { + return getEnum(env, "HEADER_LEVEL"); + } + + private: + /** + * Get the Java Class org.rocksdb.InfoLogLevel + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/InfoLogLevel"); + } + + /** + * Get an enum field of org.rocksdb.InfoLogLevel + * + * @param env A pointer to the Java environment + * @param name The name of the enum field + * + * @return A reference to the enum field value or a nullptr if + * the enum field value could not be retrieved + */ + static jobject getEnum(JNIEnv* env, const char name[]) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jfieldID jfid = + env->GetStaticFieldID(jclazz, name, "Lorg/rocksdb/InfoLogLevel;"); + if(env->ExceptionCheck()) { + // exception occurred while getting field + return nullptr; + } else if(jfid == nullptr) { + return nullptr; + } + + jobject jinfo_log_level = env->GetStaticObjectField(jclazz, jfid); + assert(jinfo_log_level != nullptr); + return jinfo_log_level; + } +}; + +// The portal class for org.rocksdb.Logger +class LoggerJni : public RocksDBNativeClass< + std::shared_ptr<rocksdb::LoggerJniCallback>*, LoggerJni> { + public: + /** + * Get the Java Class org/rocksdb/Logger + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, "org/rocksdb/Logger"); + } + + /** + * Get the Java Method: Logger#log + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getLogMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "log", + "(Lorg/rocksdb/InfoLogLevel;Ljava/lang/String;)V"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.TransactionLogIterator.BatchResult +class BatchResultJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.TransactionLogIterator.BatchResult + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/TransactionLogIterator$BatchResult"); + } + + /** + * Create a new Java org.rocksdb.TransactionLogIterator.BatchResult object + * with the same properties as the provided C++ rocksdb::BatchResult object + * + * @param env A pointer to the Java environment + * @param batch_result The rocksdb::BatchResult object + * + * @return A reference to a Java + * org.rocksdb.TransactionLogIterator.BatchResult object, + * or nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, + rocksdb::BatchResult& batch_result) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID( + jclazz, "<init>", "(JJ)V"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jobject jbatch_result = env->NewObject(jclazz, mid, + batch_result.sequence, batch_result.writeBatchPtr.get()); + if(jbatch_result == nullptr) { + // exception thrown: InstantiationException or OutOfMemoryError + return nullptr; + } + + batch_result.writeBatchPtr.release(); + return jbatch_result; + } +}; + +// The portal class for org.rocksdb.BottommostLevelCompaction +class BottommostLevelCompactionJni { + public: + // Returns the equivalent org.rocksdb.BottommostLevelCompaction for the provided + // C++ rocksdb::BottommostLevelCompaction enum + static jint toJavaBottommostLevelCompaction( + const rocksdb::BottommostLevelCompaction& bottommost_level_compaction) { + switch(bottommost_level_compaction) { + case rocksdb::BottommostLevelCompaction::kSkip: + return 0x0; + case rocksdb::BottommostLevelCompaction::kIfHaveCompactionFilter: + return 0x1; + case rocksdb::BottommostLevelCompaction::kForce: + return 0x2; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::BottommostLevelCompaction enum for the + // provided Java org.rocksdb.BottommostLevelCompaction + static rocksdb::BottommostLevelCompaction toCppBottommostLevelCompaction( + jint bottommost_level_compaction) { + switch(bottommost_level_compaction) { + case 0x0: + return rocksdb::BottommostLevelCompaction::kSkip; + case 0x1: + return rocksdb::BottommostLevelCompaction::kIfHaveCompactionFilter; + case 0x2: + return rocksdb::BottommostLevelCompaction::kForce; + default: + // undefined/default + return rocksdb::BottommostLevelCompaction::kIfHaveCompactionFilter; + } + } +}; + +// The portal class for org.rocksdb.CompactionStopStyle +class CompactionStopStyleJni { + public: + // Returns the equivalent org.rocksdb.CompactionStopStyle for the provided + // C++ rocksdb::CompactionStopStyle enum + static jbyte toJavaCompactionStopStyle( + const rocksdb::CompactionStopStyle& compaction_stop_style) { + switch(compaction_stop_style) { + case rocksdb::CompactionStopStyle::kCompactionStopStyleSimilarSize: + return 0x0; + case rocksdb::CompactionStopStyle::kCompactionStopStyleTotalSize: + return 0x1; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::CompactionStopStyle enum for the + // provided Java org.rocksdb.CompactionStopStyle + static rocksdb::CompactionStopStyle toCppCompactionStopStyle( + jbyte jcompaction_stop_style) { + switch(jcompaction_stop_style) { + case 0x0: + return rocksdb::CompactionStopStyle::kCompactionStopStyleSimilarSize; + case 0x1: + return rocksdb::CompactionStopStyle::kCompactionStopStyleTotalSize; + default: + // undefined/default + return rocksdb::CompactionStopStyle::kCompactionStopStyleSimilarSize; + } + } +}; + +// The portal class for org.rocksdb.CompressionType +class CompressionTypeJni { + public: + // Returns the equivalent org.rocksdb.CompressionType for the provided + // C++ rocksdb::CompressionType enum + static jbyte toJavaCompressionType( + const rocksdb::CompressionType& compression_type) { + switch(compression_type) { + case rocksdb::CompressionType::kNoCompression: + return 0x0; + case rocksdb::CompressionType::kSnappyCompression: + return 0x1; + case rocksdb::CompressionType::kZlibCompression: + return 0x2; + case rocksdb::CompressionType::kBZip2Compression: + return 0x3; + case rocksdb::CompressionType::kLZ4Compression: + return 0x4; + case rocksdb::CompressionType::kLZ4HCCompression: + return 0x5; + case rocksdb::CompressionType::kXpressCompression: + return 0x6; + case rocksdb::CompressionType::kZSTD: + return 0x7; + case rocksdb::CompressionType::kDisableCompressionOption: + default: + return 0x7F; + } + } + + // Returns the equivalent C++ rocksdb::CompressionType enum for the + // provided Java org.rocksdb.CompressionType + static rocksdb::CompressionType toCppCompressionType( + jbyte jcompression_type) { + switch(jcompression_type) { + case 0x0: + return rocksdb::CompressionType::kNoCompression; + case 0x1: + return rocksdb::CompressionType::kSnappyCompression; + case 0x2: + return rocksdb::CompressionType::kZlibCompression; + case 0x3: + return rocksdb::CompressionType::kBZip2Compression; + case 0x4: + return rocksdb::CompressionType::kLZ4Compression; + case 0x5: + return rocksdb::CompressionType::kLZ4HCCompression; + case 0x6: + return rocksdb::CompressionType::kXpressCompression; + case 0x7: + return rocksdb::CompressionType::kZSTD; + case 0x7F: + default: + return rocksdb::CompressionType::kDisableCompressionOption; + } + } +}; + +// The portal class for org.rocksdb.CompactionPriority +class CompactionPriorityJni { + public: + // Returns the equivalent org.rocksdb.CompactionPriority for the provided + // C++ rocksdb::CompactionPri enum + static jbyte toJavaCompactionPriority( + const rocksdb::CompactionPri& compaction_priority) { + switch(compaction_priority) { + case rocksdb::CompactionPri::kByCompensatedSize: + return 0x0; + case rocksdb::CompactionPri::kOldestLargestSeqFirst: + return 0x1; + case rocksdb::CompactionPri::kOldestSmallestSeqFirst: + return 0x2; + case rocksdb::CompactionPri::kMinOverlappingRatio: + return 0x3; + default: + return 0x0; // undefined + } + } + + // Returns the equivalent C++ rocksdb::CompactionPri enum for the + // provided Java org.rocksdb.CompactionPriority + static rocksdb::CompactionPri toCppCompactionPriority( + jbyte jcompaction_priority) { + switch(jcompaction_priority) { + case 0x0: + return rocksdb::CompactionPri::kByCompensatedSize; + case 0x1: + return rocksdb::CompactionPri::kOldestLargestSeqFirst; + case 0x2: + return rocksdb::CompactionPri::kOldestSmallestSeqFirst; + case 0x3: + return rocksdb::CompactionPri::kMinOverlappingRatio; + default: + // undefined/default + return rocksdb::CompactionPri::kByCompensatedSize; + } + } +}; + +// The portal class for org.rocksdb.AccessHint +class AccessHintJni { + public: + // Returns the equivalent org.rocksdb.AccessHint for the provided + // C++ rocksdb::DBOptions::AccessHint enum + static jbyte toJavaAccessHint( + const rocksdb::DBOptions::AccessHint& access_hint) { + switch(access_hint) { + case rocksdb::DBOptions::AccessHint::NONE: + return 0x0; + case rocksdb::DBOptions::AccessHint::NORMAL: + return 0x1; + case rocksdb::DBOptions::AccessHint::SEQUENTIAL: + return 0x2; + case rocksdb::DBOptions::AccessHint::WILLNEED: + return 0x3; + default: + // undefined/default + return 0x1; + } + } + + // Returns the equivalent C++ rocksdb::DBOptions::AccessHint enum for the + // provided Java org.rocksdb.AccessHint + static rocksdb::DBOptions::AccessHint toCppAccessHint(jbyte jaccess_hint) { + switch(jaccess_hint) { + case 0x0: + return rocksdb::DBOptions::AccessHint::NONE; + case 0x1: + return rocksdb::DBOptions::AccessHint::NORMAL; + case 0x2: + return rocksdb::DBOptions::AccessHint::SEQUENTIAL; + case 0x3: + return rocksdb::DBOptions::AccessHint::WILLNEED; + default: + // undefined/default + return rocksdb::DBOptions::AccessHint::NORMAL; + } + } +}; + +// The portal class for org.rocksdb.WALRecoveryMode +class WALRecoveryModeJni { + public: + // Returns the equivalent org.rocksdb.WALRecoveryMode for the provided + // C++ rocksdb::WALRecoveryMode enum + static jbyte toJavaWALRecoveryMode( + const rocksdb::WALRecoveryMode& wal_recovery_mode) { + switch(wal_recovery_mode) { + case rocksdb::WALRecoveryMode::kTolerateCorruptedTailRecords: + return 0x0; + case rocksdb::WALRecoveryMode::kAbsoluteConsistency: + return 0x1; + case rocksdb::WALRecoveryMode::kPointInTimeRecovery: + return 0x2; + case rocksdb::WALRecoveryMode::kSkipAnyCorruptedRecords: + return 0x3; + default: + // undefined/default + return 0x2; + } + } + + // Returns the equivalent C++ rocksdb::WALRecoveryMode enum for the + // provided Java org.rocksdb.WALRecoveryMode + static rocksdb::WALRecoveryMode toCppWALRecoveryMode(jbyte jwal_recovery_mode) { + switch(jwal_recovery_mode) { + case 0x0: + return rocksdb::WALRecoveryMode::kTolerateCorruptedTailRecords; + case 0x1: + return rocksdb::WALRecoveryMode::kAbsoluteConsistency; + case 0x2: + return rocksdb::WALRecoveryMode::kPointInTimeRecovery; + case 0x3: + return rocksdb::WALRecoveryMode::kSkipAnyCorruptedRecords; + default: + // undefined/default + return rocksdb::WALRecoveryMode::kPointInTimeRecovery; + } + } +}; + +// The portal class for org.rocksdb.TickerType +class TickerTypeJni { + public: + // Returns the equivalent org.rocksdb.TickerType for the provided + // C++ rocksdb::Tickers enum + static jbyte toJavaTickerType( + const rocksdb::Tickers& tickers) { + switch(tickers) { + case rocksdb::Tickers::BLOCK_CACHE_MISS: + return 0x0; + case rocksdb::Tickers::BLOCK_CACHE_HIT: + return 0x1; + case rocksdb::Tickers::BLOCK_CACHE_ADD: + return 0x2; + case rocksdb::Tickers::BLOCK_CACHE_ADD_FAILURES: + return 0x3; + case rocksdb::Tickers::BLOCK_CACHE_INDEX_MISS: + return 0x4; + case rocksdb::Tickers::BLOCK_CACHE_INDEX_HIT: + return 0x5; + case rocksdb::Tickers::BLOCK_CACHE_INDEX_ADD: + return 0x6; + case rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT: + return 0x7; + case rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT: + return 0x8; + case rocksdb::Tickers::BLOCK_CACHE_FILTER_MISS: + return 0x9; + case rocksdb::Tickers::BLOCK_CACHE_FILTER_HIT: + return 0xA; + case rocksdb::Tickers::BLOCK_CACHE_FILTER_ADD: + return 0xB; + case rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT: + return 0xC; + case rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT: + return 0xD; + case rocksdb::Tickers::BLOCK_CACHE_DATA_MISS: + return 0xE; + case rocksdb::Tickers::BLOCK_CACHE_DATA_HIT: + return 0xF; + case rocksdb::Tickers::BLOCK_CACHE_DATA_ADD: + return 0x10; + case rocksdb::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT: + return 0x11; + case rocksdb::Tickers::BLOCK_CACHE_BYTES_READ: + return 0x12; + case rocksdb::Tickers::BLOCK_CACHE_BYTES_WRITE: + return 0x13; + case rocksdb::Tickers::BLOOM_FILTER_USEFUL: + return 0x14; + case rocksdb::Tickers::PERSISTENT_CACHE_HIT: + return 0x15; + case rocksdb::Tickers::PERSISTENT_CACHE_MISS: + return 0x16; + case rocksdb::Tickers::SIM_BLOCK_CACHE_HIT: + return 0x17; + case rocksdb::Tickers::SIM_BLOCK_CACHE_MISS: + return 0x18; + case rocksdb::Tickers::MEMTABLE_HIT: + return 0x19; + case rocksdb::Tickers::MEMTABLE_MISS: + return 0x1A; + case rocksdb::Tickers::GET_HIT_L0: + return 0x1B; + case rocksdb::Tickers::GET_HIT_L1: + return 0x1C; + case rocksdb::Tickers::GET_HIT_L2_AND_UP: + return 0x1D; + case rocksdb::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY: + return 0x1E; + case rocksdb::Tickers::COMPACTION_KEY_DROP_OBSOLETE: + return 0x1F; + case rocksdb::Tickers::COMPACTION_KEY_DROP_RANGE_DEL: + return 0x20; + case rocksdb::Tickers::COMPACTION_KEY_DROP_USER: + return 0x21; + case rocksdb::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE: + return 0x22; + case rocksdb::Tickers::NUMBER_KEYS_WRITTEN: + return 0x23; + case rocksdb::Tickers::NUMBER_KEYS_READ: + return 0x24; + case rocksdb::Tickers::NUMBER_KEYS_UPDATED: + return 0x25; + case rocksdb::Tickers::BYTES_WRITTEN: + return 0x26; + case rocksdb::Tickers::BYTES_READ: + return 0x27; + case rocksdb::Tickers::NUMBER_DB_SEEK: + return 0x28; + case rocksdb::Tickers::NUMBER_DB_NEXT: + return 0x29; + case rocksdb::Tickers::NUMBER_DB_PREV: + return 0x2A; + case rocksdb::Tickers::NUMBER_DB_SEEK_FOUND: + return 0x2B; + case rocksdb::Tickers::NUMBER_DB_NEXT_FOUND: + return 0x2C; + case rocksdb::Tickers::NUMBER_DB_PREV_FOUND: + return 0x2D; + case rocksdb::Tickers::ITER_BYTES_READ: + return 0x2E; + case rocksdb::Tickers::NO_FILE_CLOSES: + return 0x2F; + case rocksdb::Tickers::NO_FILE_OPENS: + return 0x30; + case rocksdb::Tickers::NO_FILE_ERRORS: + return 0x31; + case rocksdb::Tickers::STALL_L0_SLOWDOWN_MICROS: + return 0x32; + case rocksdb::Tickers::STALL_MEMTABLE_COMPACTION_MICROS: + return 0x33; + case rocksdb::Tickers::STALL_L0_NUM_FILES_MICROS: + return 0x34; + case rocksdb::Tickers::STALL_MICROS: + return 0x35; + case rocksdb::Tickers::DB_MUTEX_WAIT_MICROS: + return 0x36; + case rocksdb::Tickers::RATE_LIMIT_DELAY_MILLIS: + return 0x37; + case rocksdb::Tickers::NO_ITERATORS: + return 0x38; + case rocksdb::Tickers::NUMBER_MULTIGET_CALLS: + return 0x39; + case rocksdb::Tickers::NUMBER_MULTIGET_KEYS_READ: + return 0x3A; + case rocksdb::Tickers::NUMBER_MULTIGET_BYTES_READ: + return 0x3B; + case rocksdb::Tickers::NUMBER_FILTERED_DELETES: + return 0x3C; + case rocksdb::Tickers::NUMBER_MERGE_FAILURES: + return 0x3D; + case rocksdb::Tickers::BLOOM_FILTER_PREFIX_CHECKED: + return 0x3E; + case rocksdb::Tickers::BLOOM_FILTER_PREFIX_USEFUL: + return 0x3F; + case rocksdb::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION: + return 0x40; + case rocksdb::Tickers::GET_UPDATES_SINCE_CALLS: + return 0x41; + case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_MISS: + return 0x42; + case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_HIT: + return 0x43; + case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD: + return 0x44; + case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES: + return 0x45; + case rocksdb::Tickers::WAL_FILE_SYNCED: + return 0x46; + case rocksdb::Tickers::WAL_FILE_BYTES: + return 0x47; + case rocksdb::Tickers::WRITE_DONE_BY_SELF: + return 0x48; + case rocksdb::Tickers::WRITE_DONE_BY_OTHER: + return 0x49; + case rocksdb::Tickers::WRITE_TIMEDOUT: + return 0x4A; + case rocksdb::Tickers::WRITE_WITH_WAL: + return 0x4B; + case rocksdb::Tickers::COMPACT_READ_BYTES: + return 0x4C; + case rocksdb::Tickers::COMPACT_WRITE_BYTES: + return 0x4D; + case rocksdb::Tickers::FLUSH_WRITE_BYTES: + return 0x4E; + case rocksdb::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES: + return 0x4F; + case rocksdb::Tickers::NUMBER_SUPERVERSION_ACQUIRES: + return 0x50; + case rocksdb::Tickers::NUMBER_SUPERVERSION_RELEASES: + return 0x51; + case rocksdb::Tickers::NUMBER_SUPERVERSION_CLEANUPS: + return 0x52; + case rocksdb::Tickers::NUMBER_BLOCK_COMPRESSED: + return 0x53; + case rocksdb::Tickers::NUMBER_BLOCK_DECOMPRESSED: + return 0x54; + case rocksdb::Tickers::NUMBER_BLOCK_NOT_COMPRESSED: + return 0x55; + case rocksdb::Tickers::MERGE_OPERATION_TOTAL_TIME: + return 0x56; + case rocksdb::Tickers::FILTER_OPERATION_TOTAL_TIME: + return 0x57; + case rocksdb::Tickers::ROW_CACHE_HIT: + return 0x58; + case rocksdb::Tickers::ROW_CACHE_MISS: + return 0x59; + case rocksdb::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES: + return 0x5A; + case rocksdb::Tickers::READ_AMP_TOTAL_READ_BYTES: + return 0x5B; + case rocksdb::Tickers::NUMBER_RATE_LIMITER_DRAINS: + return 0x5C; + case rocksdb::Tickers::NUMBER_ITER_SKIP: + return 0x5D; + case rocksdb::Tickers::NUMBER_MULTIGET_KEYS_FOUND: + return 0x5E; + case rocksdb::Tickers::NO_ITERATOR_CREATED: + // -0x01 to fixate the new value that incorrectly changed TICKER_ENUM_MAX. + return -0x01; + case rocksdb::Tickers::NO_ITERATOR_DELETED: + return 0x60; + case rocksdb::Tickers::COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE: + return 0x61; + case rocksdb::Tickers::COMPACTION_CANCELLED: + return 0x62; + case rocksdb::Tickers::BLOOM_FILTER_FULL_POSITIVE: + return 0x63; + case rocksdb::Tickers::BLOOM_FILTER_FULL_TRUE_POSITIVE: + return 0x64; + case rocksdb::Tickers::BLOB_DB_NUM_PUT: + return 0x65; + case rocksdb::Tickers::BLOB_DB_NUM_WRITE: + return 0x66; + case rocksdb::Tickers::BLOB_DB_NUM_GET: + return 0x67; + case rocksdb::Tickers::BLOB_DB_NUM_MULTIGET: + return 0x68; + case rocksdb::Tickers::BLOB_DB_NUM_SEEK: + return 0x69; + case rocksdb::Tickers::BLOB_DB_NUM_NEXT: + return 0x6A; + case rocksdb::Tickers::BLOB_DB_NUM_PREV: + return 0x6B; + case rocksdb::Tickers::BLOB_DB_NUM_KEYS_WRITTEN: + return 0x6C; + case rocksdb::Tickers::BLOB_DB_NUM_KEYS_READ: + return 0x6D; + case rocksdb::Tickers::BLOB_DB_BYTES_WRITTEN: + return 0x6E; + case rocksdb::Tickers::BLOB_DB_BYTES_READ: + return 0x6F; + case rocksdb::Tickers::BLOB_DB_WRITE_INLINED: + return 0x70; + case rocksdb::Tickers::BLOB_DB_WRITE_INLINED_TTL: + return 0x71; + case rocksdb::Tickers::BLOB_DB_WRITE_BLOB: + return 0x72; + case rocksdb::Tickers::BLOB_DB_WRITE_BLOB_TTL: + return 0x73; + case rocksdb::Tickers::BLOB_DB_BLOB_FILE_BYTES_WRITTEN: + return 0x74; + case rocksdb::Tickers::BLOB_DB_BLOB_FILE_BYTES_READ: + return 0x75; + case rocksdb::Tickers::BLOB_DB_BLOB_FILE_SYNCED: + return 0x76; + case rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_COUNT: + return 0x77; + case rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_SIZE: + return 0x78; + case rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_COUNT: + return 0x79; + case rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_SIZE: + return 0x7A; + case rocksdb::Tickers::BLOB_DB_GC_NUM_FILES: + return 0x7B; + case rocksdb::Tickers::BLOB_DB_GC_NUM_NEW_FILES: + return 0x7C; + case rocksdb::Tickers::BLOB_DB_GC_FAILURES: + return 0x7D; + case rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_OVERWRITTEN: + return 0x7E; + case rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_EXPIRED: + return 0x7F; + case rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_RELOCATED: + return -0x02; + case rocksdb::Tickers::BLOB_DB_GC_BYTES_OVERWRITTEN: + return -0x03; + case rocksdb::Tickers::BLOB_DB_GC_BYTES_EXPIRED: + return -0x04; + case rocksdb::Tickers::BLOB_DB_GC_BYTES_RELOCATED: + return -0x05; + case rocksdb::Tickers::BLOB_DB_FIFO_NUM_FILES_EVICTED: + return -0x06; + case rocksdb::Tickers::BLOB_DB_FIFO_NUM_KEYS_EVICTED: + return -0x07; + case rocksdb::Tickers::BLOB_DB_FIFO_BYTES_EVICTED: + return -0x08; + case rocksdb::Tickers::TXN_PREPARE_MUTEX_OVERHEAD: + return -0x09; + case rocksdb::Tickers::TXN_OLD_COMMIT_MAP_MUTEX_OVERHEAD: + return -0x0A; + case rocksdb::Tickers::TXN_DUPLICATE_KEY_OVERHEAD: + return -0x0B; + case rocksdb::Tickers::TXN_SNAPSHOT_MUTEX_OVERHEAD: + return -0x0C; + case rocksdb::Tickers::TICKER_ENUM_MAX: + // 0x5F for backwards compatibility on current minor version. + return 0x5F; + default: + // undefined/default + return 0x0; + } + } + + // Returns the equivalent C++ rocksdb::Tickers enum for the + // provided Java org.rocksdb.TickerType + static rocksdb::Tickers toCppTickers(jbyte jticker_type) { + switch(jticker_type) { + case 0x0: + return rocksdb::Tickers::BLOCK_CACHE_MISS; + case 0x1: + return rocksdb::Tickers::BLOCK_CACHE_HIT; + case 0x2: + return rocksdb::Tickers::BLOCK_CACHE_ADD; + case 0x3: + return rocksdb::Tickers::BLOCK_CACHE_ADD_FAILURES; + case 0x4: + return rocksdb::Tickers::BLOCK_CACHE_INDEX_MISS; + case 0x5: + return rocksdb::Tickers::BLOCK_CACHE_INDEX_HIT; + case 0x6: + return rocksdb::Tickers::BLOCK_CACHE_INDEX_ADD; + case 0x7: + return rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT; + case 0x8: + return rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT; + case 0x9: + return rocksdb::Tickers::BLOCK_CACHE_FILTER_MISS; + case 0xA: + return rocksdb::Tickers::BLOCK_CACHE_FILTER_HIT; + case 0xB: + return rocksdb::Tickers::BLOCK_CACHE_FILTER_ADD; + case 0xC: + return rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT; + case 0xD: + return rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT; + case 0xE: + return rocksdb::Tickers::BLOCK_CACHE_DATA_MISS; + case 0xF: + return rocksdb::Tickers::BLOCK_CACHE_DATA_HIT; + case 0x10: + return rocksdb::Tickers::BLOCK_CACHE_DATA_ADD; + case 0x11: + return rocksdb::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT; + case 0x12: + return rocksdb::Tickers::BLOCK_CACHE_BYTES_READ; + case 0x13: + return rocksdb::Tickers::BLOCK_CACHE_BYTES_WRITE; + case 0x14: + return rocksdb::Tickers::BLOOM_FILTER_USEFUL; + case 0x15: + return rocksdb::Tickers::PERSISTENT_CACHE_HIT; + case 0x16: + return rocksdb::Tickers::PERSISTENT_CACHE_MISS; + case 0x17: + return rocksdb::Tickers::SIM_BLOCK_CACHE_HIT; + case 0x18: + return rocksdb::Tickers::SIM_BLOCK_CACHE_MISS; + case 0x19: + return rocksdb::Tickers::MEMTABLE_HIT; + case 0x1A: + return rocksdb::Tickers::MEMTABLE_MISS; + case 0x1B: + return rocksdb::Tickers::GET_HIT_L0; + case 0x1C: + return rocksdb::Tickers::GET_HIT_L1; + case 0x1D: + return rocksdb::Tickers::GET_HIT_L2_AND_UP; + case 0x1E: + return rocksdb::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY; + case 0x1F: + return rocksdb::Tickers::COMPACTION_KEY_DROP_OBSOLETE; + case 0x20: + return rocksdb::Tickers::COMPACTION_KEY_DROP_RANGE_DEL; + case 0x21: + return rocksdb::Tickers::COMPACTION_KEY_DROP_USER; + case 0x22: + return rocksdb::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE; + case 0x23: + return rocksdb::Tickers::NUMBER_KEYS_WRITTEN; + case 0x24: + return rocksdb::Tickers::NUMBER_KEYS_READ; + case 0x25: + return rocksdb::Tickers::NUMBER_KEYS_UPDATED; + case 0x26: + return rocksdb::Tickers::BYTES_WRITTEN; + case 0x27: + return rocksdb::Tickers::BYTES_READ; + case 0x28: + return rocksdb::Tickers::NUMBER_DB_SEEK; + case 0x29: + return rocksdb::Tickers::NUMBER_DB_NEXT; + case 0x2A: + return rocksdb::Tickers::NUMBER_DB_PREV; + case 0x2B: + return rocksdb::Tickers::NUMBER_DB_SEEK_FOUND; + case 0x2C: + return rocksdb::Tickers::NUMBER_DB_NEXT_FOUND; + case 0x2D: + return rocksdb::Tickers::NUMBER_DB_PREV_FOUND; + case 0x2E: + return rocksdb::Tickers::ITER_BYTES_READ; + case 0x2F: + return rocksdb::Tickers::NO_FILE_CLOSES; + case 0x30: + return rocksdb::Tickers::NO_FILE_OPENS; + case 0x31: + return rocksdb::Tickers::NO_FILE_ERRORS; + case 0x32: + return rocksdb::Tickers::STALL_L0_SLOWDOWN_MICROS; + case 0x33: + return rocksdb::Tickers::STALL_MEMTABLE_COMPACTION_MICROS; + case 0x34: + return rocksdb::Tickers::STALL_L0_NUM_FILES_MICROS; + case 0x35: + return rocksdb::Tickers::STALL_MICROS; + case 0x36: + return rocksdb::Tickers::DB_MUTEX_WAIT_MICROS; + case 0x37: + return rocksdb::Tickers::RATE_LIMIT_DELAY_MILLIS; + case 0x38: + return rocksdb::Tickers::NO_ITERATORS; + case 0x39: + return rocksdb::Tickers::NUMBER_MULTIGET_CALLS; + case 0x3A: + return rocksdb::Tickers::NUMBER_MULTIGET_KEYS_READ; + case 0x3B: + return rocksdb::Tickers::NUMBER_MULTIGET_BYTES_READ; + case 0x3C: + return rocksdb::Tickers::NUMBER_FILTERED_DELETES; + case 0x3D: + return rocksdb::Tickers::NUMBER_MERGE_FAILURES; + case 0x3E: + return rocksdb::Tickers::BLOOM_FILTER_PREFIX_CHECKED; + case 0x3F: + return rocksdb::Tickers::BLOOM_FILTER_PREFIX_USEFUL; + case 0x40: + return rocksdb::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION; + case 0x41: + return rocksdb::Tickers::GET_UPDATES_SINCE_CALLS; + case 0x42: + return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_MISS; + case 0x43: + return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_HIT; + case 0x44: + return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD; + case 0x45: + return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES; + case 0x46: + return rocksdb::Tickers::WAL_FILE_SYNCED; + case 0x47: + return rocksdb::Tickers::WAL_FILE_BYTES; + case 0x48: + return rocksdb::Tickers::WRITE_DONE_BY_SELF; + case 0x49: + return rocksdb::Tickers::WRITE_DONE_BY_OTHER; + case 0x4A: + return rocksdb::Tickers::WRITE_TIMEDOUT; + case 0x4B: + return rocksdb::Tickers::WRITE_WITH_WAL; + case 0x4C: + return rocksdb::Tickers::COMPACT_READ_BYTES; + case 0x4D: + return rocksdb::Tickers::COMPACT_WRITE_BYTES; + case 0x4E: + return rocksdb::Tickers::FLUSH_WRITE_BYTES; + case 0x4F: + return rocksdb::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES; + case 0x50: + return rocksdb::Tickers::NUMBER_SUPERVERSION_ACQUIRES; + case 0x51: + return rocksdb::Tickers::NUMBER_SUPERVERSION_RELEASES; + case 0x52: + return rocksdb::Tickers::NUMBER_SUPERVERSION_CLEANUPS; + case 0x53: + return rocksdb::Tickers::NUMBER_BLOCK_COMPRESSED; + case 0x54: + return rocksdb::Tickers::NUMBER_BLOCK_DECOMPRESSED; + case 0x55: + return rocksdb::Tickers::NUMBER_BLOCK_NOT_COMPRESSED; + case 0x56: + return rocksdb::Tickers::MERGE_OPERATION_TOTAL_TIME; + case 0x57: + return rocksdb::Tickers::FILTER_OPERATION_TOTAL_TIME; + case 0x58: + return rocksdb::Tickers::ROW_CACHE_HIT; + case 0x59: + return rocksdb::Tickers::ROW_CACHE_MISS; + case 0x5A: + return rocksdb::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES; + case 0x5B: + return rocksdb::Tickers::READ_AMP_TOTAL_READ_BYTES; + case 0x5C: + return rocksdb::Tickers::NUMBER_RATE_LIMITER_DRAINS; + case 0x5D: + return rocksdb::Tickers::NUMBER_ITER_SKIP; + case 0x5E: + return rocksdb::Tickers::NUMBER_MULTIGET_KEYS_FOUND; + case -0x01: + // -0x01 to fixate the new value that incorrectly changed TICKER_ENUM_MAX. + return rocksdb::Tickers::NO_ITERATOR_CREATED; + case 0x60: + return rocksdb::Tickers::NO_ITERATOR_DELETED; + case 0x61: + return rocksdb::Tickers::COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE; + case 0x62: + return rocksdb::Tickers::COMPACTION_CANCELLED; + case 0x63: + return rocksdb::Tickers::BLOOM_FILTER_FULL_POSITIVE; + case 0x64: + return rocksdb::Tickers::BLOOM_FILTER_FULL_TRUE_POSITIVE; + case 0x65: + return rocksdb::Tickers::BLOB_DB_NUM_PUT; + case 0x66: + return rocksdb::Tickers::BLOB_DB_NUM_WRITE; + case 0x67: + return rocksdb::Tickers::BLOB_DB_NUM_GET; + case 0x68: + return rocksdb::Tickers::BLOB_DB_NUM_MULTIGET; + case 0x69: + return rocksdb::Tickers::BLOB_DB_NUM_SEEK; + case 0x6A: + return rocksdb::Tickers::BLOB_DB_NUM_NEXT; + case 0x6B: + return rocksdb::Tickers::BLOB_DB_NUM_PREV; + case 0x6C: + return rocksdb::Tickers::BLOB_DB_NUM_KEYS_WRITTEN; + case 0x6D: + return rocksdb::Tickers::BLOB_DB_NUM_KEYS_READ; + case 0x6E: + return rocksdb::Tickers::BLOB_DB_BYTES_WRITTEN; + case 0x6F: + return rocksdb::Tickers::BLOB_DB_BYTES_READ; + case 0x70: + return rocksdb::Tickers::BLOB_DB_WRITE_INLINED; + case 0x71: + return rocksdb::Tickers::BLOB_DB_WRITE_INLINED_TTL; + case 0x72: + return rocksdb::Tickers::BLOB_DB_WRITE_BLOB; + case 0x73: + return rocksdb::Tickers::BLOB_DB_WRITE_BLOB_TTL; + case 0x74: + return rocksdb::Tickers::BLOB_DB_BLOB_FILE_BYTES_WRITTEN; + case 0x75: + return rocksdb::Tickers::BLOB_DB_BLOB_FILE_BYTES_READ; + case 0x76: + return rocksdb::Tickers::BLOB_DB_BLOB_FILE_SYNCED; + case 0x77: + return rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_COUNT; + case 0x78: + return rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EXPIRED_SIZE; + case 0x79: + return rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_COUNT; + case 0x7A: + return rocksdb::Tickers::BLOB_DB_BLOB_INDEX_EVICTED_SIZE; + case 0x7B: + return rocksdb::Tickers::BLOB_DB_GC_NUM_FILES; + case 0x7C: + return rocksdb::Tickers::BLOB_DB_GC_NUM_NEW_FILES; + case 0x7D: + return rocksdb::Tickers::BLOB_DB_GC_FAILURES; + case 0x7E: + return rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_OVERWRITTEN; + case 0x7F: + return rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_EXPIRED; + case -0x02: + return rocksdb::Tickers::BLOB_DB_GC_NUM_KEYS_RELOCATED; + case -0x03: + return rocksdb::Tickers::BLOB_DB_GC_BYTES_OVERWRITTEN; + case -0x04: + return rocksdb::Tickers::BLOB_DB_GC_BYTES_EXPIRED; + case -0x05: + return rocksdb::Tickers::BLOB_DB_GC_BYTES_RELOCATED; + case -0x06: + return rocksdb::Tickers::BLOB_DB_FIFO_NUM_FILES_EVICTED; + case -0x07: + return rocksdb::Tickers::BLOB_DB_FIFO_NUM_KEYS_EVICTED; + case -0x08: + return rocksdb::Tickers::BLOB_DB_FIFO_BYTES_EVICTED; + case -0x09: + return rocksdb::Tickers::TXN_PREPARE_MUTEX_OVERHEAD; + case -0x0A: + return rocksdb::Tickers::TXN_OLD_COMMIT_MAP_MUTEX_OVERHEAD; + case -0x0B: + return rocksdb::Tickers::TXN_DUPLICATE_KEY_OVERHEAD; + case -0x0C: + return rocksdb::Tickers::TXN_SNAPSHOT_MUTEX_OVERHEAD; + case 0x5F: + // 0x5F for backwards compatibility on current minor version. + return rocksdb::Tickers::TICKER_ENUM_MAX; + + default: + // undefined/default + return rocksdb::Tickers::BLOCK_CACHE_MISS; + } + } +}; + +// The portal class for org.rocksdb.HistogramType +class HistogramTypeJni { + public: + // Returns the equivalent org.rocksdb.HistogramType for the provided + // C++ rocksdb::Histograms enum + static jbyte toJavaHistogramsType( + const rocksdb::Histograms& histograms) { + switch(histograms) { + case rocksdb::Histograms::DB_GET: + return 0x0; + case rocksdb::Histograms::DB_WRITE: + return 0x1; + case rocksdb::Histograms::COMPACTION_TIME: + return 0x2; + case rocksdb::Histograms::SUBCOMPACTION_SETUP_TIME: + return 0x3; + case rocksdb::Histograms::TABLE_SYNC_MICROS: + return 0x4; + case rocksdb::Histograms::COMPACTION_OUTFILE_SYNC_MICROS: + return 0x5; + case rocksdb::Histograms::WAL_FILE_SYNC_MICROS: + return 0x6; + case rocksdb::Histograms::MANIFEST_FILE_SYNC_MICROS: + return 0x7; + case rocksdb::Histograms::TABLE_OPEN_IO_MICROS: + return 0x8; + case rocksdb::Histograms::DB_MULTIGET: + return 0x9; + case rocksdb::Histograms::READ_BLOCK_COMPACTION_MICROS: + return 0xA; + case rocksdb::Histograms::READ_BLOCK_GET_MICROS: + return 0xB; + case rocksdb::Histograms::WRITE_RAW_BLOCK_MICROS: + return 0xC; + case rocksdb::Histograms::STALL_L0_SLOWDOWN_COUNT: + return 0xD; + case rocksdb::Histograms::STALL_MEMTABLE_COMPACTION_COUNT: + return 0xE; + case rocksdb::Histograms::STALL_L0_NUM_FILES_COUNT: + return 0xF; + case rocksdb::Histograms::HARD_RATE_LIMIT_DELAY_COUNT: + return 0x10; + case rocksdb::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT: + return 0x11; + case rocksdb::Histograms::NUM_FILES_IN_SINGLE_COMPACTION: + return 0x12; + case rocksdb::Histograms::DB_SEEK: + return 0x13; + case rocksdb::Histograms::WRITE_STALL: + return 0x14; + case rocksdb::Histograms::SST_READ_MICROS: + return 0x15; + case rocksdb::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED: + return 0x16; + case rocksdb::Histograms::BYTES_PER_READ: + return 0x17; + case rocksdb::Histograms::BYTES_PER_WRITE: + return 0x18; + case rocksdb::Histograms::BYTES_PER_MULTIGET: + return 0x19; + case rocksdb::Histograms::BYTES_COMPRESSED: + return 0x1A; + case rocksdb::Histograms::BYTES_DECOMPRESSED: + return 0x1B; + case rocksdb::Histograms::COMPRESSION_TIMES_NANOS: + return 0x1C; + case rocksdb::Histograms::DECOMPRESSION_TIMES_NANOS: + return 0x1D; + case rocksdb::Histograms::READ_NUM_MERGE_OPERANDS: + return 0x1E; + // 0x20 to skip 0x1F so TICKER_ENUM_MAX remains unchanged for minor version compatibility. + case rocksdb::Histograms::FLUSH_TIME: + return 0x20; + case rocksdb::Histograms::BLOB_DB_KEY_SIZE: + return 0x21; + case rocksdb::Histograms::BLOB_DB_VALUE_SIZE: + return 0x22; + case rocksdb::Histograms::BLOB_DB_WRITE_MICROS: + return 0x23; + case rocksdb::Histograms::BLOB_DB_GET_MICROS: + return 0x24; + case rocksdb::Histograms::BLOB_DB_MULTIGET_MICROS: + return 0x25; + case rocksdb::Histograms::BLOB_DB_SEEK_MICROS: + return 0x26; + case rocksdb::Histograms::BLOB_DB_NEXT_MICROS: + return 0x27; + case rocksdb::Histograms::BLOB_DB_PREV_MICROS: + return 0x28; + case rocksdb::Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS: + return 0x29; + case rocksdb::Histograms::BLOB_DB_BLOB_FILE_READ_MICROS: + return 0x2A; + case rocksdb::Histograms::BLOB_DB_BLOB_FILE_SYNC_MICROS: + return 0x2B; + case rocksdb::Histograms::BLOB_DB_GC_MICROS: + return 0x2C; + case rocksdb::Histograms::BLOB_DB_COMPRESSION_MICROS: + return 0x2D; + case rocksdb::Histograms::BLOB_DB_DECOMPRESSION_MICROS: + return 0x2E; + case rocksdb::Histograms::HISTOGRAM_ENUM_MAX: + // 0x1F for backwards compatibility on current minor version. + return 0x1F; + + default: + // undefined/default + return 0x0; + } + } + + // Returns the equivalent C++ rocksdb::Histograms enum for the + // provided Java org.rocksdb.HistogramsType + static rocksdb::Histograms toCppHistograms(jbyte jhistograms_type) { + switch(jhistograms_type) { + case 0x0: + return rocksdb::Histograms::DB_GET; + case 0x1: + return rocksdb::Histograms::DB_WRITE; + case 0x2: + return rocksdb::Histograms::COMPACTION_TIME; + case 0x3: + return rocksdb::Histograms::SUBCOMPACTION_SETUP_TIME; + case 0x4: + return rocksdb::Histograms::TABLE_SYNC_MICROS; + case 0x5: + return rocksdb::Histograms::COMPACTION_OUTFILE_SYNC_MICROS; + case 0x6: + return rocksdb::Histograms::WAL_FILE_SYNC_MICROS; + case 0x7: + return rocksdb::Histograms::MANIFEST_FILE_SYNC_MICROS; + case 0x8: + return rocksdb::Histograms::TABLE_OPEN_IO_MICROS; + case 0x9: + return rocksdb::Histograms::DB_MULTIGET; + case 0xA: + return rocksdb::Histograms::READ_BLOCK_COMPACTION_MICROS; + case 0xB: + return rocksdb::Histograms::READ_BLOCK_GET_MICROS; + case 0xC: + return rocksdb::Histograms::WRITE_RAW_BLOCK_MICROS; + case 0xD: + return rocksdb::Histograms::STALL_L0_SLOWDOWN_COUNT; + case 0xE: + return rocksdb::Histograms::STALL_MEMTABLE_COMPACTION_COUNT; + case 0xF: + return rocksdb::Histograms::STALL_L0_NUM_FILES_COUNT; + case 0x10: + return rocksdb::Histograms::HARD_RATE_LIMIT_DELAY_COUNT; + case 0x11: + return rocksdb::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT; + case 0x12: + return rocksdb::Histograms::NUM_FILES_IN_SINGLE_COMPACTION; + case 0x13: + return rocksdb::Histograms::DB_SEEK; + case 0x14: + return rocksdb::Histograms::WRITE_STALL; + case 0x15: + return rocksdb::Histograms::SST_READ_MICROS; + case 0x16: + return rocksdb::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED; + case 0x17: + return rocksdb::Histograms::BYTES_PER_READ; + case 0x18: + return rocksdb::Histograms::BYTES_PER_WRITE; + case 0x19: + return rocksdb::Histograms::BYTES_PER_MULTIGET; + case 0x1A: + return rocksdb::Histograms::BYTES_COMPRESSED; + case 0x1B: + return rocksdb::Histograms::BYTES_DECOMPRESSED; + case 0x1C: + return rocksdb::Histograms::COMPRESSION_TIMES_NANOS; + case 0x1D: + return rocksdb::Histograms::DECOMPRESSION_TIMES_NANOS; + case 0x1E: + return rocksdb::Histograms::READ_NUM_MERGE_OPERANDS; + // 0x20 to skip 0x1F so TICKER_ENUM_MAX remains unchanged for minor version compatibility. + case 0x20: + return rocksdb::Histograms::FLUSH_TIME; + case 0x21: + return rocksdb::Histograms::BLOB_DB_KEY_SIZE; + case 0x22: + return rocksdb::Histograms::BLOB_DB_VALUE_SIZE; + case 0x23: + return rocksdb::Histograms::BLOB_DB_WRITE_MICROS; + case 0x24: + return rocksdb::Histograms::BLOB_DB_GET_MICROS; + case 0x25: + return rocksdb::Histograms::BLOB_DB_MULTIGET_MICROS; + case 0x26: + return rocksdb::Histograms::BLOB_DB_SEEK_MICROS; + case 0x27: + return rocksdb::Histograms::BLOB_DB_NEXT_MICROS; + case 0x28: + return rocksdb::Histograms::BLOB_DB_PREV_MICROS; + case 0x29: + return rocksdb::Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS; + case 0x2A: + return rocksdb::Histograms::BLOB_DB_BLOB_FILE_READ_MICROS; + case 0x2B: + return rocksdb::Histograms::BLOB_DB_BLOB_FILE_SYNC_MICROS; + case 0x2C: + return rocksdb::Histograms::BLOB_DB_GC_MICROS; + case 0x2D: + return rocksdb::Histograms::BLOB_DB_COMPRESSION_MICROS; + case 0x2E: + return rocksdb::Histograms::BLOB_DB_DECOMPRESSION_MICROS; + case 0x1F: + // 0x1F for backwards compatibility on current minor version. + return rocksdb::Histograms::HISTOGRAM_ENUM_MAX; + + default: + // undefined/default + return rocksdb::Histograms::DB_GET; + } + } +}; + +// The portal class for org.rocksdb.StatsLevel +class StatsLevelJni { + public: + // Returns the equivalent org.rocksdb.StatsLevel for the provided + // C++ rocksdb::StatsLevel enum + static jbyte toJavaStatsLevel( + const rocksdb::StatsLevel& stats_level) { + switch(stats_level) { + case rocksdb::StatsLevel::kExceptDetailedTimers: + return 0x0; + case rocksdb::StatsLevel::kExceptTimeForMutex: + return 0x1; + case rocksdb::StatsLevel::kAll: + return 0x2; + + default: + // undefined/default + return 0x0; + } + } + + // Returns the equivalent C++ rocksdb::StatsLevel enum for the + // provided Java org.rocksdb.StatsLevel + static rocksdb::StatsLevel toCppStatsLevel(jbyte jstats_level) { + switch(jstats_level) { + case 0x0: + return rocksdb::StatsLevel::kExceptDetailedTimers; + case 0x1: + return rocksdb::StatsLevel::kExceptTimeForMutex; + case 0x2: + return rocksdb::StatsLevel::kAll; + + default: + // undefined/default + return rocksdb::StatsLevel::kExceptDetailedTimers; + } + } +}; + +// The portal class for org.rocksdb.RateLimiterMode +class RateLimiterModeJni { + public: + // Returns the equivalent org.rocksdb.RateLimiterMode for the provided + // C++ rocksdb::RateLimiter::Mode enum + static jbyte toJavaRateLimiterMode( + const rocksdb::RateLimiter::Mode& rate_limiter_mode) { + switch(rate_limiter_mode) { + case rocksdb::RateLimiter::Mode::kReadsOnly: + return 0x0; + case rocksdb::RateLimiter::Mode::kWritesOnly: + return 0x1; + case rocksdb::RateLimiter::Mode::kAllIo: + return 0x2; + + default: + // undefined/default + return 0x1; + } + } + + // Returns the equivalent C++ rocksdb::RateLimiter::Mode enum for the + // provided Java org.rocksdb.RateLimiterMode + static rocksdb::RateLimiter::Mode toCppRateLimiterMode(jbyte jrate_limiter_mode) { + switch(jrate_limiter_mode) { + case 0x0: + return rocksdb::RateLimiter::Mode::kReadsOnly; + case 0x1: + return rocksdb::RateLimiter::Mode::kWritesOnly; + case 0x2: + return rocksdb::RateLimiter::Mode::kAllIo; + + default: + // undefined/default + return rocksdb::RateLimiter::Mode::kWritesOnly; + } + } +}; + +// The portal class for org.rocksdb.MemoryUsageType +class MemoryUsageTypeJni { +public: + // Returns the equivalent org.rocksdb.MemoryUsageType for the provided + // C++ rocksdb::MemoryUtil::UsageType enum + static jbyte toJavaMemoryUsageType( + const rocksdb::MemoryUtil::UsageType& usage_type) { + switch(usage_type) { + case rocksdb::MemoryUtil::UsageType::kMemTableTotal: + return 0x0; + case rocksdb::MemoryUtil::UsageType::kMemTableUnFlushed: + return 0x1; + case rocksdb::MemoryUtil::UsageType::kTableReadersTotal: + return 0x2; + case rocksdb::MemoryUtil::UsageType::kCacheTotal: + return 0x3; + default: + // undefined: use kNumUsageTypes + return 0x4; + } + } + + // Returns the equivalent C++ rocksdb::MemoryUtil::UsageType enum for the + // provided Java org.rocksdb.MemoryUsageType + static rocksdb::MemoryUtil::UsageType toCppMemoryUsageType( + jbyte usage_type) { + switch(usage_type) { + case 0x0: + return rocksdb::MemoryUtil::UsageType::kMemTableTotal; + case 0x1: + return rocksdb::MemoryUtil::UsageType::kMemTableUnFlushed; + case 0x2: + return rocksdb::MemoryUtil::UsageType::kTableReadersTotal; + case 0x3: + return rocksdb::MemoryUtil::UsageType::kCacheTotal; + default: + // undefined/default: use kNumUsageTypes + return rocksdb::MemoryUtil::UsageType::kNumUsageTypes; + } + } +}; + +// The portal class for org.rocksdb.Transaction +class TransactionJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.Transaction + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/Transaction"); + } + + /** + * Create a new Java org.rocksdb.Transaction.WaitingTransactions object + * + * @param env A pointer to the Java environment + * @param jtransaction A Java org.rocksdb.Transaction object + * @param column_family_id The id of the column family + * @param key The key + * @param transaction_ids The transaction ids + * + * @return A reference to a Java + * org.rocksdb.Transaction.WaitingTransactions object, + * or nullptr if an an exception occurs + */ + static jobject newWaitingTransactions(JNIEnv* env, jobject jtransaction, + const uint32_t column_family_id, const std::string &key, + const std::vector<TransactionID> &transaction_ids) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID( + jclazz, "newWaitingTransactions", "(JLjava/lang/String;[J)Lorg/rocksdb/Transaction$WaitingTransactions;"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jstring jkey = env->NewStringUTF(key.c_str()); + if(jkey == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + const size_t len = transaction_ids.size(); + jlongArray jtransaction_ids = env->NewLongArray(static_cast<jsize>(len)); + if(jtransaction_ids == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jkey); + return nullptr; + } + + jlong *body = env->GetLongArrayElements(jtransaction_ids, nullptr); + if(body == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jkey); + env->DeleteLocalRef(jtransaction_ids); + return nullptr; + } + for(size_t i = 0; i < len; ++i) { + body[i] = static_cast<jlong>(transaction_ids[i]); + } + env->ReleaseLongArrayElements(jtransaction_ids, body, 0); + + jobject jwaiting_transactions = env->CallObjectMethod(jtransaction, + mid, static_cast<jlong>(column_family_id), jkey, jtransaction_ids); + if(env->ExceptionCheck()) { + // exception thrown: InstantiationException or OutOfMemoryError + env->DeleteLocalRef(jkey); + env->DeleteLocalRef(jtransaction_ids); + return nullptr; + } + + return jwaiting_transactions; + } +}; + +// The portal class for org.rocksdb.TransactionDB +class TransactionDBJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.TransactionDB + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/TransactionDB"); + } + + /** + * Create a new Java org.rocksdb.TransactionDB.DeadlockInfo object + * + * @param env A pointer to the Java environment + * @param jtransaction A Java org.rocksdb.Transaction object + * @param column_family_id The id of the column family + * @param key The key + * @param transaction_ids The transaction ids + * + * @return A reference to a Java + * org.rocksdb.Transaction.WaitingTransactions object, + * or nullptr if an an exception occurs + */ + static jobject newDeadlockInfo(JNIEnv* env, jobject jtransaction_db, + const rocksdb::TransactionID transaction_id, + const uint32_t column_family_id, const std::string &waiting_key, + const bool exclusive) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID( + jclazz, "newDeadlockInfo", "(JJLjava/lang/String;Z)Lorg/rocksdb/TransactionDB$DeadlockInfo;"); + if(mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jstring jwaiting_key = env->NewStringUTF(waiting_key.c_str()); + if(jwaiting_key == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + // resolve the column family id to a ColumnFamilyHandle + jobject jdeadlock_info = env->CallObjectMethod(jtransaction_db, + mid, transaction_id, static_cast<jlong>(column_family_id), + jwaiting_key, exclusive); + if(env->ExceptionCheck()) { + // exception thrown: InstantiationException or OutOfMemoryError + env->DeleteLocalRef(jwaiting_key); + return nullptr; + } + + return jdeadlock_info; + } +}; + +// The portal class for org.rocksdb.TxnDBWritePolicy +class TxnDBWritePolicyJni { + public: + // Returns the equivalent org.rocksdb.TxnDBWritePolicy for the provided + // C++ rocksdb::TxnDBWritePolicy enum + static jbyte toJavaTxnDBWritePolicy( + const rocksdb::TxnDBWritePolicy& txndb_write_policy) { + switch(txndb_write_policy) { + case rocksdb::TxnDBWritePolicy::WRITE_COMMITTED: + return 0x0; + case rocksdb::TxnDBWritePolicy::WRITE_PREPARED: + return 0x1; + case rocksdb::TxnDBWritePolicy::WRITE_UNPREPARED: + return 0x2; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::TxnDBWritePolicy enum for the + // provided Java org.rocksdb.TxnDBWritePolicy + static rocksdb::TxnDBWritePolicy toCppTxnDBWritePolicy( + jbyte jtxndb_write_policy) { + switch(jtxndb_write_policy) { + case 0x0: + return rocksdb::TxnDBWritePolicy::WRITE_COMMITTED; + case 0x1: + return rocksdb::TxnDBWritePolicy::WRITE_PREPARED; + case 0x2: + return rocksdb::TxnDBWritePolicy::WRITE_UNPREPARED; + default: + // undefined/default + return rocksdb::TxnDBWritePolicy::WRITE_COMMITTED; + } + } +}; + +// The portal class for org.rocksdb.TransactionDB.KeyLockInfo +class KeyLockInfoJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.TransactionDB.KeyLockInfo + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/TransactionDB$KeyLockInfo"); + } + + /** + * Create a new Java org.rocksdb.TransactionDB.KeyLockInfo object + * with the same properties as the provided C++ rocksdb::KeyLockInfo object + * + * @param env A pointer to the Java environment + * @param key_lock_info The rocksdb::KeyLockInfo object + * + * @return A reference to a Java + * org.rocksdb.TransactionDB.KeyLockInfo object, + * or nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, + const rocksdb::KeyLockInfo& key_lock_info) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID( + jclazz, "<init>", "(Ljava/lang/String;[JZ)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jstring jkey = env->NewStringUTF(key_lock_info.key.c_str()); + if (jkey == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + const jsize jtransaction_ids_len = static_cast<jsize>(key_lock_info.ids.size()); + jlongArray jtransactions_ids = env->NewLongArray(jtransaction_ids_len); + if (jtransactions_ids == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jkey); + return nullptr; + } + + const jobject jkey_lock_info = env->NewObject(jclazz, mid, + jkey, jtransactions_ids, key_lock_info.exclusive); + if(jkey_lock_info == nullptr) { + // exception thrown: InstantiationException or OutOfMemoryError + env->DeleteLocalRef(jtransactions_ids); + env->DeleteLocalRef(jkey); + return nullptr; + } + + return jkey_lock_info; + } +}; + +// The portal class for org.rocksdb.TransactionDB.DeadlockInfo +class DeadlockInfoJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.TransactionDB.DeadlockInfo + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env,"org/rocksdb/TransactionDB$DeadlockInfo"); + } +}; + +// The portal class for org.rocksdb.TransactionDB.DeadlockPath +class DeadlockPathJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.TransactionDB.DeadlockPath + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/TransactionDB$DeadlockPath"); + } + + /** + * Create a new Java org.rocksdb.TransactionDB.DeadlockPath object + * + * @param env A pointer to the Java environment + * + * @return A reference to a Java + * org.rocksdb.TransactionDB.DeadlockPath object, + * or nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, + const jobjectArray jdeadlock_infos, const bool limit_exceeded) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID( + jclazz, "<init>", "([LDeadlockInfo;Z)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + const jobject jdeadlock_path = env->NewObject(jclazz, mid, + jdeadlock_infos, limit_exceeded); + if(jdeadlock_path == nullptr) { + // exception thrown: InstantiationException or OutOfMemoryError + return nullptr; + } + + return jdeadlock_path; + } +}; + +class AbstractTableFilterJni : public RocksDBNativeClass<const rocksdb::TableFilterJniCallback*, AbstractTableFilterJni> { + public: + /** + * Get the Java Method: TableFilter#filter(TableProperties) + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getFilterMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = + env->GetMethodID(jclazz, "filter", "(Lorg/rocksdb/TableProperties;)Z"); + assert(mid != nullptr); + return mid; + } + + private: + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/TableFilter"); + } +}; + +class TablePropertiesJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.TableProperties object. + * + * @param env A pointer to the Java environment + * @param table_properties A Cpp table properties object + * + * @return A reference to a Java org.rocksdb.TableProperties object, or + * nullptr if an an exception occurs + */ + static jobject fromCppTableProperties(JNIEnv* env, const rocksdb::TableProperties& table_properties) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJJJJJJJJJJJJJJJJJJ[BLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jbyteArray jcolumn_family_name = rocksdb::JniUtil::copyBytes(env, table_properties.column_family_name); + if (jcolumn_family_name == nullptr) { + // exception occurred creating java string + return nullptr; + } + + jstring jfilter_policy_name = rocksdb::JniUtil::toJavaString(env, &table_properties.filter_policy_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + return nullptr; + } + + jstring jcomparator_name = rocksdb::JniUtil::toJavaString(env, &table_properties.comparator_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + return nullptr; + } + + jstring jmerge_operator_name = rocksdb::JniUtil::toJavaString(env, &table_properties.merge_operator_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + return nullptr; + } + + jstring jprefix_extractor_name = rocksdb::JniUtil::toJavaString(env, &table_properties.prefix_extractor_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + return nullptr; + } + + jstring jproperty_collectors_names = rocksdb::JniUtil::toJavaString(env, &table_properties.property_collectors_names, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + env->DeleteLocalRef(jprefix_extractor_name); + return nullptr; + } + + jstring jcompression_name = rocksdb::JniUtil::toJavaString(env, &table_properties.compression_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + env->DeleteLocalRef(jprefix_extractor_name); + env->DeleteLocalRef(jproperty_collectors_names); + return nullptr; + } + + // Map<String, String> + jobject juser_collected_properties = rocksdb::HashMapJni::fromCppMap(env, &table_properties.user_collected_properties); + if (env->ExceptionCheck()) { + // exception occurred creating java map + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + env->DeleteLocalRef(jprefix_extractor_name); + env->DeleteLocalRef(jproperty_collectors_names); + env->DeleteLocalRef(jcompression_name); + return nullptr; + } + + // Map<String, String> + jobject jreadable_properties = rocksdb::HashMapJni::fromCppMap(env, &table_properties.readable_properties); + if (env->ExceptionCheck()) { + // exception occurred creating java map + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + env->DeleteLocalRef(jprefix_extractor_name); + env->DeleteLocalRef(jproperty_collectors_names); + env->DeleteLocalRef(jcompression_name); + env->DeleteLocalRef(juser_collected_properties); + return nullptr; + } + + // Map<String, Long> + jobject jproperties_offsets = rocksdb::HashMapJni::fromCppMap(env, &table_properties.properties_offsets); + if (env->ExceptionCheck()) { + // exception occurred creating java map + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfilter_policy_name); + env->DeleteLocalRef(jcomparator_name); + env->DeleteLocalRef(jmerge_operator_name); + env->DeleteLocalRef(jprefix_extractor_name); + env->DeleteLocalRef(jproperty_collectors_names); + env->DeleteLocalRef(jcompression_name); + env->DeleteLocalRef(juser_collected_properties); + env->DeleteLocalRef(jreadable_properties); + return nullptr; + } + + jobject jtable_properties = env->NewObject(jclazz, mid, + static_cast<jlong>(table_properties.data_size), + static_cast<jlong>(table_properties.index_size), + static_cast<jlong>(table_properties.index_partitions), + static_cast<jlong>(table_properties.top_level_index_size), + static_cast<jlong>(table_properties.index_key_is_user_key), + static_cast<jlong>(table_properties.index_value_is_delta_encoded), + static_cast<jlong>(table_properties.filter_size), + static_cast<jlong>(table_properties.raw_key_size), + static_cast<jlong>(table_properties.raw_value_size), + static_cast<jlong>(table_properties.num_data_blocks), + static_cast<jlong>(table_properties.num_entries), + static_cast<jlong>(table_properties.num_deletions), + static_cast<jlong>(table_properties.num_merge_operands), + static_cast<jlong>(table_properties.num_range_deletions), + static_cast<jlong>(table_properties.format_version), + static_cast<jlong>(table_properties.fixed_key_len), + static_cast<jlong>(table_properties.column_family_id), + static_cast<jlong>(table_properties.creation_time), + static_cast<jlong>(table_properties.oldest_key_time), + jcolumn_family_name, + jfilter_policy_name, + jcomparator_name, + jmerge_operator_name, + jprefix_extractor_name, + jproperty_collectors_names, + jcompression_name, + juser_collected_properties, + jreadable_properties, + jproperties_offsets + ); + + if (env->ExceptionCheck()) { + return nullptr; + } + + return jtable_properties; + } + + private: + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/TableProperties"); + } +}; + +class ColumnFamilyDescriptorJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.ColumnFamilyDescriptor + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyDescriptor"); + } + + /** + * Create a new Java org.rocksdb.ColumnFamilyDescriptor object with the same + * properties as the provided C++ rocksdb::ColumnFamilyDescriptor object + * + * @param env A pointer to the Java environment + * @param cfd A pointer to rocksdb::ColumnFamilyDescriptor object + * + * @return A reference to a Java org.rocksdb.ColumnFamilyDescriptor object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, ColumnFamilyDescriptor* cfd) { + jbyteArray jcf_name = JniUtil::copyBytes(env, cfd->name); + jobject cfopts = ColumnFamilyOptionsJni::construct(env, &(cfd->options)); + + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", + "([BLorg/rocksdb/ColumnFamilyOptions;)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + env->DeleteLocalRef(jcf_name); + return nullptr; + } + + jobject jcfd = env->NewObject(jclazz, mid, jcf_name, cfopts); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jcf_name); + return nullptr; + } + + return jcfd; + } + + /** + * Get the Java Method: ColumnFamilyDescriptor#columnFamilyName + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getColumnFamilyNameMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID(jclazz, "columnFamilyName", "()[B"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: ColumnFamilyDescriptor#columnFamilyOptions + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getColumnFamilyOptionsMethod(JNIEnv* env) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "columnFamilyOptions", "()Lorg/rocksdb/ColumnFamilyOptions;"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.IndexType +class IndexTypeJni { + public: + // Returns the equivalent org.rocksdb.IndexType for the provided + // C++ rocksdb::IndexType enum + static jbyte toJavaIndexType( + const rocksdb::BlockBasedTableOptions::IndexType& index_type) { + switch(index_type) { + case rocksdb::BlockBasedTableOptions::IndexType::kBinarySearch: + return 0x0; + case rocksdb::BlockBasedTableOptions::IndexType::kHashSearch: + return 0x1; + case rocksdb::BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch: + return 0x2; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::IndexType enum for the + // provided Java org.rocksdb.IndexType + static rocksdb::BlockBasedTableOptions::IndexType toCppIndexType( + jbyte jindex_type) { + switch(jindex_type) { + case 0x0: + return rocksdb::BlockBasedTableOptions::IndexType::kBinarySearch; + case 0x1: + return rocksdb::BlockBasedTableOptions::IndexType::kHashSearch; + case 0x2: + return rocksdb::BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch; + default: + // undefined/default + return rocksdb::BlockBasedTableOptions::IndexType::kBinarySearch; + } + } +}; + +// The portal class for org.rocksdb.DataBlockIndexType +class DataBlockIndexTypeJni { + public: + // Returns the equivalent org.rocksdb.DataBlockIndexType for the provided + // C++ rocksdb::DataBlockIndexType enum + static jbyte toJavaDataBlockIndexType( + const rocksdb::BlockBasedTableOptions::DataBlockIndexType& index_type) { + switch(index_type) { + case rocksdb::BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch: + return 0x0; + case rocksdb::BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinaryAndHash: + return 0x1; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::DataBlockIndexType enum for the + // provided Java org.rocksdb.DataBlockIndexType + static rocksdb::BlockBasedTableOptions::DataBlockIndexType toCppDataBlockIndexType( + jbyte jindex_type) { + switch(jindex_type) { + case 0x0: + return rocksdb::BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch; + case 0x1: + return rocksdb::BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinaryAndHash; + default: + // undefined/default + return rocksdb::BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch; + } + } +}; + +// The portal class for org.rocksdb.ChecksumType +class ChecksumTypeJni { + public: + // Returns the equivalent org.rocksdb.ChecksumType for the provided + // C++ rocksdb::ChecksumType enum + static jbyte toJavaChecksumType( + const rocksdb::ChecksumType& checksum_type) { + switch(checksum_type) { + case rocksdb::ChecksumType::kNoChecksum: + return 0x0; + case rocksdb::ChecksumType::kCRC32c: + return 0x1; + case rocksdb::ChecksumType::kxxHash: + return 0x2; + case rocksdb::ChecksumType::kxxHash64: + return 0x3; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::ChecksumType enum for the + // provided Java org.rocksdb.ChecksumType + static rocksdb::ChecksumType toCppChecksumType( + jbyte jchecksum_type) { + switch(jchecksum_type) { + case 0x0: + return rocksdb::ChecksumType::kNoChecksum; + case 0x1: + return rocksdb::ChecksumType::kCRC32c; + case 0x2: + return rocksdb::ChecksumType::kxxHash; + case 0x3: + return rocksdb::ChecksumType::kxxHash64; + default: + // undefined/default + return rocksdb::ChecksumType::kCRC32c; + } + } +}; + +// The portal class for org.rocksdb.Priority +class PriorityJni { + public: + // Returns the equivalent org.rocksdb.Priority for the provided + // C++ rocksdb::Env::Priority enum + static jbyte toJavaPriority( + const rocksdb::Env::Priority& priority) { + switch(priority) { + case rocksdb::Env::Priority::BOTTOM: + return 0x0; + case rocksdb::Env::Priority::LOW: + return 0x1; + case rocksdb::Env::Priority::HIGH: + return 0x2; + case rocksdb::Env::Priority::TOTAL: + return 0x3; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::env::Priority enum for the + // provided Java org.rocksdb.Priority + static rocksdb::Env::Priority toCppPriority( + jbyte jpriority) { + switch(jpriority) { + case 0x0: + return rocksdb::Env::Priority::BOTTOM; + case 0x1: + return rocksdb::Env::Priority::LOW; + case 0x2: + return rocksdb::Env::Priority::HIGH; + case 0x3: + return rocksdb::Env::Priority::TOTAL; + default: + // undefined/default + return rocksdb::Env::Priority::LOW; + } + } +}; + +// The portal class for org.rocksdb.ThreadType +class ThreadTypeJni { + public: + // Returns the equivalent org.rocksdb.ThreadType for the provided + // C++ rocksdb::ThreadStatus::ThreadType enum + static jbyte toJavaThreadType( + const rocksdb::ThreadStatus::ThreadType& thread_type) { + switch(thread_type) { + case rocksdb::ThreadStatus::ThreadType::HIGH_PRIORITY: + return 0x0; + case rocksdb::ThreadStatus::ThreadType::LOW_PRIORITY: + return 0x1; + case rocksdb::ThreadStatus::ThreadType::USER: + return 0x2; + case rocksdb::ThreadStatus::ThreadType::BOTTOM_PRIORITY: + return 0x3; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::ThreadStatus::ThreadType enum for the + // provided Java org.rocksdb.ThreadType + static rocksdb::ThreadStatus::ThreadType toCppThreadType( + jbyte jthread_type) { + switch(jthread_type) { + case 0x0: + return rocksdb::ThreadStatus::ThreadType::HIGH_PRIORITY; + case 0x1: + return rocksdb::ThreadStatus::ThreadType::LOW_PRIORITY; + case 0x2: + return ThreadStatus::ThreadType::USER; + case 0x3: + return rocksdb::ThreadStatus::ThreadType::BOTTOM_PRIORITY; + default: + // undefined/default + return rocksdb::ThreadStatus::ThreadType::LOW_PRIORITY; + } + } +}; + +// The portal class for org.rocksdb.OperationType +class OperationTypeJni { + public: + // Returns the equivalent org.rocksdb.OperationType for the provided + // C++ rocksdb::ThreadStatus::OperationType enum + static jbyte toJavaOperationType( + const rocksdb::ThreadStatus::OperationType& operation_type) { + switch(operation_type) { + case rocksdb::ThreadStatus::OperationType::OP_UNKNOWN: + return 0x0; + case rocksdb::ThreadStatus::OperationType::OP_COMPACTION: + return 0x1; + case rocksdb::ThreadStatus::OperationType::OP_FLUSH: + return 0x2; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::ThreadStatus::OperationType enum for the + // provided Java org.rocksdb.OperationType + static rocksdb::ThreadStatus::OperationType toCppOperationType( + jbyte joperation_type) { + switch(joperation_type) { + case 0x0: + return rocksdb::ThreadStatus::OperationType::OP_UNKNOWN; + case 0x1: + return rocksdb::ThreadStatus::OperationType::OP_COMPACTION; + case 0x2: + return rocksdb::ThreadStatus::OperationType::OP_FLUSH; + default: + // undefined/default + return rocksdb::ThreadStatus::OperationType::OP_UNKNOWN; + } + } +}; + +// The portal class for org.rocksdb.OperationStage +class OperationStageJni { + public: + // Returns the equivalent org.rocksdb.OperationStage for the provided + // C++ rocksdb::ThreadStatus::OperationStage enum + static jbyte toJavaOperationStage( + const rocksdb::ThreadStatus::OperationStage& operation_stage) { + switch(operation_stage) { + case rocksdb::ThreadStatus::OperationStage::STAGE_UNKNOWN: + return 0x0; + case rocksdb::ThreadStatus::OperationStage::STAGE_FLUSH_RUN: + return 0x1; + case rocksdb::ThreadStatus::OperationStage::STAGE_FLUSH_WRITE_L0: + return 0x2; + case rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_PREPARE: + return 0x3; + case rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_RUN: + return 0x4; + case rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_PROCESS_KV: + return 0x5; + case rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_INSTALL: + return 0x6; + case rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_SYNC_FILE: + return 0x7; + case rocksdb::ThreadStatus::OperationStage::STAGE_PICK_MEMTABLES_TO_FLUSH: + return 0x8; + case rocksdb::ThreadStatus::OperationStage::STAGE_MEMTABLE_ROLLBACK: + return 0x9; + case rocksdb::ThreadStatus::OperationStage::STAGE_MEMTABLE_INSTALL_FLUSH_RESULTS: + return 0xA; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::ThreadStatus::OperationStage enum for the + // provided Java org.rocksdb.OperationStage + static rocksdb::ThreadStatus::OperationStage toCppOperationStage( + jbyte joperation_stage) { + switch(joperation_stage) { + case 0x0: + return rocksdb::ThreadStatus::OperationStage::STAGE_UNKNOWN; + case 0x1: + return rocksdb::ThreadStatus::OperationStage::STAGE_FLUSH_RUN; + case 0x2: + return rocksdb::ThreadStatus::OperationStage::STAGE_FLUSH_WRITE_L0; + case 0x3: + return rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_PREPARE; + case 0x4: + return rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_RUN; + case 0x5: + return rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_PROCESS_KV; + case 0x6: + return rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_INSTALL; + case 0x7: + return rocksdb::ThreadStatus::OperationStage::STAGE_COMPACTION_SYNC_FILE; + case 0x8: + return rocksdb::ThreadStatus::OperationStage::STAGE_PICK_MEMTABLES_TO_FLUSH; + case 0x9: + return rocksdb::ThreadStatus::OperationStage::STAGE_MEMTABLE_ROLLBACK; + case 0xA: + return rocksdb::ThreadStatus::OperationStage::STAGE_MEMTABLE_INSTALL_FLUSH_RESULTS; + default: + // undefined/default + return rocksdb::ThreadStatus::OperationStage::STAGE_UNKNOWN; + } + } +}; + +// The portal class for org.rocksdb.StateType +class StateTypeJni { + public: + // Returns the equivalent org.rocksdb.StateType for the provided + // C++ rocksdb::ThreadStatus::StateType enum + static jbyte toJavaStateType( + const rocksdb::ThreadStatus::StateType& state_type) { + switch(state_type) { + case rocksdb::ThreadStatus::StateType::STATE_UNKNOWN: + return 0x0; + case rocksdb::ThreadStatus::StateType::STATE_MUTEX_WAIT: + return 0x1; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::ThreadStatus::StateType enum for the + // provided Java org.rocksdb.StateType + static rocksdb::ThreadStatus::StateType toCppStateType( + jbyte jstate_type) { + switch(jstate_type) { + case 0x0: + return rocksdb::ThreadStatus::StateType::STATE_UNKNOWN; + case 0x1: + return rocksdb::ThreadStatus::StateType::STATE_MUTEX_WAIT; + default: + // undefined/default + return rocksdb::ThreadStatus::StateType::STATE_UNKNOWN; + } + } +}; + +// The portal class for org.rocksdb.ThreadStatus +class ThreadStatusJni : public JavaClass { + public: + /** + * Get the Java Class org.rocksdb.ThreadStatus + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, + "org/rocksdb/ThreadStatus"); + } + + /** + * Create a new Java org.rocksdb.ThreadStatus object with the same + * properties as the provided C++ rocksdb::ThreadStatus object + * + * @param env A pointer to the Java environment + * @param thread_status A pointer to rocksdb::ThreadStatus object + * + * @return A reference to a Java org.rocksdb.ColumnFamilyOptions object, or + * nullptr if an an exception occurs + */ + static jobject construct(JNIEnv* env, + const rocksdb::ThreadStatus* thread_status) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JBLjava/lang/String;Ljava/lang/String;BJB[JB)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jstring jdb_name = + JniUtil::toJavaString(env, &(thread_status->db_name), true); + if (env->ExceptionCheck()) { + // an error occurred + return nullptr; + } + + jstring jcf_name = + JniUtil::toJavaString(env, &(thread_status->cf_name), true); + if (env->ExceptionCheck()) { + // an error occurred + env->DeleteLocalRef(jdb_name); + return nullptr; + } + + // long[] + const jsize len = static_cast<jsize>(rocksdb::ThreadStatus::kNumOperationProperties); + jlongArray joperation_properties = + env->NewLongArray(len); + if (joperation_properties == nullptr) { + // an exception occurred + env->DeleteLocalRef(jdb_name); + env->DeleteLocalRef(jcf_name); + return nullptr; + } + jlong *body = env->GetLongArrayElements(joperation_properties, nullptr); + if (body == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jdb_name); + env->DeleteLocalRef(jcf_name); + env->DeleteLocalRef(joperation_properties); + return nullptr; + } + for (size_t i = 0; i < len; ++i) { + body[i] = static_cast<jlong>(thread_status->op_properties[i]); + } + env->ReleaseLongArrayElements(joperation_properties, body, 0); + + jobject jcfd = env->NewObject(jclazz, mid, + static_cast<jlong>(thread_status->thread_id), + ThreadTypeJni::toJavaThreadType(thread_status->thread_type), + jdb_name, + jcf_name, + OperationTypeJni::toJavaOperationType(thread_status->operation_type), + static_cast<jlong>(thread_status->op_elapsed_micros), + OperationStageJni::toJavaOperationStage(thread_status->operation_stage), + joperation_properties, + StateTypeJni::toJavaStateType(thread_status->state_type)); + if (env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(jdb_name); + env->DeleteLocalRef(jcf_name); + env->DeleteLocalRef(joperation_properties); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jdb_name); + env->DeleteLocalRef(jcf_name); + env->DeleteLocalRef(joperation_properties); + + return jcfd; + } +}; + +// The portal class for org.rocksdb.CompactionStyle +class CompactionStyleJni { + public: + // Returns the equivalent org.rocksdb.CompactionStyle for the provided + // C++ rocksdb::CompactionStyle enum + static jbyte toJavaCompactionStyle( + const rocksdb::CompactionStyle& compaction_style) { + switch(compaction_style) { + case rocksdb::CompactionStyle::kCompactionStyleLevel: + return 0x0; + case rocksdb::CompactionStyle::kCompactionStyleUniversal: + return 0x1; + case rocksdb::CompactionStyle::kCompactionStyleFIFO: + return 0x2; + case rocksdb::CompactionStyle::kCompactionStyleNone: + return 0x3; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::CompactionStyle enum for the + // provided Java org.rocksdb.CompactionStyle + static rocksdb::CompactionStyle toCppCompactionStyle( + jbyte jcompaction_style) { + switch(jcompaction_style) { + case 0x0: + return rocksdb::CompactionStyle::kCompactionStyleLevel; + case 0x1: + return rocksdb::CompactionStyle::kCompactionStyleUniversal; + case 0x2: + return rocksdb::CompactionStyle::kCompactionStyleFIFO; + case 0x3: + return rocksdb::CompactionStyle::kCompactionStyleNone; + default: + // undefined/default + return rocksdb::CompactionStyle::kCompactionStyleLevel; + } + } +}; + +// The portal class for org.rocksdb.CompactionReason +class CompactionReasonJni { + public: + // Returns the equivalent org.rocksdb.CompactionReason for the provided + // C++ rocksdb::CompactionReason enum + static jbyte toJavaCompactionReason( + const rocksdb::CompactionReason& compaction_reason) { + switch(compaction_reason) { + case rocksdb::CompactionReason::kUnknown: + return 0x0; + case rocksdb::CompactionReason::kLevelL0FilesNum: + return 0x1; + case rocksdb::CompactionReason::kLevelMaxLevelSize: + return 0x2; + case rocksdb::CompactionReason::kUniversalSizeAmplification: + return 0x3; + case rocksdb::CompactionReason::kUniversalSizeRatio: + return 0x4; + case rocksdb::CompactionReason::kUniversalSortedRunNum: + return 0x5; + case rocksdb::CompactionReason::kFIFOMaxSize: + return 0x6; + case rocksdb::CompactionReason::kFIFOReduceNumFiles: + return 0x7; + case rocksdb::CompactionReason::kFIFOTtl: + return 0x8; + case rocksdb::CompactionReason::kManualCompaction: + return 0x9; + case rocksdb::CompactionReason::kFilesMarkedForCompaction: + return 0x10; + case rocksdb::CompactionReason::kBottommostFiles: + return 0x0A; + case rocksdb::CompactionReason::kTtl: + return 0x0B; + case rocksdb::CompactionReason::kFlush: + return 0x0C; + case rocksdb::CompactionReason::kExternalSstIngestion: + return 0x0D; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::CompactionReason enum for the + // provided Java org.rocksdb.CompactionReason + static rocksdb::CompactionReason toCppCompactionReason( + jbyte jcompaction_reason) { + switch(jcompaction_reason) { + case 0x0: + return rocksdb::CompactionReason::kUnknown; + case 0x1: + return rocksdb::CompactionReason::kLevelL0FilesNum; + case 0x2: + return rocksdb::CompactionReason::kLevelMaxLevelSize; + case 0x3: + return rocksdb::CompactionReason::kUniversalSizeAmplification; + case 0x4: + return rocksdb::CompactionReason::kUniversalSizeRatio; + case 0x5: + return rocksdb::CompactionReason::kUniversalSortedRunNum; + case 0x6: + return rocksdb::CompactionReason::kFIFOMaxSize; + case 0x7: + return rocksdb::CompactionReason::kFIFOReduceNumFiles; + case 0x8: + return rocksdb::CompactionReason::kFIFOTtl; + case 0x9: + return rocksdb::CompactionReason::kManualCompaction; + case 0x10: + return rocksdb::CompactionReason::kFilesMarkedForCompaction; + case 0x0A: + return rocksdb::CompactionReason::kBottommostFiles; + case 0x0B: + return rocksdb::CompactionReason::kTtl; + case 0x0C: + return rocksdb::CompactionReason::kFlush; + case 0x0D: + return rocksdb::CompactionReason::kExternalSstIngestion; + default: + // undefined/default + return rocksdb::CompactionReason::kUnknown; + } + } +}; + +// The portal class for org.rocksdb.WalFileType +class WalFileTypeJni { + public: + // Returns the equivalent org.rocksdb.WalFileType for the provided + // C++ rocksdb::WalFileType enum + static jbyte toJavaWalFileType( + const rocksdb::WalFileType& wal_file_type) { + switch(wal_file_type) { + case rocksdb::WalFileType::kArchivedLogFile: + return 0x0; + case rocksdb::WalFileType::kAliveLogFile: + return 0x1; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::WalFileType enum for the + // provided Java org.rocksdb.WalFileType + static rocksdb::WalFileType toCppWalFileType( + jbyte jwal_file_type) { + switch(jwal_file_type) { + case 0x0: + return rocksdb::WalFileType::kArchivedLogFile; + case 0x1: + return rocksdb::WalFileType::kAliveLogFile; + default: + // undefined/default + return rocksdb::WalFileType::kAliveLogFile; + } + } +}; + +class LogFileJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.LogFile object. + * + * @param env A pointer to the Java environment + * @param log_file A Cpp log file object + * + * @return A reference to a Java org.rocksdb.LogFile object, or + * nullptr if an an exception occurs + */ + static jobject fromCppLogFile(JNIEnv* env, rocksdb::LogFile* log_file) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;JBJJ)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + std::string path_name = log_file->PathName(); + jstring jpath_name = rocksdb::JniUtil::toJavaString(env, &path_name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + return nullptr; + } + + jobject jlog_file = env->NewObject(jclazz, mid, + jpath_name, + static_cast<jlong>(log_file->LogNumber()), + rocksdb::WalFileTypeJni::toJavaWalFileType(log_file->Type()), + static_cast<jlong>(log_file->StartSequence()), + static_cast<jlong>(log_file->SizeFileBytes()) + ); + + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jpath_name); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jpath_name); + + return jlog_file; + } + + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/LogFile"); + } +}; + +class LiveFileMetaDataJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.LiveFileMetaData object. + * + * @param env A pointer to the Java environment + * @param live_file_meta_data A Cpp live file meta data object + * + * @return A reference to a Java org.rocksdb.LiveFileMetaData object, or + * nullptr if an an exception occurs + */ + static jobject fromCppLiveFileMetaData(JNIEnv* env, + rocksdb::LiveFileMetaData* live_file_meta_data) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "([BILjava/lang/String;Ljava/lang/String;JJJ[B[BJZJJ)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jbyteArray jcolumn_family_name = rocksdb::JniUtil::copyBytes( + env, live_file_meta_data->column_family_name); + if (jcolumn_family_name == nullptr) { + // exception occurred creating java byte array + return nullptr; + } + + jstring jfile_name = rocksdb::JniUtil::toJavaString( + env, &live_file_meta_data->name, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + return nullptr; + } + + jstring jpath = rocksdb::JniUtil::toJavaString( + env, &live_file_meta_data->db_path, true); + if (env->ExceptionCheck()) { + // exception occurred creating java string + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfile_name); + return nullptr; + } + + jbyteArray jsmallest_key = rocksdb::JniUtil::copyBytes( + env, live_file_meta_data->smallestkey); + if (jsmallest_key == nullptr) { + // exception occurred creating java byte array + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + return nullptr; + } + + jbyteArray jlargest_key = rocksdb::JniUtil::copyBytes( + env, live_file_meta_data->largestkey); + if (jlargest_key == nullptr) { + // exception occurred creating java byte array + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + return nullptr; + } + + jobject jlive_file_meta_data = env->NewObject(jclazz, mid, + jcolumn_family_name, + static_cast<jint>(live_file_meta_data->level), + jfile_name, + jpath, + static_cast<jlong>(live_file_meta_data->size), + static_cast<jlong>(live_file_meta_data->smallest_seqno), + static_cast<jlong>(live_file_meta_data->largest_seqno), + jsmallest_key, + jlargest_key, + static_cast<jlong>(live_file_meta_data->num_reads_sampled), + static_cast<jboolean>(live_file_meta_data->being_compacted), + static_cast<jlong>(live_file_meta_data->num_entries), + static_cast<jlong>(live_file_meta_data->num_deletions) + ); + + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + env->DeleteLocalRef(jlargest_key); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jcolumn_family_name); + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + env->DeleteLocalRef(jlargest_key); + + return jlive_file_meta_data; + } + + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/LiveFileMetaData"); + } +}; + +class SstFileMetaDataJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.SstFileMetaData object. + * + * @param env A pointer to the Java environment + * @param sst_file_meta_data A Cpp sst file meta data object + * + * @return A reference to a Java org.rocksdb.SstFileMetaData object, or + * nullptr if an an exception occurs + */ + static jobject fromCppSstFileMetaData(JNIEnv* env, + const rocksdb::SstFileMetaData* sst_file_meta_data) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;JJJ[B[BJZJJ)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jstring jfile_name = rocksdb::JniUtil::toJavaString( + env, &sst_file_meta_data->name, true); + if (jfile_name == nullptr) { + // exception occurred creating java byte array + return nullptr; + } + + jstring jpath = rocksdb::JniUtil::toJavaString( + env, &sst_file_meta_data->db_path, true); + if (jpath == nullptr) { + // exception occurred creating java byte array + env->DeleteLocalRef(jfile_name); + return nullptr; + } + + jbyteArray jsmallest_key = rocksdb::JniUtil::copyBytes( + env, sst_file_meta_data->smallestkey); + if (jsmallest_key == nullptr) { + // exception occurred creating java byte array + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + return nullptr; + } + + jbyteArray jlargest_key = rocksdb::JniUtil::copyBytes( + env, sst_file_meta_data->largestkey); + if (jlargest_key == nullptr) { + // exception occurred creating java byte array + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + return nullptr; + } + + jobject jsst_file_meta_data = env->NewObject(jclazz, mid, + jfile_name, + jpath, + static_cast<jlong>(sst_file_meta_data->size), + static_cast<jint>(sst_file_meta_data->smallest_seqno), + static_cast<jlong>(sst_file_meta_data->largest_seqno), + jsmallest_key, + jlargest_key, + static_cast<jlong>(sst_file_meta_data->num_reads_sampled), + static_cast<jboolean>(sst_file_meta_data->being_compacted), + static_cast<jlong>(sst_file_meta_data->num_entries), + static_cast<jlong>(sst_file_meta_data->num_deletions) + ); + + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + env->DeleteLocalRef(jlargest_key); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jfile_name); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(jsmallest_key); + env->DeleteLocalRef(jlargest_key); + + return jsst_file_meta_data; + } + + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/SstFileMetaData"); + } +}; + +class LevelMetaDataJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.LevelMetaData object. + * + * @param env A pointer to the Java environment + * @param level_meta_data A Cpp level meta data object + * + * @return A reference to a Java org.rocksdb.LevelMetaData object, or + * nullptr if an an exception occurs + */ + static jobject fromCppLevelMetaData(JNIEnv* env, + const rocksdb::LevelMetaData* level_meta_data) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(IJ[Lorg/rocksdb/SstFileMetaData;)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + const jsize jlen = + static_cast<jsize>(level_meta_data->files.size()); + jobjectArray jfiles = env->NewObjectArray(jlen, SstFileMetaDataJni::getJClass(env), nullptr); + if (jfiles == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jsize i = 0; + for (auto it = level_meta_data->files.begin(); + it != level_meta_data->files.end(); ++it) { + jobject jfile = SstFileMetaDataJni::fromCppSstFileMetaData(env, &(*it)); + if (jfile == nullptr) { + // exception occurred + env->DeleteLocalRef(jfiles); + return nullptr; + } + env->SetObjectArrayElement(jfiles, i++, jfile); + } + + jobject jlevel_meta_data = env->NewObject(jclazz, mid, + static_cast<jint>(level_meta_data->level), + static_cast<jlong>(level_meta_data->size), + jfiles + ); + + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jfiles); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jfiles); + + return jlevel_meta_data; + } + + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/LevelMetaData"); + } +}; + +class ColumnFamilyMetaDataJni : public JavaClass { + public: + /** + * Create a new Java org.rocksdb.ColumnFamilyMetaData object. + * + * @param env A pointer to the Java environment + * @param column_famly_meta_data A Cpp live file meta data object + * + * @return A reference to a Java org.rocksdb.ColumnFamilyMetaData object, or + * nullptr if an an exception occurs + */ + static jobject fromCppColumnFamilyMetaData(JNIEnv* env, + const rocksdb::ColumnFamilyMetaData* column_famly_meta_data) { + jclass jclazz = getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = env->GetMethodID(jclazz, "<init>", "(JJ[B[Lorg/rocksdb/LevelMetaData;)V"); + if (mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return nullptr; + } + + jbyteArray jname = rocksdb::JniUtil::copyBytes( + env, column_famly_meta_data->name); + if (jname == nullptr) { + // exception occurred creating java byte array + return nullptr; + } + + const jsize jlen = + static_cast<jsize>(column_famly_meta_data->levels.size()); + jobjectArray jlevels = env->NewObjectArray(jlen, LevelMetaDataJni::getJClass(env), nullptr); + if(jlevels == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jname); + return nullptr; + } + + jsize i = 0; + for (auto it = column_famly_meta_data->levels.begin(); + it != column_famly_meta_data->levels.end(); ++it) { + jobject jlevel = LevelMetaDataJni::fromCppLevelMetaData(env, &(*it)); + if (jlevel == nullptr) { + // exception occurred + env->DeleteLocalRef(jname); + env->DeleteLocalRef(jlevels); + return nullptr; + } + env->SetObjectArrayElement(jlevels, i++, jlevel); + } + + jobject jcolumn_family_meta_data = env->NewObject(jclazz, mid, + static_cast<jlong>(column_famly_meta_data->size), + static_cast<jlong>(column_famly_meta_data->file_count), + jname, + jlevels + ); + + if (env->ExceptionCheck()) { + env->DeleteLocalRef(jname); + env->DeleteLocalRef(jlevels); + return nullptr; + } + + // cleanup + env->DeleteLocalRef(jname); + env->DeleteLocalRef(jlevels); + + return jcolumn_family_meta_data; + } + + static jclass getJClass(JNIEnv* env) { + return JavaClass::getJClass(env, "org/rocksdb/ColumnFamilyMetaData"); + } +}; + +// The portal class for org.rocksdb.AbstractTraceWriter +class AbstractTraceWriterJni : public RocksDBNativeClass< + const rocksdb::TraceWriterJniCallback*, + AbstractTraceWriterJni> { + public: + /** + * Get the Java Class org.rocksdb.AbstractTraceWriter + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/AbstractTraceWriter"); + } + + /** + * Get the Java Method: AbstractTraceWriter#write + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getWriteProxyMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "writeProxy", "(J)S"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: AbstractTraceWriter#closeWriter + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getCloseWriterProxyMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "closeWriterProxy", "()S"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: AbstractTraceWriter#getFileSize + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getGetFileSizeMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "getFileSize", "()J"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.AbstractWalFilter +class AbstractWalFilterJni : public RocksDBNativeClass< + const rocksdb::WalFilterJniCallback*, + AbstractWalFilterJni> { + public: + /** + * Get the Java Class org.rocksdb.AbstractWalFilter + * + * @param env A pointer to the Java environment + * + * @return The Java Class or nullptr if one of the + * ClassFormatError, ClassCircularityError, NoClassDefFoundError, + * OutOfMemoryError or ExceptionInInitializerError exceptions is thrown + */ + static jclass getJClass(JNIEnv* env) { + return RocksDBNativeClass::getJClass(env, + "org/rocksdb/AbstractWalFilter"); + } + + /** + * Get the Java Method: AbstractWalFilter#columnFamilyLogNumberMap + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getColumnFamilyLogNumberMapMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "columnFamilyLogNumberMap", + "(Ljava/util/Map;Ljava/util/Map;)V"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: AbstractTraceWriter#logRecordFoundProxy + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getLogRecordFoundProxyMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "logRecordFoundProxy", "(JLjava/lang/String;JJ)S"); + assert(mid != nullptr); + return mid; + } + + /** + * Get the Java Method: AbstractTraceWriter#name + * + * @param env A pointer to the Java environment + * + * @return The Java Method ID or nullptr if the class or method id could not + * be retieved + */ + static jmethodID getNameMethodId(JNIEnv* env) { + jclass jclazz = getJClass(env); + if(jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + static jmethodID mid = env->GetMethodID( + jclazz, "name", "()Ljava/lang/String;"); + assert(mid != nullptr); + return mid; + } +}; + +// The portal class for org.rocksdb.WalProcessingOption +class WalProcessingOptionJni { + public: + // Returns the equivalent org.rocksdb.WalProcessingOption for the provided + // C++ rocksdb::WalFilter::WalProcessingOption enum + static jbyte toJavaWalProcessingOption( + const rocksdb::WalFilter::WalProcessingOption& wal_processing_option) { + switch(wal_processing_option) { + case rocksdb::WalFilter::WalProcessingOption::kContinueProcessing: + return 0x0; + case rocksdb::WalFilter::WalProcessingOption::kIgnoreCurrentRecord: + return 0x1; + case rocksdb::WalFilter::WalProcessingOption::kStopReplay: + return 0x2; + case rocksdb::WalFilter::WalProcessingOption::kCorruptedRecord: + return 0x3; + default: + return 0x7F; // undefined + } + } + + // Returns the equivalent C++ rocksdb::WalFilter::WalProcessingOption enum for + // the provided Java org.rocksdb.WalProcessingOption + static rocksdb::WalFilter::WalProcessingOption toCppWalProcessingOption( + jbyte jwal_processing_option) { + switch(jwal_processing_option) { + case 0x0: + return rocksdb::WalFilter::WalProcessingOption::kContinueProcessing; + case 0x1: + return rocksdb::WalFilter::WalProcessingOption::kIgnoreCurrentRecord; + case 0x2: + return rocksdb::WalFilter::WalProcessingOption::kStopReplay; + case 0x3: + return rocksdb::WalFilter::WalProcessingOption::kCorruptedRecord; + default: + // undefined/default + return rocksdb::WalFilter::WalProcessingOption::kCorruptedRecord; + } + } +}; +} // namespace rocksdb +#endif // JAVA_ROCKSJNI_PORTAL_H_ diff --git a/src/rocksdb/java/rocksjni/ratelimiterjni.cc b/src/rocksdb/java/rocksjni/ratelimiterjni.cc new file mode 100644 index 00000000..0804c2fb --- /dev/null +++ b/src/rocksdb/java/rocksjni/ratelimiterjni.cc @@ -0,0 +1,121 @@ +// 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 "bridge" between Java and C++ for RateLimiter. + +#include "include/org_rocksdb_RateLimiter.h" +#include "rocksdb/rate_limiter.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_RateLimiter + * Method: newRateLimiterHandle + * Signature: (JJIBZ)J + */ +jlong Java_org_rocksdb_RateLimiter_newRateLimiterHandle( + JNIEnv* /*env*/, jclass /*jclazz*/, jlong jrate_bytes_per_second, + jlong jrefill_period_micros, jint jfairness, jbyte jrate_limiter_mode, + jboolean jauto_tune) { + auto rate_limiter_mode = + rocksdb::RateLimiterModeJni::toCppRateLimiterMode(jrate_limiter_mode); + auto* sptr_rate_limiter = + new std::shared_ptr<rocksdb::RateLimiter>(rocksdb::NewGenericRateLimiter( + static_cast<int64_t>(jrate_bytes_per_second), + static_cast<int64_t>(jrefill_period_micros), + static_cast<int32_t>(jfairness), rate_limiter_mode, jauto_tune)); + + return reinterpret_cast<jlong>(sptr_rate_limiter); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RateLimiter_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* handle = + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(jhandle); + delete handle; // delete std::shared_ptr +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: setBytesPerSecond + * Signature: (JJ)V + */ +void Java_org_rocksdb_RateLimiter_setBytesPerSecond(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle, + jlong jbytes_per_second) { + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->SetBytesPerSecond(jbytes_per_second); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: getBytesPerSecond + * Signature: (J)J + */ +jlong Java_org_rocksdb_RateLimiter_getBytesPerSecond(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->GetBytesPerSecond(); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: request + * Signature: (JJ)V + */ +void Java_org_rocksdb_RateLimiter_request(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jlong jbytes) { + reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->Request(jbytes, rocksdb::Env::IO_TOTAL); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: getSingleBurstBytes + * Signature: (J)J + */ +jlong Java_org_rocksdb_RateLimiter_getSingleBurstBytes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->GetSingleBurstBytes(); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: getTotalBytesThrough + * Signature: (J)J + */ +jlong Java_org_rocksdb_RateLimiter_getTotalBytesThrough(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->GetTotalBytesThrough(); +} + +/* + * Class: org_rocksdb_RateLimiter + * Method: getTotalRequests + * Signature: (J)J + */ +jlong Java_org_rocksdb_RateLimiter_getTotalRequests(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<std::shared_ptr<rocksdb::RateLimiter>*>(handle) + ->get() + ->GetTotalRequests(); +} diff --git a/src/rocksdb/java/rocksjni/remove_emptyvalue_compactionfilterjni.cc b/src/rocksdb/java/rocksjni/remove_emptyvalue_compactionfilterjni.cc new file mode 100644 index 00000000..ede150fa --- /dev/null +++ b/src/rocksdb/java/rocksjni/remove_emptyvalue_compactionfilterjni.cc @@ -0,0 +1,22 @@ +// 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). + +#include <jni.h> + +#include "include/org_rocksdb_RemoveEmptyValueCompactionFilter.h" +#include "utilities/compaction_filters/remove_emptyvalue_compactionfilter.h" + +/* + * Class: org_rocksdb_RemoveEmptyValueCompactionFilter + * Method: createNewRemoveEmptyValueCompactionFilter0 + * Signature: ()J + */ +jlong Java_org_rocksdb_RemoveEmptyValueCompactionFilter_createNewRemoveEmptyValueCompactionFilter0( + JNIEnv* /*env*/, jclass /*jcls*/) { + auto* compaction_filter = new rocksdb::RemoveEmptyValueCompactionFilter(); + + // set the native handle to our native compaction filter + return reinterpret_cast<jlong>(compaction_filter); +} diff --git a/src/rocksdb/java/rocksjni/restorejni.cc b/src/rocksdb/java/rocksjni/restorejni.cc new file mode 100644 index 00000000..beca74fb --- /dev/null +++ b/src/rocksdb/java/rocksjni/restorejni.cc @@ -0,0 +1,40 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::RestoreOptions methods +// from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include "include/org_rocksdb_RestoreOptions.h" +#include "rocksdb/utilities/backupable_db.h" +#include "rocksjni/portal.h" +/* + * Class: org_rocksdb_RestoreOptions + * Method: newRestoreOptions + * Signature: (Z)J + */ +jlong Java_org_rocksdb_RestoreOptions_newRestoreOptions( + JNIEnv* /*env*/, jclass /*jcls*/, jboolean keep_log_files) { + auto* ropt = new rocksdb::RestoreOptions(keep_log_files); + return reinterpret_cast<jlong>(ropt); +} + +/* + * Class: org_rocksdb_RestoreOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RestoreOptions_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* ropt = reinterpret_cast<rocksdb::RestoreOptions*>(jhandle); + assert(ropt); + delete ropt; +} diff --git a/src/rocksdb/java/rocksjni/rocks_callback_object.cc b/src/rocksdb/java/rocksjni/rocks_callback_object.cc new file mode 100644 index 00000000..874ef337 --- /dev/null +++ b/src/rocksdb/java/rocksjni/rocks_callback_object.cc @@ -0,0 +1,31 @@ +// 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 "bridge" between Java and C++ for +// JNI Callbacks from C++ to sub-classes or org.rocksdb.RocksCallbackObject + +#include <jni.h> + +#include "include/org_rocksdb_RocksCallbackObject.h" +#include "jnicallback.h" + +/* + * Class: org_rocksdb_RocksCallbackObject + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksCallbackObject_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + // TODO(AR) is deleting from the super class JniCallback OK, or must we delete + // the subclass? Example hierarchies: + // 1) Comparator -> BaseComparatorJniCallback + JniCallback -> + // DirectComparatorJniCallback 2) Comparator -> BaseComparatorJniCallback + + // JniCallback -> ComparatorJniCallback + // I think this is okay, as Comparator and JniCallback both have virtual + // destructors... + delete reinterpret_cast<rocksdb::JniCallback*>(handle); + // @lint-ignore TXT4 T25377293 Grandfathered in +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/rocksdb_exception_test.cc b/src/rocksdb/java/rocksjni/rocksdb_exception_test.cc new file mode 100644 index 00000000..6e597812 --- /dev/null +++ b/src/rocksdb/java/rocksjni/rocksdb_exception_test.cc @@ -0,0 +1,78 @@ +// 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). + +#include <jni.h> + +#include "include/org_rocksdb_RocksDBExceptionTest.h" + +#include "rocksdb/slice.h" +#include "rocksdb/status.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseException + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseException(JNIEnv* env, + jobject /*jobj*/) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, std::string("test message")); +} + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseExceptionWithStatusCode + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCode( + JNIEnv* env, jobject /*jobj*/) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, "test message", + rocksdb::Status::NotSupported()); +} + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseExceptionNoMsgWithStatusCode + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionNoMsgWithStatusCode( + JNIEnv* env, jobject /*jobj*/) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotSupported()); +} + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseExceptionWithStatusCodeSubCode + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCodeSubCode( + JNIEnv* env, jobject /*jobj*/) { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, "test message", + rocksdb::Status::TimedOut(rocksdb::Status::SubCode::kLockTimeout)); +} + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseExceptionNoMsgWithStatusCodeSubCode + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionNoMsgWithStatusCodeSubCode( + JNIEnv* env, jobject /*jobj*/) { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::TimedOut(rocksdb::Status::SubCode::kLockTimeout)); +} + +/* + * Class: org_rocksdb_RocksDBExceptionTest + * Method: raiseExceptionWithStatusCodeState + * Signature: ()V + */ +void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCodeState( + JNIEnv* env, jobject /*jobj*/) { + rocksdb::Slice state("test state"); + rocksdb::RocksDBExceptionJni::ThrowNew(env, "test message", + rocksdb::Status::NotSupported(state)); +} diff --git a/src/rocksdb/java/rocksjni/rocksjni.cc b/src/rocksdb/java/rocksjni/rocksjni.cc new file mode 100644 index 00000000..53224232 --- /dev/null +++ b/src/rocksdb/java/rocksjni/rocksjni.cc @@ -0,0 +1,3046 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::DB methods from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <algorithm> +#include <functional> +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include "include/org_rocksdb_RocksDB.h" +#include "rocksdb/cache.h" +#include "rocksdb/db.h" +#include "rocksdb/options.h" +#include "rocksdb/types.h" +#include "rocksjni/portal.h" + +#ifdef min +#undef min +#endif + +jlong rocksdb_open_helper( + JNIEnv* env, jlong jopt_handle, jstring jdb_path, + std::function<rocksdb::Status(const rocksdb::Options&, const std::string&, + rocksdb::DB**)> + open_fn) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle); + rocksdb::DB* db = nullptr; + rocksdb::Status s = open_fn(*opt, db_path, &db); + + env->ReleaseStringUTFChars(jdb_path, db_path); + + if (s.ok()) { + return reinterpret_cast<jlong>(db); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: open + * Signature: (JLjava/lang/String;)J + */ +jlong Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) { + return rocksdb_open_helper( + env, jopt_handle, jdb_path, + (rocksdb::Status(*)(const rocksdb::Options&, const std::string&, + rocksdb::DB**)) & + rocksdb::DB::Open); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: openROnly + * Signature: (JLjava/lang/String;)J + */ +jlong Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) { + return rocksdb_open_helper(env, jopt_handle, jdb_path, + [](const rocksdb::Options& options, + const std::string& db_path, rocksdb::DB** db) { + return rocksdb::DB::OpenForReadOnly(options, + db_path, db); + }); +} + +jlongArray rocksdb_open_helper( + JNIEnv* env, jlong jopt_handle, jstring jdb_path, + jobjectArray jcolumn_names, jlongArray jcolumn_options, + std::function<rocksdb::Status( + const rocksdb::DBOptions&, const std::string&, + const std::vector<rocksdb::ColumnFamilyDescriptor>&, + std::vector<rocksdb::ColumnFamilyHandle*>*, rocksdb::DB**)> + open_fn) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + const jsize len_cols = env->GetArrayLength(jcolumn_names); + jlong* jco = env->GetLongArrayElements(jcolumn_options, nullptr); + if (jco == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + std::vector<rocksdb::ColumnFamilyDescriptor> column_families; + jboolean has_exception = JNI_FALSE; + rocksdb::JniUtil::byteStrings<std::string>( + env, jcolumn_names, + [](const char* str_data, const size_t str_len) { + return std::string(str_data, str_len); + }, + [&jco, &column_families](size_t idx, std::string cf_name) { + rocksdb::ColumnFamilyOptions* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[idx]); + column_families.push_back( + rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options)); + }, + &has_exception); + + env->ReleaseLongArrayElements(jcolumn_options, jco, JNI_ABORT); + + if (has_exception == JNI_TRUE) { + // exception occurred + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jopt_handle); + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + rocksdb::DB* db = nullptr; + rocksdb::Status s = open_fn(*opt, db_path, column_families, &cf_handles, &db); + + // we have now finished with db_path + env->ReleaseStringUTFChars(jdb_path, db_path); + + // check if open operation was successful + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + const jsize resultsLen = 1 + len_cols; // db handle + column family handles + std::unique_ptr<jlong[]> results = + std::unique_ptr<jlong[]>(new jlong[resultsLen]); + results[0] = reinterpret_cast<jlong>(db); + for (int i = 1; i <= len_cols; i++) { + results[i] = reinterpret_cast<jlong>(cf_handles[i - 1]); + } + + jlongArray jresults = env->NewLongArray(resultsLen); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetLongArrayRegion(jresults, 0, resultsLen, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jresults); + return nullptr; + } + + return jresults; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: openROnly + * Signature: (JLjava/lang/String;[[B[J)[J + */ +jlongArray Java_org_rocksdb_RocksDB_openROnly__JLjava_lang_String_2_3_3B_3J( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path, + jobjectArray jcolumn_names, jlongArray jcolumn_options) { + return rocksdb_open_helper( + env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options, + [](const rocksdb::DBOptions& options, const std::string& db_path, + const std::vector<rocksdb::ColumnFamilyDescriptor>& column_families, + std::vector<rocksdb::ColumnFamilyHandle*>* handles, rocksdb::DB** db) { + return rocksdb::DB::OpenForReadOnly(options, db_path, column_families, + handles, db); + }); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: open + * Signature: (JLjava/lang/String;[[B[J)[J + */ +jlongArray Java_org_rocksdb_RocksDB_open__JLjava_lang_String_2_3_3B_3J( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path, + jobjectArray jcolumn_names, jlongArray jcolumn_options) { + return rocksdb_open_helper( + env, jopt_handle, jdb_path, jcolumn_names, jcolumn_options, + (rocksdb::Status(*)(const rocksdb::DBOptions&, const std::string&, + const std::vector<rocksdb::ColumnFamilyDescriptor>&, + std::vector<rocksdb::ColumnFamilyHandle*>*, + rocksdb::DB**)) & + rocksdb::DB::Open); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jhandle); + assert(db != nullptr); + delete db; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: closeDatabase + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_closeDatabase( + JNIEnv* env, jclass, jlong jhandle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jhandle); + assert(db != nullptr); + rocksdb::Status s = db->Close(); + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: listColumnFamilies + * Signature: (JLjava/lang/String;)[[B + */ +jobjectArray Java_org_rocksdb_RocksDB_listColumnFamilies( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path) { + std::vector<std::string> column_family_names; + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle); + rocksdb::Status s = + rocksdb::DB::ListColumnFamilies(*opt, db_path, &column_family_names); + + env->ReleaseStringUTFChars(jdb_path, db_path); + + jobjectArray jcolumn_family_names = + rocksdb::JniUtil::stringsBytes(env, column_family_names); + + return jcolumn_family_names; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: createColumnFamily + * Signature: (J[BIJ)J + */ +jlong Java_org_rocksdb_RocksDB_createColumnFamily( + JNIEnv* env, jobject, jlong jhandle, jbyteArray jcf_name, + jint jcf_name_len, jlong jcf_options_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jhandle); + jboolean has_exception = JNI_FALSE; + const std::string cf_name = + rocksdb::JniUtil::byteString<std::string>(env, jcf_name, jcf_name_len, + [](const char* str, const size_t len) { + return std::string(str, len); + }, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return 0; + } + auto* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jcf_options_handle); + rocksdb::ColumnFamilyHandle *cf_handle; + rocksdb::Status s = db->CreateColumnFamily(*cf_options, cf_name, &cf_handle); + if (!s.ok()) { + // error occurred + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } + return reinterpret_cast<jlong>(cf_handle); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: createColumnFamilies + * Signature: (JJ[[B)[J + */ +jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__JJ_3_3B( + JNIEnv* env, jobject, jlong jhandle, jlong jcf_options_handle, + jobjectArray jcf_names) { + auto* db = reinterpret_cast<rocksdb::DB*>(jhandle); + auto* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jcf_options_handle); + jboolean has_exception = JNI_FALSE; + std::vector<std::string> cf_names; + rocksdb::JniUtil::byteStrings<std::string>(env, jcf_names, + [](const char* str, const size_t len) { + return std::string(str, len); + }, + [&cf_names](const size_t, std::string str) { + cf_names.push_back(str); + }, + &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return nullptr; + } + + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + rocksdb::Status s = db->CreateColumnFamilies(*cf_options, cf_names, &cf_handles); + if (!s.ok()) { + // error occurred + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + jlongArray jcf_handles = rocksdb::JniUtil::toJPointers<rocksdb::ColumnFamilyHandle>( + env, cf_handles, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return nullptr; + } + return jcf_handles; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: createColumnFamilies + * Signature: (J[J[[B)[J + */ +jlongArray Java_org_rocksdb_RocksDB_createColumnFamilies__J_3J_3_3B( + JNIEnv* env, jobject, jlong jhandle, jlongArray jcf_options_handles, + jobjectArray jcf_names) { + auto* db = reinterpret_cast<rocksdb::DB*>(jhandle); + const jsize jlen = env->GetArrayLength(jcf_options_handles); + std::vector<rocksdb::ColumnFamilyDescriptor> cf_descriptors; + cf_descriptors.reserve(jlen); + + jboolean jcf_options_handles_is_copy = JNI_FALSE; + jlong *jcf_options_handles_elems = env->GetLongArrayElements(jcf_options_handles, &jcf_options_handles_is_copy); + if(jcf_options_handles_elems == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + // extract the column family descriptors + jboolean has_exception = JNI_FALSE; + for (jsize i = 0; i < jlen; i++) { + auto* cf_options = reinterpret_cast<rocksdb::ColumnFamilyOptions*>( + jcf_options_handles_elems[i]); + jbyteArray jcf_name = static_cast<jbyteArray>( + env->GetObjectArrayElement(jcf_names, i)); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT); + return nullptr; + } + const std::string cf_name = + rocksdb::JniUtil::byteString<std::string>(env, jcf_name, + [](const char* str, const size_t len) { + return std::string(str, len); + }, + &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + env->DeleteLocalRef(jcf_name); + env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT); + return nullptr; + } + + cf_descriptors.push_back(rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options)); + + env->DeleteLocalRef(jcf_name); + } + + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + rocksdb::Status s = db->CreateColumnFamilies(cf_descriptors, &cf_handles); + + env->ReleaseLongArrayElements(jcf_options_handles, jcf_options_handles_elems, JNI_ABORT); + + if (!s.ok()) { + // error occurred + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + jlongArray jcf_handles = rocksdb::JniUtil::toJPointers<rocksdb::ColumnFamilyHandle>( + env, cf_handles, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return nullptr; + } + return jcf_handles; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: dropColumnFamily + * Signature: (JJ)V; + */ +void Java_org_rocksdb_RocksDB_dropColumnFamily( + JNIEnv* env, jobject, jlong jdb_handle, + jlong jcf_handle) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + rocksdb::Status s = db_handle->DropColumnFamily(cf_handle); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: dropColumnFamilies + * Signature: (J[J)V + */ +void Java_org_rocksdb_RocksDB_dropColumnFamilies( + JNIEnv* env, jobject, jlong jdb_handle, + jlongArray jcolumn_family_handles) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + if (jcolumn_family_handles != nullptr) { + const jsize len_cols = env->GetArrayLength(jcolumn_family_handles); + + jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr); + if (jcfh == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + for (jsize i = 0; i < len_cols; i++) { + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcfh[i]); + cf_handles.push_back(cf_handle); + } + env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT); + } + + rocksdb::Status s = db_handle->DropColumnFamilies(cf_handles); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::Put + +/** + * @return true if the put succeeded, false if a Java Exception was thrown + */ +bool rocksdb_put_helper( + JNIEnv* env, rocksdb::DB* db, + const rocksdb::WriteOptions& write_options, + rocksdb::ColumnFamilyHandle* cf_handle, jbyteArray jkey, + jint jkey_off, jint jkey_len, jbyteArray jval, + jint jval_off, jint jval_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + return false; + } + + jbyte* value = new jbyte[jval_len]; + env->GetByteArrayRegion(jval, jval_off, jval_len, value); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] value; + delete[] key; + return false; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + rocksdb::Slice value_slice(reinterpret_cast<char*>(value), jval_len); + + rocksdb::Status s; + if (cf_handle != nullptr) { + s = db->Put(write_options, cf_handle, key_slice, value_slice); + } else { + // backwards compatibility + s = db->Put(write_options, key_slice, value_slice); + } + + // cleanup + delete[] value; + delete[] key; + + if (s.ok()) { + return true; + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return false; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: put + * Signature: (J[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_put__J_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + rocksdb_put_helper(env, db, default_write_options, nullptr, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: put + * Signature: (J[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_put__J_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_put_helper(env, db, default_write_options, cf_handle, jkey, + jkey_off, jkey_len, jval, jval_off, jval_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: put + * Signature: (JJ[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jlong jwrite_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + rocksdb_put_helper(env, db, *write_options, nullptr, jkey, jkey_off, jkey_len, + jval, jval_off, jval_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: put + * Signature: (JJ[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_put__JJ_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_put_helper(env, db, *write_options, cf_handle, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::Delete() + +/** + * @return true if the delete succeeded, false if a Java Exception was thrown + */ +bool rocksdb_delete_helper( + JNIEnv* env, rocksdb::DB* db, const rocksdb::WriteOptions& write_options, + rocksdb::ColumnFamilyHandle* cf_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + return false; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + rocksdb::Status s; + if (cf_handle != nullptr) { + s = db->Delete(write_options, cf_handle, key_slice); + } else { + // backwards compatibility + s = db->Delete(write_options, key_slice); + } + + // cleanup + delete[] key; + + if (s.ok()) { + return true; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return false; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: delete + * Signature: (J[BII)V + */ +void Java_org_rocksdb_RocksDB_delete__J_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + rocksdb_delete_helper(env, db, default_write_options, nullptr, jkey, jkey_off, + jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: delete + * Signature: (J[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_delete__J_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_delete_helper(env, db, default_write_options, cf_handle, jkey, + jkey_off, jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: delete + * Signature: (JJ[BII)V + */ +void Java_org_rocksdb_RocksDB_delete__JJ_3BII( + JNIEnv* env, jobject, + jlong jdb_handle, + jlong jwrite_options, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + rocksdb_delete_helper(env, db, *write_options, nullptr, jkey, jkey_off, + jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: delete + * Signature: (JJ[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_delete__JJ_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options, + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_delete_helper(env, db, *write_options, cf_handle, jkey, jkey_off, + jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::SingleDelete() +/** + * @return true if the single delete succeeded, false if a Java Exception + * was thrown + */ +bool rocksdb_single_delete_helper( + JNIEnv* env, rocksdb::DB* db, + const rocksdb::WriteOptions& write_options, + rocksdb::ColumnFamilyHandle* cf_handle, + jbyteArray jkey, jint jkey_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return false; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + rocksdb::Status s; + if (cf_handle != nullptr) { + s = db->SingleDelete(write_options, cf_handle, key_slice); + } else { + // backwards compatibility + s = db->SingleDelete(write_options, key_slice); + } + + // trigger java unref on key and value. + // by passing JNI_ABORT, it will simply release the reference without + // copying the result back to the java byte array. + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (s.ok()) { + return true; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return false; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: singleDelete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_RocksDB_singleDelete__J_3BI( + JNIEnv* env, jobject, + jlong jdb_handle, + jbyteArray jkey, + jint jkey_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + rocksdb_single_delete_helper(env, db, default_write_options, nullptr, + jkey, jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: singleDelete + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_RocksDB_singleDelete__J_3BIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_single_delete_helper(env, db, default_write_options, cf_handle, + jkey, jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: singleDelete + * Signature: (JJ[BIJ)V + */ +void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BI( + JNIEnv* env, jobject, jlong jdb_handle, + jlong jwrite_options, + jbyteArray jkey, + jint jkey_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + rocksdb_single_delete_helper(env, db, *write_options, nullptr, jkey, + jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: singleDelete + * Signature: (JJ[BIJ)V + */ +void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options, + jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_single_delete_helper(env, db, *write_options, cf_handle, jkey, + jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::DeleteRange() +/** + * @return true if the delete range succeeded, false if a Java Exception + * was thrown + */ +bool rocksdb_delete_range_helper( + JNIEnv* env, rocksdb::DB* db, + const rocksdb::WriteOptions& write_options, + rocksdb::ColumnFamilyHandle* cf_handle, + jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len, + jbyteArray jend_key, jint jend_key_off, jint jend_key_len) { + jbyte* begin_key = new jbyte[jbegin_key_len]; + env->GetByteArrayRegion(jbegin_key, jbegin_key_off, jbegin_key_len, + begin_key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] begin_key; + return false; + } + rocksdb::Slice begin_key_slice(reinterpret_cast<char*>(begin_key), + jbegin_key_len); + + jbyte* end_key = new jbyte[jend_key_len]; + env->GetByteArrayRegion(jend_key, jend_key_off, jend_key_len, end_key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] begin_key; + delete[] end_key; + return false; + } + rocksdb::Slice end_key_slice(reinterpret_cast<char*>(end_key), jend_key_len); + + rocksdb::Status s = + db->DeleteRange(write_options, cf_handle, begin_key_slice, end_key_slice); + + // cleanup + delete[] begin_key; + delete[] end_key; + + if (s.ok()) { + return true; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return false; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: deleteRange + * Signature: (J[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len, + jbyteArray jend_key, jint jend_key_off, jint jend_key_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + rocksdb_delete_range_helper(env, db, default_write_options, nullptr, + jbegin_key, jbegin_key_off, jbegin_key_len, + jend_key, jend_key_off, jend_key_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: deleteRange + * Signature: (J[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len, + jbyteArray jend_key, jint jend_key_off, jint jend_key_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_delete_range_helper(env, db, default_write_options, cf_handle, + jbegin_key, jbegin_key_off, jbegin_key_len, + jend_key, jend_key_off, jend_key_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: deleteRange + * Signature: (JJ[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options, + jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len, + jbyteArray jend_key, jint jend_key_off, jint jend_key_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + rocksdb_delete_range_helper(env, db, *write_options, nullptr, jbegin_key, + jbegin_key_off, jbegin_key_len, jend_key, + jend_key_off, jend_key_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: deleteRange + * Signature: (JJ[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options, + jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len, + jbyteArray jend_key, jint jend_key_off, jint jend_key_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_delete_range_helper(env, db, *write_options, cf_handle, + jbegin_key, jbegin_key_off, jbegin_key_len, + jend_key, jend_key_off, jend_key_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::Merge + +/** + * @return true if the merge succeeded, false if a Java Exception was thrown + */ +bool rocksdb_merge_helper( + JNIEnv* env, rocksdb::DB* db, const rocksdb::WriteOptions& write_options, + rocksdb::ColumnFamilyHandle* cf_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + return false; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + jbyte* value = new jbyte[jval_len]; + env->GetByteArrayRegion(jval, jval_off, jval_len, value); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] value; + delete[] key; + return false; + } + rocksdb::Slice value_slice(reinterpret_cast<char*>(value), jval_len); + + rocksdb::Status s; + if (cf_handle != nullptr) { + s = db->Merge(write_options, cf_handle, key_slice, value_slice); + } else { + s = db->Merge(write_options, key_slice, value_slice); + } + + // cleanup + delete[] value; + delete[] key; + + if (s.ok()) { + return true; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return false; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: merge + * Signature: (J[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_merge__J_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + rocksdb_merge_helper(env, db, default_write_options, nullptr, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: merge + * Signature: (J[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + static const rocksdb::WriteOptions default_write_options = + rocksdb::WriteOptions(); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_merge_helper(env, db, default_write_options, cf_handle, jkey, + jkey_off, jkey_len, jval, jval_off, jval_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: merge + * Signature: (JJ[BII[BII)V + */ +void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + rocksdb_merge_helper(env, db, *write_options, nullptr, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: merge + * Signature: (JJ[BII[BIIJ)V + */ +void Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jwrite_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + rocksdb_merge_helper(env, db, *write_options, cf_handle, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + } +} + +jlong rocksdb_iterator_helper(rocksdb::DB* db, + rocksdb::ReadOptions read_options, + rocksdb::ColumnFamilyHandle* cf_handle) { + rocksdb::Iterator* iterator = nullptr; + if (cf_handle != nullptr) { + iterator = db->NewIterator(read_options, cf_handle); + } else { + iterator = db->NewIterator(read_options); + } + return reinterpret_cast<jlong>(iterator); +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::Write +/* + * Class: org_rocksdb_RocksDB + * Method: write0 + * Signature: (JJJ)V + */ +void Java_org_rocksdb_RocksDB_write0( + JNIEnv* env, jobject, jlong jdb_handle, + jlong jwrite_options_handle, jlong jwb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + + rocksdb::Status s = db->Write(*write_options, wb); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: write1 + * Signature: (JJJ)V + */ +void Java_org_rocksdb_RocksDB_write1( + JNIEnv* env, jobject, jlong jdb_handle, + jlong jwrite_options_handle, jlong jwbwi_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* wb = wbwi->GetWriteBatch(); + + rocksdb::Status s = db->Write(*write_options, wb); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::Get + +jbyteArray rocksdb_get_helper( + JNIEnv* env, rocksdb::DB* db, + const rocksdb::ReadOptions& read_opt, + rocksdb::ColumnFamilyHandle* column_family_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + std::string value; + rocksdb::Status s; + if (column_family_handle != nullptr) { + s = db->Get(read_opt, column_family_handle, key_slice, &value); + } else { + // backwards compatibility + s = db->Get(read_opt, key_slice, &value); + } + + // cleanup + delete[] key; + + if (s.IsNotFound()) { + return nullptr; + } + + if (s.ok()) { + jbyteArray jret_value = rocksdb::JniUtil::copyBytes(env, value); + if (jret_value == nullptr) { + // exception occurred + return nullptr; + } + return jret_value; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (J[BII)[B + */ +jbyteArray Java_org_rocksdb_RocksDB_get__J_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + return rocksdb_get_helper(env, reinterpret_cast<rocksdb::DB*>(jdb_handle), + rocksdb::ReadOptions(), nullptr, jkey, jkey_off, jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (J[BIIJ)[B + */ +jbyteArray Java_org_rocksdb_RocksDB_get__J_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { + auto db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + return rocksdb_get_helper(env, db_handle, rocksdb::ReadOptions(), cf_handle, + jkey, jkey_off, jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + return nullptr; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (JJ[BII)[B + */ +jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BII( + JNIEnv* env, jobject, + jlong jdb_handle, jlong jropt_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len) { + return rocksdb_get_helper( + env, reinterpret_cast<rocksdb::DB*>(jdb_handle), + *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle), nullptr, jkey, + jkey_off, jkey_len); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (JJ[BIIJ)[B + */ +jbyteArray Java_org_rocksdb_RocksDB_get__JJ_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto& ro_opt = *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + return rocksdb_get_helper( + env, db_handle, ro_opt, cf_handle, jkey, jkey_off, jkey_len); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + return nullptr; + } +} + +jint rocksdb_get_helper( + JNIEnv* env, rocksdb::DB* db, const rocksdb::ReadOptions& read_options, + rocksdb::ColumnFamilyHandle* column_family_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + bool* has_exception) { + static const int kNotFound = -1; + static const int kStatusError = -2; + + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + delete[] key; + *has_exception = true; + return kStatusError; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + // TODO(yhchiang): we might save one memory allocation here by adding + // a DB::Get() function which takes preallocated jbyte* as input. + std::string cvalue; + rocksdb::Status s; + if (column_family_handle != nullptr) { + s = db->Get(read_options, column_family_handle, key_slice, &cvalue); + } else { + // backwards compatibility + s = db->Get(read_options, key_slice, &cvalue); + } + + // cleanup + delete[] key; + + if (s.IsNotFound()) { + *has_exception = false; + return kNotFound; + } else if (!s.ok()) { + *has_exception = true; + // Here since we are throwing a Java exception from c++ side. + // As a result, c++ does not know calling this function will in fact + // throwing an exception. As a result, the execution flow will + // not stop here, and codes after this throw will still be + // executed. + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + + // Return a dummy const value to avoid compilation error, although + // java side might not have a chance to get the return value :) + return kStatusError; + } + + const jint cvalue_len = static_cast<jint>(cvalue.size()); + const jint length = std::min(jval_len, cvalue_len); + + env->SetByteArrayRegion( + jval, jval_off, length, + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(cvalue.c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: OutOfMemoryError + *has_exception = true; + return kStatusError; + } + + *has_exception = false; + return cvalue_len; +} + + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (J[BII[BII)I + */ +jint Java_org_rocksdb_RocksDB_get__J_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + bool has_exception = false; + return rocksdb_get_helper(env, reinterpret_cast<rocksdb::DB*>(jdb_handle), + rocksdb::ReadOptions(), nullptr, jkey, jkey_off, + jkey_len, jval, jval_off, jval_len, &has_exception); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (J[BII[BIIJ)I + */ +jint Java_org_rocksdb_RocksDB_get__J_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + jlong jcf_handle) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + bool has_exception = false; + return rocksdb_get_helper(env, db_handle, rocksdb::ReadOptions(), cf_handle, + jkey, jkey_off, jkey_len, jval, jval_off, + jval_len, &has_exception); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + // will never be evaluated + return 0; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (JJ[BII[BII)I + */ +jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BII( + JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len) { + bool has_exception = false; + return rocksdb_get_helper( + env, reinterpret_cast<rocksdb::DB*>(jdb_handle), + *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle), nullptr, jkey, + jkey_off, jkey_len, jval, jval_off, jval_len, &has_exception); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: get + * Signature: (JJ[BII[BIIJ)I + */ +jint Java_org_rocksdb_RocksDB_get__JJ_3BII_3BIIJ( + JNIEnv* env, jobject, jlong jdb_handle, jlong jropt_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jbyteArray jval, jint jval_off, jint jval_len, + jlong jcf_handle) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto& ro_opt = *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + bool has_exception = false; + return rocksdb_get_helper(env, db_handle, ro_opt, cf_handle, + jkey, jkey_off, jkey_len, + jval, jval_off, jval_len, + &has_exception); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + // will never be evaluated + return 0; + } +} + +inline void multi_get_helper_release_keys( + JNIEnv* env, std::vector<std::pair<jbyte*, jobject>>& keys_to_free) { + auto end = keys_to_free.end(); + for (auto it = keys_to_free.begin(); it != end; ++it) { + delete[] it->first; + env->DeleteLocalRef(it->second); + } + keys_to_free.clear(); +} + +/** + * cf multi get + * + * @return byte[][] of values or nullptr if an exception occurs + */ +jobjectArray multi_get_helper( + JNIEnv* env, jobject, rocksdb::DB* db, const rocksdb::ReadOptions& rOpt, + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens, + jlongArray jcolumn_family_handles) { + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + if (jcolumn_family_handles != nullptr) { + const jsize len_cols = env->GetArrayLength(jcolumn_family_handles); + + jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr); + if (jcfh == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + for (jsize i = 0; i < len_cols; i++) { + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcfh[i]); + cf_handles.push_back(cf_handle); + } + env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT); + } + + const jsize len_keys = env->GetArrayLength(jkeys); + if (env->EnsureLocalCapacity(len_keys) != 0) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jint* jkey_off = env->GetIntArrayElements(jkey_offs, nullptr); + if (jkey_off == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jint* jkey_len = env->GetIntArrayElements(jkey_lens, nullptr); + if (jkey_len == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT); + return nullptr; + } + + std::vector<rocksdb::Slice> keys; + std::vector<std::pair<jbyte*, jobject>> keys_to_free; + for (jsize i = 0; i < len_keys; i++) { + jobject jkey = env->GetObjectArrayElement(jkeys, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT); + env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT); + multi_get_helper_release_keys(env, keys_to_free); + return nullptr; + } + + jbyteArray jkey_ba = reinterpret_cast<jbyteArray>(jkey); + + const jint len_key = jkey_len[i]; + jbyte* key = new jbyte[len_key]; + env->GetByteArrayRegion(jkey_ba, jkey_off[i], len_key, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + env->DeleteLocalRef(jkey); + env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT); + env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT); + multi_get_helper_release_keys(env, keys_to_free); + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), len_key); + keys.push_back(key_slice); + + keys_to_free.push_back(std::pair<jbyte*, jobject>(key, jkey)); + } + + // cleanup jkey_off and jken_len + env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT); + env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT); + + std::vector<std::string> values; + std::vector<rocksdb::Status> s; + if (cf_handles.size() == 0) { + s = db->MultiGet(rOpt, keys, &values); + } else { + s = db->MultiGet(rOpt, cf_handles, keys, &values); + } + + // free up allocated byte arrays + multi_get_helper_release_keys(env, keys_to_free); + + // prepare the results + jobjectArray jresults = + rocksdb::ByteJni::new2dByteArray(env, static_cast<jsize>(s.size())); + if (jresults == nullptr) { + // exception occurred + return nullptr; + } + + // TODO(AR) it is not clear to me why EnsureLocalCapacity is needed for the + // loop as we cleanup references with env->DeleteLocalRef(jentry_value); + if (env->EnsureLocalCapacity(static_cast<jint>(s.size())) != 0) { + // exception thrown: OutOfMemoryError + return nullptr; + } + // add to the jresults + for (std::vector<rocksdb::Status>::size_type i = 0; i != s.size(); i++) { + if (s[i].ok()) { + std::string* value = &values[i]; + const jsize jvalue_len = static_cast<jsize>(value->size()); + jbyteArray jentry_value = env->NewByteArray(jvalue_len); + if (jentry_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + jentry_value, 0, static_cast<jsize>(jvalue_len), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value->c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jentry_value); + return nullptr; + } + + env->SetObjectArrayElement(jresults, static_cast<jsize>(i), jentry_value); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jentry_value); + return nullptr; + } + + env->DeleteLocalRef(jentry_value); + } + } + + return jresults; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: multiGet + * Signature: (J[[B[I[I)[[B + */ +jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I( + JNIEnv* env, jobject jdb, jlong jdb_handle, + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens) { + return multi_get_helper(env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle), + rocksdb::ReadOptions(), jkeys, jkey_offs, jkey_lens, + nullptr); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: multiGet + * Signature: (J[[B[I[I[J)[[B + */ +jobjectArray Java_org_rocksdb_RocksDB_multiGet__J_3_3B_3I_3I_3J( + JNIEnv* env, jobject jdb, jlong jdb_handle, + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens, + jlongArray jcolumn_family_handles) { + return multi_get_helper(env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle), + rocksdb::ReadOptions(), jkeys, jkey_offs, jkey_lens, + jcolumn_family_handles); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: multiGet + * Signature: (JJ[[B[I[I)[[B + */ +jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I( + JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens) { + return multi_get_helper( + env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle), + *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle), jkeys, jkey_offs, + jkey_lens, nullptr); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: multiGet + * Signature: (JJ[[B[I[I[J)[[B + */ +jobjectArray Java_org_rocksdb_RocksDB_multiGet__JJ_3_3B_3I_3I_3J( + JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jropt_handle, + jobjectArray jkeys, jintArray jkey_offs, jintArray jkey_lens, + jlongArray jcolumn_family_handles) { + return multi_get_helper( + env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle), + *reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle), jkeys, jkey_offs, + jkey_lens, jcolumn_family_handles); +} + +////////////////////////////////////////////////////////////////////////////// +// rocksdb::DB::KeyMayExist +jboolean key_may_exist_helper(JNIEnv* env, rocksdb::DB* db, + const rocksdb::ReadOptions& read_opt, + rocksdb::ColumnFamilyHandle* cf_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jobject jstring_builder, bool* has_exception) { + jbyte* key = new jbyte[jkey_len]; + env->GetByteArrayRegion(jkey, jkey_off, jkey_len, key); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete[] key; + *has_exception = true; + return false; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_len); + + std::string value; + bool value_found = false; + bool keyMayExist; + if (cf_handle != nullptr) { + keyMayExist = + db->KeyMayExist(read_opt, cf_handle, key_slice, &value, &value_found); + } else { + keyMayExist = db->KeyMayExist(read_opt, key_slice, &value, &value_found); + } + + // cleanup + delete[] key; + + // extract the value + if (value_found && !value.empty()) { + jobject jresult_string_builder = + rocksdb::StringBuilderJni::append(env, jstring_builder, value.c_str()); + if (jresult_string_builder == nullptr) { + *has_exception = true; + return false; + } + } + + *has_exception = false; + return static_cast<jboolean>(keyMayExist); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: keyMayExist + * Signature: (J[BIILjava/lang/StringBuilder;)Z + */ +jboolean Java_org_rocksdb_RocksDB_keyMayExist__J_3BIILjava_lang_StringBuilder_2( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, jobject jstring_builder) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + bool has_exception = false; + return key_may_exist_helper(env, db, rocksdb::ReadOptions(), nullptr, jkey, + jkey_off, jkey_len, jstring_builder, &has_exception); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: keyMayExist + * Signature: (J[BIIJLjava/lang/StringBuilder;)Z + */ +jboolean +Java_org_rocksdb_RocksDB_keyMayExist__J_3BIIJLjava_lang_StringBuilder_2( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, + jlong jcf_handle, jobject jstring_builder) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + bool has_exception = false; + return key_may_exist_helper(env, db, rocksdb::ReadOptions(), cf_handle, + jkey, jkey_off, jkey_len, jstring_builder, + &has_exception); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + return true; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: keyMayExist + * Signature: (JJ[BIILjava/lang/StringBuilder;)Z + */ +jboolean +Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIILjava_lang_StringBuilder_2( + JNIEnv* env, jobject, jlong jdb_handle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, jobject jstring_builder) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto& read_options = + *reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + bool has_exception = false; + return key_may_exist_helper(env, db, read_options, nullptr, jkey, jkey_off, + jkey_len, jstring_builder, &has_exception); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: keyMayExist + * Signature: (JJ[BIIJLjava/lang/StringBuilder;)Z + */ +jboolean +Java_org_rocksdb_RocksDB_keyMayExist__JJ_3BIIJLjava_lang_StringBuilder_2( + JNIEnv* env, jobject, jlong jdb_handle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_off, jint jkey_len, jlong jcf_handle, + jobject jstring_builder) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto& read_options = + *reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + if (cf_handle != nullptr) { + bool has_exception = false; + return key_may_exist_helper(env, db, read_options, cf_handle, jkey, + jkey_off, jkey_len, jstring_builder, &has_exception); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle.")); + return true; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: iterator + * Signature: (J)J + */ +jlong Java_org_rocksdb_RocksDB_iterator__J( + JNIEnv*, jobject, jlong db_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + return rocksdb_iterator_helper(db, rocksdb::ReadOptions(), nullptr); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: iterator + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_RocksDB_iterator__JJ( + JNIEnv*, jobject, jlong db_handle, jlong jread_options_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto& read_options = + *reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + return rocksdb_iterator_helper(db, read_options, nullptr); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: iteratorCF + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_RocksDB_iteratorCF__JJ( + JNIEnv*, jobject, jlong db_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + return rocksdb_iterator_helper(db, rocksdb::ReadOptions(), cf_handle); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: iteratorCF + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_RocksDB_iteratorCF__JJJ( + JNIEnv*, jobject, + jlong db_handle, jlong jcf_handle, jlong jread_options_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + auto& read_options = + *reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + return rocksdb_iterator_helper(db, read_options, cf_handle); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: iterators + * Signature: (J[JJ)[J + */ +jlongArray Java_org_rocksdb_RocksDB_iterators( + JNIEnv* env, jobject, jlong db_handle, + jlongArray jcolumn_family_handles, + jlong jread_options_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto& read_options = + *reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + if (jcolumn_family_handles != nullptr) { + const jsize len_cols = env->GetArrayLength(jcolumn_family_handles); + jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr); + if (jcfh == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + for (jsize i = 0; i < len_cols; i++) { + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcfh[i]); + cf_handles.push_back(cf_handle); + } + + env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT); + } + + std::vector<rocksdb::Iterator*> iterators; + rocksdb::Status s = db->NewIterators(read_options, cf_handles, &iterators); + if (s.ok()) { + jlongArray jLongArray = + env->NewLongArray(static_cast<jsize>(iterators.size())); + if (jLongArray == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + for (std::vector<rocksdb::Iterator*>::size_type i = 0; i < iterators.size(); + i++) { + env->SetLongArrayRegion( + jLongArray, static_cast<jsize>(i), 1, + const_cast<jlong*>(reinterpret_cast<const jlong*>(&iterators[i]))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jLongArray); + return nullptr; + } + } + + return jLongArray; + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } +} + +/* + * Method: getSnapshot + * Signature: (J)J + */ +jlong Java_org_rocksdb_RocksDB_getSnapshot( + JNIEnv*, jobject, jlong db_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + const rocksdb::Snapshot* snapshot = db->GetSnapshot(); + return reinterpret_cast<jlong>(snapshot); +} + +/* + * Method: releaseSnapshot + * Signature: (JJ)V + */ +void Java_org_rocksdb_RocksDB_releaseSnapshot( + JNIEnv*, jobject, jlong db_handle, + jlong snapshot_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + auto* snapshot = reinterpret_cast<rocksdb::Snapshot*>(snapshot_handle); + db->ReleaseSnapshot(snapshot); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getProperty + * Signature: (JJLjava/lang/String;I)Ljava/lang/String; + */ +jstring Java_org_rocksdb_RocksDB_getProperty( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jstring jproperty, jint jproperty_len) { + const char* property = env->GetStringUTFChars(jproperty, nullptr); + if (property == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + rocksdb::Slice property_name(property, jproperty_len); + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + std::string property_value; + bool retCode = db->GetProperty(cf_handle, property_name, &property_value); + env->ReleaseStringUTFChars(jproperty, property); + + if (retCode) { + return env->NewStringUTF(property_value.c_str()); + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotFound()); + return nullptr; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getMapProperty + * Signature: (JJLjava/lang/String;I)Ljava/util/Map; + */ +jobject Java_org_rocksdb_RocksDB_getMapProperty( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jstring jproperty, jint jproperty_len) { + const char* property = env->GetStringUTFChars(jproperty, nullptr); + if (property == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + rocksdb::Slice property_name(property, jproperty_len); + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + std::map<std::string, std::string> property_value; + bool retCode = db->GetMapProperty(cf_handle, property_name, &property_value); + env->ReleaseStringUTFChars(jproperty, property); + + if (retCode) { + return rocksdb::HashMapJni::fromCppMap(env, &property_value); + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotFound()); + return nullptr; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getLongProperty + * Signature: (JJLjava/lang/String;I)J + */ +jlong Java_org_rocksdb_RocksDB_getLongProperty( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jstring jproperty, jint jproperty_len) { + const char* property = env->GetStringUTFChars(jproperty, nullptr); + if (property == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + rocksdb::Slice property_name(property, jproperty_len); + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + uint64_t property_value; + bool retCode = db->GetIntProperty(cf_handle, property_name, &property_value); + env->ReleaseStringUTFChars(jproperty, property); + + if (retCode) { + return property_value; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotFound()); + return 0; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: resetStats + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_resetStats( + JNIEnv *, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + db->ResetStats(); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getAggregatedLongProperty + * Signature: (JLjava/lang/String;I)J + */ +jlong Java_org_rocksdb_RocksDB_getAggregatedLongProperty( + JNIEnv* env, jobject, jlong db_handle, + jstring jproperty, jint jproperty_len) { + const char* property = env->GetStringUTFChars(jproperty, nullptr); + if (property == nullptr) { + return 0; + } + rocksdb::Slice property_name(property, jproperty_len); + auto* db = reinterpret_cast<rocksdb::DB*>(db_handle); + uint64_t property_value = 0; + bool retCode = db->GetAggregatedIntProperty(property_name, &property_value); + env->ReleaseStringUTFChars(jproperty, property); + + if (retCode) { + return property_value; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotFound()); + return 0; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getApproximateSizes + * Signature: (JJ[JB)[J + */ +jlongArray Java_org_rocksdb_RocksDB_getApproximateSizes( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jlongArray jrange_slice_handles, jbyte jinclude_flags) { + const jsize jlen = env->GetArrayLength(jrange_slice_handles); + const size_t range_count = jlen / 2; + + jboolean jranges_is_copy = JNI_FALSE; + jlong* jranges = env->GetLongArrayElements(jrange_slice_handles, + &jranges_is_copy); + if (jranges == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + auto ranges = std::unique_ptr<rocksdb::Range[]>( + new rocksdb::Range[range_count]); + for (jsize i = 0; i < jlen; ++i) { + auto* start = reinterpret_cast<rocksdb::Slice*>(jranges[i]); + auto* limit = reinterpret_cast<rocksdb::Slice*>(jranges[++i]); + ranges.get()[i] = rocksdb::Range(*start, *limit); + } + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + auto sizes = std::unique_ptr<uint64_t[]>(new uint64_t[range_count]); + db->GetApproximateSizes(cf_handle, ranges.get(), + static_cast<int>(range_count), sizes.get(), + static_cast<uint8_t>(jinclude_flags)); + + // release LongArrayElements + env->ReleaseLongArrayElements(jrange_slice_handles, jranges, JNI_ABORT); + + // prepare results + auto results = std::unique_ptr<jlong[]>(new jlong[range_count]); + for (size_t i = 0; i < range_count; ++i) { + results.get()[i] = static_cast<jlong>(sizes.get()[i]); + } + + const jsize jrange_count = jlen / 2; + jlongArray jresults = env->NewLongArray(jrange_count); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetLongArrayRegion(jresults, 0, jrange_count, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jresults); + return nullptr; + } + + return jresults; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getApproximateMemTableStats + * Signature: (JJJJ)[J + */ +jlongArray Java_org_rocksdb_RocksDB_getApproximateMemTableStats( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jlong jstartHandle, jlong jlimitHandle) { + auto* start = reinterpret_cast<rocksdb::Slice*>(jstartHandle); + auto* limit = reinterpret_cast<rocksdb::Slice*>( jlimitHandle); + const rocksdb::Range range(*start, *limit); + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + uint64_t count = 0; + uint64_t sizes = 0; + db->GetApproximateMemTableStats(cf_handle, range, &count, &sizes); + + // prepare results + jlong results[2] = { + static_cast<jlong>(count), + static_cast<jlong>(sizes)}; + + const jsize jcount = static_cast<jsize>(count); + jlongArray jsizes = env->NewLongArray(jcount); + if (jsizes == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetLongArrayRegion(jsizes, 0, jcount, results); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jsizes); + return nullptr; + } + + return jsizes; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: compactRange + * Signature: (J[BI[BIJJ)V + */ +void Java_org_rocksdb_RocksDB_compactRange( + JNIEnv* env, jobject, jlong jdb_handle, + jbyteArray jbegin, jint jbegin_len, + jbyteArray jend, jint jend_len, + jlong jcompact_range_opts_handle, + jlong jcf_handle) { + jboolean has_exception = JNI_FALSE; + + std::string str_begin; + if (jbegin_len > 0) { + str_begin = rocksdb::JniUtil::byteString<std::string>(env, jbegin, jbegin_len, + [](const char* str, const size_t len) { + return std::string(str, len); + }, + &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + } + + std::string str_end; + if (jend_len > 0) { + str_end = rocksdb::JniUtil::byteString<std::string>(env, jend, jend_len, + [](const char* str, const size_t len) { + return std::string(str, len); + }, + &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + } + + rocksdb::CompactRangeOptions *compact_range_opts = nullptr; + if (jcompact_range_opts_handle == 0) { + // NOTE: we DO own the pointer! + compact_range_opts = new rocksdb::CompactRangeOptions(); + } else { + // NOTE: we do NOT own the pointer! + compact_range_opts = + reinterpret_cast<rocksdb::CompactRangeOptions*>(jcompact_range_opts_handle); + } + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + rocksdb::Status s; + if (jbegin_len > 0 || jend_len > 0) { + const rocksdb::Slice begin(str_begin); + const rocksdb::Slice end(str_end); + s = db->CompactRange(*compact_range_opts, cf_handle, &begin, &end); + } else { + s = db->CompactRange(*compact_range_opts, cf_handle, nullptr, nullptr); + } + + if (jcompact_range_opts_handle == 0) { + delete compact_range_opts; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: setOptions + * Signature: (JJ[Ljava/lang/String;[Ljava/lang/String;)V + */ +void Java_org_rocksdb_RocksDB_setOptions( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jobjectArray jkeys, jobjectArray jvalues) { + const jsize len = env->GetArrayLength(jkeys); + assert(len == env->GetArrayLength(jvalues)); + + std::unordered_map<std::string, std::string> options_map; + for (jsize i = 0; i < len; i++) { + jobject jobj_key = env->GetObjectArrayElement(jkeys, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return; + } + + jobject jobj_value = env->GetObjectArrayElement(jvalues, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jobj_key); + return; + } + + jboolean has_exception = JNI_FALSE; + std::string s_key = + rocksdb::JniUtil::copyStdString( + env, reinterpret_cast<jstring>(jobj_key), &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + env->DeleteLocalRef(jobj_value); + env->DeleteLocalRef(jobj_key); + return; + } + + std::string s_value = + rocksdb::JniUtil::copyStdString( + env, reinterpret_cast<jstring>(jobj_value), &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + env->DeleteLocalRef(jobj_value); + env->DeleteLocalRef(jobj_key); + return; + } + + options_map[s_key] = s_value; + + env->DeleteLocalRef(jobj_key); + env->DeleteLocalRef(jobj_value); + } + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + auto s = db->SetOptions(cf_handle, options_map); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: setDBOptions + * Signature: (J[Ljava/lang/String;[Ljava/lang/String;)V + */ +void Java_org_rocksdb_RocksDB_setDBOptions( + JNIEnv* env, jobject, jlong jdb_handle, + jobjectArray jkeys, jobjectArray jvalues) { + const jsize len = env->GetArrayLength(jkeys); + assert(len == env->GetArrayLength(jvalues)); + + std::unordered_map<std::string, std::string> options_map; + for (jsize i = 0; i < len; i++) { + jobject jobj_key = env->GetObjectArrayElement(jkeys, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return; + } + + jobject jobj_value = env->GetObjectArrayElement(jvalues, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jobj_key); + return; + } + + jboolean has_exception = JNI_FALSE; + std::string s_key = + rocksdb::JniUtil::copyStdString( + env, reinterpret_cast<jstring>(jobj_key), &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + env->DeleteLocalRef(jobj_value); + env->DeleteLocalRef(jobj_key); + return; + } + + std::string s_value = + rocksdb::JniUtil::copyStdString( + env, reinterpret_cast<jstring>(jobj_value), &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + env->DeleteLocalRef(jobj_value); + env->DeleteLocalRef(jobj_key); + return; + } + + options_map[s_key] = s_value; + + env->DeleteLocalRef(jobj_key); + env->DeleteLocalRef(jobj_value); + } + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->SetDBOptions(options_map); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: compactFiles + * Signature: (JJJ[Ljava/lang/String;IIJ)[Ljava/lang/String; + */ +jobjectArray Java_org_rocksdb_RocksDB_compactFiles( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcompaction_opts_handle, + jlong jcf_handle, jobjectArray jinput_file_names, jint joutput_level, + jint joutput_path_id, jlong jcompaction_job_info_handle) { + jboolean has_exception = JNI_FALSE; + const std::vector<std::string> input_file_names = + rocksdb::JniUtil::copyStrings(env, jinput_file_names, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return nullptr; + } + + auto* compaction_opts = + reinterpret_cast<rocksdb::CompactionOptions*>(jcompaction_opts_handle); + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + + rocksdb::CompactionJobInfo* compaction_job_info = nullptr; + if (jcompaction_job_info_handle != 0) { + compaction_job_info = + reinterpret_cast<rocksdb::CompactionJobInfo*>(jcompaction_job_info_handle); + } + + std::vector<std::string> output_file_names; + auto s = db->CompactFiles(*compaction_opts, cf_handle, input_file_names, + static_cast<int>(joutput_level), static_cast<int>(joutput_path_id), + &output_file_names, compaction_job_info); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + return rocksdb::JniUtil::toJavaStrings(env, &output_file_names); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: pauseBackgroundWork + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_pauseBackgroundWork( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->PauseBackgroundWork(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: continueBackgroundWork + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_continueBackgroundWork( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->ContinueBackgroundWork(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: enableAutoCompaction + * Signature: (J[J)V + */ +void Java_org_rocksdb_RocksDB_enableAutoCompaction( + JNIEnv* env, jobject, jlong jdb_handle, jlongArray jcf_handles) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + jboolean has_exception = JNI_FALSE; + const std::vector<rocksdb::ColumnFamilyHandle*> cf_handles = + rocksdb::JniUtil::fromJPointers<rocksdb::ColumnFamilyHandle>(env, jcf_handles, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + db->EnableAutoCompaction(cf_handles); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: numberLevels + * Signature: (JJ)I + */ +jint Java_org_rocksdb_RocksDB_numberLevels( + JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + return static_cast<jint>(db->NumberLevels(cf_handle)); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: maxMemCompactionLevel + * Signature: (JJ)I + */ +jint Java_org_rocksdb_RocksDB_maxMemCompactionLevel( + JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + return static_cast<jint>(db->MaxMemCompactionLevel(cf_handle)); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: level0StopWriteTrigger + * Signature: (JJ)I + */ +jint Java_org_rocksdb_RocksDB_level0StopWriteTrigger( + JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + return static_cast<jint>(db->Level0StopWriteTrigger(cf_handle)); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getName + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_RocksDB_getName( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + std::string name = db->GetName(); + return rocksdb::JniUtil::toJavaString(env, &name, false); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getEnv + * Signature: (J)J + */ +jlong Java_org_rocksdb_RocksDB_getEnv( + JNIEnv*, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + return reinterpret_cast<jlong>(db->GetEnv()); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: flush + * Signature: (JJ[J)V + */ +void Java_org_rocksdb_RocksDB_flush( + JNIEnv* env, jobject, jlong jdb_handle, jlong jflush_opts_handle, + jlongArray jcf_handles) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* flush_opts = + reinterpret_cast<rocksdb::FlushOptions*>(jflush_opts_handle); + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + if (jcf_handles == nullptr) { + cf_handles.push_back(db->DefaultColumnFamily()); + } else { + jboolean has_exception = JNI_FALSE; + cf_handles = + rocksdb::JniUtil::fromJPointers<rocksdb::ColumnFamilyHandle>( + env, jcf_handles, &has_exception); + if (has_exception) { + // exception occurred + return; + } + } + auto s = db->Flush(*flush_opts, cf_handles); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: flushWal + * Signature: (JZ)V + */ +void Java_org_rocksdb_RocksDB_flushWal( + JNIEnv* env, jobject, jlong jdb_handle, jboolean jsync) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->FlushWAL(jsync == JNI_TRUE); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: syncWal + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_syncWal( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->SyncWAL(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getLatestSequenceNumber + * Signature: (J)V + */ +jlong Java_org_rocksdb_RocksDB_getLatestSequenceNumber( + JNIEnv*, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + return db->GetLatestSequenceNumber(); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: setPreserveDeletesSequenceNumber + * Signature: (JJ)Z + */ +jboolean JNICALL Java_org_rocksdb_RocksDB_setPreserveDeletesSequenceNumber( + JNIEnv*, jobject, jlong jdb_handle, jlong jseq_number) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + if (db->SetPreserveDeletesSequenceNumber( + static_cast<uint64_t>(jseq_number))) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: disableFileDeletions + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_disableFileDeletions( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::Status s = db->DisableFileDeletions(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: enableFileDeletions + * Signature: (JZ)V + */ +void Java_org_rocksdb_RocksDB_enableFileDeletions( + JNIEnv* env, jobject, jlong jdb_handle, jboolean jforce) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::Status s = db->EnableFileDeletions(jforce); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getLiveFiles + * Signature: (JZ)[Ljava/lang/String; + */ +jobjectArray Java_org_rocksdb_RocksDB_getLiveFiles( + JNIEnv* env, jobject, jlong jdb_handle, jboolean jflush_memtable) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + std::vector<std::string> live_files; + uint64_t manifest_file_size = 0; + auto s = db->GetLiveFiles( + live_files, &manifest_file_size, jflush_memtable == JNI_TRUE); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + // append the manifest_file_size to the vector + // for passing back to java + live_files.push_back(std::to_string(manifest_file_size)); + + return rocksdb::JniUtil::toJavaStrings(env, &live_files); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getSortedWalFiles + * Signature: (J)[Lorg/rocksdb/LogFile; + */ +jobjectArray Java_org_rocksdb_RocksDB_getSortedWalFiles( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + std::vector<std::unique_ptr<rocksdb::LogFile>> sorted_wal_files; + auto s = db->GetSortedWalFiles(sorted_wal_files); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + // convert to Java type + const jsize jlen = static_cast<jsize>(sorted_wal_files.size()); + jobjectArray jsorted_wal_files = env->NewObjectArray( + jlen, rocksdb::LogFileJni::getJClass(env), nullptr); + if(jsorted_wal_files == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jsize i = 0; + for (auto it = sorted_wal_files.begin(); it != sorted_wal_files.end(); ++it) { + jobject jlog_file = rocksdb::LogFileJni::fromCppLogFile(env, it->get()); + if (jlog_file == nullptr) { + // exception occurred + env->DeleteLocalRef(jsorted_wal_files); + return nullptr; + } + + env->SetObjectArrayElement(jsorted_wal_files, i++, jlog_file); + if (env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(jlog_file); + env->DeleteLocalRef(jsorted_wal_files); + return nullptr; + } + + env->DeleteLocalRef(jlog_file); + } + + return jsorted_wal_files; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getUpdatesSince + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_RocksDB_getUpdatesSince( + JNIEnv* env, jobject, jlong jdb_handle, jlong jsequence_number) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::SequenceNumber sequence_number = + static_cast<rocksdb::SequenceNumber>(jsequence_number); + std::unique_ptr<rocksdb::TransactionLogIterator> iter; + rocksdb::Status s = db->GetUpdatesSince(sequence_number, &iter); + if (s.ok()) { + return reinterpret_cast<jlong>(iter.release()); + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: deleteFile + * Signature: (JLjava/lang/String;)V + */ +void Java_org_rocksdb_RocksDB_deleteFile( + JNIEnv* env, jobject, jlong jdb_handle, jstring jname) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + jboolean has_exception = JNI_FALSE; + std::string name = + rocksdb::JniUtil::copyStdString(env, jname, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + db->DeleteFile(name); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getLiveFilesMetaData + * Signature: (J)[Lorg/rocksdb/LiveFileMetaData; + */ +jobjectArray Java_org_rocksdb_RocksDB_getLiveFilesMetaData( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + std::vector<rocksdb::LiveFileMetaData> live_files_meta_data; + db->GetLiveFilesMetaData(&live_files_meta_data); + + // convert to Java type + const jsize jlen = static_cast<jsize>(live_files_meta_data.size()); + jobjectArray jlive_files_meta_data = env->NewObjectArray( + jlen, rocksdb::LiveFileMetaDataJni::getJClass(env), nullptr); + if(jlive_files_meta_data == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + jsize i = 0; + for (auto it = live_files_meta_data.begin(); it != live_files_meta_data.end(); ++it) { + jobject jlive_file_meta_data = + rocksdb::LiveFileMetaDataJni::fromCppLiveFileMetaData(env, &(*it)); + if (jlive_file_meta_data == nullptr) { + // exception occurred + env->DeleteLocalRef(jlive_files_meta_data); + return nullptr; + } + + env->SetObjectArrayElement(jlive_files_meta_data, i++, jlive_file_meta_data); + if (env->ExceptionCheck()) { + // exception occurred + env->DeleteLocalRef(jlive_file_meta_data); + env->DeleteLocalRef(jlive_files_meta_data); + return nullptr; + } + + env->DeleteLocalRef(jlive_file_meta_data); + } + + return jlive_files_meta_data; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getColumnFamilyMetaData + * Signature: (JJ)Lorg/rocksdb/ColumnFamilyMetaData; + */ +jobject Java_org_rocksdb_RocksDB_getColumnFamilyMetaData( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + rocksdb::ColumnFamilyMetaData cf_metadata; + db->GetColumnFamilyMetaData(cf_handle, &cf_metadata); + return rocksdb::ColumnFamilyMetaDataJni::fromCppColumnFamilyMetaData( + env, &cf_metadata); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: ingestExternalFile + * Signature: (JJ[Ljava/lang/String;IJ)V + */ +void Java_org_rocksdb_RocksDB_ingestExternalFile( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jobjectArray jfile_path_list, jint jfile_path_list_len, + jlong jingest_external_file_options_handle) { + jboolean has_exception = JNI_FALSE; + std::vector<std::string> file_path_list = rocksdb::JniUtil::copyStrings( + env, jfile_path_list, jfile_path_list_len, &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return; + } + + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* column_family = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + auto* ifo = reinterpret_cast<rocksdb::IngestExternalFileOptions*>( + jingest_external_file_options_handle); + rocksdb::Status s = + db->IngestExternalFile(column_family, file_path_list, *ifo); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: verifyChecksum + * Signature: (J)V + */ +void Java_org_rocksdb_RocksDB_verifyChecksum( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->VerifyChecksum(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getDefaultColumnFamily + * Signature: (J)J + */ +jlong Java_org_rocksdb_RocksDB_getDefaultColumnFamily( + JNIEnv*, jobject, jlong jdb_handle) { + auto* db_handle = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* cf_handle = db_handle->DefaultColumnFamily(); + return reinterpret_cast<jlong>(cf_handle); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getPropertiesOfAllTables + * Signature: (JJ)Ljava/util/Map; + */ +jobject Java_org_rocksdb_RocksDB_getPropertiesOfAllTables( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + rocksdb::TablePropertiesCollection table_properties_collection; + auto s = db->GetPropertiesOfAllTables(cf_handle, + &table_properties_collection); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } + + // convert to Java type + jobject jhash_map = rocksdb::HashMapJni::construct( + env, static_cast<uint32_t>(table_properties_collection.size())); + if (jhash_map == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, const std::shared_ptr<const rocksdb::TableProperties>, jobject, jobject> fn_map_kv = + [env](const std::pair<const std::string, const std::shared_ptr<const rocksdb::TableProperties>>& kv) { + jstring jkey = rocksdb::JniUtil::toJavaString(env, &(kv.first), false); + if (env->ExceptionCheck()) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + jobject jtable_properties = rocksdb::TablePropertiesJni::fromCppTableProperties(env, *(kv.second.get())); + if (jtable_properties == nullptr) { + // an error occurred + env->DeleteLocalRef(jkey); + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + + return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(static_cast<jobject>(jkey), static_cast<jobject>(jtable_properties))); + }; + + if (!rocksdb::HashMapJni::putAll(env, jhash_map, table_properties_collection.begin(), table_properties_collection.end(), fn_map_kv)) { + // exception occurred + return nullptr; + } + + return jhash_map; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: getPropertiesOfTablesInRange + * Signature: (JJ[J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_RocksDB_getPropertiesOfTablesInRange( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle, + jlongArray jrange_slice_handles) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + const jsize jlen = env->GetArrayLength(jrange_slice_handles); + jboolean jrange_slice_handles_is_copy = JNI_FALSE; + jlong *jrange_slice_handle = env->GetLongArrayElements( + jrange_slice_handles, &jrange_slice_handles_is_copy); + if (jrange_slice_handle == nullptr) { + // exception occurred + return nullptr; + } + + const size_t ranges_len = static_cast<size_t>(jlen / 2); + auto ranges = std::unique_ptr<rocksdb::Range[]>(new rocksdb::Range[ranges_len]); + for (jsize i = 0, j = 0; i < jlen; ++i) { + auto* start = reinterpret_cast<rocksdb::Slice*>( + jrange_slice_handle[i]); + auto* limit = reinterpret_cast<rocksdb::Slice*>( + jrange_slice_handle[++i]); + ranges[j++] = rocksdb::Range(*start, *limit); + } + + rocksdb::TablePropertiesCollection table_properties_collection; + auto s = db->GetPropertiesOfTablesInRange( + cf_handle, ranges.get(), ranges_len, &table_properties_collection); + if (!s.ok()) { + // error occurred + env->ReleaseLongArrayElements(jrange_slice_handles, jrange_slice_handle, JNI_ABORT); + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + // cleanup + env->ReleaseLongArrayElements(jrange_slice_handles, jrange_slice_handle, JNI_ABORT); + + return jrange_slice_handles; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: suggestCompactRange + * Signature: (JJ)[J + */ +jlongArray Java_org_rocksdb_RocksDB_suggestCompactRange( + JNIEnv* env, jobject, jlong jdb_handle, jlong jcf_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + auto* begin = new rocksdb::Slice(); + auto* end = new rocksdb::Slice(); + auto s = db->SuggestCompactRange(cf_handle, begin, end); + if (!s.ok()) { + // error occurred + delete begin; + delete end; + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } + + jlongArray jslice_handles = env->NewLongArray(2); + if (jslice_handles == nullptr) { + // exception thrown: OutOfMemoryError + delete begin; + delete end; + return nullptr; + } + + jlong slice_handles[2]; + slice_handles[0] = reinterpret_cast<jlong>(begin); + slice_handles[1] = reinterpret_cast<jlong>(end); + env->SetLongArrayRegion(jslice_handles, 0, 2, slice_handles); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + delete begin; + delete end; + env->DeleteLocalRef(jslice_handles); + return nullptr; + } + + return jslice_handles; +} + +/* + * Class: org_rocksdb_RocksDB + * Method: promoteL0 + * Signature: (JJI)V + */ +void Java_org_rocksdb_RocksDB_promoteL0( + JNIEnv*, jobject, jlong jdb_handle, jlong jcf_handle, jint jtarget_level) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::ColumnFamilyHandle* cf_handle; + if (jcf_handle == 0) { + cf_handle = db->DefaultColumnFamily(); + } else { + cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + } + db->PromoteL0(cf_handle, static_cast<int>(jtarget_level)); +} + +/* + * Class: org_rocksdb_RocksDB + * Method: startTrace + * Signature: (JJJ)V + */ +void Java_org_rocksdb_RocksDB_startTrace( + JNIEnv* env, jobject, jlong jdb_handle, jlong jmax_trace_file_size, + jlong jtrace_writer_jnicallback_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + rocksdb::TraceOptions trace_options; + trace_options.max_trace_file_size = + static_cast<uint64_t>(jmax_trace_file_size); + // transfer ownership of trace writer from Java to C++ + auto trace_writer = std::unique_ptr<rocksdb::TraceWriterJniCallback>( + reinterpret_cast<rocksdb::TraceWriterJniCallback*>( + jtrace_writer_jnicallback_handle)); + auto s = db->StartTrace(trace_options, std::move(trace_writer)); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: endTrace + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_rocksdb_RocksDB_endTrace( + JNIEnv* env, jobject, jlong jdb_handle) { + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto s = db->EndTrace(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RocksDB + * Method: destroyDB + * Signature: (Ljava/lang/String;J)V + */ +void Java_org_rocksdb_RocksDB_destroyDB( + JNIEnv* env, jclass, jstring jdb_path, jlong joptions_handle) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + auto* options = reinterpret_cast<rocksdb::Options*>(joptions_handle); + if (options == nullptr) { + rocksdb::RocksDBExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Invalid Options.")); + } + + rocksdb::Status s = rocksdb::DestroyDB(db_path, *options); + env->ReleaseStringUTFChars(jdb_path, db_path); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} diff --git a/src/rocksdb/java/rocksjni/slice.cc b/src/rocksdb/java/rocksjni/slice.cc new file mode 100644 index 00000000..e617cde2 --- /dev/null +++ b/src/rocksdb/java/rocksjni/slice.cc @@ -0,0 +1,356 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::Slice. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include "include/org_rocksdb_AbstractSlice.h" +#include "include/org_rocksdb_DirectSlice.h" +#include "include/org_rocksdb_Slice.h" +#include "rocksdb/slice.h" +#include "rocksjni/portal.h" + +// <editor-fold desc="org.rocksdb.AbstractSlice> + +/* + * Class: org_rocksdb_AbstractSlice + * Method: createNewSliceFromString + * Signature: (Ljava/lang/String;)J + */ +jlong Java_org_rocksdb_AbstractSlice_createNewSliceFromString(JNIEnv* env, + jclass /*jcls*/, + jstring jstr) { + const auto* str = env->GetStringUTFChars(jstr, nullptr); + if (str == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + const size_t len = strlen(str); + + // NOTE: buf will be deleted in the + // Java_org_rocksdb_Slice_disposeInternalBuf or + // or Java_org_rocksdb_DirectSlice_disposeInternalBuf methods + char* buf = new char[len + 1]; + memcpy(buf, str, len); + buf[len] = 0; + env->ReleaseStringUTFChars(jstr, str); + + const auto* slice = new rocksdb::Slice(buf); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: size0 + * Signature: (J)I + */ +jint Java_org_rocksdb_AbstractSlice_size0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return static_cast<jint>(slice->size()); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: empty0 + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_AbstractSlice_empty0(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return slice->empty(); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: toString0 + * Signature: (JZ)Ljava/lang/String; + */ +jstring Java_org_rocksdb_AbstractSlice_toString0(JNIEnv* env, jobject /*jobj*/, + jlong handle, jboolean hex) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const std::string s = slice->ToString(hex); + return env->NewStringUTF(s.c_str()); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: compare0 + * Signature: (JJ)I; + */ +jint Java_org_rocksdb_AbstractSlice_compare0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jlong otherHandle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const auto* otherSlice = reinterpret_cast<rocksdb::Slice*>(otherHandle); + return slice->compare(*otherSlice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: startsWith0 + * Signature: (JJ)Z; + */ +jboolean Java_org_rocksdb_AbstractSlice_startsWith0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle, + jlong otherHandle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const auto* otherSlice = reinterpret_cast<rocksdb::Slice*>(otherHandle); + return slice->starts_with(*otherSlice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_AbstractSlice_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + delete reinterpret_cast<rocksdb::Slice*>(handle); +} + +// </editor-fold> + +// <editor-fold desc="org.rocksdb.Slice> + +/* + * Class: org_rocksdb_Slice + * Method: createNewSlice0 + * Signature: ([BI)J + */ +jlong Java_org_rocksdb_Slice_createNewSlice0(JNIEnv* env, jclass /*jcls*/, + jbyteArray data, jint offset) { + const jsize dataSize = env->GetArrayLength(data); + const int len = dataSize - offset; + + // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf + // method + jbyte* buf = new jbyte[len]; + env->GetByteArrayRegion(data, offset, len, buf); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return 0; + } + + const auto* slice = new rocksdb::Slice((const char*)buf, len); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_Slice + * Method: createNewSlice1 + * Signature: ([B)J + */ +jlong Java_org_rocksdb_Slice_createNewSlice1(JNIEnv* env, jclass /*jcls*/, + jbyteArray data) { + jbyte* ptrData = env->GetByteArrayElements(data, nullptr); + if (ptrData == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + const int len = env->GetArrayLength(data) + 1; + + // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf + // method + char* buf = new char[len]; + memcpy(buf, ptrData, len - 1); + buf[len - 1] = '\0'; + + const auto* slice = new rocksdb::Slice(buf, len - 1); + + env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT); + + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_Slice + * Method: data0 + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_Slice_data0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const jsize len = static_cast<jsize>(slice->size()); + const jbyteArray data = env->NewByteArray(len); + if (data == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + data, 0, len, + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(slice->data()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(data); + return nullptr; + } + + return data; +} + +/* + * Class: org_rocksdb_Slice + * Method: clear0 + * Signature: (JZJ)V + */ +void Java_org_rocksdb_Slice_clear0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jboolean shouldRelease, + jlong internalBufferOffset) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + if (shouldRelease == JNI_TRUE) { + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; + } + slice->clear(); +} + +/* + * Class: org_rocksdb_Slice + * Method: removePrefix0 + * Signature: (JI)V + */ +void Java_org_rocksdb_Slice_removePrefix0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jint length) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + slice->remove_prefix(length); +} + +/* + * Class: org_rocksdb_Slice + * Method: disposeInternalBuf + * Signature: (JJ)V + */ +void Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle, + jlong internalBufferOffset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; +} + +// </editor-fold> + +// <editor-fold desc="org.rocksdb.DirectSlice> + +/* + * Class: org_rocksdb_DirectSlice + * Method: createNewDirectSlice0 + * Signature: (Ljava/nio/ByteBuffer;I)J + */ +jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv* env, + jclass /*jcls*/, + jobject data, + jint length) { + assert(data != nullptr); + void* data_addr = env->GetDirectBufferAddress(data); + if (data_addr == nullptr) { + // error: memory region is undefined, given object is not a direct + // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM + rocksdb::IllegalArgumentExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Could not access DirectBuffer")); + return 0; + } + + const auto* ptrData = reinterpret_cast<char*>(data_addr); + const auto* slice = new rocksdb::Slice(ptrData, length); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: createNewDirectSlice1 + * Signature: (Ljava/nio/ByteBuffer;)J + */ +jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv* env, + jclass /*jcls*/, + jobject data) { + void* data_addr = env->GetDirectBufferAddress(data); + if (data_addr == nullptr) { + // error: memory region is undefined, given object is not a direct + // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM + rocksdb::IllegalArgumentExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Could not access DirectBuffer")); + return 0; + } + + const auto* ptrData = reinterpret_cast<char*>(data_addr); + const auto* slice = new rocksdb::Slice(ptrData); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: data0 + * Signature: (J)Ljava/lang/Object; + */ +jobject Java_org_rocksdb_DirectSlice_data0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return env->NewDirectByteBuffer(const_cast<char*>(slice->data()), + slice->size()); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: get0 + * Signature: (JI)B + */ +jbyte Java_org_rocksdb_DirectSlice_get0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jint offset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return (*slice)[offset]; +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: clear0 + * Signature: (JZJ)V + */ +void Java_org_rocksdb_DirectSlice_clear0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jboolean shouldRelease, + jlong internalBufferOffset) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + if (shouldRelease == JNI_TRUE) { + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; + } + slice->clear(); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: removePrefix0 + * Signature: (JI)V + */ +void Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle, + jint length) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + slice->remove_prefix(length); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: disposeInternalBuf + * Signature: (JJ)V + */ +void Java_org_rocksdb_DirectSlice_disposeInternalBuf( + JNIEnv* /*env*/, jobject /*jobj*/, jlong handle, + jlong internalBufferOffset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; +} + +// </editor-fold> diff --git a/src/rocksdb/java/rocksjni/snapshot.cc b/src/rocksdb/java/rocksjni/snapshot.cc new file mode 100644 index 00000000..679271db --- /dev/null +++ b/src/rocksdb/java/rocksjni/snapshot.cc @@ -0,0 +1,26 @@ +// 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 "bridge" between Java and C++. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> + +#include "include/org_rocksdb_Snapshot.h" +#include "rocksdb/db.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_Snapshot + * Method: getSequenceNumber + * Signature: (J)J + */ +jlong Java_org_rocksdb_Snapshot_getSequenceNumber(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jsnapshot_handle) { + auto* snapshot = reinterpret_cast<rocksdb::Snapshot*>(jsnapshot_handle); + return snapshot->GetSequenceNumber(); +} diff --git a/src/rocksdb/java/rocksjni/sst_file_manager.cc b/src/rocksdb/java/rocksjni/sst_file_manager.cc new file mode 100644 index 00000000..3df3c996 --- /dev/null +++ b/src/rocksdb/java/rocksjni/sst_file_manager.cc @@ -0,0 +1,232 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::SstFileManager methods +// from Java side. + +#include <jni.h> +#include <memory> + +#include "include/org_rocksdb_SstFileManager.h" +#include "rocksdb/sst_file_manager.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_SstFileManager + * Method: newSstFileManager + * Signature: (JJJDJ)J + */ +jlong Java_org_rocksdb_SstFileManager_newSstFileManager( + JNIEnv* jnienv, jclass /*jcls*/, jlong jenv_handle, jlong jlogger_handle, + jlong jrate_bytes, jdouble jmax_trash_db_ratio, + jlong jmax_delete_chunk_bytes) { + auto* env = reinterpret_cast<rocksdb::Env*>(jenv_handle); + rocksdb::Status s; + rocksdb::SstFileManager* sst_file_manager = nullptr; + + if (jlogger_handle != 0) { + auto* sptr_logger = + reinterpret_cast<std::shared_ptr<rocksdb::Logger>*>(jlogger_handle); + sst_file_manager = rocksdb::NewSstFileManager( + env, *sptr_logger, "", jrate_bytes, true, &s, jmax_trash_db_ratio, + jmax_delete_chunk_bytes); + } else { + sst_file_manager = rocksdb::NewSstFileManager(env, nullptr, "", jrate_bytes, + true, &s, jmax_trash_db_ratio, + jmax_delete_chunk_bytes); + } + + if (!s.ok()) { + if (sst_file_manager != nullptr) { + delete sst_file_manager; + } + rocksdb::RocksDBExceptionJni::ThrowNew(jnienv, s); + } + auto* sptr_sst_file_manager = + new std::shared_ptr<rocksdb::SstFileManager>(sst_file_manager); + + return reinterpret_cast<jlong>(sptr_sst_file_manager); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: setMaxAllowedSpaceUsage + * Signature: (JJ)V + */ +void Java_org_rocksdb_SstFileManager_setMaxAllowedSpaceUsage( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jmax_allowed_space) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + sptr_sst_file_manager->get()->SetMaxAllowedSpaceUsage(jmax_allowed_space); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: setCompactionBufferSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_SstFileManager_setCompactionBufferSize( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jcompaction_buffer_size) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + sptr_sst_file_manager->get()->SetCompactionBufferSize( + jcompaction_buffer_size); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: isMaxAllowedSpaceReached + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_SstFileManager_isMaxAllowedSpaceReached( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + return sptr_sst_file_manager->get()->IsMaxAllowedSpaceReached(); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: isMaxAllowedSpaceReachedIncludingCompactions + * Signature: (J)Z + */ +jboolean +Java_org_rocksdb_SstFileManager_isMaxAllowedSpaceReachedIncludingCompactions( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + return sptr_sst_file_manager->get() + ->IsMaxAllowedSpaceReachedIncludingCompactions(); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: getTotalSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_SstFileManager_getTotalSize(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + return sptr_sst_file_manager->get()->GetTotalSize(); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: getTrackedFiles + * Signature: (J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_SstFileManager_getTrackedFiles(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + auto tracked_files = sptr_sst_file_manager->get()->GetTrackedFiles(); + + //TODO(AR) could refactor to share code with rocksdb::HashMapJni::fromCppMap(env, tracked_files); + + const jobject jtracked_files = rocksdb::HashMapJni::construct( + env, static_cast<uint32_t>(tracked_files.size())); + if (jtracked_files == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const std::string, const uint64_t, jobject, jobject> + fn_map_kv = + [env](const std::pair<const std::string, const uint64_t>& pair) { + const jstring jtracked_file_path = + env->NewStringUTF(pair.first.c_str()); + if (jtracked_file_path == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + const jobject jtracked_file_size = + rocksdb::LongJni::valueOf(env, pair.second); + if (jtracked_file_size == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + return std::unique_ptr<std::pair<jobject, jobject>>( + new std::pair<jobject, jobject>(jtracked_file_path, + jtracked_file_size)); + }; + + if (!rocksdb::HashMapJni::putAll(env, jtracked_files, tracked_files.begin(), + tracked_files.end(), fn_map_kv)) { + // exception occcurred + return nullptr; + } + + return jtracked_files; +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: getDeleteRateBytesPerSecond + * Signature: (J)J + */ +jlong Java_org_rocksdb_SstFileManager_getDeleteRateBytesPerSecond( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + return sptr_sst_file_manager->get()->GetDeleteRateBytesPerSecond(); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: setDeleteRateBytesPerSecond + * Signature: (JJ)V + */ +void Java_org_rocksdb_SstFileManager_setDeleteRateBytesPerSecond( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jlong jdelete_rate) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + sptr_sst_file_manager->get()->SetDeleteRateBytesPerSecond(jdelete_rate); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: getMaxTrashDBRatio + * Signature: (J)D + */ +jdouble Java_org_rocksdb_SstFileManager_getMaxTrashDBRatio(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + return sptr_sst_file_manager->get()->GetMaxTrashDBRatio(); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: setMaxTrashDBRatio + * Signature: (JD)V + */ +void Java_org_rocksdb_SstFileManager_setMaxTrashDBRatio(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jdouble jratio) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + sptr_sst_file_manager->get()->SetMaxTrashDBRatio(jratio); +} + +/* + * Class: org_rocksdb_SstFileManager + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_SstFileManager_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* sptr_sst_file_manager = + reinterpret_cast<std::shared_ptr<rocksdb::SstFileManager>*>(jhandle); + delete sptr_sst_file_manager; +} diff --git a/src/rocksdb/java/rocksjni/sst_file_writerjni.cc b/src/rocksdb/java/rocksjni/sst_file_writerjni.cc new file mode 100644 index 00000000..76212ed8 --- /dev/null +++ b/src/rocksdb/java/rocksjni/sst_file_writerjni.cc @@ -0,0 +1,268 @@ +// 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 "bridge" between Java and C++ and enables +// calling C++ rocksdb::SstFileWriter methods +// from Java side. + +#include <jni.h> +#include <string> + +#include "include/org_rocksdb_SstFileWriter.h" +#include "rocksdb/comparator.h" +#include "rocksdb/env.h" +#include "rocksdb/options.h" +#include "rocksdb/sst_file_writer.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_SstFileWriter + * Method: newSstFileWriter + * Signature: (JJJB)J + */ +jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJB( + JNIEnv * /*env*/, jclass /*jcls*/, jlong jenvoptions, jlong joptions, + jlong jcomparator_handle, jbyte jcomparator_type) { + rocksdb::Comparator *comparator = nullptr; + switch (jcomparator_type) { + // JAVA_COMPARATOR + case 0x0: + comparator = reinterpret_cast<rocksdb::ComparatorJniCallback *>( + jcomparator_handle); + break; + + // JAVA_DIRECT_COMPARATOR + case 0x1: + comparator = reinterpret_cast<rocksdb::DirectComparatorJniCallback *>( + jcomparator_handle); + break; + + // JAVA_NATIVE_COMPARATOR_WRAPPER + case 0x2: + comparator = reinterpret_cast<rocksdb::Comparator *>(jcomparator_handle); + break; + } + auto *env_options = + reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions); + auto *options = reinterpret_cast<const rocksdb::Options *>(joptions); + rocksdb::SstFileWriter *sst_file_writer = + new rocksdb::SstFileWriter(*env_options, *options, comparator); + return reinterpret_cast<jlong>(sst_file_writer); +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: newSstFileWriter + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJ(JNIEnv * /*env*/, + jclass /*jcls*/, + jlong jenvoptions, + jlong joptions) { + auto *env_options = + reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions); + auto *options = reinterpret_cast<const rocksdb::Options *>(joptions); + rocksdb::SstFileWriter *sst_file_writer = + new rocksdb::SstFileWriter(*env_options, *options); + return reinterpret_cast<jlong>(sst_file_writer); +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: open + * Signature: (JLjava/lang/String;)V + */ +void Java_org_rocksdb_SstFileWriter_open(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, jstring jfile_path) { + const char *file_path = env->GetStringUTFChars(jfile_path, nullptr); + if (file_path == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Open(file_path); + env->ReleaseStringUTFChars(jfile_path, file_path); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: put + * Signature: (JJJ)V + */ +void Java_org_rocksdb_SstFileWriter_put__JJJ(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, jlong jkey_handle, + jlong jvalue_handle) { + auto *key_slice = reinterpret_cast<rocksdb::Slice *>(jkey_handle); + auto *value_slice = reinterpret_cast<rocksdb::Slice *>(jvalue_handle); + rocksdb::Status s = reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Put( + *key_slice, *value_slice); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: put + * Signature: (JJJ)V + */ +void Java_org_rocksdb_SstFileWriter_put__J_3B_3B(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jbyteArray jval) { + jbyte *key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + rocksdb::Slice key_slice(reinterpret_cast<char *>(key), + env->GetArrayLength(jkey)); + + jbyte *value = env->GetByteArrayElements(jval, nullptr); + if (value == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + return; + } + rocksdb::Slice value_slice(reinterpret_cast<char *>(value), + env->GetArrayLength(jval)); + + rocksdb::Status s = reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Put( + key_slice, value_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + env->ReleaseByteArrayElements(jval, value, JNI_ABORT); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: merge + * Signature: (JJJ)V + */ +void Java_org_rocksdb_SstFileWriter_merge__JJJ(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, jlong jkey_handle, + jlong jvalue_handle) { + auto *key_slice = reinterpret_cast<rocksdb::Slice *>(jkey_handle); + auto *value_slice = reinterpret_cast<rocksdb::Slice *>(jvalue_handle); + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Merge(*key_slice, + *value_slice); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: merge + * Signature: (J[B[B)V + */ +void Java_org_rocksdb_SstFileWriter_merge__J_3B_3B(JNIEnv *env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jbyteArray jval) { + jbyte *key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + rocksdb::Slice key_slice(reinterpret_cast<char *>(key), + env->GetArrayLength(jkey)); + + jbyte *value = env->GetByteArrayElements(jval, nullptr); + if (value == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + return; + } + rocksdb::Slice value_slice(reinterpret_cast<char *>(value), + env->GetArrayLength(jval)); + + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Merge(key_slice, + value_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + env->ReleaseByteArrayElements(jval, value, JNI_ABORT); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: delete + * Signature: (JJJ)V + */ +void Java_org_rocksdb_SstFileWriter_delete__J_3B(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey) { + jbyte *key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + rocksdb::Slice key_slice(reinterpret_cast<char *>(key), + env->GetArrayLength(jkey)); + + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Delete(key_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: delete + * Signature: (JJJ)V + */ +void Java_org_rocksdb_SstFileWriter_delete__JJ(JNIEnv *env, jobject /*jobj*/, + jlong jhandle, + jlong jkey_handle) { + auto *key_slice = reinterpret_cast<rocksdb::Slice *>(jkey_handle); + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Delete(*key_slice); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: finish + * Signature: (J)V + */ +void Java_org_rocksdb_SstFileWriter_finish(JNIEnv *env, jobject /*jobj*/, + jlong jhandle) { + rocksdb::Status s = + reinterpret_cast<rocksdb::SstFileWriter *>(jhandle)->Finish(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_SstFileWriter + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_SstFileWriter_disposeInternal(JNIEnv * /*env*/, + jobject /*jobj*/, + jlong jhandle) { + delete reinterpret_cast<rocksdb::SstFileWriter *>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/statistics.cc b/src/rocksdb/java/rocksjni/statistics.cc new file mode 100644 index 00000000..ae7ad535 --- /dev/null +++ b/src/rocksdb/java/rocksjni/statistics.cc @@ -0,0 +1,247 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::Statistics methods from Java side. + +#include <jni.h> +#include <memory> +#include <set> + +#include "include/org_rocksdb_Statistics.h" +#include "rocksdb/statistics.h" +#include "rocksjni/portal.h" +#include "rocksjni/statisticsjni.h" + +/* + * Class: org_rocksdb_Statistics + * Method: newStatistics + * Signature: ()J + */ +jlong Java_org_rocksdb_Statistics_newStatistics__( + JNIEnv* env, jclass jcls) { + return Java_org_rocksdb_Statistics_newStatistics___3BJ( + env, jcls, nullptr, 0); +} + +/* + * Class: org_rocksdb_Statistics + * Method: newStatistics + * Signature: (J)J + */ +jlong Java_org_rocksdb_Statistics_newStatistics__J( + JNIEnv* env, jclass jcls, jlong jother_statistics_handle) { + return Java_org_rocksdb_Statistics_newStatistics___3BJ( + env, jcls, nullptr, jother_statistics_handle); +} + +/* + * Class: org_rocksdb_Statistics + * Method: newStatistics + * Signature: ([B)J + */ +jlong Java_org_rocksdb_Statistics_newStatistics___3B( + JNIEnv* env, jclass jcls, jbyteArray jhistograms) { + return Java_org_rocksdb_Statistics_newStatistics___3BJ( + env, jcls, jhistograms, 0); +} + +/* + * Class: org_rocksdb_Statistics + * Method: newStatistics + * Signature: ([BJ)J + */ +jlong Java_org_rocksdb_Statistics_newStatistics___3BJ( + JNIEnv* env, jclass, jbyteArray jhistograms, jlong jother_statistics_handle) { + std::shared_ptr<rocksdb::Statistics>* pSptr_other_statistics = nullptr; + if (jother_statistics_handle > 0) { + pSptr_other_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>( + jother_statistics_handle); + } + + std::set<uint32_t> histograms; + if (jhistograms != nullptr) { + const jsize len = env->GetArrayLength(jhistograms); + if (len > 0) { + jbyte* jhistogram = env->GetByteArrayElements(jhistograms, nullptr); + if (jhistogram == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + for (jsize i = 0; i < len; i++) { + const rocksdb::Histograms histogram = + rocksdb::HistogramTypeJni::toCppHistograms(jhistogram[i]); + histograms.emplace(histogram); + } + + env->ReleaseByteArrayElements(jhistograms, jhistogram, JNI_ABORT); + } + } + + std::shared_ptr<rocksdb::Statistics> sptr_other_statistics = nullptr; + if (pSptr_other_statistics != nullptr) { + sptr_other_statistics = *pSptr_other_statistics; + } + + auto* pSptr_statistics = new std::shared_ptr<rocksdb::StatisticsJni>( + new rocksdb::StatisticsJni(sptr_other_statistics, histograms)); + + return reinterpret_cast<jlong>(pSptr_statistics); +} + +/* + * Class: org_rocksdb_Statistics + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_Statistics_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + if (jhandle > 0) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + delete pSptr_statistics; + } +} + +/* + * Class: org_rocksdb_Statistics + * Method: statsLevel + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Statistics_statsLevel( + JNIEnv*, jobject, jlong jhandle) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + return rocksdb::StatsLevelJni::toJavaStatsLevel( + pSptr_statistics->get()->get_stats_level()); +} + +/* + * Class: org_rocksdb_Statistics + * Method: setStatsLevel + * Signature: (JB)V + */ +void Java_org_rocksdb_Statistics_setStatsLevel( + JNIEnv*, jobject, jlong jhandle, jbyte jstats_level) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + auto stats_level = rocksdb::StatsLevelJni::toCppStatsLevel(jstats_level); + pSptr_statistics->get()->set_stats_level(stats_level); +} + +/* + * Class: org_rocksdb_Statistics + * Method: getTickerCount + * Signature: (JB)J + */ +jlong Java_org_rocksdb_Statistics_getTickerCount( + JNIEnv*, jobject, jlong jhandle, jbyte jticker_type) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + auto ticker = rocksdb::TickerTypeJni::toCppTickers(jticker_type); + uint64_t count = pSptr_statistics->get()->getTickerCount(ticker); + return static_cast<jlong>(count); +} + +/* + * Class: org_rocksdb_Statistics + * Method: getAndResetTickerCount + * Signature: (JB)J + */ +jlong Java_org_rocksdb_Statistics_getAndResetTickerCount( + JNIEnv*, jobject, jlong jhandle, jbyte jticker_type) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + auto ticker = rocksdb::TickerTypeJni::toCppTickers(jticker_type); + return pSptr_statistics->get()->getAndResetTickerCount(ticker); +} + +/* + * Class: org_rocksdb_Statistics + * Method: getHistogramData + * Signature: (JB)Lorg/rocksdb/HistogramData; + */ +jobject Java_org_rocksdb_Statistics_getHistogramData( + JNIEnv* env, jobject, jlong jhandle, jbyte jhistogram_type) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + + // TODO(AR) perhaps better to construct a Java Object Wrapper that + // uses ptr to C++ `new HistogramData` + rocksdb::HistogramData data; + + auto histogram = rocksdb::HistogramTypeJni::toCppHistograms(jhistogram_type); + pSptr_statistics->get()->histogramData( + static_cast<rocksdb::Histograms>(histogram), &data); + + jclass jclazz = rocksdb::HistogramDataJni::getJClass(env); + if (jclazz == nullptr) { + // exception occurred accessing class + return nullptr; + } + + jmethodID mid = rocksdb::HistogramDataJni::getConstructorMethodId(env); + if (mid == nullptr) { + // exception occurred accessing method + return nullptr; + } + + return env->NewObject(jclazz, mid, data.median, data.percentile95, + data.percentile99, data.average, + data.standard_deviation, data.max, data.count, + data.sum, data.min); +} + +/* + * Class: org_rocksdb_Statistics + * Method: getHistogramString + * Signature: (JB)Ljava/lang/String; + */ +jstring Java_org_rocksdb_Statistics_getHistogramString( + JNIEnv* env, jobject, jlong jhandle, jbyte jhistogram_type) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + auto histogram = rocksdb::HistogramTypeJni::toCppHistograms(jhistogram_type); + auto str = pSptr_statistics->get()->getHistogramString(histogram); + return env->NewStringUTF(str.c_str()); +} + +/* + * Class: org_rocksdb_Statistics + * Method: reset + * Signature: (J)V + */ +void Java_org_rocksdb_Statistics_reset( + JNIEnv* env, jobject, jlong jhandle) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + rocksdb::Status s = pSptr_statistics->get()->Reset(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Statistics + * Method: toString + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_Statistics_toString( + JNIEnv* env, jobject, jlong jhandle) { + auto* pSptr_statistics = + reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle); + assert(pSptr_statistics != nullptr); + auto str = pSptr_statistics->get()->ToString(); + return env->NewStringUTF(str.c_str()); +} diff --git a/src/rocksdb/java/rocksjni/statisticsjni.cc b/src/rocksdb/java/rocksjni/statisticsjni.cc new file mode 100644 index 00000000..f59ace4d --- /dev/null +++ b/src/rocksdb/java/rocksjni/statisticsjni.cc @@ -0,0 +1,32 @@ +// 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::Statistics + +#include "rocksjni/statisticsjni.h" + +namespace rocksdb { + +StatisticsJni::StatisticsJni(std::shared_ptr<Statistics> stats) + : StatisticsImpl(stats), m_ignore_histograms() {} + +StatisticsJni::StatisticsJni(std::shared_ptr<Statistics> stats, + const std::set<uint32_t> ignore_histograms) + : StatisticsImpl(stats), m_ignore_histograms(ignore_histograms) {} + +bool StatisticsJni::HistEnabledForType(uint32_t type) const { + if (type >= HISTOGRAM_ENUM_MAX) { + return false; + } + + if (m_ignore_histograms.count(type) > 0) { + return false; + } + + return true; +} +// @lint-ignore TXT4 T25377293 Grandfathered in +};
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/statisticsjni.h b/src/rocksdb/java/rocksjni/statisticsjni.h new file mode 100644 index 00000000..56186789 --- /dev/null +++ b/src/rocksdb/java/rocksjni/statisticsjni.h @@ -0,0 +1,34 @@ +// 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::Statistics + +#ifndef JAVA_ROCKSJNI_STATISTICSJNI_H_ +#define JAVA_ROCKSJNI_STATISTICSJNI_H_ + +#include <memory> +#include <set> +#include <string> +#include "rocksdb/statistics.h" +#include "monitoring/statistics.h" + +namespace rocksdb { + + class StatisticsJni : public StatisticsImpl { + public: + StatisticsJni(std::shared_ptr<Statistics> stats); + StatisticsJni(std::shared_ptr<Statistics> stats, + const std::set<uint32_t> ignore_histograms); + virtual bool HistEnabledForType(uint32_t type) const override; + + private: + const std::set<uint32_t> m_ignore_histograms; + }; + +} // namespace rocksdb + +// @lint-ignore TXT4 T25377293 Grandfathered in +#endif // JAVA_ROCKSJNI_STATISTICSJNI_H_
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/table.cc b/src/rocksdb/java/rocksjni/table.cc new file mode 100644 index 00000000..1ccc550a --- /dev/null +++ b/src/rocksdb/java/rocksjni/table.cc @@ -0,0 +1,139 @@ +// 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 "bridge" between Java and C++ for rocksdb::Options. + +#include "rocksdb/table.h" +#include <jni.h> +#include "include/org_rocksdb_BlockBasedTableConfig.h" +#include "include/org_rocksdb_PlainTableConfig.h" +#include "portal.h" +#include "rocksdb/cache.h" +#include "rocksdb/filter_policy.h" + +/* + * Class: org_rocksdb_PlainTableConfig + * Method: newTableFactoryHandle + * Signature: (IIDIIBZZ)J + */ +jlong Java_org_rocksdb_PlainTableConfig_newTableFactoryHandle( + JNIEnv * /*env*/, jobject /*jobj*/, jint jkey_size, + jint jbloom_bits_per_key, jdouble jhash_table_ratio, jint jindex_sparseness, + jint jhuge_page_tlb_size, jbyte jencoding_type, jboolean jfull_scan_mode, + jboolean jstore_index_in_file) { + rocksdb::PlainTableOptions options = rocksdb::PlainTableOptions(); + options.user_key_len = jkey_size; + options.bloom_bits_per_key = jbloom_bits_per_key; + options.hash_table_ratio = jhash_table_ratio; + options.index_sparseness = jindex_sparseness; + options.huge_page_tlb_size = jhuge_page_tlb_size; + options.encoding_type = static_cast<rocksdb::EncodingType>(jencoding_type); + options.full_scan_mode = jfull_scan_mode; + options.store_index_in_file = jstore_index_in_file; + return reinterpret_cast<jlong>(rocksdb::NewPlainTableFactory(options)); +} + +/* + * Class: org_rocksdb_BlockBasedTableConfig + * Method: newTableFactoryHandle + * Signature: (ZZZZBBDBZJJJJIIIJZZJZZIIZZJIJI)J + */ +jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle( + JNIEnv*, jobject, jboolean jcache_index_and_filter_blocks, + jboolean jcache_index_and_filter_blocks_with_high_priority, + jboolean jpin_l0_filter_and_index_blocks_in_cache, + jboolean jpin_top_level_index_and_filter, jbyte jindex_type_value, + jbyte jdata_block_index_type_value, + jdouble jdata_block_hash_table_util_ratio, jbyte jchecksum_type_value, + jboolean jno_block_cache, jlong jblock_cache_handle, + jlong jpersistent_cache_handle, + jlong jblock_cache_compressed_handle, jlong jblock_size, + jint jblock_size_deviation, jint jblock_restart_interval, + jint jindex_block_restart_interval, jlong jmetadata_block_size, + jboolean jpartition_filters, jboolean juse_delta_encoding, + jlong jfilter_policy_handle, jboolean jwhole_key_filtering, + jboolean jverify_compression, jint jread_amp_bytes_per_bit, + jint jformat_version, jboolean jenable_index_compression, + jboolean jblock_align, jlong jblock_cache_size, + jint jblock_cache_num_shard_bits, jlong jblock_cache_compressed_size, + jint jblock_cache_compressed_num_shard_bits) { + rocksdb::BlockBasedTableOptions options; + options.cache_index_and_filter_blocks = + static_cast<bool>(jcache_index_and_filter_blocks); + options.cache_index_and_filter_blocks_with_high_priority = + static_cast<bool>(jcache_index_and_filter_blocks_with_high_priority); + options.pin_l0_filter_and_index_blocks_in_cache = + static_cast<bool>(jpin_l0_filter_and_index_blocks_in_cache); + options.pin_top_level_index_and_filter = + static_cast<bool>(jpin_top_level_index_and_filter); + options.index_type = + rocksdb::IndexTypeJni::toCppIndexType(jindex_type_value); + options.data_block_index_type = + rocksdb::DataBlockIndexTypeJni::toCppDataBlockIndexType( + jdata_block_index_type_value); + options.data_block_hash_table_util_ratio = + static_cast<double>(jdata_block_hash_table_util_ratio); + options.checksum = + rocksdb::ChecksumTypeJni::toCppChecksumType(jchecksum_type_value); + options.no_block_cache = static_cast<bool>(jno_block_cache); + if (options.no_block_cache) { + options.block_cache = nullptr; + } else { + if (jblock_cache_handle > 0) { + std::shared_ptr<rocksdb::Cache> *pCache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(jblock_cache_handle); + options.block_cache = *pCache; + } else if (jblock_cache_size > 0) { + if (jblock_cache_num_shard_bits > 0) { + options.block_cache = rocksdb::NewLRUCache( + static_cast<size_t>(jblock_cache_size), + static_cast<int>(jblock_cache_num_shard_bits)); + } else { + options.block_cache = rocksdb::NewLRUCache( + static_cast<size_t>(jblock_cache_size)); + } + } + } + if (jpersistent_cache_handle > 0) { + std::shared_ptr<rocksdb::PersistentCache> *pCache = + reinterpret_cast<std::shared_ptr<rocksdb::PersistentCache> *>(jpersistent_cache_handle); + options.persistent_cache = *pCache; + } + if (jblock_cache_compressed_handle > 0) { + std::shared_ptr<rocksdb::Cache> *pCache = + reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(jblock_cache_compressed_handle); + options.block_cache_compressed = *pCache; + } else if (jblock_cache_compressed_size > 0) { + if (jblock_cache_compressed_num_shard_bits > 0) { + options.block_cache_compressed = rocksdb::NewLRUCache( + static_cast<size_t>(jblock_cache_compressed_size), + static_cast<int>(jblock_cache_compressed_num_shard_bits)); + } else { + options.block_cache_compressed = rocksdb::NewLRUCache( + static_cast<size_t>(jblock_cache_compressed_size)); + } + } + options.block_size = static_cast<size_t>(jblock_size); + options.block_size_deviation = static_cast<int>(jblock_size_deviation); + options.block_restart_interval = static_cast<int>(jblock_restart_interval); + options.index_block_restart_interval = static_cast<int>(jindex_block_restart_interval); + options.metadata_block_size = static_cast<uint64_t>(jmetadata_block_size); + options.partition_filters = static_cast<bool>(jpartition_filters); + options.use_delta_encoding = static_cast<bool>(juse_delta_encoding); + if (jfilter_policy_handle > 0) { + std::shared_ptr<rocksdb::FilterPolicy> *pFilterPolicy = + reinterpret_cast<std::shared_ptr<rocksdb::FilterPolicy> *>( + jfilter_policy_handle); + options.filter_policy = *pFilterPolicy; + } + options.whole_key_filtering = static_cast<bool>(jwhole_key_filtering); + options.verify_compression = static_cast<bool>(jverify_compression); + options.read_amp_bytes_per_bit = static_cast<uint32_t>(jread_amp_bytes_per_bit); + options.format_version = static_cast<uint32_t>(jformat_version); + options.enable_index_compression = static_cast<bool>(jenable_index_compression); + options.block_align = static_cast<bool>(jblock_align); + + return reinterpret_cast<jlong>(rocksdb::NewBlockBasedTableFactory(options)); +} diff --git a/src/rocksdb/java/rocksjni/table_filter.cc b/src/rocksdb/java/rocksjni/table_filter.cc new file mode 100644 index 00000000..e5b35562 --- /dev/null +++ b/src/rocksdb/java/rocksjni/table_filter.cc @@ -0,0 +1,25 @@ +// 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 "bridge" between Java and C++ for +// org.rocksdb.AbstractTableFilter. + +#include <jni.h> +#include <memory> + +#include "include/org_rocksdb_AbstractTableFilter.h" +#include "rocksjni/table_filter_jnicallback.h" + +/* + * Class: org_rocksdb_AbstractTableFilter + * Method: createNewTableFilter + * Signature: ()J + */ +jlong Java_org_rocksdb_AbstractTableFilter_createNewTableFilter( + JNIEnv* env, jobject jtable_filter) { + auto* table_filter_jnicallback = + new rocksdb::TableFilterJniCallback(env, jtable_filter); + return reinterpret_cast<jlong>(table_filter_jnicallback); +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/table_filter_jnicallback.cc b/src/rocksdb/java/rocksjni/table_filter_jnicallback.cc new file mode 100644 index 00000000..680c0144 --- /dev/null +++ b/src/rocksdb/java/rocksjni/table_filter_jnicallback.cc @@ -0,0 +1,62 @@ +// 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::TableFilter. + +#include "rocksjni/table_filter_jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +TableFilterJniCallback::TableFilterJniCallback( + JNIEnv* env, jobject jtable_filter) + : JniCallback(env, jtable_filter) { + m_jfilter_methodid = + AbstractTableFilterJni::getFilterMethod(env); + if(m_jfilter_methodid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + // create the function reference + /* + Note the JNI ENV must be obtained/release + on each call to the function itself as + it may be called from multiple threads + */ + m_table_filter_function = [this](const rocksdb::TableProperties& table_properties) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* thread_env = getJniEnv(&attached_thread); + assert(thread_env != nullptr); + + // create a Java TableProperties object + jobject jtable_properties = TablePropertiesJni::fromCppTableProperties(thread_env, table_properties); + if (jtable_properties == nullptr) { + // exception thrown from fromCppTableProperties + thread_env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return false; + } + + jboolean result = thread_env->CallBooleanMethod(m_jcallback_obj, m_jfilter_methodid, jtable_properties); + if (thread_env->ExceptionCheck()) { + // exception thrown from CallBooleanMethod + thread_env->DeleteLocalRef(jtable_properties); + thread_env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return false; + } + + // ok... cleanup and then return + releaseJniEnv(attached_thread); + return static_cast<bool>(result); + }; +} + +std::function<bool(const rocksdb::TableProperties&)> TableFilterJniCallback::GetTableFilterFunction() { + return m_table_filter_function; +} + +} // namespace rocksdb diff --git a/src/rocksdb/java/rocksjni/table_filter_jnicallback.h b/src/rocksdb/java/rocksjni/table_filter_jnicallback.h new file mode 100644 index 00000000..39a0c90e --- /dev/null +++ b/src/rocksdb/java/rocksjni/table_filter_jnicallback.h @@ -0,0 +1,34 @@ +// 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::TableFilter. + +#ifndef JAVA_ROCKSJNI_TABLE_FILTER_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_TABLE_FILTER_JNICALLBACK_H_ + +#include <jni.h> +#include <functional> +#include <memory> + +#include "rocksdb/table_properties.h" +#include "rocksjni/jnicallback.h" + +namespace rocksdb { + +class TableFilterJniCallback : public JniCallback { + public: + TableFilterJniCallback( + JNIEnv* env, jobject jtable_filter); + std::function<bool(const rocksdb::TableProperties&)> GetTableFilterFunction(); + + private: + jmethodID m_jfilter_methodid; + std::function<bool(const rocksdb::TableProperties&)> m_table_filter_function; +}; + +} //namespace rocksdb + +#endif // JAVA_ROCKSJNI_TABLE_FILTER_JNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/thread_status.cc b/src/rocksdb/java/rocksjni/thread_status.cc new file mode 100644 index 00000000..f70d515a --- /dev/null +++ b/src/rocksdb/java/rocksjni/thread_status.cc @@ -0,0 +1,121 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::ThreadStatus methods from Java side. + +#include <jni.h> + +#include "portal.h" +#include "include/org_rocksdb_ThreadStatus.h" +#include "rocksdb/thread_status.h" + +/* + * Class: org_rocksdb_ThreadStatus + * Method: getThreadTypeName + * Signature: (B)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_getThreadTypeName( + JNIEnv* env, jclass, jbyte jthread_type_value) { + auto name = rocksdb::ThreadStatus::GetThreadTypeName( + rocksdb::ThreadTypeJni::toCppThreadType(jthread_type_value)); + return rocksdb::JniUtil::toJavaString(env, &name, true); +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: getOperationName + * Signature: (B)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_getOperationName( + JNIEnv* env, jclass, jbyte joperation_type_value) { + auto name = rocksdb::ThreadStatus::GetOperationName( + rocksdb::OperationTypeJni::toCppOperationType(joperation_type_value)); + return rocksdb::JniUtil::toJavaString(env, &name, true); +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: microsToStringNative + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_microsToStringNative( + JNIEnv* env, jclass, jlong jmicros) { + auto str = + rocksdb::ThreadStatus::MicrosToString(static_cast<uint64_t>(jmicros)); + return rocksdb::JniUtil::toJavaString(env, &str, true); +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: getOperationStageName + * Signature: (B)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_getOperationStageName( + JNIEnv* env, jclass, jbyte joperation_stage_value) { + auto name = rocksdb::ThreadStatus::GetOperationStageName( + rocksdb::OperationStageJni::toCppOperationStage(joperation_stage_value)); + return rocksdb::JniUtil::toJavaString(env, &name, true); +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: getOperationPropertyName + * Signature: (BI)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_getOperationPropertyName( + JNIEnv* env, jclass, jbyte joperation_type_value, jint jindex) { + auto name = rocksdb::ThreadStatus::GetOperationPropertyName( + rocksdb::OperationTypeJni::toCppOperationType(joperation_type_value), + static_cast<int>(jindex)); + return rocksdb::JniUtil::toJavaString(env, &name, true); +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: interpretOperationProperties + * Signature: (B[J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_ThreadStatus_interpretOperationProperties( + JNIEnv* env, jclass, jbyte joperation_type_value, + jlongArray joperation_properties) { + + //convert joperation_properties + const jsize len = env->GetArrayLength(joperation_properties); + const std::unique_ptr<uint64_t[]> op_properties(new uint64_t[len]); + jlong* jop = env->GetLongArrayElements(joperation_properties, nullptr); + if (jop == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + for (jsize i = 0; i < len; i++) { + op_properties[i] = static_cast<uint64_t>(jop[i]); + } + env->ReleaseLongArrayElements(joperation_properties, jop, JNI_ABORT); + + // call the function + auto result = rocksdb::ThreadStatus::InterpretOperationProperties( + rocksdb::OperationTypeJni::toCppOperationType(joperation_type_value), + op_properties.get()); + jobject jresult = rocksdb::HashMapJni::fromCppMap(env, &result); + if (env->ExceptionCheck()) { + // exception occurred + return nullptr; + } + + return jresult; +} + +/* + * Class: org_rocksdb_ThreadStatus + * Method: getStateName + * Signature: (B)Ljava/lang/String; + */ +jstring Java_org_rocksdb_ThreadStatus_getStateName( + JNIEnv* env, jclass, jbyte jstate_type_value) { + auto name = rocksdb::ThreadStatus::GetStateName( + rocksdb::StateTypeJni::toCppStateType(jstate_type_value)); + return rocksdb::JniUtil::toJavaString(env, &name, true); +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/trace_writer.cc b/src/rocksdb/java/rocksjni/trace_writer.cc new file mode 100644 index 00000000..5d47cfcb --- /dev/null +++ b/src/rocksdb/java/rocksjni/trace_writer.cc @@ -0,0 +1,23 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::CompactionFilterFactory. + +#include <jni.h> + +#include "include/org_rocksdb_AbstractTraceWriter.h" +#include "rocksjni/trace_writer_jnicallback.h" + +/* + * Class: org_rocksdb_AbstractTraceWriter + * Method: createNewTraceWriter + * Signature: ()J + */ +jlong Java_org_rocksdb_AbstractTraceWriter_createNewTraceWriter( + JNIEnv* env, jobject jobj) { + auto* trace_writer = new rocksdb::TraceWriterJniCallback(env, jobj); + return reinterpret_cast<jlong>(trace_writer); +} diff --git a/src/rocksdb/java/rocksjni/trace_writer_jnicallback.cc b/src/rocksdb/java/rocksjni/trace_writer_jnicallback.cc new file mode 100644 index 00000000..d547fb3f --- /dev/null +++ b/src/rocksdb/java/rocksjni/trace_writer_jnicallback.cc @@ -0,0 +1,115 @@ +// 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::TraceWriter. + +#include "rocksjni/trace_writer_jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +TraceWriterJniCallback::TraceWriterJniCallback( + JNIEnv* env, jobject jtrace_writer) + : JniCallback(env, jtrace_writer) { + m_jwrite_proxy_methodid = + AbstractTraceWriterJni::getWriteProxyMethodId(env); + if(m_jwrite_proxy_methodid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + m_jclose_writer_proxy_methodid = + AbstractTraceWriterJni::getCloseWriterProxyMethodId(env); + if(m_jclose_writer_proxy_methodid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + m_jget_file_size_methodid = + AbstractTraceWriterJni::getGetFileSizeMethodId(env); + if(m_jget_file_size_methodid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } +} + +Status TraceWriterJniCallback::Write(const Slice& data) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + if (env == nullptr) { + return Status::IOError("Unable to attach JNI Environment"); + } + + jshort jstatus = env->CallShortMethod(m_jcallback_obj, + m_jwrite_proxy_methodid, + &data); + + if(env->ExceptionCheck()) { + // exception thrown from CallShortMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return Status::IOError("Unable to call AbstractTraceWriter#writeProxy(long)"); + } + + // unpack status code and status sub-code from jstatus + jbyte jcode_value = (jstatus >> 8) & 0xFF; + jbyte jsub_code_value = jstatus & 0xFF; + std::unique_ptr<Status> s = StatusJni::toCppStatus(jcode_value, jsub_code_value); + + releaseJniEnv(attached_thread); + + return Status(*s); +} + +Status TraceWriterJniCallback::Close() { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + if (env == nullptr) { + return Status::IOError("Unable to attach JNI Environment"); + } + + jshort jstatus = env->CallShortMethod(m_jcallback_obj, + m_jclose_writer_proxy_methodid); + + if(env->ExceptionCheck()) { + // exception thrown from CallShortMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return Status::IOError("Unable to call AbstractTraceWriter#closeWriterProxy()"); + } + + // unpack status code and status sub-code from jstatus + jbyte code_value = (jstatus >> 8) & 0xFF; + jbyte sub_code_value = jstatus & 0xFF; + std::unique_ptr<Status> s = StatusJni::toCppStatus(code_value, sub_code_value); + + releaseJniEnv(attached_thread); + + return Status(*s); +} + +uint64_t TraceWriterJniCallback::GetFileSize() { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + if (env == nullptr) { + return 0; + } + + jlong jfile_size = env->CallLongMethod(m_jcallback_obj, + m_jget_file_size_methodid); + + if(env->ExceptionCheck()) { + // exception thrown from CallLongMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return 0; + } + + releaseJniEnv(attached_thread); + + return static_cast<uint64_t>(jfile_size); +} + +} // namespace rocksdb
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/trace_writer_jnicallback.h b/src/rocksdb/java/rocksjni/trace_writer_jnicallback.h new file mode 100644 index 00000000..610b6c46 --- /dev/null +++ b/src/rocksdb/java/rocksjni/trace_writer_jnicallback.h @@ -0,0 +1,36 @@ +// 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::TraceWriter. + +#ifndef JAVA_ROCKSJNI_TRACE_WRITER_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_TRACE_WRITER_JNICALLBACK_H_ + +#include <jni.h> +#include <memory> + +#include "rocksdb/trace_reader_writer.h" +#include "rocksjni/jnicallback.h" + +namespace rocksdb { + +class TraceWriterJniCallback : public JniCallback, public TraceWriter { + public: + TraceWriterJniCallback( + JNIEnv* env, jobject jtrace_writer); + virtual Status Write(const Slice& data); + virtual Status Close(); + virtual uint64_t GetFileSize(); + + private: + jmethodID m_jwrite_proxy_methodid; + jmethodID m_jclose_writer_proxy_methodid; + jmethodID m_jget_file_size_methodid; +}; + +} //namespace rocksdb + +#endif // JAVA_ROCKSJNI_TRACE_WRITER_JNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/transaction.cc b/src/rocksdb/java/rocksjni/transaction.cc new file mode 100644 index 00000000..04eb654d --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction.cc @@ -0,0 +1,1584 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::Transaction. + +#include <jni.h> +#include <functional> + +#include "include/org_rocksdb_Transaction.h" + +#include "rocksdb/utilities/transaction.h" +#include "rocksjni/portal.h" + +using namespace std::placeholders; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4503) // identifier' : decorated name length + // exceeded, name was truncated +#endif + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshot + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSnapshot(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->SetSnapshot(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshotOnNextOperation + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSnapshotOnNextOperation__J( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->SetSnapshotOnNextOperation(nullptr); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSnapshotOnNextOperation + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setSnapshotOnNextOperation__JJ( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jtxn_notifier_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* txn_notifier = + reinterpret_cast<std::shared_ptr<rocksdb::TransactionNotifierJniCallback>*>( + jtxn_notifier_handle); + txn->SetSnapshotOnNextOperation(*txn_notifier); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getSnapshot + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getSnapshot(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + const rocksdb::Snapshot* snapshot = txn->GetSnapshot(); + return reinterpret_cast<jlong>(snapshot); +} + +/* + * Class: org_rocksdb_Transaction + * Method: clearSnapshot + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_clearSnapshot(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->ClearSnapshot(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: prepare + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_prepare(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::Status s = txn->Prepare(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: commit + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_commit(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::Status s = txn->Commit(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: rollback + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_rollback(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::Status s = txn->Rollback(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: setSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_setSavePoint(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->SetSavePoint(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: rollbackToSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_rollbackToSavePoint(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::Status s = txn->RollbackToSavePoint(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +typedef std::function<rocksdb::Status(const rocksdb::ReadOptions&, + const rocksdb::Slice&, std::string*)> + FnGet; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +jbyteArray txn_get_helper(JNIEnv* env, const FnGet& fn_get, + const jlong& jread_options_handle, + const jbyteArray& jkey, const jint& jkey_part_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + + auto* read_options = + reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + std::string value; + rocksdb::Status s = fn_get(*read_options, key_slice, &value); + + // trigger java unref on key. + // by passing JNI_ABORT, it will simply release the reference without + // copying the result back to the java byte array. + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (s.IsNotFound()) { + return nullptr; + } + + if (s.ok()) { + jbyteArray jret_value = env->NewByteArray(static_cast<jsize>(value.size())); + if (jret_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetByteArrayRegion(jret_value, 0, static_cast<jsize>(value.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value.c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return nullptr; + } + return jret_value; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; +} + +/* + * Class: org_rocksdb_Transaction + * Method: get + * Signature: (JJ[BIJ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_get__JJ_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnGet fn_get = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, rocksdb::ColumnFamilyHandle*, + const rocksdb::Slice&, std::string*)>(&rocksdb::Transaction::Get, txn, _1, + column_family_handle, _2, _3); + return txn_get_helper(env, fn_get, jread_options_handle, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: get + * Signature: (JJ[BI)[B + */ +jbyteArray Java_org_rocksdb_Transaction_get__JJ_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnGet fn_get = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, const rocksdb::Slice&, std::string*)>( + &rocksdb::Transaction::Get, txn, _1, _2, _3); + return txn_get_helper(env, fn_get, jread_options_handle, jkey, jkey_part_len); +} + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +// used by txn_multi_get_helper below +std::vector<rocksdb::ColumnFamilyHandle*> txn_column_families_helper( + JNIEnv* env, jlongArray jcolumn_family_handles, bool* has_exception) { + std::vector<rocksdb::ColumnFamilyHandle*> cf_handles; + if (jcolumn_family_handles != nullptr) { + const jsize len_cols = env->GetArrayLength(jcolumn_family_handles); + if (len_cols > 0) { + if (env->EnsureLocalCapacity(len_cols) != 0) { + // out of memory + *has_exception = JNI_TRUE; + return std::vector<rocksdb::ColumnFamilyHandle*>(); + } + + jlong* jcfh = env->GetLongArrayElements(jcolumn_family_handles, nullptr); + if (jcfh == nullptr) { + // exception thrown: OutOfMemoryError + *has_exception = JNI_TRUE; + return std::vector<rocksdb::ColumnFamilyHandle*>(); + } + for (int i = 0; i < len_cols; i++) { + auto* cf_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcfh[i]); + cf_handles.push_back(cf_handle); + } + env->ReleaseLongArrayElements(jcolumn_family_handles, jcfh, JNI_ABORT); + } + } + return cf_handles; +} + +typedef std::function<std::vector<rocksdb::Status>( + const rocksdb::ReadOptions&, const std::vector<rocksdb::Slice>&, + std::vector<std::string>*)> + FnMultiGet; + +void free_parts( + JNIEnv* env, + std::vector<std::tuple<jbyteArray, jbyte*, jobject>>& parts_to_free) { + for (auto& value : parts_to_free) { + jobject jk; + jbyteArray jk_ba; + jbyte* jk_val; + std::tie(jk_ba, jk_val, jk) = value; + env->ReleaseByteArrayElements(jk_ba, jk_val, JNI_ABORT); + env->DeleteLocalRef(jk); + } +} + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +// cf multi get +jobjectArray txn_multi_get_helper(JNIEnv* env, const FnMultiGet& fn_multi_get, + const jlong& jread_options_handle, + const jobjectArray& jkey_parts) { + const jsize len_key_parts = env->GetArrayLength(jkey_parts); + if (env->EnsureLocalCapacity(len_key_parts) != 0) { + // out of memory + return nullptr; + } + + std::vector<rocksdb::Slice> key_parts; + std::vector<std::tuple<jbyteArray, jbyte*, jobject>> key_parts_to_free; + for (int i = 0; i < len_key_parts; i++) { + const jobject jk = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, key_parts_to_free); + return nullptr; + } + jbyteArray jk_ba = reinterpret_cast<jbyteArray>(jk); + const jsize len_key = env->GetArrayLength(jk_ba); + if (env->EnsureLocalCapacity(len_key) != 0) { + // out of memory + env->DeleteLocalRef(jk); + free_parts(env, key_parts_to_free); + return nullptr; + } + jbyte* jk_val = env->GetByteArrayElements(jk_ba, nullptr); + if (jk_val == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jk); + free_parts(env, key_parts_to_free); + return nullptr; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(jk_val), len_key); + key_parts.push_back(key_slice); + + key_parts_to_free.push_back(std::make_tuple(jk_ba, jk_val, jk)); + } + + auto* read_options = + reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + std::vector<std::string> value_parts; + std::vector<rocksdb::Status> s = + fn_multi_get(*read_options, key_parts, &value_parts); + + // free up allocated byte arrays + free_parts(env, key_parts_to_free); + + // prepare the results + const jclass jcls_ba = env->FindClass("[B"); + jobjectArray jresults = + env->NewObjectArray(static_cast<jsize>(s.size()), jcls_ba, nullptr); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + // add to the jresults + for (std::vector<rocksdb::Status>::size_type i = 0; i != s.size(); i++) { + if (s[i].ok()) { + jbyteArray jentry_value = + env->NewByteArray(static_cast<jsize>(value_parts[i].size())); + if (jentry_value == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + jentry_value, 0, static_cast<jsize>(value_parts[i].size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value_parts[i].c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jentry_value); + return nullptr; + } + + env->SetObjectArrayElement(jresults, static_cast<jsize>(i), jentry_value); + env->DeleteLocalRef(jentry_value); + } + } + + return jresults; +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGet + * Signature: (JJ[[B[J)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGet__JJ_3_3B_3J( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts, jlongArray jcolumn_family_handles) { + bool has_exception = false; + const std::vector<rocksdb::ColumnFamilyHandle*> column_family_handles = + txn_column_families_helper(env, jcolumn_family_handles, &has_exception); + if (has_exception) { + // exception thrown: OutOfMemoryError + return nullptr; + } + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnMultiGet fn_multi_get = + std::bind<std::vector<rocksdb::Status> (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, + const std::vector<rocksdb::ColumnFamilyHandle*>&, + const std::vector<rocksdb::Slice>&, std::vector<std::string>*)>( + &rocksdb::Transaction::MultiGet, txn, _1, column_family_handles, _2, + _3); + return txn_multi_get_helper(env, fn_multi_get, jread_options_handle, + jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGet + * Signature: (JJ[[B)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGet__JJ_3_3B( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnMultiGet fn_multi_get = + std::bind<std::vector<rocksdb::Status> (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, const std::vector<rocksdb::Slice>&, + std::vector<std::string>*)>(&rocksdb::Transaction::MultiGet, txn, _1, + _2, _3); + return txn_multi_get_helper(env, fn_multi_get, jread_options_handle, + jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getForUpdate + * Signature: (JJ[BIJZZ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_getForUpdate__JJ_3BIJZZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jlong jcolumn_family_handle, + jboolean jexclusive, jboolean jdo_validate) { + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnGet fn_get_for_update = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, rocksdb::ColumnFamilyHandle*, + const rocksdb::Slice&, std::string*, bool, bool)>( + &rocksdb::Transaction::GetForUpdate, txn, _1, column_family_handle, _2, + _3, jexclusive, jdo_validate); + return txn_get_helper(env, fn_get_for_update, jread_options_handle, jkey, + jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getForUpdate + * Signature: (JJ[BIZZ)[B + */ +jbyteArray Java_org_rocksdb_Transaction_getForUpdate__JJ_3BIZZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jbyteArray jkey, jint jkey_part_len, jboolean jexclusive, + jboolean jdo_validate) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnGet fn_get_for_update = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, const rocksdb::Slice&, std::string*, bool, + bool)>(&rocksdb::Transaction::GetForUpdate, txn, _1, _2, _3, jexclusive, + jdo_validate); + return txn_get_helper(env, fn_get_for_update, jread_options_handle, jkey, + jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGetForUpdate + * Signature: (JJ[[B[J)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGetForUpdate__JJ_3_3B_3J( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts, jlongArray jcolumn_family_handles) { + bool has_exception = false; + const std::vector<rocksdb::ColumnFamilyHandle*> column_family_handles = + txn_column_families_helper(env, jcolumn_family_handles, &has_exception); + if (has_exception) { + // exception thrown: OutOfMemoryError + return nullptr; + } + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnMultiGet fn_multi_get_for_update = + std::bind<std::vector<rocksdb::Status> (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, + const std::vector<rocksdb::ColumnFamilyHandle*>&, + const std::vector<rocksdb::Slice>&, std::vector<std::string>*)>( + &rocksdb::Transaction::MultiGetForUpdate, txn, _1, + column_family_handles, _2, _3); + return txn_multi_get_helper(env, fn_multi_get_for_update, + jread_options_handle, jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: multiGetForUpdate + * Signature: (JJ[[B)[[B + */ +jobjectArray Java_org_rocksdb_Transaction_multiGetForUpdate__JJ_3_3B( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jread_options_handle, + jobjectArray jkey_parts) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnMultiGet fn_multi_get_for_update = + std::bind<std::vector<rocksdb::Status> (rocksdb::Transaction::*)( + const rocksdb::ReadOptions&, const std::vector<rocksdb::Slice>&, + std::vector<std::string>*)>(&rocksdb::Transaction::MultiGetForUpdate, + txn, _1, _2, _3); + return txn_multi_get_helper(env, fn_multi_get_for_update, + jread_options_handle, jkey_parts); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getIterator + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_Transaction_getIterator__JJ(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jread_options_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* read_options = + reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + return reinterpret_cast<jlong>(txn->GetIterator(*read_options)); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getIterator + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_Transaction_getIterator__JJJ( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jread_options_handle, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* read_options = + reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + return reinterpret_cast<jlong>( + txn->GetIterator(*read_options, column_family_handle)); +} + +typedef std::function<rocksdb::Status(const rocksdb::Slice&, + const rocksdb::Slice&)> + FnWriteKV; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_kv_helper(JNIEnv* env, const FnWriteKV& fn_write_kv, + const jbyteArray& jkey, const jint& jkey_part_len, + const jbyteArray& jval, const jint& jval_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + jbyte* value = env->GetByteArrayElements(jval, nullptr); + if (value == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + return; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + rocksdb::Slice value_slice(reinterpret_cast<char*>(value), jval_len); + + rocksdb::Status s = fn_write_kv(key_slice, value_slice); + + // trigger java unref on key. + // by passing JNI_ABORT, it will simply release the reference without + // copying the result back to the java byte array. + env->ReleaseByteArrayElements(jval, value, JNI_ABORT); + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[BI[BIJZ)V + */ +void Java_org_rocksdb_Transaction_put__J_3BI_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKV fn_put = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::Slice&, + const rocksdb::Slice&, bool)>(&rocksdb::Transaction::Put, txn, + column_family_handle, _1, _2, + jassume_tracked); + txn_write_kv_helper(env, fn_put, jkey, jkey_part_len, jval, jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_put__J_3BI_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len, + jbyteArray jval, + jint jval_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKV fn_put = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::Slice&, const rocksdb::Slice&)>(&rocksdb::Transaction::Put, + txn, _1, _2); + txn_write_kv_helper(env, fn_put, jkey, jkey_part_len, jval, jval_len); +} + +typedef std::function<rocksdb::Status(const rocksdb::SliceParts&, + const rocksdb::SliceParts&)> + FnWriteKVParts; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_kv_parts_helper(JNIEnv* env, + const FnWriteKVParts& fn_write_kv_parts, + const jobjectArray& jkey_parts, + const jint& jkey_parts_len, + const jobjectArray& jvalue_parts, + const jint& jvalue_parts_len) { +#ifndef DEBUG + (void) jvalue_parts_len; +#else + assert(jkey_parts_len == jvalue_parts_len); +#endif + + auto key_parts = std::vector<rocksdb::Slice>(); + auto value_parts = std::vector<rocksdb::Slice>(); + auto jparts_to_free = std::vector<std::tuple<jbyteArray, jbyte*, jobject>>(); + + // convert java key_parts/value_parts byte[][] to Slice(s) + for (jsize i = 0; i < jkey_parts_len; ++i) { + const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, jparts_to_free); + return; + } + const jobject jobj_value_part = env->GetObjectArrayElement(jvalue_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + const jbyteArray jba_key_part = reinterpret_cast<jbyteArray>(jobj_key_part); + const jsize jkey_part_len = env->GetArrayLength(jba_key_part); + if (env->EnsureLocalCapacity(jkey_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); + if (jkey_part == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + const jbyteArray jba_value_part = + reinterpret_cast<jbyteArray>(jobj_value_part); + const jsize jvalue_part_len = env->GetArrayLength(jba_value_part); + if (env->EnsureLocalCapacity(jvalue_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + jbyte* jvalue_part = env->GetByteArrayElements(jba_value_part, nullptr); + if (jvalue_part == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseByteArrayElements(jba_value_part, jvalue_part, JNI_ABORT); + env->DeleteLocalRef(jobj_value_part); + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jparts_to_free); + return; + } + + jparts_to_free.push_back( + std::make_tuple(jba_key_part, jkey_part, jobj_key_part)); + jparts_to_free.push_back( + std::make_tuple(jba_value_part, jvalue_part, jobj_value_part)); + + key_parts.push_back( + rocksdb::Slice(reinterpret_cast<char*>(jkey_part), jkey_part_len)); + value_parts.push_back( + rocksdb::Slice(reinterpret_cast<char*>(jvalue_part), jvalue_part_len)); + } + + // call the write_multi function + rocksdb::Status s = fn_write_kv_parts( + rocksdb::SliceParts(key_parts.data(), (int)key_parts.size()), + rocksdb::SliceParts(value_parts.data(), (int)value_parts.size())); + + // cleanup temporary memory + free_parts(env, jparts_to_free); + + // return + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[[BI[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_put__J_3_3BI_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKVParts fn_put_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::SliceParts&, + const rocksdb::SliceParts&, bool)>(&rocksdb::Transaction::Put, txn, + column_family_handle, _1, _2, + jassume_tracked); + txn_write_kv_parts_helper(env, fn_put_parts, jkey_parts, jkey_parts_len, + jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: put + * Signature: (J[[BI[[BI)V + */ +void Java_org_rocksdb_Transaction_put__J_3_3BI_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKVParts fn_put_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::SliceParts&, const rocksdb::SliceParts&)>( + &rocksdb::Transaction::Put, txn, _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts, jkey_parts, jkey_parts_len, + jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: merge + * Signature: (J[BI[BIJZ)V + */ +void Java_org_rocksdb_Transaction_merge__J_3BI_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKV fn_merge = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::Slice&, + const rocksdb::Slice&, bool)>(&rocksdb::Transaction::Merge, txn, + column_family_handle, _1, _2, + jassume_tracked); + txn_write_kv_helper(env, fn_merge, jkey, jkey_part_len, jval, jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: merge + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_merge__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKV fn_merge = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::Slice&, const rocksdb::Slice&)>( + &rocksdb::Transaction::Merge, txn, _1, _2); + txn_write_kv_helper(env, fn_merge, jkey, jkey_part_len, jval, jval_len); +} + +typedef std::function<rocksdb::Status(const rocksdb::Slice&)> FnWriteK; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_k_helper(JNIEnv* env, const FnWriteK& fn_write_k, + const jbyteArray& jkey, const jint& jkey_part_len) { + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + + rocksdb::Status s = fn_write_k(key_slice); + + // trigger java unref on key. + // by passing JNI_ABORT, it will simply release the reference without + // copying the result back to the java byte array. + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); + + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[BIJZ)V + */ +void Java_org_rocksdb_Transaction_delete__J_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteK fn_delete = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::Slice&, bool)>( + &rocksdb::Transaction::Delete, txn, column_family_handle, _1, + jassume_tracked); + txn_write_k_helper(env, fn_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_delete__J_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteK fn_delete = std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::Slice&)>(&rocksdb::Transaction::Delete, txn, _1); + txn_write_k_helper(env, fn_delete, jkey, jkey_part_len); +} + +typedef std::function<rocksdb::Status(const rocksdb::SliceParts&)> + FnWriteKParts; + +// TODO(AR) consider refactoring to share this between here and rocksjni.cc +void txn_write_k_parts_helper(JNIEnv* env, + const FnWriteKParts& fn_write_k_parts, + const jobjectArray& jkey_parts, + const jint& jkey_parts_len) { + std::vector<rocksdb::Slice> key_parts; + std::vector<std::tuple<jbyteArray, jbyte*, jobject>> jkey_parts_to_free; + + // convert java key_parts byte[][] to Slice(s) + for (jint i = 0; i < jkey_parts_len; ++i) { + const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + free_parts(env, jkey_parts_to_free); + return; + } + + const jbyteArray jba_key_part = reinterpret_cast<jbyteArray>(jobj_key_part); + const jsize jkey_part_len = env->GetArrayLength(jba_key_part); + if (env->EnsureLocalCapacity(jkey_part_len) != 0) { + // out of memory + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jkey_parts_to_free); + return; + } + jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); + if (jkey_part == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jobj_key_part); + free_parts(env, jkey_parts_to_free); + return; + } + + jkey_parts_to_free.push_back(std::tuple<jbyteArray, jbyte*, jobject>( + jba_key_part, jkey_part, jobj_key_part)); + + key_parts.push_back( + rocksdb::Slice(reinterpret_cast<char*>(jkey_part), jkey_part_len)); + } + + // call the write_multi function + rocksdb::Status s = fn_write_k_parts( + rocksdb::SliceParts(key_parts.data(), (int)key_parts.size())); + + // cleanup temporary memory + free_parts(env, jkey_parts_to_free); + + // return + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_delete__J_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle, + jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKParts fn_delete_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::SliceParts&, bool)>( + &rocksdb::Transaction::Delete, txn, column_family_handle, _1, + jassume_tracked); + txn_write_k_parts_helper(env, fn_delete_parts, jkey_parts, jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: delete + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_delete__J_3_3BI(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, + jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKParts fn_delete_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::SliceParts&)>(&rocksdb::Transaction::Delete, txn, _1); + txn_write_k_parts_helper(env, fn_delete_parts, jkey_parts, jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[BIJZ)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle, jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteK fn_single_delete = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::Slice&, bool)>( + &rocksdb::Transaction::SingleDelete, txn, column_family_handle, _1, + jassume_tracked); + txn_write_k_helper(env, fn_single_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteK fn_single_delete = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::Slice&)>(&rocksdb::Transaction::SingleDelete, txn, _1); + txn_write_k_helper(env, fn_single_delete, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[[BIJZ)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3_3BIJZ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle, + jboolean jassume_tracked) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKParts fn_single_delete_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::SliceParts&, bool)>( + &rocksdb::Transaction::SingleDelete, txn, column_family_handle, _1, + jassume_tracked); + txn_write_k_parts_helper(env, fn_single_delete_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: singleDelete + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_singleDelete__J_3_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKParts fn_single_delete_parts = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(const rocksdb::SliceParts&)>( + &rocksdb::Transaction::SingleDelete, txn, _1); + txn_write_k_parts_helper(env, fn_single_delete_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3BI_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKV fn_put_untracked = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(rocksdb::ColumnFamilyHandle*, + const rocksdb::Slice&, const rocksdb::Slice&)>( + &rocksdb::Transaction::PutUntracked, txn, column_family_handle, _1, _2); + txn_write_kv_helper(env, fn_put_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKV fn_put_untracked = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(const rocksdb::Slice&, const rocksdb::Slice&)>( + &rocksdb::Transaction::PutUntracked, txn, _1, _2); + txn_write_kv_helper(env, fn_put_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[[BI[[BIJ)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3_3BI_3_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKVParts fn_put_parts_untracked = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::SliceParts&, + const rocksdb::SliceParts&)>(&rocksdb::Transaction::PutUntracked, txn, + column_family_handle, _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts_untracked, jkey_parts, + jkey_parts_len, jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putUntracked + * Signature: (J[[BI[[BI)V + */ +void Java_org_rocksdb_Transaction_putUntracked__J_3_3BI_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jobjectArray jvalue_parts, jint jvalue_parts_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKVParts fn_put_parts_untracked = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + const rocksdb::SliceParts&, const rocksdb::SliceParts&)>( + &rocksdb::Transaction::PutUntracked, txn, _1, _2); + txn_write_kv_parts_helper(env, fn_put_parts_untracked, jkey_parts, + jkey_parts_len, jvalue_parts, jvalue_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: mergeUntracked + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_Transaction_mergeUntracked__J_3BI_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len, + jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKV fn_merge_untracked = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(rocksdb::ColumnFamilyHandle*, + const rocksdb::Slice&, const rocksdb::Slice&)>( + &rocksdb::Transaction::MergeUntracked, txn, column_family_handle, _1, _2); + txn_write_kv_helper(env, fn_merge_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: mergeUntracked + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_Transaction_mergeUntracked__J_3BI_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jbyteArray jval, jint jval_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKV fn_merge_untracked = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(const rocksdb::Slice&, const rocksdb::Slice&)>( + &rocksdb::Transaction::MergeUntracked, txn, _1, _2); + txn_write_kv_helper(env, fn_merge_untracked, jkey, jkey_part_len, jval, + jval_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteK fn_delete_untracked = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::Slice&)>( + &rocksdb::Transaction::DeleteUntracked, txn, column_family_handle, + _1); + txn_write_k_helper(env, fn_delete_untracked, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteK fn_delete_untracked = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(const rocksdb::Slice&)>( + &rocksdb::Transaction::DeleteUntracked, txn, _1); + txn_write_k_helper(env, fn_delete_untracked, jkey, jkey_part_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[[BIJ)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + FnWriteKParts fn_delete_untracked_parts = + std::bind<rocksdb::Status (rocksdb::Transaction::*)( + rocksdb::ColumnFamilyHandle*, const rocksdb::SliceParts&)>( + &rocksdb::Transaction::DeleteUntracked, txn, column_family_handle, + _1); + txn_write_k_parts_helper(env, fn_delete_untracked_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: deleteUntracked + * Signature: (J[[BI)V + */ +void Java_org_rocksdb_Transaction_deleteUntracked__J_3_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jobjectArray jkey_parts, + jint jkey_parts_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + FnWriteKParts fn_delete_untracked_parts = std::bind<rocksdb::Status ( + rocksdb::Transaction::*)(const rocksdb::SliceParts&)>( + &rocksdb::Transaction::DeleteUntracked, txn, _1); + txn_write_k_parts_helper(env, fn_delete_untracked_parts, jkey_parts, + jkey_parts_len); +} + +/* + * Class: org_rocksdb_Transaction + * Method: putLogData + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_putLogData(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + txn->PutLogData(key_slice); + + // trigger java unref on key. + // by passing JNI_ABORT, it will simply release the reference without + // copying the result back to the java byte array. + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Transaction + * Method: disableIndexing + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_disableIndexing(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->DisableIndexing(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: enableIndexing + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_enableIndexing(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->EnableIndexing(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumKeys + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumKeys(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetNumKeys(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumPuts + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumPuts(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetNumPuts(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumDeletes + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumDeletes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetNumDeletes(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getNumMerges + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getNumMerges(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetNumMerges(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getElapsedTime + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getElapsedTime(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetElapsedTime(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWriteBatch + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getWriteBatch(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetWriteBatch()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setLockTimeout + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setLockTimeout(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jlock_timeout) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->SetLockTimeout(jlock_timeout); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWriteOptions + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getWriteOptions(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetWriteOptions()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setWriteOptions + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setWriteOptions(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jwrite_options_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + txn->SetWriteOptions(*write_options); +} + +/* + * Class: org_rocksdb_Transaction + * Method: undo + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_Transaction_undoGetForUpdate__J_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jbyteArray jkey, + jint jkey_part_len, jlong jcolumn_family_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* column_family_handle = + reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcolumn_family_handle); + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + txn->UndoGetForUpdate(column_family_handle, key_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Transaction + * Method: undoGetForUpdate + * Signature: (J[BI)V + */ +void Java_org_rocksdb_Transaction_undoGetForUpdate__J_3BI(JNIEnv* env, + jobject /*jobj*/, + jlong jhandle, + jbyteArray jkey, + jint jkey_part_len) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + jbyte* key = env->GetByteArrayElements(jkey, nullptr); + if (key == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice key_slice(reinterpret_cast<char*>(key), jkey_part_len); + txn->UndoGetForUpdate(key_slice); + + env->ReleaseByteArrayElements(jkey, key, JNI_ABORT); +} + +/* + * Class: org_rocksdb_Transaction + * Method: rebuildFromWriteBatch + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_rebuildFromWriteBatch( + JNIEnv* env, jobject /*jobj*/, jlong jhandle, jlong jwrite_batch_handle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + auto* write_batch = + reinterpret_cast<rocksdb::WriteBatch*>(jwrite_batch_handle); + rocksdb::Status s = txn->RebuildFromWriteBatch(write_batch); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: getCommitTimeWriteBatch + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getCommitTimeWriteBatch(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return reinterpret_cast<jlong>(txn->GetCommitTimeWriteBatch()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setLogNumber + * Signature: (JJ)V + */ +void Java_org_rocksdb_Transaction_setLogNumber(JNIEnv* /*env*/, + jobject /*jobj*/, jlong jhandle, + jlong jlog_number) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + txn->SetLogNumber(jlog_number); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getLogNumber + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getLogNumber(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return txn->GetLogNumber(); +} + +/* + * Class: org_rocksdb_Transaction + * Method: setName + * Signature: (JLjava/lang/String;)V + */ +void Java_org_rocksdb_Transaction_setName(JNIEnv* env, jobject /*jobj*/, + jlong jhandle, jstring jname) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + const char* name = env->GetStringUTFChars(jname, nullptr); + if (name == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Status s = txn->SetName(name); + + env->ReleaseStringUTFChars(jname, name); + + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_Transaction + * Method: getName + * Signature: (J)Ljava/lang/String; + */ +jstring Java_org_rocksdb_Transaction_getName(JNIEnv* env, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::TransactionName name = txn->GetName(); + return env->NewStringUTF(name.data()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getID + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getID(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::TransactionID id = txn->GetID(); + return static_cast<jlong>(id); +} + +/* + * Class: org_rocksdb_Transaction + * Method: isDeadlockDetect + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_Transaction_isDeadlockDetect(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + return static_cast<jboolean>(txn->IsDeadlockDetect()); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getWaitingTxns + * Signature: (J)Lorg/rocksdb/Transaction/WaitingTransactions; + */ +jobject Java_org_rocksdb_Transaction_getWaitingTxns(JNIEnv* env, + jobject jtransaction_obj, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + uint32_t column_family_id; + std::string key; + std::vector<rocksdb::TransactionID> waiting_txns = + txn->GetWaitingTxns(&column_family_id, &key); + jobject jwaiting_txns = rocksdb::TransactionJni::newWaitingTransactions( + env, jtransaction_obj, column_family_id, key, waiting_txns); + return jwaiting_txns; +} + +/* + * Class: org_rocksdb_Transaction + * Method: getState + * Signature: (J)B + */ +jbyte Java_org_rocksdb_Transaction_getState(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + rocksdb::Transaction::TransactionState txn_status = txn->GetState(); + switch (txn_status) { + case rocksdb::Transaction::TransactionState::STARTED: + return 0x0; + + case rocksdb::Transaction::TransactionState::AWAITING_PREPARE: + return 0x1; + + case rocksdb::Transaction::TransactionState::PREPARED: + return 0x2; + + case rocksdb::Transaction::TransactionState::AWAITING_COMMIT: + return 0x3; + + case rocksdb::Transaction::TransactionState::COMMITED: + return 0x4; + + case rocksdb::Transaction::TransactionState::AWAITING_ROLLBACK: + return 0x5; + + case rocksdb::Transaction::TransactionState::ROLLEDBACK: + return 0x6; + + case rocksdb::Transaction::TransactionState::LOCKS_STOLEN: + return 0x7; + } + + assert(false); + return static_cast<jbyte>(-1); +} + +/* + * Class: org_rocksdb_Transaction + * Method: getId + * Signature: (J)J + */ +jlong Java_org_rocksdb_Transaction_getId(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jhandle) { + auto* txn = reinterpret_cast<rocksdb::Transaction*>(jhandle); + uint64_t id = txn->GetId(); + return static_cast<jlong>(id); +} + +/* + * Class: org_rocksdb_Transaction + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_Transaction_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + delete reinterpret_cast<rocksdb::Transaction*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/transaction_db.cc b/src/rocksdb/java/rocksjni/transaction_db.cc new file mode 100644 index 00000000..c2c40bf1 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_db.cc @@ -0,0 +1,453 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::TransactionDB. + +#include <jni.h> +#include <functional> +#include <memory> +#include <utility> + +#include "include/org_rocksdb_TransactionDB.h" + +#include "rocksdb/options.h" +#include "rocksdb/utilities/transaction.h" +#include "rocksdb/utilities/transaction_db.h" + +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_TransactionDB + * Method: open + * Signature: (JJLjava/lang/String;)J + */ +jlong Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2( + JNIEnv* env, jclass, jlong joptions_handle, + jlong jtxn_db_options_handle, jstring jdb_path) { + auto* options = reinterpret_cast<rocksdb::Options*>(joptions_handle); + auto* txn_db_options = + reinterpret_cast<rocksdb::TransactionDBOptions*>(jtxn_db_options_handle); + rocksdb::TransactionDB* tdb = nullptr; + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + rocksdb::Status s = + rocksdb::TransactionDB::Open(*options, *txn_db_options, db_path, &tdb); + env->ReleaseStringUTFChars(jdb_path, db_path); + + if (s.ok()) { + return reinterpret_cast<jlong>(tdb); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: open + * Signature: (JJLjava/lang/String;[[B[J)[J + */ +jlongArray Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2_3_3B_3J( + JNIEnv* env, jclass, jlong jdb_options_handle, + jlong jtxn_db_options_handle, jstring jdb_path, jobjectArray jcolumn_names, + jlongArray jcolumn_options_handles) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + const jsize len_cols = env->GetArrayLength(jcolumn_names); + if (env->EnsureLocalCapacity(len_cols) != 0) { + // out of memory + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + jlong* jco = env->GetLongArrayElements(jcolumn_options_handles, nullptr); + if (jco == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + std::vector<rocksdb::ColumnFamilyDescriptor> column_families; + for (int i = 0; i < len_cols; i++) { + const jobject jcn = env->GetObjectArrayElement(jcolumn_names, i); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + const jbyteArray jcn_ba = reinterpret_cast<jbyteArray>(jcn); + jbyte* jcf_name = env->GetByteArrayElements(jcn_ba, nullptr); + if (jcf_name == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jcn); + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + const int jcf_name_len = env->GetArrayLength(jcn_ba); + if (env->EnsureLocalCapacity(jcf_name_len) != 0) { + // out of memory + env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT); + env->DeleteLocalRef(jcn); + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + const std::string cf_name(reinterpret_cast<char*>(jcf_name), jcf_name_len); + const rocksdb::ColumnFamilyOptions* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[i]); + column_families.push_back( + rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options)); + + env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT); + env->DeleteLocalRef(jcn); + } + env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT); + + auto* db_options = reinterpret_cast<rocksdb::DBOptions*>(jdb_options_handle); + auto* txn_db_options = + reinterpret_cast<rocksdb::TransactionDBOptions*>(jtxn_db_options_handle); + std::vector<rocksdb::ColumnFamilyHandle*> handles; + rocksdb::TransactionDB* tdb = nullptr; + const rocksdb::Status s = rocksdb::TransactionDB::Open( + *db_options, *txn_db_options, db_path, column_families, &handles, &tdb); + + // check if open operation was successful + if (s.ok()) { + const jsize resultsLen = 1 + len_cols; // db handle + column family handles + std::unique_ptr<jlong[]> results = + std::unique_ptr<jlong[]>(new jlong[resultsLen]); + results[0] = reinterpret_cast<jlong>(tdb); + for (int i = 1; i <= len_cols; i++) { + results[i] = reinterpret_cast<jlong>(handles[i - 1]); + } + + jlongArray jresults = env->NewLongArray(resultsLen); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetLongArrayRegion(jresults, 0, resultsLen, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jresults); + return nullptr; + } + return jresults; + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return nullptr; + } +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionDB_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + assert(txn_db != nullptr); + delete txn_db; +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: closeDatabase + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionDB_closeDatabase( + JNIEnv* env, jclass, jlong jhandle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + assert(txn_db != nullptr); + rocksdb::Status s = txn_db->Close(); + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: beginTransaction + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + rocksdb::Transaction* txn = txn_db->BeginTransaction(*write_options); + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: beginTransaction + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle, + jlong jtxn_options_handle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* txn_options = + reinterpret_cast<rocksdb::TransactionOptions*>(jtxn_options_handle); + rocksdb::Transaction* txn = + txn_db->BeginTransaction(*write_options, *txn_options); + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: beginTransaction_withOld + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle, + jlong jold_txn_handle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle); + rocksdb::TransactionOptions txn_options; + rocksdb::Transaction* txn = + txn_db->BeginTransaction(*write_options, txn_options, old_txn); + + // RocksJava relies on the assumption that + // we do not allocate a new Transaction object + // when providing an old_txn + assert(txn == old_txn); + + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: beginTransaction_withOld + * Signature: (JJJJ)J + */ +jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJJ( + JNIEnv*, jobject, jlong jhandle, jlong jwrite_options_handle, + jlong jtxn_options_handle, jlong jold_txn_handle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + auto* write_options = + reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle); + auto* txn_options = + reinterpret_cast<rocksdb::TransactionOptions*>(jtxn_options_handle); + auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle); + rocksdb::Transaction* txn = + txn_db->BeginTransaction(*write_options, *txn_options, old_txn); + + // RocksJava relies on the assumption that + // we do not allocate a new Transaction object + // when providing an old_txn + assert(txn == old_txn); + + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: getTransactionByName + * Signature: (JLjava/lang/String;)J + */ +jlong Java_org_rocksdb_TransactionDB_getTransactionByName( + JNIEnv* env, jobject, jlong jhandle, jstring jname) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + const char* name = env->GetStringUTFChars(jname, nullptr); + if (name == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + rocksdb::Transaction* txn = txn_db->GetTransactionByName(name); + env->ReleaseStringUTFChars(jname, name); + return reinterpret_cast<jlong>(txn); +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: getAllPreparedTransactions + * Signature: (J)[J + */ +jlongArray Java_org_rocksdb_TransactionDB_getAllPreparedTransactions( + JNIEnv* env, jobject, jlong jhandle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + std::vector<rocksdb::Transaction*> txns; + txn_db->GetAllPreparedTransactions(&txns); + + const size_t size = txns.size(); + assert(size < UINT32_MAX); // does it fit in a jint? + + const jsize len = static_cast<jsize>(size); + std::vector<jlong> tmp(len); + for (jsize i = 0; i < len; ++i) { + tmp[i] = reinterpret_cast<jlong>(txns[i]); + } + + jlongArray jtxns = env->NewLongArray(len); + if (jtxns == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + env->SetLongArrayRegion(jtxns, 0, len, tmp.data()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jtxns); + return nullptr; + } + + return jtxns; +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: getLockStatusData + * Signature: (J)Ljava/util/Map; + */ +jobject Java_org_rocksdb_TransactionDB_getLockStatusData( + JNIEnv* env, jobject, jlong jhandle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + const std::unordered_multimap<uint32_t, rocksdb::KeyLockInfo> + lock_status_data = txn_db->GetLockStatusData(); + const jobject jlock_status_data = rocksdb::HashMapJni::construct( + env, static_cast<uint32_t>(lock_status_data.size())); + if (jlock_status_data == nullptr) { + // exception occurred + return nullptr; + } + + const rocksdb::HashMapJni::FnMapKV<const int32_t, const rocksdb::KeyLockInfo, jobject, jobject> + fn_map_kv = + [env]( + const std::pair<const int32_t, const rocksdb::KeyLockInfo>& + pair) { + const jobject jlong_column_family_id = + rocksdb::LongJni::valueOf(env, pair.first); + if (jlong_column_family_id == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + const jobject jkey_lock_info = + rocksdb::KeyLockInfoJni::construct(env, pair.second); + if (jkey_lock_info == nullptr) { + // an error occurred + return std::unique_ptr<std::pair<jobject, jobject>>(nullptr); + } + return std::unique_ptr<std::pair<jobject, jobject>>( + new std::pair<jobject, jobject>(jlong_column_family_id, + jkey_lock_info)); + }; + + if (!rocksdb::HashMapJni::putAll(env, jlock_status_data, + lock_status_data.begin(), + lock_status_data.end(), fn_map_kv)) { + // exception occcurred + return nullptr; + } + + return jlock_status_data; +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: getDeadlockInfoBuffer + * Signature: (J)[Lorg/rocksdb/TransactionDB/DeadlockPath; + */ +jobjectArray Java_org_rocksdb_TransactionDB_getDeadlockInfoBuffer( + JNIEnv* env, jobject jobj, jlong jhandle) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + const std::vector<rocksdb::DeadlockPath> deadlock_info_buffer = + txn_db->GetDeadlockInfoBuffer(); + + const jsize deadlock_info_buffer_len = + static_cast<jsize>(deadlock_info_buffer.size()); + jobjectArray jdeadlock_info_buffer = + env->NewObjectArray(deadlock_info_buffer_len, + rocksdb::DeadlockPathJni::getJClass(env), nullptr); + if (jdeadlock_info_buffer == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + jsize jdeadlock_info_buffer_offset = 0; + + auto buf_end = deadlock_info_buffer.end(); + for (auto buf_it = deadlock_info_buffer.begin(); buf_it != buf_end; + ++buf_it) { + const rocksdb::DeadlockPath deadlock_path = *buf_it; + const std::vector<rocksdb::DeadlockInfo> deadlock_infos = + deadlock_path.path; + const jsize deadlock_infos_len = + static_cast<jsize>(deadlock_info_buffer.size()); + jobjectArray jdeadlock_infos = env->NewObjectArray( + deadlock_infos_len, rocksdb::DeadlockInfoJni::getJClass(env), nullptr); + if (jdeadlock_infos == nullptr) { + // exception thrown: OutOfMemoryError + env->DeleteLocalRef(jdeadlock_info_buffer); + return nullptr; + } + jsize jdeadlock_infos_offset = 0; + + auto infos_end = deadlock_infos.end(); + for (auto infos_it = deadlock_infos.begin(); infos_it != infos_end; + ++infos_it) { + const rocksdb::DeadlockInfo deadlock_info = *infos_it; + const jobject jdeadlock_info = rocksdb::TransactionDBJni::newDeadlockInfo( + env, jobj, deadlock_info.m_txn_id, deadlock_info.m_cf_id, + deadlock_info.m_waiting_key, deadlock_info.m_exclusive); + if (jdeadlock_info == nullptr) { + // exception occcurred + env->DeleteLocalRef(jdeadlock_info_buffer); + return nullptr; + } + env->SetObjectArrayElement(jdeadlock_infos, jdeadlock_infos_offset++, + jdeadlock_info); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException or + // ArrayStoreException + env->DeleteLocalRef(jdeadlock_info); + env->DeleteLocalRef(jdeadlock_info_buffer); + return nullptr; + } + } + + const jobject jdeadlock_path = rocksdb::DeadlockPathJni::construct( + env, jdeadlock_infos, deadlock_path.limit_exceeded); + if (jdeadlock_path == nullptr) { + // exception occcurred + env->DeleteLocalRef(jdeadlock_info_buffer); + return nullptr; + } + env->SetObjectArrayElement(jdeadlock_info_buffer, + jdeadlock_info_buffer_offset++, jdeadlock_path); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException or ArrayStoreException + env->DeleteLocalRef(jdeadlock_path); + env->DeleteLocalRef(jdeadlock_info_buffer); + return nullptr; + } + } + + return jdeadlock_info_buffer; +} + +/* + * Class: org_rocksdb_TransactionDB + * Method: setDeadlockInfoBufferSize + * Signature: (JI)V + */ +void Java_org_rocksdb_TransactionDB_setDeadlockInfoBufferSize( + JNIEnv*, jobject, jlong jhandle, jint jdeadlock_info_buffer_size) { + auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle); + txn_db->SetDeadlockInfoBufferSize(jdeadlock_info_buffer_size); +} diff --git a/src/rocksdb/java/rocksjni/transaction_db_options.cc b/src/rocksdb/java/rocksjni/transaction_db_options.cc new file mode 100644 index 00000000..391accc3 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_db_options.cc @@ -0,0 +1,158 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::TransactionDBOptions. + +#include <jni.h> + +#include "include/org_rocksdb_TransactionDBOptions.h" + +#include "rocksdb/utilities/transaction_db.h" + +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: newTransactionDBOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_TransactionDBOptions_newTransactionDBOptions( + JNIEnv* /*env*/, jclass /*jcls*/) { + rocksdb::TransactionDBOptions* opts = new rocksdb::TransactionDBOptions(); + return reinterpret_cast<jlong>(opts); +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: getMaxNumLocks + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionDBOptions_getMaxNumLocks(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + return opts->max_num_locks; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: setMaxNumLocks + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionDBOptions_setMaxNumLocks( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jlong jmax_num_locks) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + opts->max_num_locks = jmax_num_locks; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: getNumStripes + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionDBOptions_getNumStripes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + return opts->num_stripes; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: setNumStripes + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionDBOptions_setNumStripes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jnum_stripes) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + opts->num_stripes = jnum_stripes; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: getTransactionLockTimeout + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionDBOptions_getTransactionLockTimeout( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + return opts->transaction_lock_timeout; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: setTransactionLockTimeout + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionDBOptions_setTransactionLockTimeout( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jtransaction_lock_timeout) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + opts->transaction_lock_timeout = jtransaction_lock_timeout; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: getDefaultLockTimeout + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionDBOptions_getDefaultLockTimeout( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + return opts->default_lock_timeout; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: setDefaultLockTimeout + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionDBOptions_setDefaultLockTimeout( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jdefault_lock_timeout) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + opts->default_lock_timeout = jdefault_lock_timeout; +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: getWritePolicy + * Signature: (J)B + */ +jbyte Java_org_rocksdb_TransactionDBOptions_getWritePolicy(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + return rocksdb::TxnDBWritePolicyJni::toJavaTxnDBWritePolicy( + opts->write_policy); +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: setWritePolicy + * Signature: (JB)V + */ +void Java_org_rocksdb_TransactionDBOptions_setWritePolicy(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jbyte jwrite_policy) { + auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); + opts->write_policy = + rocksdb::TxnDBWritePolicyJni::toCppTxnDBWritePolicy(jwrite_policy); +} + +/* + * Class: org_rocksdb_TransactionDBOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionDBOptions_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + delete reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/transaction_log.cc b/src/rocksdb/java/rocksjni/transaction_log.cc new file mode 100644 index 00000000..8186a846 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_log.cc @@ -0,0 +1,76 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::Iterator methods from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> + +#include "include/org_rocksdb_TransactionLogIterator.h" +#include "rocksdb/transaction_log.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_TransactionLogIterator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionLogIterator_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + delete reinterpret_cast<rocksdb::TransactionLogIterator*>(handle); +} + +/* + * Class: org_rocksdb_TransactionLogIterator + * Method: isValid + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_TransactionLogIterator_isValid(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<rocksdb::TransactionLogIterator*>(handle)->Valid(); +} + +/* + * Class: org_rocksdb_TransactionLogIterator + * Method: next + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionLogIterator_next(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::TransactionLogIterator*>(handle)->Next(); +} + +/* + * Class: org_rocksdb_TransactionLogIterator + * Method: status + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionLogIterator_status(JNIEnv* env, + jobject /*jobj*/, + jlong handle) { + rocksdb::Status s = + reinterpret_cast<rocksdb::TransactionLogIterator*>(handle)->status(); + if (!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_TransactionLogIterator + * Method: getBatch + * Signature: (J)Lorg/rocksdb/TransactionLogIterator$BatchResult + */ +jobject Java_org_rocksdb_TransactionLogIterator_getBatch(JNIEnv* env, + jobject /*jobj*/, + jlong handle) { + rocksdb::BatchResult batch_result = + reinterpret_cast<rocksdb::TransactionLogIterator*>(handle)->GetBatch(); + return rocksdb::BatchResultJni::construct(env, batch_result); +} diff --git a/src/rocksdb/java/rocksjni/transaction_notifier.cc b/src/rocksdb/java/rocksjni/transaction_notifier.cc new file mode 100644 index 00000000..b60076e1 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_notifier.cc @@ -0,0 +1,42 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::TransactionNotifier. + +#include <jni.h> + +#include "include/org_rocksdb_AbstractTransactionNotifier.h" +#include "rocksjni/transaction_notifier_jnicallback.h" + +/* + * Class: org_rocksdb_AbstractTransactionNotifier + * Method: createNewTransactionNotifier + * Signature: ()J + */ +jlong Java_org_rocksdb_AbstractTransactionNotifier_createNewTransactionNotifier( + JNIEnv* env, jobject jobj) { + auto* transaction_notifier = + new rocksdb::TransactionNotifierJniCallback(env, jobj); + auto* sptr_transaction_notifier = + new std::shared_ptr<rocksdb::TransactionNotifierJniCallback>( + transaction_notifier); + return reinterpret_cast<jlong>(sptr_transaction_notifier); +} + +/* + * Class: org_rocksdb_AbstractTransactionNotifier + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_AbstractTransactionNotifier_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + // TODO(AR) refactor to use JniCallback::JniCallback + // when https://github.com/facebook/rocksdb/pull/1241/ is merged + std::shared_ptr<rocksdb::TransactionNotifierJniCallback>* handle = + reinterpret_cast< + std::shared_ptr<rocksdb::TransactionNotifierJniCallback>*>(jhandle); + delete handle; +} diff --git a/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.cc b/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.cc new file mode 100644 index 00000000..85f2a194 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.cc @@ -0,0 +1,39 @@ +// 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::TransactionNotifier. + +#include "rocksjni/transaction_notifier_jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { + +TransactionNotifierJniCallback::TransactionNotifierJniCallback(JNIEnv* env, + jobject jtransaction_notifier) : JniCallback(env, jtransaction_notifier) { + // we cache the method id for the JNI callback + m_jsnapshot_created_methodID = + AbstractTransactionNotifierJni::getSnapshotCreatedMethodId(env); +} + +void TransactionNotifierJniCallback::SnapshotCreated( + const Snapshot* newSnapshot) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + assert(env != nullptr); + + env->CallVoidMethod(m_jcallback_obj, + m_jsnapshot_created_methodID, reinterpret_cast<jlong>(newSnapshot)); + + if(env->ExceptionCheck()) { + // exception thrown from CallVoidMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return; + } + + releaseJniEnv(attached_thread); +} +} // namespace rocksdb diff --git a/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.h b/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.h new file mode 100644 index 00000000..8f67cdb8 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_notifier_jnicallback.h @@ -0,0 +1,42 @@ +// 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::TransactionNotifier. + +#ifndef JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_ + +#include <jni.h> + +#include "rocksdb/utilities/transaction.h" +#include "rocksjni/jnicallback.h" + +namespace rocksdb { + +/** + * This class acts as a bridge between C++ + * and Java. The methods in this class will be + * called back from the RocksDB TransactionDB or OptimisticTransactionDB (C++), + * we then callback to the appropriate Java method + * this enables TransactionNotifier to be implemented in Java. + * + * Unlike RocksJava's Comparator JNI Callback, we do not attempt + * to reduce Java object allocations by caching the Snapshot object + * presented to the callback. This could be revisited in future + * if performance is lacking. + */ +class TransactionNotifierJniCallback: public JniCallback, + public TransactionNotifier { + public: + TransactionNotifierJniCallback(JNIEnv* env, jobject jtransaction_notifier); + virtual void SnapshotCreated(const Snapshot* newSnapshot); + + private: + jmethodID m_jsnapshot_created_methodID; +}; +} // namespace rocksdb + +#endif // JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/transaction_options.cc b/src/rocksdb/java/rocksjni/transaction_options.cc new file mode 100644 index 00000000..d18a5294 --- /dev/null +++ b/src/rocksdb/java/rocksjni/transaction_options.cc @@ -0,0 +1,179 @@ +// 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 "bridge" between Java and C++ +// for rocksdb::TransactionOptions. + +#include <jni.h> + +#include "include/org_rocksdb_TransactionOptions.h" + +#include "rocksdb/utilities/transaction_db.h" + +/* + * Class: org_rocksdb_TransactionOptions + * Method: newTransactionOptions + * Signature: ()J + */ +jlong Java_org_rocksdb_TransactionOptions_newTransactionOptions( + JNIEnv* /*env*/, jclass /*jcls*/) { + auto* opts = new rocksdb::TransactionOptions(); + return reinterpret_cast<jlong>(opts); +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: isSetSnapshot + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_TransactionOptions_isSetSnapshot(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->set_snapshot; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setSetSnapshot + * Signature: (JZ)V + */ +void Java_org_rocksdb_TransactionOptions_setSetSnapshot( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, jboolean jset_snapshot) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->set_snapshot = jset_snapshot; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: isDeadlockDetect + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_TransactionOptions_isDeadlockDetect(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->deadlock_detect; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setDeadlockDetect + * Signature: (JZ)V + */ +void Java_org_rocksdb_TransactionOptions_setDeadlockDetect( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jboolean jdeadlock_detect) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->deadlock_detect = jdeadlock_detect; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: getLockTimeout + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionOptions_getLockTimeout(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->lock_timeout; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setLockTimeout + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionOptions_setLockTimeout(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jlock_timeout) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->lock_timeout = jlock_timeout; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: getExpiration + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionOptions_getExpiration(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->expiration; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setExpiration + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionOptions_setExpiration(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle, + jlong jexpiration) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->expiration = jexpiration; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: getDeadlockDetectDepth + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionOptions_getDeadlockDetectDepth( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->deadlock_detect_depth; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setDeadlockDetectDepth + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionOptions_setDeadlockDetectDepth( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jdeadlock_detect_depth) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->deadlock_detect_depth = jdeadlock_detect_depth; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: getMaxWriteBatchSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_TransactionOptions_getMaxWriteBatchSize(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + return opts->max_write_batch_size; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: setMaxWriteBatchSize + * Signature: (JJ)V + */ +void Java_org_rocksdb_TransactionOptions_setMaxWriteBatchSize( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle, + jlong jmax_write_batch_size) { + auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); + opts->max_write_batch_size = jmax_write_batch_size; +} + +/* + * Class: org_rocksdb_TransactionOptions + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TransactionOptions_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jhandle) { + delete reinterpret_cast<rocksdb::TransactionOptions*>(jhandle); +} diff --git a/src/rocksdb/java/rocksjni/ttl.cc b/src/rocksdb/java/rocksjni/ttl.cc new file mode 100644 index 00000000..4b071e7b --- /dev/null +++ b/src/rocksdb/java/rocksjni/ttl.cc @@ -0,0 +1,207 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::TtlDB methods. +// from Java side. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory> +#include <string> +#include <vector> + +#include "include/org_rocksdb_TtlDB.h" +#include "rocksdb/utilities/db_ttl.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_TtlDB + * Method: open + * Signature: (JLjava/lang/String;IZ)J + */ +jlong Java_org_rocksdb_TtlDB_open( + JNIEnv* env, jclass, jlong joptions_handle, jstring jdb_path, jint jttl, + jboolean jread_only) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + auto* opt = reinterpret_cast<rocksdb::Options*>(joptions_handle); + rocksdb::DBWithTTL* db = nullptr; + rocksdb::Status s = + rocksdb::DBWithTTL::Open(*opt, db_path, &db, jttl, jread_only); + env->ReleaseStringUTFChars(jdb_path, db_path); + + // as TTLDB extends RocksDB on the java side, we can reuse + // the RocksDB portal here. + if (s.ok()) { + return reinterpret_cast<jlong>(db); + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; + } +} + +/* + * Class: org_rocksdb_TtlDB + * Method: openCF + * Signature: (JLjava/lang/String;[[B[J[IZ)[J + */ +jlongArray Java_org_rocksdb_TtlDB_openCF( + JNIEnv* env, jclass, jlong jopt_handle, jstring jdb_path, + jobjectArray jcolumn_names, jlongArray jcolumn_options, + jintArray jttls, jboolean jread_only) { + const char* db_path = env->GetStringUTFChars(jdb_path, nullptr); + if (db_path == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + const jsize len_cols = env->GetArrayLength(jcolumn_names); + jlong* jco = env->GetLongArrayElements(jcolumn_options, nullptr); + if (jco == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + std::vector<rocksdb::ColumnFamilyDescriptor> column_families; + jboolean has_exception = JNI_FALSE; + rocksdb::JniUtil::byteStrings<std::string>( + env, jcolumn_names, + [](const char* str_data, const size_t str_len) { + return std::string(str_data, str_len); + }, + [&jco, &column_families](size_t idx, std::string cf_name) { + rocksdb::ColumnFamilyOptions* cf_options = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[idx]); + column_families.push_back( + rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options)); + }, + &has_exception); + + env->ReleaseLongArrayElements(jcolumn_options, jco, JNI_ABORT); + + if (has_exception == JNI_TRUE) { + // exception occurred + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + + std::vector<int32_t> ttl_values; + jint* jttlv = env->GetIntArrayElements(jttls, nullptr); + if (jttlv == nullptr) { + // exception thrown: OutOfMemoryError + env->ReleaseStringUTFChars(jdb_path, db_path); + return nullptr; + } + const jsize len_ttls = env->GetArrayLength(jttls); + for (jsize i = 0; i < len_ttls; i++) { + ttl_values.push_back(jttlv[i]); + } + env->ReleaseIntArrayElements(jttls, jttlv, JNI_ABORT); + + auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jopt_handle); + std::vector<rocksdb::ColumnFamilyHandle*> handles; + rocksdb::DBWithTTL* db = nullptr; + rocksdb::Status s = rocksdb::DBWithTTL::Open( + *opt, db_path, column_families, &handles, &db, ttl_values, jread_only); + + // we have now finished with db_path + env->ReleaseStringUTFChars(jdb_path, db_path); + + // check if open operation was successful + if (s.ok()) { + const jsize resultsLen = 1 + len_cols; // db handle + column family handles + std::unique_ptr<jlong[]> results = + std::unique_ptr<jlong[]>(new jlong[resultsLen]); + results[0] = reinterpret_cast<jlong>(db); + for (int i = 1; i <= len_cols; i++) { + results[i] = reinterpret_cast<jlong>(handles[i - 1]); + } + + jlongArray jresults = env->NewLongArray(resultsLen); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetLongArrayRegion(jresults, 0, resultsLen, results.get()); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jresults); + return nullptr; + } + + return jresults; + } else { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return NULL; + } +} + +/* + * Class: org_rocksdb_TtlDB + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_TtlDB_disposeInternal( + JNIEnv*, jobject, jlong jhandle) { + auto* ttl_db = reinterpret_cast<rocksdb::DBWithTTL*>(jhandle); + assert(ttl_db != nullptr); + delete ttl_db; +} + +/* + * Class: org_rocksdb_TtlDB + * Method: closeDatabase + * Signature: (J)V + */ +void Java_org_rocksdb_TtlDB_closeDatabase( + JNIEnv* /* env */, jclass, jlong /* jhandle */) { + //auto* ttl_db = reinterpret_cast<rocksdb::DBWithTTL*>(jhandle); + //assert(ttl_db != nullptr); + //rocksdb::Status s = ttl_db->Close(); + //rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + + //TODO(AR) this is disabled until https://github.com/facebook/rocksdb/issues/4818 is resolved! +} + +/* + * Class: org_rocksdb_TtlDB + * Method: createColumnFamilyWithTtl + * Signature: (JLorg/rocksdb/ColumnFamilyDescriptor;[BJI)J; + */ +jlong Java_org_rocksdb_TtlDB_createColumnFamilyWithTtl( + JNIEnv* env, jobject, jlong jdb_handle, jbyteArray jcolumn_name, + jlong jcolumn_options, jint jttl) { + jbyte* cfname = env->GetByteArrayElements(jcolumn_name, nullptr); + if (cfname == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + const jsize len = env->GetArrayLength(jcolumn_name); + + auto* cfOptions = + reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jcolumn_options); + + auto* db_handle = reinterpret_cast<rocksdb::DBWithTTL*>(jdb_handle); + rocksdb::ColumnFamilyHandle* handle; + rocksdb::Status s = db_handle->CreateColumnFamilyWithTtl( + *cfOptions, std::string(reinterpret_cast<char*>(cfname), len), &handle, + jttl); + + env->ReleaseByteArrayElements(jcolumn_name, cfname, 0); + + if (s.ok()) { + return reinterpret_cast<jlong>(handle); + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + return 0; +} diff --git a/src/rocksdb/java/rocksjni/wal_filter.cc b/src/rocksdb/java/rocksjni/wal_filter.cc new file mode 100644 index 00000000..c74e5425 --- /dev/null +++ b/src/rocksdb/java/rocksjni/wal_filter.cc @@ -0,0 +1,23 @@ +// 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 "bridge" between Java and C++ for +// rocksdb::WalFilter. + +#include <jni.h> + +#include "include/org_rocksdb_AbstractWalFilter.h" +#include "rocksjni/wal_filter_jnicallback.h" + +/* + * Class: org_rocksdb_AbstractWalFilter + * Method: createNewWalFilter + * Signature: ()J + */ +jlong Java_org_rocksdb_AbstractWalFilter_createNewWalFilter( + JNIEnv* env, jobject jobj) { + auto* wal_filter = new rocksdb::WalFilterJniCallback(env, jobj); + return reinterpret_cast<jlong>(wal_filter); +}
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/wal_filter_jnicallback.cc b/src/rocksdb/java/rocksjni/wal_filter_jnicallback.cc new file mode 100644 index 00000000..8fd90925 --- /dev/null +++ b/src/rocksdb/java/rocksjni/wal_filter_jnicallback.cc @@ -0,0 +1,144 @@ +// 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::WalFilter. + +#include "rocksjni/wal_filter_jnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +WalFilterJniCallback::WalFilterJniCallback( + JNIEnv* env, jobject jwal_filter) + : JniCallback(env, jwal_filter) { + // Note: The name of a WalFilter will not change during it's lifetime, + // so we cache it in a global var + jmethodID jname_mid = AbstractWalFilterJni::getNameMethodId(env); + if(jname_mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + jstring jname = (jstring)env->CallObjectMethod(m_jcallback_obj, jname_mid); + if(env->ExceptionCheck()) { + // exception thrown + return; + } + jboolean has_exception = JNI_FALSE; + m_name = JniUtil::copyString(env, jname, + &has_exception); // also releases jname + if (has_exception == JNI_TRUE) { + // exception thrown + return; + } + + m_column_family_log_number_map_mid = + AbstractWalFilterJni::getColumnFamilyLogNumberMapMethodId(env); + if(m_column_family_log_number_map_mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } + + m_log_record_found_proxy_mid = + AbstractWalFilterJni::getLogRecordFoundProxyMethodId(env); + if(m_log_record_found_proxy_mid == nullptr) { + // exception thrown: NoSuchMethodException or OutOfMemoryError + return; + } +} + +void WalFilterJniCallback::ColumnFamilyLogNumberMap( + const std::map<uint32_t, uint64_t>& cf_lognumber_map, + const std::map<std::string, uint32_t>& cf_name_id_map) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + if (env == nullptr) { + return; + } + + jobject jcf_lognumber_map = + rocksdb::HashMapJni::fromCppMap(env, &cf_lognumber_map); + if (jcf_lognumber_map == nullptr) { + // exception occurred + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return; + } + + jobject jcf_name_id_map = + rocksdb::HashMapJni::fromCppMap(env, &cf_name_id_map); + if (jcf_name_id_map == nullptr) { + // exception occurred + env->ExceptionDescribe(); // print out exception to stderr + env->DeleteLocalRef(jcf_lognumber_map); + releaseJniEnv(attached_thread); + return; + } + + env->CallVoidMethod(m_jcallback_obj, + m_column_family_log_number_map_mid, + jcf_lognumber_map, + jcf_name_id_map); + + env->DeleteLocalRef(jcf_lognumber_map); + env->DeleteLocalRef(jcf_name_id_map); + + if(env->ExceptionCheck()) { + // exception thrown from CallVoidMethod + env->ExceptionDescribe(); // print out exception to stderr + } + + releaseJniEnv(attached_thread); +} + + WalFilter::WalProcessingOption WalFilterJniCallback::LogRecordFound( + unsigned long long log_number, const std::string& log_file_name, + const WriteBatch& batch, WriteBatch* new_batch, bool* batch_changed) { + jboolean attached_thread = JNI_FALSE; + JNIEnv* env = getJniEnv(&attached_thread); + if (env == nullptr) { + return WalFilter::WalProcessingOption::kCorruptedRecord; + } + + jstring jlog_file_name = JniUtil::toJavaString(env, &log_file_name); + if (jlog_file_name == nullptr) { + // exception occcurred + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return WalFilter::WalProcessingOption::kCorruptedRecord; + } + + jshort jlog_record_found_result = env->CallShortMethod(m_jcallback_obj, + m_log_record_found_proxy_mid, + static_cast<jlong>(log_number), + jlog_file_name, + reinterpret_cast<jlong>(&batch), + reinterpret_cast<jlong>(new_batch)); + + env->DeleteLocalRef(jlog_file_name); + + if (env->ExceptionCheck()) { + // exception thrown from CallShortMethod + env->ExceptionDescribe(); // print out exception to stderr + releaseJniEnv(attached_thread); + return WalFilter::WalProcessingOption::kCorruptedRecord; + } + + // unpack WalProcessingOption and batch_changed from jlog_record_found_result + jbyte jwal_processing_option_value = (jlog_record_found_result >> 8) & 0xFF; + jbyte jbatch_changed_value = jlog_record_found_result & 0xFF; + + releaseJniEnv(attached_thread); + + *batch_changed = jbatch_changed_value == JNI_TRUE; + + return WalProcessingOptionJni::toCppWalProcessingOption( + jwal_processing_option_value); +} + +const char* WalFilterJniCallback::Name() const { + return m_name.get(); +} + +} // namespace rocksdb
\ No newline at end of file diff --git a/src/rocksdb/java/rocksjni/wal_filter_jnicallback.h b/src/rocksdb/java/rocksjni/wal_filter_jnicallback.h new file mode 100644 index 00000000..df6394ce --- /dev/null +++ b/src/rocksdb/java/rocksjni/wal_filter_jnicallback.h @@ -0,0 +1,42 @@ +// 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::WalFilter. + +#ifndef JAVA_ROCKSJNI_WAL_FILTER_JNICALLBACK_H_ +#define JAVA_ROCKSJNI_WAL_FILTER_JNICALLBACK_H_ + +#include <jni.h> +#include <map> +#include <memory> +#include <string> + +#include "rocksdb/wal_filter.h" +#include "rocksjni/jnicallback.h" + +namespace rocksdb { + +class WalFilterJniCallback : public JniCallback, public WalFilter { + public: + WalFilterJniCallback( + JNIEnv* env, jobject jwal_filter); + virtual void ColumnFamilyLogNumberMap( + const std::map<uint32_t, uint64_t>& cf_lognumber_map, + const std::map<std::string, uint32_t>& cf_name_id_map); + virtual WalFilter::WalProcessingOption LogRecordFound( + unsigned long long log_number, const std::string& log_file_name, + const WriteBatch& batch, WriteBatch* new_batch, bool* batch_changed); + virtual const char* Name() const; + + private: + std::unique_ptr<const char[]> m_name; + jmethodID m_column_family_log_number_map_mid; + jmethodID m_log_record_found_proxy_mid; +}; + +} //namespace rocksdb + +#endif // JAVA_ROCKSJNI_WAL_FILTER_JNICALLBACK_H_ diff --git a/src/rocksdb/java/rocksjni/write_batch.cc b/src/rocksdb/java/rocksjni/write_batch.cc new file mode 100644 index 00000000..f1b77446 --- /dev/null +++ b/src/rocksdb/java/rocksjni/write_batch.cc @@ -0,0 +1,604 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::WriteBatch methods from Java side. +#include <memory> + +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "include/org_rocksdb_WriteBatch.h" +#include "include/org_rocksdb_WriteBatch_Handler.h" +#include "rocksdb/db.h" +#include "rocksdb/env.h" +#include "rocksdb/memtablerep.h" +#include "rocksdb/status.h" +#include "rocksdb/write_batch.h" +#include "rocksdb/write_buffer_manager.h" +#include "rocksjni/portal.h" +#include "rocksjni/writebatchhandlerjnicallback.h" +#include "table/scoped_arena_iterator.h" +#include "util/logging.h" + +/* + * Class: org_rocksdb_WriteBatch + * Method: newWriteBatch + * Signature: (I)J + */ +jlong Java_org_rocksdb_WriteBatch_newWriteBatch__I(JNIEnv* /*env*/, + jclass /*jcls*/, + jint jreserved_bytes) { + auto* wb = new rocksdb::WriteBatch(static_cast<size_t>(jreserved_bytes)); + return reinterpret_cast<jlong>(wb); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: newWriteBatch + * Signature: ([BI)J + */ +jlong Java_org_rocksdb_WriteBatch_newWriteBatch___3BI(JNIEnv* env, + jclass /*jcls*/, + jbyteArray jserialized, + jint jserialized_length) { + jboolean has_exception = JNI_FALSE; + std::string serialized = rocksdb::JniUtil::byteString<std::string>( + env, jserialized, jserialized_length, + [](const char* str, const size_t len) { return std::string(str, len); }, + &has_exception); + if (has_exception == JNI_TRUE) { + // exception occurred + return 0; + } + + auto* wb = new rocksdb::WriteBatch(serialized); + return reinterpret_cast<jlong>(wb); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: count0 + * Signature: (J)I + */ +jint Java_org_rocksdb_WriteBatch_count0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return static_cast<jint>(wb->Count()); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: clear0 + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_clear0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + wb->Clear(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: setSavePoint0 + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_setSavePoint0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + wb->SetSavePoint(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: rollbackToSavePoint0 + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_rollbackToSavePoint0(JNIEnv* env, + jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + auto s = wb->RollbackToSavePoint(); + + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: popSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_popSavePoint(JNIEnv* env, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + auto s = wb->PopSavePoint(); + + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: setMaxBytes + * Signature: (JJ)V + */ +void Java_org_rocksdb_WriteBatch_setMaxBytes(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jwb_handle, + jlong jmax_bytes) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + wb->SetMaxBytes(static_cast<size_t>(jmax_bytes)); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: put + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatch_put__J_3BI_3BI(JNIEnv* env, jobject jobj, + jlong jwb_handle, + jbyteArray jkey, jint jkey_len, + jbyteArray jentry_value, + jint jentry_value_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto put = [&wb](rocksdb::Slice key, rocksdb::Slice value) { + return wb->Put(key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: put + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatch_put__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jkey, jint jkey_len, + jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto put = [&wb, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) { + return wb->Put(cf_handle, key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: merge + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatch_merge__J_3BI_3BI( + JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jkey, jint jkey_len, + jbyteArray jentry_value, jint jentry_value_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto merge = [&wb](rocksdb::Slice key, rocksdb::Slice value) { + return wb->Merge(key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: merge + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatch_merge__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jkey, jint jkey_len, + jbyteArray jentry_value, jint jentry_value_len, jlong jcf_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto merge = [&wb, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) { + return wb->Merge(cf_handle, key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: delete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatch_delete__J_3BI(JNIEnv* env, jobject jobj, + jlong jwb_handle, + jbyteArray jkey, jint jkey_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto remove = [&wb](rocksdb::Slice key) { return wb->Delete(key); }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: delete + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_WriteBatch_delete__J_3BIJ(JNIEnv* env, jobject jobj, + jlong jwb_handle, + jbyteArray jkey, jint jkey_len, + jlong jcf_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto remove = [&wb, &cf_handle](rocksdb::Slice key) { + return wb->Delete(cf_handle, key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: singleDelete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatch_singleDelete__J_3BI(JNIEnv* env, jobject jobj, + jlong jwb_handle, + jbyteArray jkey, + jint jkey_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto single_delete = [&wb](rocksdb::Slice key) { + return wb->SingleDelete(key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: singleDelete + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_WriteBatch_singleDelete__J_3BIJ(JNIEnv* env, jobject jobj, + jlong jwb_handle, + jbyteArray jkey, + jint jkey_len, + jlong jcf_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto single_delete = [&wb, &cf_handle](rocksdb::Slice key) { + return wb->SingleDelete(cf_handle, key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: deleteRange + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI( + JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key, + jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto deleteRange = [&wb](rocksdb::Slice beginKey, rocksdb::Slice endKey) { + return wb->DeleteRange(beginKey, endKey); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, + jbegin_key_len, jend_key, jend_key_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: deleteRange + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key, + jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len, + jlong jcf_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto deleteRange = [&wb, &cf_handle](rocksdb::Slice beginKey, + rocksdb::Slice endKey) { + return wb->DeleteRange(cf_handle, beginKey, endKey); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, + jbegin_key_len, jend_key, jend_key_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: putLogData + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatch_putLogData(JNIEnv* env, jobject jobj, + jlong jwb_handle, jbyteArray jblob, + jint jblob_len) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + auto putLogData = [&wb](rocksdb::Slice blob) { return wb->PutLogData(blob); }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: iterate + * Signature: (JJ)V + */ +void Java_org_rocksdb_WriteBatch_iterate(JNIEnv* env, jobject /*jobj*/, + jlong jwb_handle, + jlong handlerHandle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + rocksdb::Status s = wb->Iterate( + reinterpret_cast<rocksdb::WriteBatchHandlerJniCallback*>(handlerHandle)); + + if (s.ok()) { + return; + } + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: data + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_WriteBatch_data(JNIEnv* env, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + auto data = wb->Data(); + return rocksdb::JniUtil::copyBytes(env, data); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: getDataSize + * Signature: (J)J + */ +jlong Java_org_rocksdb_WriteBatch_getDataSize(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + auto data_size = wb->GetDataSize(); + return static_cast<jlong>(data_size); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasPut + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteBatch_hasPut(JNIEnv* /*env*/, jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasPut(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasDelete + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WriteBatch_hasDelete(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasDelete(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasSingleDelete + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasSingleDelete( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasSingleDelete(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasDeleteRange + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasDeleteRange( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasDeleteRange(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasMerge + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasMerge( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasMerge(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasBeginPrepare + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasBeginPrepare( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasBeginPrepare(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasEndPrepare + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasEndPrepare( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasEndPrepare(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasCommit + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasCommit( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasCommit(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: hasRollback + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasRollback( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return wb->HasRollback(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: markWalTerminationPoint + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_markWalTerminationPoint(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + wb->MarkWalTerminationPoint(); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: getWalTerminationPoint + * Signature: (J)Lorg/rocksdb/WriteBatch/SavePoint; + */ +jobject Java_org_rocksdb_WriteBatch_getWalTerminationPoint(JNIEnv* env, + jobject /*jobj*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + auto save_point = wb->GetWalTerminationPoint(); + return rocksdb::WriteBatchSavePointJni::construct(env, save_point); +} + +/* + * Class: org_rocksdb_WriteBatch + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatch_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(handle); + assert(wb != nullptr); + delete wb; +} + +/* + * Class: org_rocksdb_WriteBatch_Handler + * Method: createNewHandler0 + * Signature: ()J + */ +jlong Java_org_rocksdb_WriteBatch_00024Handler_createNewHandler0(JNIEnv* env, + jobject jobj) { + auto* wbjnic = new rocksdb::WriteBatchHandlerJniCallback(env, jobj); + return reinterpret_cast<jlong>(wbjnic); +} diff --git a/src/rocksdb/java/rocksjni/write_batch_test.cc b/src/rocksdb/java/rocksjni/write_batch_test.cc new file mode 100644 index 00000000..266fb4ab --- /dev/null +++ b/src/rocksdb/java/rocksjni/write_batch_test.cc @@ -0,0 +1,194 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::WriteBatch methods testing from Java side. +#include <memory> + +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "include/org_rocksdb_WriteBatch.h" +#include "include/org_rocksdb_WriteBatchTest.h" +#include "include/org_rocksdb_WriteBatchTestInternalHelper.h" +#include "include/org_rocksdb_WriteBatch_Handler.h" +#include "options/cf_options.h" +#include "rocksdb/db.h" +#include "rocksdb/env.h" +#include "rocksdb/memtablerep.h" +#include "rocksdb/status.h" +#include "rocksdb/write_batch.h" +#include "rocksdb/write_buffer_manager.h" +#include "rocksjni/portal.h" +#include "table/scoped_arena_iterator.h" +#include "util/string_util.h" +#include "util/testharness.h" + +/* + * Class: org_rocksdb_WriteBatchTest + * Method: getContents + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(JNIEnv* env, + jclass /*jclazz*/, + jlong jwb_handle) { + auto* b = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(b != nullptr); + + // todo: Currently the following code is directly copied from + // db/write_bench_test.cc. It could be implemented in java once + // all the necessary components can be accessed via jni api. + + rocksdb::InternalKeyComparator cmp(rocksdb::BytewiseComparator()); + auto factory = std::make_shared<rocksdb::SkipListFactory>(); + rocksdb::Options options; + rocksdb::WriteBufferManager wb(options.db_write_buffer_size); + options.memtable_factory = factory; + rocksdb::MemTable* mem = new rocksdb::MemTable( + cmp, rocksdb::ImmutableCFOptions(options), + rocksdb::MutableCFOptions(options), &wb, rocksdb::kMaxSequenceNumber, + 0 /* column_family_id */); + mem->Ref(); + std::string state; + rocksdb::ColumnFamilyMemTablesDefault cf_mems_default(mem); + rocksdb::Status s = + rocksdb::WriteBatchInternal::InsertInto(b, &cf_mems_default, nullptr); + int count = 0; + rocksdb::Arena arena; + rocksdb::ScopedArenaIterator iter( + mem->NewIterator(rocksdb::ReadOptions(), &arena)); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + rocksdb::ParsedInternalKey ikey; + ikey.clear(); + bool parsed = rocksdb::ParseInternalKey(iter->key(), &ikey); + if (!parsed) { + assert(parsed); + } + switch (ikey.type) { + case rocksdb::kTypeValue: + state.append("Put("); + state.append(ikey.user_key.ToString()); + state.append(", "); + state.append(iter->value().ToString()); + state.append(")"); + count++; + break; + case rocksdb::kTypeMerge: + state.append("Merge("); + state.append(ikey.user_key.ToString()); + state.append(", "); + state.append(iter->value().ToString()); + state.append(")"); + count++; + break; + case rocksdb::kTypeDeletion: + state.append("Delete("); + state.append(ikey.user_key.ToString()); + state.append(")"); + count++; + break; + case rocksdb::kTypeSingleDeletion: + state.append("SingleDelete("); + state.append(ikey.user_key.ToString()); + state.append(")"); + count++; + break; + case rocksdb::kTypeRangeDeletion: + state.append("DeleteRange("); + state.append(ikey.user_key.ToString()); + state.append(", "); + state.append(iter->value().ToString()); + state.append(")"); + count++; + break; + case rocksdb::kTypeLogData: + state.append("LogData("); + state.append(ikey.user_key.ToString()); + state.append(")"); + count++; + break; + default: + assert(false); + state.append("Err:Expected("); + state.append(std::to_string(ikey.type)); + state.append(")"); + count++; + break; + } + state.append("@"); + state.append(rocksdb::NumberToString(ikey.sequence)); + } + if (!s.ok()) { + state.append(s.ToString()); + } else if (rocksdb::WriteBatchInternal::Count(b) != count) { + state.append("Err:CountMismatch(expected="); + state.append(std::to_string(rocksdb::WriteBatchInternal::Count(b))); + state.append(", actual="); + state.append(std::to_string(count)); + state.append(")"); + } + delete mem->Unref(); + + jbyteArray jstate = env->NewByteArray(static_cast<jsize>(state.size())); + if (jstate == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + jstate, 0, static_cast<jsize>(state.size()), + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(state.c_str()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jstate); + return nullptr; + } + + return jstate; +} + +/* + * Class: org_rocksdb_WriteBatchTestInternalHelper + * Method: setSequence + * Signature: (JJ)V + */ +void Java_org_rocksdb_WriteBatchTestInternalHelper_setSequence( + JNIEnv* /*env*/, jclass /*jclazz*/, jlong jwb_handle, jlong jsn) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + rocksdb::WriteBatchInternal::SetSequence( + wb, static_cast<rocksdb::SequenceNumber>(jsn)); +} + +/* + * Class: org_rocksdb_WriteBatchTestInternalHelper + * Method: sequence + * Signature: (J)J + */ +jlong Java_org_rocksdb_WriteBatchTestInternalHelper_sequence(JNIEnv* /*env*/, + jclass /*jclazz*/, + jlong jwb_handle) { + auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); + assert(wb != nullptr); + + return static_cast<jlong>(rocksdb::WriteBatchInternal::Sequence(wb)); +} + +/* + * Class: org_rocksdb_WriteBatchTestInternalHelper + * Method: append + * Signature: (JJ)V + */ +void Java_org_rocksdb_WriteBatchTestInternalHelper_append(JNIEnv* /*env*/, + jclass /*jclazz*/, + jlong jwb_handle_1, + jlong jwb_handle_2) { + auto* wb1 = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle_1); + assert(wb1 != nullptr); + auto* wb2 = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle_2); + assert(wb2 != nullptr); + + rocksdb::WriteBatchInternal::Append(wb1, wb2); +} diff --git a/src/rocksdb/java/rocksjni/write_batch_with_index.cc b/src/rocksdb/java/rocksjni/write_batch_with_index.cc new file mode 100644 index 00000000..12ca299a --- /dev/null +++ b/src/rocksdb/java/rocksjni/write_batch_with_index.cc @@ -0,0 +1,746 @@ +// 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 "bridge" between Java and C++ and enables +// calling c++ rocksdb::WriteBatchWithIndex methods from Java side. + +#include "rocksdb/utilities/write_batch_with_index.h" +#include "include/org_rocksdb_WBWIRocksIterator.h" +#include "include/org_rocksdb_WriteBatchWithIndex.h" +#include "rocksdb/comparator.h" +#include "rocksjni/portal.h" + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: newWriteBatchWithIndex + * Signature: ()J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__( + JNIEnv* /*env*/, jclass /*jcls*/) { + auto* wbwi = new rocksdb::WriteBatchWithIndex(); + return reinterpret_cast<jlong>(wbwi); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: newWriteBatchWithIndex + * Signature: (Z)J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__Z( + JNIEnv* /*env*/, jclass /*jcls*/, jboolean joverwrite_key) { + auto* wbwi = new rocksdb::WriteBatchWithIndex( + rocksdb::BytewiseComparator(), 0, static_cast<bool>(joverwrite_key)); + return reinterpret_cast<jlong>(wbwi); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: newWriteBatchWithIndex + * Signature: (JBIZ)J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JBIZ( + JNIEnv* /*env*/, jclass /*jcls*/, jlong jfallback_index_comparator_handle, + jbyte jcomparator_type, jint jreserved_bytes, jboolean joverwrite_key) { + rocksdb::Comparator* fallback_comparator = nullptr; + switch (jcomparator_type) { + // JAVA_COMPARATOR + case 0x0: + fallback_comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>( + jfallback_index_comparator_handle); + break; + + // JAVA_DIRECT_COMPARATOR + case 0x1: + fallback_comparator = + reinterpret_cast<rocksdb::DirectComparatorJniCallback*>( + jfallback_index_comparator_handle); + break; + + // JAVA_NATIVE_COMPARATOR_WRAPPER + case 0x2: + fallback_comparator = reinterpret_cast<rocksdb::Comparator*>( + jfallback_index_comparator_handle); + break; + } + auto* wbwi = new rocksdb::WriteBatchWithIndex( + fallback_comparator, static_cast<size_t>(jreserved_bytes), + static_cast<bool>(joverwrite_key)); + return reinterpret_cast<jlong>(wbwi); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: count0 + * Signature: (J)I + */ +jint Java_org_rocksdb_WriteBatchWithIndex_count0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + return static_cast<jint>(wbwi->GetWriteBatch()->Count()); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: put + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BI( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jbyteArray jentry_value, jint jentry_value_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto put = [&wbwi](rocksdb::Slice key, rocksdb::Slice value) { + return wbwi->Put(key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: put + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jbyteArray jentry_value, jint jentry_value_len, + jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto put = [&wbwi, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) { + return wbwi->Put(cf_handle, key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + put, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: merge + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BI( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jbyteArray jentry_value, jint jentry_value_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto merge = [&wbwi](rocksdb::Slice key, rocksdb::Slice value) { + return wbwi->Merge(key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: merge + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jbyteArray jentry_value, jint jentry_value_len, + jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto merge = [&wbwi, &cf_handle](rocksdb::Slice key, rocksdb::Slice value) { + return wbwi->Merge(cf_handle, key, value); + }; + std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op( + merge, env, jobj, jkey, jkey_len, jentry_value, jentry_value_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: delete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BI(JNIEnv* env, + jobject jobj, + jlong jwbwi_handle, + jbyteArray jkey, + jint jkey_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto remove = [&wbwi](rocksdb::Slice key) { return wbwi->Delete(key); }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: delete + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BIJ( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto remove = [&wbwi, &cf_handle](rocksdb::Slice key) { + return wbwi->Delete(cf_handle, key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: singleDelete + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BI( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto single_delete = [&wbwi](rocksdb::Slice key) { + return wbwi->SingleDelete(key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: singleDelete + * Signature: (J[BIJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BIJ( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, + jint jkey_len, jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto single_delete = [&wbwi, &cf_handle](rocksdb::Slice key) { + return wbwi->SingleDelete(cf_handle, key); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(single_delete, env, jobj, jkey, jkey_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: deleteRange + * Signature: (J[BI[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BI( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jbegin_key, + jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto deleteRange = [&wbwi](rocksdb::Slice beginKey, rocksdb::Slice endKey) { + return wbwi->DeleteRange(beginKey, endKey); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, + jbegin_key_len, jend_key, jend_key_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: deleteRange + * Signature: (J[BI[BIJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BIJ( + JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jbegin_key, + jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len, + jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + assert(cf_handle != nullptr); + auto deleteRange = [&wbwi, &cf_handle](rocksdb::Slice beginKey, + rocksdb::Slice endKey) { + return wbwi->DeleteRange(cf_handle, beginKey, endKey); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, + jbegin_key_len, jend_key, jend_key_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: putLogData + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_putLogData(JNIEnv* env, jobject jobj, + jlong jwbwi_handle, + jbyteArray jblob, + jint jblob_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + auto putLogData = [&wbwi](rocksdb::Slice blob) { + return wbwi->PutLogData(blob); + }; + std::unique_ptr<rocksdb::Status> status = + rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len); + if (status != nullptr && !status->ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, status); + } +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: clear + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_clear0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + wbwi->Clear(); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: setSavePoint0 + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_setSavePoint0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + wbwi->SetSavePoint(); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: rollbackToSavePoint0 + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_rollbackToSavePoint0( + JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + auto s = wbwi->RollbackToSavePoint(); + + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: popSavePoint + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_popSavePoint(JNIEnv* env, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + auto s = wbwi->PopSavePoint(); + + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: setMaxBytes + * Signature: (JJ)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_setMaxBytes(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle, + jlong jmax_bytes) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + wbwi->SetMaxBytes(static_cast<size_t>(jmax_bytes)); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: getWriteBatch + * Signature: (J)Lorg/rocksdb/WriteBatch; + */ +jobject Java_org_rocksdb_WriteBatchWithIndex_getWriteBatch(JNIEnv* env, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + assert(wbwi != nullptr); + + auto* wb = wbwi->GetWriteBatch(); + + // TODO(AR) is the `wb` object owned by us? + return rocksdb::WriteBatchJni::construct(env, wb); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: iterator0 + * Signature: (J)J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_iterator0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* wbwi_iterator = wbwi->NewIterator(); + return reinterpret_cast<jlong>(wbwi_iterator); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: iterator1 + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_iterator1(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle, + jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + auto* wbwi_iterator = wbwi->NewIterator(cf_handle); + return reinterpret_cast<jlong>(wbwi_iterator); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: iteratorWithBase + * Signature: (JJJ)J + */ +jlong Java_org_rocksdb_WriteBatchWithIndex_iteratorWithBase(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong jwbwi_handle, + jlong jcf_handle, + jlong jbi_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + auto* base_iterator = reinterpret_cast<rocksdb::Iterator*>(jbi_handle); + auto* iterator = wbwi->NewIteratorWithBase(cf_handle, base_iterator); + return reinterpret_cast<jlong>(iterator); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: getFromBatch + * Signature: (JJ[BI)[B + */ +jbyteArray JNICALL Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdbopt_handle, + jbyteArray jkey, jint jkey_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* dbopt = reinterpret_cast<rocksdb::DBOptions*>(jdbopt_handle); + + auto getter = [&wbwi, &dbopt](const rocksdb::Slice& key, std::string* value) { + return wbwi->GetFromBatch(*dbopt, key, value); + }; + + return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: getFromBatch + * Signature: (JJ[BIJ)[B + */ +jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatch__JJ_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdbopt_handle, + jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* dbopt = reinterpret_cast<rocksdb::DBOptions*>(jdbopt_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + + auto getter = [&wbwi, &cf_handle, &dbopt](const rocksdb::Slice& key, + std::string* value) { + return wbwi->GetFromBatch(cf_handle, *dbopt, key, value); + }; + + return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: getFromBatchAndDB + * Signature: (JJJ[BI)[B + */ +jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BI( + JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdb_handle, + jlong jreadopt_handle, jbyteArray jkey, jint jkey_len) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* readopt = reinterpret_cast<rocksdb::ReadOptions*>(jreadopt_handle); + + auto getter = [&wbwi, &db, &readopt](const rocksdb::Slice& key, + std::string* value) { + return wbwi->GetFromBatchAndDB(db, *readopt, key, value); + }; + + return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: getFromBatchAndDB + * Signature: (JJJ[BIJ)[B + */ +jbyteArray Java_org_rocksdb_WriteBatchWithIndex_getFromBatchAndDB__JJJ_3BIJ( + JNIEnv* env, jobject /*jobj*/, jlong jwbwi_handle, jlong jdb_handle, + jlong jreadopt_handle, jbyteArray jkey, jint jkey_len, jlong jcf_handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); + auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle); + auto* readopt = reinterpret_cast<rocksdb::ReadOptions*>(jreadopt_handle); + auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); + + auto getter = [&wbwi, &db, &cf_handle, &readopt](const rocksdb::Slice& key, + std::string* value) { + return wbwi->GetFromBatchAndDB(db, *readopt, cf_handle, key, value); + }; + + return rocksdb::JniUtil::v_op(getter, env, jkey, jkey_len); +} + +/* + * Class: org_rocksdb_WriteBatchWithIndex + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBatchWithIndex_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(handle); + assert(wbwi != nullptr); + delete wbwi; +} + +/* WBWIRocksIterator below */ + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle); + assert(it != nullptr); + delete it; +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: isValid0 + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_WBWIRocksIterator_isValid0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + return reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Valid(); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: seekToFirst0 + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_seekToFirst0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::WBWIIterator*>(handle)->SeekToFirst(); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: seekToLast0 + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_seekToLast0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::WBWIIterator*>(handle)->SeekToLast(); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: next0 + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_next0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Next(); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: prev0 + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_prev0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + reinterpret_cast<rocksdb::WBWIIterator*>(handle)->Prev(); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: seek0 + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WBWIRocksIterator_seek0(JNIEnv* env, jobject /*jobj*/, + jlong handle, jbyteArray jtarget, + jint jtarget_len) { + auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle); + jbyte* target = env->GetByteArrayElements(jtarget, nullptr); + if (target == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len); + + it->Seek(target_slice); + + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: seekForPrev0 + * Signature: (J[BI)V + */ +void Java_org_rocksdb_WBWIRocksIterator_seekForPrev0(JNIEnv* env, + jobject /*jobj*/, + jlong handle, + jbyteArray jtarget, + jint jtarget_len) { + auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle); + jbyte* target = env->GetByteArrayElements(jtarget, nullptr); + if (target == nullptr) { + // exception thrown: OutOfMemoryError + return; + } + + rocksdb::Slice target_slice(reinterpret_cast<char*>(target), jtarget_len); + + it->SeekForPrev(target_slice); + + env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: status0 + * Signature: (J)V + */ +void Java_org_rocksdb_WBWIRocksIterator_status0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle); + rocksdb::Status s = it->status(); + + if (s.ok()) { + return; + } + + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); +} + +/* + * Class: org_rocksdb_WBWIRocksIterator + * Method: entry1 + * Signature: (J)[J + */ +jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(JNIEnv* env, + jobject /*jobj*/, + jlong handle) { + auto* it = reinterpret_cast<rocksdb::WBWIIterator*>(handle); + const rocksdb::WriteEntry& we = it->Entry(); + + jlong results[3]; + + // set the type of the write entry + results[0] = rocksdb::WriteTypeJni::toJavaWriteType(we.type); + + // NOTE: key_slice and value_slice will be freed by + // org.rocksdb.DirectSlice#close + + auto* key_slice = new rocksdb::Slice(we.key.data(), we.key.size()); + results[1] = reinterpret_cast<jlong>(key_slice); + if (we.type == rocksdb::kDeleteRecord || + we.type == rocksdb::kSingleDeleteRecord || + we.type == rocksdb::kLogDataRecord) { + // set native handle of value slice to null if no value available + results[2] = 0; + } else { + auto* value_slice = new rocksdb::Slice(we.value.data(), we.value.size()); + results[2] = reinterpret_cast<jlong>(value_slice); + } + + jlongArray jresults = env->NewLongArray(3); + if (jresults == nullptr) { + // exception thrown: OutOfMemoryError + if (results[2] != 0) { + auto* value_slice = reinterpret_cast<rocksdb::Slice*>(results[2]); + delete value_slice; + } + delete key_slice; + return nullptr; + } + + env->SetLongArrayRegion(jresults, 0, 3, results); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(jresults); + if (results[2] != 0) { + auto* value_slice = reinterpret_cast<rocksdb::Slice*>(results[2]); + delete value_slice; + } + delete key_slice; + return nullptr; + } + + return jresults; +} diff --git a/src/rocksdb/java/rocksjni/write_buffer_manager.cc b/src/rocksdb/java/rocksjni/write_buffer_manager.cc new file mode 100644 index 00000000..043f6903 --- /dev/null +++ b/src/rocksdb/java/rocksjni/write_buffer_manager.cc @@ -0,0 +1,38 @@ +// 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). + +#include <jni.h> + +#include "include/org_rocksdb_WriteBufferManager.h" + +#include "rocksdb/cache.h" +#include "rocksdb/write_buffer_manager.h" + +/* + * Class: org_rocksdb_WriteBufferManager + * Method: newWriteBufferManager + * Signature: (JJ)J + */ +jlong Java_org_rocksdb_WriteBufferManager_newWriteBufferManager( + JNIEnv* /*env*/, jclass /*jclazz*/, jlong jbuffer_size, jlong jcache_handle) { + auto* cache_ptr = + reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(jcache_handle); + auto* write_buffer_manager = new std::shared_ptr<rocksdb::WriteBufferManager>( + std::make_shared<rocksdb::WriteBufferManager>(jbuffer_size, *cache_ptr)); + return reinterpret_cast<jlong>(write_buffer_manager); +} + +/* + * Class: org_rocksdb_WriteBufferManager + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_WriteBufferManager_disposeInternal( + JNIEnv* /*env*/, jobject /*jobj*/, jlong jhandle) { + auto* write_buffer_manager = + reinterpret_cast<std::shared_ptr<rocksdb::WriteBufferManager> *>(jhandle); + assert(write_buffer_manager != nullptr); + delete write_buffer_manager; +} diff --git a/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.cc b/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.cc new file mode 100644 index 00000000..bf900111 --- /dev/null +++ b/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.cc @@ -0,0 +1,514 @@ +// 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::Comparator. + +#include "rocksjni/writebatchhandlerjnicallback.h" +#include "rocksjni/portal.h" + +namespace rocksdb { +WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback( + JNIEnv* env, jobject jWriteBatchHandler) + : JniCallback(env, jWriteBatchHandler), m_env(env) { + + m_jPutCfMethodId = WriteBatchHandlerJni::getPutCfMethodId(env); + if(m_jPutCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jPutMethodId = WriteBatchHandlerJni::getPutMethodId(env); + if(m_jPutMethodId == nullptr) { + // exception thrown + return; + } + + m_jMergeCfMethodId = WriteBatchHandlerJni::getMergeCfMethodId(env); + if(m_jMergeCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jMergeMethodId = WriteBatchHandlerJni::getMergeMethodId(env); + if(m_jMergeMethodId == nullptr) { + // exception thrown + return; + } + + m_jDeleteCfMethodId = WriteBatchHandlerJni::getDeleteCfMethodId(env); + if(m_jDeleteCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jDeleteMethodId = WriteBatchHandlerJni::getDeleteMethodId(env); + if(m_jDeleteMethodId == nullptr) { + // exception thrown + return; + } + + m_jSingleDeleteCfMethodId = + WriteBatchHandlerJni::getSingleDeleteCfMethodId(env); + if(m_jSingleDeleteCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jSingleDeleteMethodId = WriteBatchHandlerJni::getSingleDeleteMethodId(env); + if(m_jSingleDeleteMethodId == nullptr) { + // exception thrown + return; + } + + m_jDeleteRangeCfMethodId = + WriteBatchHandlerJni::getDeleteRangeCfMethodId(env); + if (m_jDeleteRangeCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env); + if (m_jDeleteRangeMethodId == nullptr) { + // exception thrown + return; + } + + m_jLogDataMethodId = WriteBatchHandlerJni::getLogDataMethodId(env); + if(m_jLogDataMethodId == nullptr) { + // exception thrown + return; + } + + m_jPutBlobIndexCfMethodId = + WriteBatchHandlerJni::getPutBlobIndexCfMethodId(env); + if(m_jPutBlobIndexCfMethodId == nullptr) { + // exception thrown + return; + } + + m_jMarkBeginPrepareMethodId = + WriteBatchHandlerJni::getMarkBeginPrepareMethodId(env); + if(m_jMarkBeginPrepareMethodId == nullptr) { + // exception thrown + return; + } + + m_jMarkEndPrepareMethodId = + WriteBatchHandlerJni::getMarkEndPrepareMethodId(env); + if(m_jMarkEndPrepareMethodId == nullptr) { + // exception thrown + return; + } + + m_jMarkNoopMethodId = WriteBatchHandlerJni::getMarkNoopMethodId(env); + if(m_jMarkNoopMethodId == nullptr) { + // exception thrown + return; + } + + m_jMarkRollbackMethodId = WriteBatchHandlerJni::getMarkRollbackMethodId(env); + if(m_jMarkRollbackMethodId == nullptr) { + // exception thrown + return; + } + + m_jMarkCommitMethodId = WriteBatchHandlerJni::getMarkCommitMethodId(env); + if(m_jMarkCommitMethodId == nullptr) { + // exception thrown + return; + } + + m_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env); + if(m_jContinueMethodId == nullptr) { + // exception thrown + return; + } +} + +rocksdb::Status WriteBatchHandlerJniCallback::PutCF(uint32_t column_family_id, + const Slice& key, const Slice& value) { + auto put = [this, column_family_id] ( + jbyteArray j_key, jbyteArray j_value) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jPutCfMethodId, + static_cast<jint>(column_family_id), + j_key, + j_value); + }; + auto status = WriteBatchHandlerJniCallback::kv_op(key, value, put); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) { + auto put = [this] ( + jbyteArray j_key, jbyteArray j_value) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jPutMethodId, + j_key, + j_value); + }; + WriteBatchHandlerJniCallback::kv_op(key, value, put); +} + +rocksdb::Status WriteBatchHandlerJniCallback::MergeCF(uint32_t column_family_id, + const Slice& key, const Slice& value) { + auto merge = [this, column_family_id] ( + jbyteArray j_key, jbyteArray j_value) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jMergeCfMethodId, + static_cast<jint>(column_family_id), + j_key, + j_value); + }; + auto status = WriteBatchHandlerJniCallback::kv_op(key, value, merge); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) { + auto merge = [this] ( + jbyteArray j_key, jbyteArray j_value) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jMergeMethodId, + j_key, + j_value); + }; + WriteBatchHandlerJniCallback::kv_op(key, value, merge); +} + +rocksdb::Status WriteBatchHandlerJniCallback::DeleteCF(uint32_t column_family_id, + const Slice& key) { + auto remove = [this, column_family_id] (jbyteArray j_key) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jDeleteCfMethodId, + static_cast<jint>(column_family_id), + j_key); + }; + auto status = WriteBatchHandlerJniCallback::k_op(key, remove); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +void WriteBatchHandlerJniCallback::Delete(const Slice& key) { + auto remove = [this] (jbyteArray j_key) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jDeleteMethodId, + j_key); + }; + WriteBatchHandlerJniCallback::k_op(key, remove); +} + +rocksdb::Status WriteBatchHandlerJniCallback::SingleDeleteCF(uint32_t column_family_id, + const Slice& key) { + auto singleDelete = [this, column_family_id] (jbyteArray j_key) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jSingleDeleteCfMethodId, + static_cast<jint>(column_family_id), + j_key); + }; + auto status = WriteBatchHandlerJniCallback::k_op(key, singleDelete); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +void WriteBatchHandlerJniCallback::SingleDelete(const Slice& key) { + auto singleDelete = [this] (jbyteArray j_key) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jSingleDeleteMethodId, + j_key); + }; + WriteBatchHandlerJniCallback::k_op(key, singleDelete); +} + +rocksdb::Status WriteBatchHandlerJniCallback::DeleteRangeCF(uint32_t column_family_id, + const Slice& beginKey, const Slice& endKey) { + auto deleteRange = [this, column_family_id] ( + jbyteArray j_beginKey, jbyteArray j_endKey) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jDeleteRangeCfMethodId, + static_cast<jint>(column_family_id), + j_beginKey, + j_endKey); + }; + auto status = WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey, + const Slice& endKey) { + auto deleteRange = [this] ( + jbyteArray j_beginKey, jbyteArray j_endKey) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jDeleteRangeMethodId, + j_beginKey, + j_endKey); + }; + WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange); +} + +void WriteBatchHandlerJniCallback::LogData(const Slice& blob) { + auto logData = [this] (jbyteArray j_blob) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jLogDataMethodId, + j_blob); + }; + WriteBatchHandlerJniCallback::k_op(blob, logData); +} + +rocksdb::Status WriteBatchHandlerJniCallback::PutBlobIndexCF(uint32_t column_family_id, + const Slice& key, const Slice& value) { + auto putBlobIndex = [this, column_family_id] ( + jbyteArray j_key, jbyteArray j_value) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jPutBlobIndexCfMethodId, + static_cast<jint>(column_family_id), + j_key, + j_value); + }; + auto status = WriteBatchHandlerJniCallback::kv_op(key, value, putBlobIndex); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +rocksdb::Status WriteBatchHandlerJniCallback::MarkBeginPrepare(bool unprepare) { +#ifndef DEBUG + (void) unprepare; +#else + assert(!unprepare); +#endif + m_env->CallVoidMethod(m_jcallback_obj, m_jMarkBeginPrepareMethodId); + + // check for Exception, in-particular RocksDBException + if (m_env->ExceptionCheck()) { + // exception thrown + jthrowable exception = m_env->ExceptionOccurred(); + std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception); + if (status == nullptr) { + // unkown status or exception occurred extracting status + m_env->ExceptionDescribe(); + return rocksdb::Status::OK(); // TODO(AR) probably need a better error code here + + } else { + m_env->ExceptionClear(); // clear the exception, as we have extracted the status + return rocksdb::Status(*status); + } + } + + return rocksdb::Status::OK(); +} + +rocksdb::Status WriteBatchHandlerJniCallback::MarkEndPrepare(const Slice& xid) { + auto markEndPrepare = [this] ( + jbyteArray j_xid) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jMarkEndPrepareMethodId, + j_xid); + }; + auto status = WriteBatchHandlerJniCallback::k_op(xid, markEndPrepare); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +rocksdb::Status WriteBatchHandlerJniCallback::MarkNoop(bool empty_batch) { + m_env->CallVoidMethod(m_jcallback_obj, m_jMarkNoopMethodId, static_cast<jboolean>(empty_batch)); + + // check for Exception, in-particular RocksDBException + if (m_env->ExceptionCheck()) { + // exception thrown + jthrowable exception = m_env->ExceptionOccurred(); + std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception); + if (status == nullptr) { + // unkown status or exception occurred extracting status + m_env->ExceptionDescribe(); + return rocksdb::Status::OK(); // TODO(AR) probably need a better error code here + + } else { + m_env->ExceptionClear(); // clear the exception, as we have extracted the status + return rocksdb::Status(*status); + } + } + + return rocksdb::Status::OK(); +} + +rocksdb::Status WriteBatchHandlerJniCallback::MarkRollback(const Slice& xid) { + auto markRollback = [this] ( + jbyteArray j_xid) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jMarkRollbackMethodId, + j_xid); + }; + auto status = WriteBatchHandlerJniCallback::k_op(xid, markRollback); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +rocksdb::Status WriteBatchHandlerJniCallback::MarkCommit(const Slice& xid) { + auto markCommit = [this] ( + jbyteArray j_xid) { + m_env->CallVoidMethod( + m_jcallback_obj, + m_jMarkCommitMethodId, + j_xid); + }; + auto status = WriteBatchHandlerJniCallback::k_op(xid, markCommit); + if(status == nullptr) { + return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status? + } else { + return rocksdb::Status(*status); + } +} + +bool WriteBatchHandlerJniCallback::Continue() { + jboolean jContinue = m_env->CallBooleanMethod( + m_jcallback_obj, + m_jContinueMethodId); + if(m_env->ExceptionCheck()) { + // exception thrown + m_env->ExceptionDescribe(); + } + + return static_cast<bool>(jContinue == JNI_TRUE); +} + +std::unique_ptr<rocksdb::Status> WriteBatchHandlerJniCallback::kv_op(const Slice& key, const Slice& value, std::function<void(jbyteArray, jbyteArray)> kvFn) { + const jbyteArray j_key = JniUtil::copyBytes(m_env, key); + if (j_key == nullptr) { + // exception thrown + if (m_env->ExceptionCheck()) { + m_env->ExceptionDescribe(); + } + return nullptr; + } + + const jbyteArray j_value = JniUtil::copyBytes(m_env, value); + if (j_value == nullptr) { + // exception thrown + if (m_env->ExceptionCheck()) { + m_env->ExceptionDescribe(); + } + if (j_key != nullptr) { + m_env->DeleteLocalRef(j_key); + } + return nullptr; + } + + kvFn(j_key, j_value); + + // check for Exception, in-particular RocksDBException + if (m_env->ExceptionCheck()) { + if (j_value != nullptr) { + m_env->DeleteLocalRef(j_value); + } + if (j_key != nullptr) { + m_env->DeleteLocalRef(j_key); + } + + // exception thrown + jthrowable exception = m_env->ExceptionOccurred(); + std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception); + if (status == nullptr) { + // unkown status or exception occurred extracting status + m_env->ExceptionDescribe(); + return nullptr; + + } else { + m_env->ExceptionClear(); // clear the exception, as we have extracted the status + return status; + } + } + + if (j_value != nullptr) { + m_env->DeleteLocalRef(j_value); + } + if (j_key != nullptr) { + m_env->DeleteLocalRef(j_key); + } + + // all OK + return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(rocksdb::Status::OK())); +} + +std::unique_ptr<rocksdb::Status> WriteBatchHandlerJniCallback::k_op(const Slice& key, std::function<void(jbyteArray)> kFn) { + const jbyteArray j_key = JniUtil::copyBytes(m_env, key); + if (j_key == nullptr) { + // exception thrown + if (m_env->ExceptionCheck()) { + m_env->ExceptionDescribe(); + } + return nullptr; + } + + kFn(j_key); + + // check for Exception, in-particular RocksDBException + if (m_env->ExceptionCheck()) { + if (j_key != nullptr) { + m_env->DeleteLocalRef(j_key); + } + + // exception thrown + jthrowable exception = m_env->ExceptionOccurred(); + std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception); + if (status == nullptr) { + // unkown status or exception occurred extracting status + m_env->ExceptionDescribe(); + return nullptr; + + } else { + m_env->ExceptionClear(); // clear the exception, as we have extracted the status + return status; + } + } + + if (j_key != nullptr) { + m_env->DeleteLocalRef(j_key); + } + + // all OK + return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(rocksdb::Status::OK())); +} +} // namespace rocksdb diff --git a/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.h b/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.h new file mode 100644 index 00000000..720f1693 --- /dev/null +++ b/src/rocksdb/java/rocksjni/writebatchhandlerjnicallback.h @@ -0,0 +1,84 @@ +// 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::WriteBatch::Handler. + +#ifndef JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_ +#define JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_ + +#include <functional> +#include <jni.h> +#include <memory> +#include "rocksjni/jnicallback.h" +#include "rocksdb/write_batch.h" + +namespace rocksdb { +/** + * This class acts as a bridge between C++ + * and Java. The methods in this class will be + * called back from the RocksDB storage engine (C++) + * which calls the appropriate Java method. + * This enables Write Batch Handlers to be implemented in Java. + */ +class WriteBatchHandlerJniCallback : public JniCallback, public WriteBatch::Handler { + public: + WriteBatchHandlerJniCallback( + JNIEnv* env, jobject jWriteBackHandler); + Status PutCF(uint32_t column_family_id, const Slice& key, + const Slice& value); + void Put(const Slice& key, const Slice& value); + Status MergeCF(uint32_t column_family_id, const Slice& key, + const Slice& value); + void Merge(const Slice& key, const Slice& value); + Status DeleteCF(uint32_t column_family_id, const Slice& key); + void Delete(const Slice& key); + Status SingleDeleteCF(uint32_t column_family_id, const Slice& key); + void SingleDelete(const Slice& key); + Status DeleteRangeCF(uint32_t column_family_id, const Slice& beginKey, + const Slice& endKey); + void DeleteRange(const Slice& beginKey, const Slice& endKey); + void LogData(const Slice& blob); + Status PutBlobIndexCF(uint32_t column_family_id, const Slice& key, + const Slice& value); + Status MarkBeginPrepare(bool); + Status MarkEndPrepare(const Slice& xid); + Status MarkNoop(bool empty_batch); + Status MarkRollback(const Slice& xid); + Status MarkCommit(const Slice& xid); + bool Continue(); + + private: + JNIEnv* m_env; + jmethodID m_jPutCfMethodId; + jmethodID m_jPutMethodId; + jmethodID m_jMergeCfMethodId; + jmethodID m_jMergeMethodId; + jmethodID m_jDeleteCfMethodId; + jmethodID m_jDeleteMethodId; + jmethodID m_jSingleDeleteCfMethodId; + jmethodID m_jSingleDeleteMethodId; + jmethodID m_jDeleteRangeCfMethodId; + jmethodID m_jDeleteRangeMethodId; + jmethodID m_jLogDataMethodId; + jmethodID m_jPutBlobIndexCfMethodId; + jmethodID m_jMarkBeginPrepareMethodId; + jmethodID m_jMarkEndPrepareMethodId; + jmethodID m_jMarkNoopMethodId; + jmethodID m_jMarkRollbackMethodId; + jmethodID m_jMarkCommitMethodId; + jmethodID m_jContinueMethodId; + /** + * @return A pointer to a rocksdb::Status or nullptr if an unexpected exception occurred + */ + std::unique_ptr<rocksdb::Status> kv_op(const Slice& key, const Slice& value, std::function<void(jbyteArray, jbyteArray)> kvFn); + /** + * @return A pointer to a rocksdb::Status or nullptr if an unexpected exception occurred + */ + std::unique_ptr<rocksdb::Status> k_op(const Slice& key, std::function<void(jbyteArray)> kFn); +}; +} // namespace rocksdb + +#endif // JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_ |