1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 // This file implements the "bridge" between Java and C++ and enables
7 // calling C++ ROCKSDB_NAMESPACE::OptionsUtil methods from Java side.
8 
9 #include <jni.h>
10 #include <string>
11 
12 #include "include/org_rocksdb_OptionsUtil.h"
13 
14 #include "rocksdb/db.h"
15 #include "rocksdb/env.h"
16 #include "rocksdb/utilities/options_util.h"
17 #include "rocksjni/portal.h"
18 
build_column_family_descriptor_list(JNIEnv * env,jobject jcfds,std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> & cf_descs)19 void build_column_family_descriptor_list(
20     JNIEnv* env, jobject jcfds,
21     std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor>& cf_descs) {
22   jmethodID add_mid = ROCKSDB_NAMESPACE::ListJni::getListAddMethodId(env);
23   if (add_mid == nullptr) {
24     // exception occurred accessing method
25     return;
26   }
27 
28   // Column family descriptor
29   for (ROCKSDB_NAMESPACE::ColumnFamilyDescriptor& cfd : cf_descs) {
30     // Construct a ColumnFamilyDescriptor java object
31     jobject jcfd =
32         ROCKSDB_NAMESPACE::ColumnFamilyDescriptorJni::construct(env, &cfd);
33     if (env->ExceptionCheck()) {
34       // exception occurred constructing object
35       if (jcfd != nullptr) {
36         env->DeleteLocalRef(jcfd);
37       }
38       return;
39     }
40 
41     // Add the object to java list.
42     jboolean rs = env->CallBooleanMethod(jcfds, add_mid, jcfd);
43     if (env->ExceptionCheck() || rs == JNI_FALSE) {
44       // exception occurred calling method, or could not add
45       if (jcfd != nullptr) {
46         env->DeleteLocalRef(jcfd);
47       }
48       return;
49     }
50   }
51 }
52 
53 /*
54  * Class:     org_rocksdb_OptionsUtil
55  * Method:    loadLatestOptions
56  * Signature: (Ljava/lang/String;JLjava/util/List;Z)V
57  */
Java_org_rocksdb_OptionsUtil_loadLatestOptions(JNIEnv * env,jclass,jstring jdbpath,jlong jenv_handle,jlong jdb_opts_handle,jobject jcfds,jboolean ignore_unknown_options)58 void Java_org_rocksdb_OptionsUtil_loadLatestOptions(
59     JNIEnv* env, jclass /*jcls*/, jstring jdbpath, jlong jenv_handle,
60     jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) {
61   jboolean has_exception = JNI_FALSE;
62   auto db_path =
63       ROCKSDB_NAMESPACE::JniUtil::copyStdString(env, jdbpath, &has_exception);
64   if (has_exception == JNI_TRUE) {
65     // exception occurred
66     return;
67   }
68   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descs;
69   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::LoadLatestOptions(
70       db_path, reinterpret_cast<ROCKSDB_NAMESPACE::Env*>(jenv_handle),
71       reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_opts_handle),
72       &cf_descs, ignore_unknown_options);
73   if (!s.ok()) {
74     // error, raise an exception
75     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
76   } else {
77     build_column_family_descriptor_list(env, jcfds, cf_descs);
78   }
79 }
80 
81 /*
82  * Class:     org_rocksdb_OptionsUtil
83  * Method:    loadOptionsFromFile
84  * Signature: (Ljava/lang/String;JJLjava/util/List;Z)V
85  */
Java_org_rocksdb_OptionsUtil_loadOptionsFromFile(JNIEnv * env,jclass,jstring jopts_file_name,jlong jenv_handle,jlong jdb_opts_handle,jobject jcfds,jboolean ignore_unknown_options)86 void Java_org_rocksdb_OptionsUtil_loadOptionsFromFile(
87     JNIEnv* env, jclass /*jcls*/, jstring jopts_file_name, jlong jenv_handle,
88     jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) {
89   jboolean has_exception = JNI_FALSE;
90   auto opts_file_name = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
91       env, jopts_file_name, &has_exception);
92   if (has_exception == JNI_TRUE) {
93     // exception occurred
94     return;
95   }
96   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descs;
97   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::LoadOptionsFromFile(
98       opts_file_name, reinterpret_cast<ROCKSDB_NAMESPACE::Env*>(jenv_handle),
99       reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_opts_handle),
100       &cf_descs, ignore_unknown_options);
101   if (!s.ok()) {
102     // error, raise an exception
103     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
104   } else {
105     build_column_family_descriptor_list(env, jcfds, cf_descs);
106   }
107 }
108 
109 /*
110  * Class:     org_rocksdb_OptionsUtil
111  * Method:    getLatestOptionsFileName
112  * Signature: (Ljava/lang/String;J)Ljava/lang/String;
113  */
Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName(JNIEnv * env,jclass,jstring jdbpath,jlong jenv_handle)114 jstring Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName(
115     JNIEnv* env, jclass /*jcls*/, jstring jdbpath, jlong jenv_handle) {
116   jboolean has_exception = JNI_FALSE;
117   auto db_path =
118       ROCKSDB_NAMESPACE::JniUtil::copyStdString(env, jdbpath, &has_exception);
119   if (has_exception == JNI_TRUE) {
120     // exception occurred
121     return nullptr;
122   }
123   std::string options_file_name;
124   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::GetLatestOptionsFileName(
125       db_path, reinterpret_cast<ROCKSDB_NAMESPACE::Env*>(jenv_handle),
126       &options_file_name);
127   if (!s.ok()) {
128     // error, raise an exception
129     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
130     return nullptr;
131   } else {
132     return env->NewStringUTF(options_file_name.c_str());
133   }
134 }
135