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::SstFileWriter methods
8 // from Java side.
9 
10 #include <jni.h>
11 #include <string>
12 
13 #include "include/org_rocksdb_SstFileWriter.h"
14 #include "rocksdb/comparator.h"
15 #include "rocksdb/env.h"
16 #include "rocksdb/options.h"
17 #include "rocksdb/sst_file_writer.h"
18 #include "rocksjni/portal.h"
19 
20 /*
21  * Class:     org_rocksdb_SstFileWriter
22  * Method:    newSstFileWriter
23  * Signature: (JJJB)J
24  */
25 jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJB(
26     JNIEnv * /*env*/, jclass /*jcls*/, jlong jenvoptions, jlong joptions,
27     jlong jcomparator_handle, jbyte jcomparator_type) {
28   ROCKSDB_NAMESPACE::Comparator *comparator = nullptr;
29   switch (jcomparator_type) {
30     // JAVA_COMPARATOR
31     case 0x0:
32       comparator = reinterpret_cast<ROCKSDB_NAMESPACE::ComparatorJniCallback *>(
33           jcomparator_handle);
34       break;
35 
36     // JAVA_NATIVE_COMPARATOR_WRAPPER
37     case 0x1:
38       comparator =
39           reinterpret_cast<ROCKSDB_NAMESPACE::Comparator *>(jcomparator_handle);
40       break;
41   }
42   auto *env_options =
43       reinterpret_cast<const ROCKSDB_NAMESPACE::EnvOptions *>(jenvoptions);
44   auto *options =
45       reinterpret_cast<const ROCKSDB_NAMESPACE::Options *>(joptions);
46   ROCKSDB_NAMESPACE::SstFileWriter *sst_file_writer =
47       new ROCKSDB_NAMESPACE::SstFileWriter(*env_options, *options, comparator);
48   return reinterpret_cast<jlong>(sst_file_writer);
49 }
50 
51 /*
52  * Class:     org_rocksdb_SstFileWriter
53  * Method:    newSstFileWriter
54  * Signature: (JJ)J
55  */
56 jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJ(JNIEnv * /*env*/,
57                                                           jclass /*jcls*/,
58                                                           jlong jenvoptions,
59                                                           jlong joptions) {
60   auto *env_options =
61       reinterpret_cast<const ROCKSDB_NAMESPACE::EnvOptions *>(jenvoptions);
62   auto *options =
63       reinterpret_cast<const ROCKSDB_NAMESPACE::Options *>(joptions);
64   ROCKSDB_NAMESPACE::SstFileWriter *sst_file_writer =
65       new ROCKSDB_NAMESPACE::SstFileWriter(*env_options, *options);
66   return reinterpret_cast<jlong>(sst_file_writer);
67 }
68 
69 /*
70  * Class:     org_rocksdb_SstFileWriter
71  * Method:    open
72  * Signature: (JLjava/lang/String;)V
73  */
74 void Java_org_rocksdb_SstFileWriter_open(JNIEnv *env, jobject /*jobj*/,
75                                          jlong jhandle, jstring jfile_path) {
76   const char *file_path = env->GetStringUTFChars(jfile_path, nullptr);
77   if (file_path == nullptr) {
78     // exception thrown: OutOfMemoryError
79     return;
80   }
81   ROCKSDB_NAMESPACE::Status s =
82       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Open(
83           file_path);
84   env->ReleaseStringUTFChars(jfile_path, file_path);
85 
86   if (!s.ok()) {
87     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
88   }
89 }
90 
91 /*
92  * Class:     org_rocksdb_SstFileWriter
93  * Method:    put
94  * Signature: (JJJ)V
95  */
96 void Java_org_rocksdb_SstFileWriter_put__JJJ(JNIEnv *env, jobject /*jobj*/,
97                                              jlong jhandle, jlong jkey_handle,
98                                              jlong jvalue_handle) {
99   auto *key_slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice *>(jkey_handle);
100   auto *value_slice =
101       reinterpret_cast<ROCKSDB_NAMESPACE::Slice *>(jvalue_handle);
102   ROCKSDB_NAMESPACE::Status s =
103       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Put(
104           *key_slice, *value_slice);
105   if (!s.ok()) {
106     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
107   }
108 }
109 
110 /*
111  * Class:     org_rocksdb_SstFileWriter
112  * Method:    put
113  * Signature: (JJJ)V
114  */
115 void Java_org_rocksdb_SstFileWriter_put__J_3B_3B(JNIEnv *env, jobject /*jobj*/,
116                                                  jlong jhandle, jbyteArray jkey,
117                                                  jbyteArray jval) {
118   jbyte *key = env->GetByteArrayElements(jkey, nullptr);
119   if (key == nullptr) {
120     // exception thrown: OutOfMemoryError
121     return;
122   }
123   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char *>(key),
124                                      env->GetArrayLength(jkey));
125 
126   jbyte *value = env->GetByteArrayElements(jval, nullptr);
127   if (value == nullptr) {
128     // exception thrown: OutOfMemoryError
129     env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
130     return;
131   }
132   ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char *>(value),
133                                        env->GetArrayLength(jval));
134 
135   ROCKSDB_NAMESPACE::Status s =
136       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Put(
137           key_slice, value_slice);
138 
139   env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
140   env->ReleaseByteArrayElements(jval, value, JNI_ABORT);
141 
142   if (!s.ok()) {
143     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
144   }
145 }
146 
147 /*
148  * Class:     org_rocksdb_SstFileWriter
149  * Method:    putDirect
150  * Signature: (JLjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)V
151  */
152 void Java_org_rocksdb_SstFileWriter_putDirect(JNIEnv *env, jobject /*jdb*/,
153                                               jlong jdb_handle, jobject jkey,
154                                               jint jkey_off, jint jkey_len,
155                                               jobject jval, jint jval_off,
156                                               jint jval_len) {
157   auto *writer =
158       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jdb_handle);
159   auto put = [&env, &writer](ROCKSDB_NAMESPACE::Slice &key,
160                              ROCKSDB_NAMESPACE::Slice &value) {
161     ROCKSDB_NAMESPACE::Status s = writer->Put(key, value);
162     if (s.ok()) {
163       return;
164     }
165     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
166   };
167   ROCKSDB_NAMESPACE::JniUtil::kv_op_direct(put, env, jkey, jkey_off, jkey_len,
168                                            jval, jval_off, jval_len);
169 }
170 
171 /*
172  * Class:     org_rocksdb_SstFileWriter
173  * Method:    fileSize
174  * Signature: (J)J
175  */
176 jlong Java_org_rocksdb_SstFileWriter_fileSize(JNIEnv * /*env*/, jobject /*jdb*/,
177                                               jlong jdb_handle) {
178   auto *writer =
179       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jdb_handle);
180   return static_cast<jlong>(writer->FileSize());
181 }
182 
183 /*
184  * Class:     org_rocksdb_SstFileWriter
185  * Method:    merge
186  * Signature: (JJJ)V
187  */
188 void Java_org_rocksdb_SstFileWriter_merge__JJJ(JNIEnv *env, jobject /*jobj*/,
189                                                jlong jhandle, jlong jkey_handle,
190                                                jlong jvalue_handle) {
191   auto *key_slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice *>(jkey_handle);
192   auto *value_slice =
193       reinterpret_cast<ROCKSDB_NAMESPACE::Slice *>(jvalue_handle);
194   ROCKSDB_NAMESPACE::Status s =
195       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Merge(
196           *key_slice, *value_slice);
197   if (!s.ok()) {
198     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
199   }
200 }
201 
202 /*
203  * Class:     org_rocksdb_SstFileWriter
204  * Method:    merge
205  * Signature: (J[B[B)V
206  */
207 void Java_org_rocksdb_SstFileWriter_merge__J_3B_3B(JNIEnv *env,
208                                                    jobject /*jobj*/,
209                                                    jlong jhandle,
210                                                    jbyteArray jkey,
211                                                    jbyteArray jval) {
212   jbyte *key = env->GetByteArrayElements(jkey, nullptr);
213   if (key == nullptr) {
214     // exception thrown: OutOfMemoryError
215     return;
216   }
217   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char *>(key),
218                                      env->GetArrayLength(jkey));
219 
220   jbyte *value = env->GetByteArrayElements(jval, nullptr);
221   if (value == nullptr) {
222     // exception thrown: OutOfMemoryError
223     env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
224     return;
225   }
226   ROCKSDB_NAMESPACE::Slice value_slice(reinterpret_cast<char *>(value),
227                                        env->GetArrayLength(jval));
228 
229   ROCKSDB_NAMESPACE::Status s =
230       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Merge(
231           key_slice, value_slice);
232 
233   env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
234   env->ReleaseByteArrayElements(jval, value, JNI_ABORT);
235 
236   if (!s.ok()) {
237     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
238   }
239 }
240 
241 /*
242  * Class:     org_rocksdb_SstFileWriter
243  * Method:    delete
244  * Signature: (JJJ)V
245  */
246 void Java_org_rocksdb_SstFileWriter_delete__J_3B(JNIEnv *env, jobject /*jobj*/,
247                                                  jlong jhandle,
248                                                  jbyteArray jkey) {
249   jbyte *key = env->GetByteArrayElements(jkey, nullptr);
250   if (key == nullptr) {
251     // exception thrown: OutOfMemoryError
252     return;
253   }
254   ROCKSDB_NAMESPACE::Slice key_slice(reinterpret_cast<char *>(key),
255                                      env->GetArrayLength(jkey));
256 
257   ROCKSDB_NAMESPACE::Status s =
258       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Delete(
259           key_slice);
260 
261   env->ReleaseByteArrayElements(jkey, key, JNI_ABORT);
262 
263   if (!s.ok()) {
264     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
265   }
266 }
267 
268 /*
269  * Class:     org_rocksdb_SstFileWriter
270  * Method:    delete
271  * Signature: (JJJ)V
272  */
273 void Java_org_rocksdb_SstFileWriter_delete__JJ(JNIEnv *env, jobject /*jobj*/,
274                                                jlong jhandle,
275                                                jlong jkey_handle) {
276   auto *key_slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice *>(jkey_handle);
277   ROCKSDB_NAMESPACE::Status s =
278       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Delete(
279           *key_slice);
280   if (!s.ok()) {
281     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
282   }
283 }
284 
285 /*
286  * Class:     org_rocksdb_SstFileWriter
287  * Method:    finish
288  * Signature: (J)V
289  */
290 void Java_org_rocksdb_SstFileWriter_finish(JNIEnv *env, jobject /*jobj*/,
291                                            jlong jhandle) {
292   ROCKSDB_NAMESPACE::Status s =
293       reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle)->Finish();
294   if (!s.ok()) {
295     ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
296   }
297 }
298 
299 /*
300  * Class:     org_rocksdb_SstFileWriter
301  * Method:    disposeInternal
302  * Signature: (J)V
303  */
304 void Java_org_rocksdb_SstFileWriter_disposeInternal(JNIEnv * /*env*/,
305                                                     jobject /*jobj*/,
306                                                     jlong jhandle) {
307   delete reinterpret_cast<ROCKSDB_NAMESPACE::SstFileWriter *>(jhandle);
308 }
309