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__Ljava_lang_String_2JJLjava_util_List_2Z(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__Ljava_lang_String_2JJLjava_util_List_2Z(
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:    loadLatestOptions_1
84  * Signature: (JLjava/lang/String;JLjava/util/List;)V
85  */
Java_org_rocksdb_OptionsUtil_loadLatestOptions__JLjava_lang_String_2JLjava_util_List_2(JNIEnv * env,jclass,jlong cfg_handle,jstring jdbpath,jlong jdb_opts_handle,jobject jcfds)86 void Java_org_rocksdb_OptionsUtil_loadLatestOptions__JLjava_lang_String_2JLjava_util_List_2(
87     JNIEnv* env, jclass /*jcls*/, jlong cfg_handle, jstring jdbpath,
88     jlong jdb_opts_handle, jobject jcfds) {
89   jboolean has_exception = JNI_FALSE;
90   auto db_path =
91       ROCKSDB_NAMESPACE::JniUtil::copyStdString(env, jdbpath, &has_exception);
92   if (has_exception == JNI_TRUE) {
93     // exception occurred
94     return;
95   }
96   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descs;
97   auto* config_options =
98       reinterpret_cast<ROCKSDB_NAMESPACE::ConfigOptions*>(cfg_handle);
99   auto* db_options =
100       reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_opts_handle);
101   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::LoadLatestOptions(
102       *config_options, db_path, db_options, &cf_descs);
103   if (!s.ok()) {
104     // error, raise an exception
105     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
106   } else {
107     build_column_family_descriptor_list(env, jcfds, cf_descs);
108   }
109 }
110 
111 /*
112  * Class:     org_rocksdb_OptionsUtil
113  * Method:    loadOptionsFromFile
114  * Signature: (Ljava/lang/String;JJLjava/util/List;Z)V
115  */
Java_org_rocksdb_OptionsUtil_loadOptionsFromFile__Ljava_lang_String_2JJLjava_util_List_2Z(JNIEnv * env,jclass,jstring jopts_file_name,jlong jenv_handle,jlong jdb_opts_handle,jobject jcfds,jboolean ignore_unknown_options)116 void Java_org_rocksdb_OptionsUtil_loadOptionsFromFile__Ljava_lang_String_2JJLjava_util_List_2Z(
117     JNIEnv* env, jclass /*jcls*/, jstring jopts_file_name, jlong jenv_handle,
118     jlong jdb_opts_handle, jobject jcfds, jboolean ignore_unknown_options) {
119   jboolean has_exception = JNI_FALSE;
120   auto opts_file_name = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
121       env, jopts_file_name, &has_exception);
122   if (has_exception == JNI_TRUE) {
123     // exception occurred
124     return;
125   }
126   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descs;
127   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::LoadOptionsFromFile(
128       opts_file_name, reinterpret_cast<ROCKSDB_NAMESPACE::Env*>(jenv_handle),
129       reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_opts_handle),
130       &cf_descs, ignore_unknown_options);
131   if (!s.ok()) {
132     // error, raise an exception
133     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
134   } else {
135     build_column_family_descriptor_list(env, jcfds, cf_descs);
136   }
137 }
138 
139 /*
140  * Class:     org_rocksdb_OptionsUtil
141  * Method:    loadOptionsFromFile
142  * Signature: (JLjava/lang/String;JLjava/util/List;)V
143  */
Java_org_rocksdb_OptionsUtil_loadOptionsFromFile__JLjava_lang_String_2JLjava_util_List_2(JNIEnv * env,jclass,jlong cfg_handle,jstring jopts_file_name,jlong jdb_opts_handle,jobject jcfds)144 void Java_org_rocksdb_OptionsUtil_loadOptionsFromFile__JLjava_lang_String_2JLjava_util_List_2(
145     JNIEnv* env, jclass /*jcls*/, jlong cfg_handle, jstring jopts_file_name,
146     jlong jdb_opts_handle, jobject jcfds) {
147   jboolean has_exception = JNI_FALSE;
148   auto opts_file_name = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
149       env, jopts_file_name, &has_exception);
150   if (has_exception == JNI_TRUE) {
151     // exception occurred
152     return;
153   }
154   std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> cf_descs;
155   auto* config_options =
156       reinterpret_cast<ROCKSDB_NAMESPACE::ConfigOptions*>(cfg_handle);
157   auto* db_options =
158       reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_opts_handle);
159   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::LoadOptionsFromFile(
160       *config_options, opts_file_name, db_options, &cf_descs);
161   if (!s.ok()) {
162     // error, raise an exception
163     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
164   } else {
165     build_column_family_descriptor_list(env, jcfds, cf_descs);
166   }
167 }
168 
169 /*
170  * Class:     org_rocksdb_OptionsUtil
171  * Method:    getLatestOptionsFileName
172  * Signature: (Ljava/lang/String;J)Ljava/lang/String;
173  */
Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName(JNIEnv * env,jclass,jstring jdbpath,jlong jenv_handle)174 jstring Java_org_rocksdb_OptionsUtil_getLatestOptionsFileName(
175     JNIEnv* env, jclass /*jcls*/, jstring jdbpath, jlong jenv_handle) {
176   jboolean has_exception = JNI_FALSE;
177   auto db_path =
178       ROCKSDB_NAMESPACE::JniUtil::copyStdString(env, jdbpath, &has_exception);
179   if (has_exception == JNI_TRUE) {
180     // exception occurred
181     return nullptr;
182   }
183   std::string options_file_name;
184   ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::GetLatestOptionsFileName(
185       db_path, reinterpret_cast<ROCKSDB_NAMESPACE::Env*>(jenv_handle),
186       &options_file_name);
187   if (!s.ok()) {
188     // error, raise an exception
189     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
190     return nullptr;
191   } else {
192     return env->NewStringUTF(options_file_name.c_str());
193   }
194 }
195