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++ for
7 // ROCKSDB_NAMESPACE::Slice.
8
9 #include <jni.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string>
13
14 #include "include/org_rocksdb_AbstractSlice.h"
15 #include "include/org_rocksdb_DirectSlice.h"
16 #include "include/org_rocksdb_Slice.h"
17 #include "rocksdb/slice.h"
18 #include "rocksjni/portal.h"
19
20 // <editor-fold desc="org.rocksdb.AbstractSlice>
21
22 /*
23 * Class: org_rocksdb_AbstractSlice
24 * Method: createNewSliceFromString
25 * Signature: (Ljava/lang/String;)J
26 */
Java_org_rocksdb_AbstractSlice_createNewSliceFromString(JNIEnv * env,jclass,jstring jstr)27 jlong Java_org_rocksdb_AbstractSlice_createNewSliceFromString(JNIEnv* env,
28 jclass /*jcls*/,
29 jstring jstr) {
30 const auto* str = env->GetStringUTFChars(jstr, nullptr);
31 if (str == nullptr) {
32 // exception thrown: OutOfMemoryError
33 return 0;
34 }
35
36 const size_t len = strlen(str);
37
38 // NOTE: buf will be deleted in the
39 // Java_org_rocksdb_Slice_disposeInternalBuf or
40 // or Java_org_rocksdb_DirectSlice_disposeInternalBuf methods
41 char* buf = new char[len + 1];
42 memcpy(buf, str, len);
43 buf[len] = 0;
44 env->ReleaseStringUTFChars(jstr, str);
45
46 const auto* slice = new ROCKSDB_NAMESPACE::Slice(buf);
47 return reinterpret_cast<jlong>(slice);
48 }
49
50 /*
51 * Class: org_rocksdb_AbstractSlice
52 * Method: size0
53 * Signature: (J)I
54 */
Java_org_rocksdb_AbstractSlice_size0(JNIEnv *,jobject,jlong handle)55 jint Java_org_rocksdb_AbstractSlice_size0(JNIEnv* /*env*/, jobject /*jobj*/,
56 jlong handle) {
57 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
58 return static_cast<jint>(slice->size());
59 }
60
61 /*
62 * Class: org_rocksdb_AbstractSlice
63 * Method: empty0
64 * Signature: (J)Z
65 */
Java_org_rocksdb_AbstractSlice_empty0(JNIEnv *,jobject,jlong handle)66 jboolean Java_org_rocksdb_AbstractSlice_empty0(JNIEnv* /*env*/,
67 jobject /*jobj*/, jlong handle) {
68 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
69 return slice->empty();
70 }
71
72 /*
73 * Class: org_rocksdb_AbstractSlice
74 * Method: toString0
75 * Signature: (JZ)Ljava/lang/String;
76 */
Java_org_rocksdb_AbstractSlice_toString0(JNIEnv * env,jobject,jlong handle,jboolean hex)77 jstring Java_org_rocksdb_AbstractSlice_toString0(JNIEnv* env, jobject /*jobj*/,
78 jlong handle, jboolean hex) {
79 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
80 const std::string s = slice->ToString(hex);
81 return env->NewStringUTF(s.c_str());
82 }
83
84 /*
85 * Class: org_rocksdb_AbstractSlice
86 * Method: compare0
87 * Signature: (JJ)I;
88 */
Java_org_rocksdb_AbstractSlice_compare0(JNIEnv *,jobject,jlong handle,jlong otherHandle)89 jint Java_org_rocksdb_AbstractSlice_compare0(JNIEnv* /*env*/, jobject /*jobj*/,
90 jlong handle, jlong otherHandle) {
91 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
92 const auto* otherSlice =
93 reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(otherHandle);
94 return slice->compare(*otherSlice);
95 }
96
97 /*
98 * Class: org_rocksdb_AbstractSlice
99 * Method: startsWith0
100 * Signature: (JJ)Z;
101 */
Java_org_rocksdb_AbstractSlice_startsWith0(JNIEnv *,jobject,jlong handle,jlong otherHandle)102 jboolean Java_org_rocksdb_AbstractSlice_startsWith0(JNIEnv* /*env*/,
103 jobject /*jobj*/,
104 jlong handle,
105 jlong otherHandle) {
106 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
107 const auto* otherSlice =
108 reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(otherHandle);
109 return slice->starts_with(*otherSlice);
110 }
111
112 /*
113 * Class: org_rocksdb_AbstractSlice
114 * Method: disposeInternal
115 * Signature: (J)V
116 */
Java_org_rocksdb_AbstractSlice_disposeInternal(JNIEnv *,jobject,jlong handle)117 void Java_org_rocksdb_AbstractSlice_disposeInternal(JNIEnv* /*env*/,
118 jobject /*jobj*/,
119 jlong handle) {
120 delete reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
121 }
122
123 // </editor-fold>
124
125 // <editor-fold desc="org.rocksdb.Slice>
126
127 /*
128 * Class: org_rocksdb_Slice
129 * Method: createNewSlice0
130 * Signature: ([BI)J
131 */
Java_org_rocksdb_Slice_createNewSlice0(JNIEnv * env,jclass,jbyteArray data,jint offset)132 jlong Java_org_rocksdb_Slice_createNewSlice0(JNIEnv* env, jclass /*jcls*/,
133 jbyteArray data, jint offset) {
134 const jsize dataSize = env->GetArrayLength(data);
135 const int len = dataSize - offset;
136
137 // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf
138 // method
139 jbyte* buf = new jbyte[len];
140 env->GetByteArrayRegion(data, offset, len, buf);
141 if (env->ExceptionCheck()) {
142 // exception thrown: ArrayIndexOutOfBoundsException
143 return 0;
144 }
145
146 const auto* slice = new ROCKSDB_NAMESPACE::Slice((const char*)buf, len);
147 return reinterpret_cast<jlong>(slice);
148 }
149
150 /*
151 * Class: org_rocksdb_Slice
152 * Method: createNewSlice1
153 * Signature: ([B)J
154 */
Java_org_rocksdb_Slice_createNewSlice1(JNIEnv * env,jclass,jbyteArray data)155 jlong Java_org_rocksdb_Slice_createNewSlice1(JNIEnv* env, jclass /*jcls*/,
156 jbyteArray data) {
157 jbyte* ptrData = env->GetByteArrayElements(data, nullptr);
158 if (ptrData == nullptr) {
159 // exception thrown: OutOfMemoryError
160 return 0;
161 }
162 const int len = env->GetArrayLength(data) + 1;
163
164 // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf
165 // method
166 char* buf = new char[len];
167 memcpy(buf, ptrData, len - 1);
168 buf[len - 1] = '\0';
169
170 const auto* slice = new ROCKSDB_NAMESPACE::Slice(buf, len - 1);
171
172 env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT);
173
174 return reinterpret_cast<jlong>(slice);
175 }
176
177 /*
178 * Class: org_rocksdb_Slice
179 * Method: data0
180 * Signature: (J)[B
181 */
Java_org_rocksdb_Slice_data0(JNIEnv * env,jobject,jlong handle)182 jbyteArray Java_org_rocksdb_Slice_data0(JNIEnv* env, jobject /*jobj*/,
183 jlong handle) {
184 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
185 const jsize len = static_cast<jsize>(slice->size());
186 const jbyteArray data = env->NewByteArray(len);
187 if (data == nullptr) {
188 // exception thrown: OutOfMemoryError
189 return nullptr;
190 }
191
192 env->SetByteArrayRegion(
193 data, 0, len,
194 const_cast<jbyte*>(reinterpret_cast<const jbyte*>(slice->data())));
195 if (env->ExceptionCheck()) {
196 // exception thrown: ArrayIndexOutOfBoundsException
197 env->DeleteLocalRef(data);
198 return nullptr;
199 }
200
201 return data;
202 }
203
204 /*
205 * Class: org_rocksdb_Slice
206 * Method: clear0
207 * Signature: (JZJ)V
208 */
Java_org_rocksdb_Slice_clear0(JNIEnv *,jobject,jlong handle,jboolean shouldRelease,jlong internalBufferOffset)209 void Java_org_rocksdb_Slice_clear0(JNIEnv* /*env*/, jobject /*jobj*/,
210 jlong handle, jboolean shouldRelease,
211 jlong internalBufferOffset) {
212 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
213 if (shouldRelease == JNI_TRUE) {
214 const char* buf = slice->data_ - internalBufferOffset;
215 delete[] buf;
216 }
217 slice->clear();
218 }
219
220 /*
221 * Class: org_rocksdb_Slice
222 * Method: removePrefix0
223 * Signature: (JI)V
224 */
Java_org_rocksdb_Slice_removePrefix0(JNIEnv *,jobject,jlong handle,jint length)225 void Java_org_rocksdb_Slice_removePrefix0(JNIEnv* /*env*/, jobject /*jobj*/,
226 jlong handle, jint length) {
227 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
228 slice->remove_prefix(length);
229 }
230
231 /*
232 * Class: org_rocksdb_DirectSlice
233 * Method: setLength0
234 * Signature: (JI)V
235 */
Java_org_rocksdb_DirectSlice_setLength0(JNIEnv *,jobject,jlong handle,jint length)236 void Java_org_rocksdb_DirectSlice_setLength0(JNIEnv* /*env*/, jobject /*jobj*/,
237 jlong handle, jint length) {
238 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
239 slice->size_ = length;
240 }
241
242 /*
243 * Class: org_rocksdb_Slice
244 * Method: disposeInternalBuf
245 * Signature: (JJ)V
246 */
Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv *,jobject,jlong handle,jlong internalBufferOffset)247 void Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv* /*env*/,
248 jobject /*jobj*/, jlong handle,
249 jlong internalBufferOffset) {
250 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
251 const char* buf = slice->data_ - internalBufferOffset;
252 delete[] buf;
253 }
254
255 // </editor-fold>
256
257 // <editor-fold desc="org.rocksdb.DirectSlice>
258
259 /*
260 * Class: org_rocksdb_DirectSlice
261 * Method: createNewDirectSlice0
262 * Signature: (Ljava/nio/ByteBuffer;I)J
263 */
Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv * env,jclass,jobject data,jint length)264 jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv* env,
265 jclass /*jcls*/,
266 jobject data,
267 jint length) {
268 assert(data != nullptr);
269 void* data_addr = env->GetDirectBufferAddress(data);
270 if (data_addr == nullptr) {
271 // error: memory region is undefined, given object is not a direct
272 // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
273 ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
274 env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
275 "Could not access DirectBuffer"));
276 return 0;
277 }
278
279 const auto* ptrData = reinterpret_cast<char*>(data_addr);
280 const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData, length);
281 return reinterpret_cast<jlong>(slice);
282 }
283
284 /*
285 * Class: org_rocksdb_DirectSlice
286 * Method: createNewDirectSlice1
287 * Signature: (Ljava/nio/ByteBuffer;)J
288 */
Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv * env,jclass,jobject data)289 jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv* env,
290 jclass /*jcls*/,
291 jobject data) {
292 void* data_addr = env->GetDirectBufferAddress(data);
293 if (data_addr == nullptr) {
294 // error: memory region is undefined, given object is not a direct
295 // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
296 ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
297 env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
298 "Could not access DirectBuffer"));
299 return 0;
300 }
301
302 const auto* ptrData = reinterpret_cast<char*>(data_addr);
303 const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData);
304 return reinterpret_cast<jlong>(slice);
305 }
306
307 /*
308 * Class: org_rocksdb_DirectSlice
309 * Method: data0
310 * Signature: (J)Ljava/lang/Object;
311 */
Java_org_rocksdb_DirectSlice_data0(JNIEnv * env,jobject,jlong handle)312 jobject Java_org_rocksdb_DirectSlice_data0(JNIEnv* env, jobject /*jobj*/,
313 jlong handle) {
314 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
315 return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
316 slice->size());
317 }
318
319 /*
320 * Class: org_rocksdb_DirectSlice
321 * Method: get0
322 * Signature: (JI)B
323 */
Java_org_rocksdb_DirectSlice_get0(JNIEnv *,jobject,jlong handle,jint offset)324 jbyte Java_org_rocksdb_DirectSlice_get0(JNIEnv* /*env*/, jobject /*jobj*/,
325 jlong handle, jint offset) {
326 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
327 return (*slice)[offset];
328 }
329
330 /*
331 * Class: org_rocksdb_DirectSlice
332 * Method: clear0
333 * Signature: (JZJ)V
334 */
Java_org_rocksdb_DirectSlice_clear0(JNIEnv *,jobject,jlong handle,jboolean shouldRelease,jlong internalBufferOffset)335 void Java_org_rocksdb_DirectSlice_clear0(JNIEnv* /*env*/, jobject /*jobj*/,
336 jlong handle, jboolean shouldRelease,
337 jlong internalBufferOffset) {
338 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
339 if (shouldRelease == JNI_TRUE) {
340 const char* buf = slice->data_ - internalBufferOffset;
341 delete[] buf;
342 }
343 slice->clear();
344 }
345
346 /*
347 * Class: org_rocksdb_DirectSlice
348 * Method: removePrefix0
349 * Signature: (JI)V
350 */
Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv *,jobject,jlong handle,jint length)351 void Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv* /*env*/,
352 jobject /*jobj*/, jlong handle,
353 jint length) {
354 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
355 slice->remove_prefix(length);
356 }
357
358 /*
359 * Class: org_rocksdb_DirectSlice
360 * Method: disposeInternalBuf
361 * Signature: (JJ)V
362 */
Java_org_rocksdb_DirectSlice_disposeInternalBuf(JNIEnv *,jobject,jlong handle,jlong internalBufferOffset)363 void Java_org_rocksdb_DirectSlice_disposeInternalBuf(
364 JNIEnv* /*env*/, jobject /*jobj*/, jlong handle,
365 jlong internalBufferOffset) {
366 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
367 const char* buf = slice->data_ - internalBufferOffset;
368 delete[] buf;
369 }
370
371 // </editor-fold>
372