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_Slice
233 * Method: disposeInternalBuf
234 * Signature: (JJ)V
235 */
Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv *,jobject,jlong handle,jlong internalBufferOffset)236 void Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv* /*env*/,
237 jobject /*jobj*/, jlong handle,
238 jlong internalBufferOffset) {
239 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
240 const char* buf = slice->data_ - internalBufferOffset;
241 delete[] buf;
242 }
243
244 // </editor-fold>
245
246 // <editor-fold desc="org.rocksdb.DirectSlice>
247
248 /*
249 * Class: org_rocksdb_DirectSlice
250 * Method: createNewDirectSlice0
251 * Signature: (Ljava/nio/ByteBuffer;I)J
252 */
Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv * env,jclass,jobject data,jint length)253 jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv* env,
254 jclass /*jcls*/,
255 jobject data,
256 jint length) {
257 assert(data != nullptr);
258 void* data_addr = env->GetDirectBufferAddress(data);
259 if (data_addr == nullptr) {
260 // error: memory region is undefined, given object is not a direct
261 // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
262 ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
263 env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
264 "Could not access DirectBuffer"));
265 return 0;
266 }
267
268 const auto* ptrData = reinterpret_cast<char*>(data_addr);
269 const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData, length);
270 return reinterpret_cast<jlong>(slice);
271 }
272
273 /*
274 * Class: org_rocksdb_DirectSlice
275 * Method: createNewDirectSlice1
276 * Signature: (Ljava/nio/ByteBuffer;)J
277 */
Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv * env,jclass,jobject data)278 jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv* env,
279 jclass /*jcls*/,
280 jobject data) {
281 void* data_addr = env->GetDirectBufferAddress(data);
282 if (data_addr == nullptr) {
283 // error: memory region is undefined, given object is not a direct
284 // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
285 ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
286 env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
287 "Could not access DirectBuffer"));
288 return 0;
289 }
290
291 const auto* ptrData = reinterpret_cast<char*>(data_addr);
292 const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData);
293 return reinterpret_cast<jlong>(slice);
294 }
295
296 /*
297 * Class: org_rocksdb_DirectSlice
298 * Method: data0
299 * Signature: (J)Ljava/lang/Object;
300 */
Java_org_rocksdb_DirectSlice_data0(JNIEnv * env,jobject,jlong handle)301 jobject Java_org_rocksdb_DirectSlice_data0(JNIEnv* env, jobject /*jobj*/,
302 jlong handle) {
303 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
304 return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
305 slice->size());
306 }
307
308 /*
309 * Class: org_rocksdb_DirectSlice
310 * Method: get0
311 * Signature: (JI)B
312 */
Java_org_rocksdb_DirectSlice_get0(JNIEnv *,jobject,jlong handle,jint offset)313 jbyte Java_org_rocksdb_DirectSlice_get0(JNIEnv* /*env*/, jobject /*jobj*/,
314 jlong handle, jint offset) {
315 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
316 return (*slice)[offset];
317 }
318
319 /*
320 * Class: org_rocksdb_DirectSlice
321 * Method: clear0
322 * Signature: (JZJ)V
323 */
Java_org_rocksdb_DirectSlice_clear0(JNIEnv *,jobject,jlong handle,jboolean shouldRelease,jlong internalBufferOffset)324 void Java_org_rocksdb_DirectSlice_clear0(JNIEnv* /*env*/, jobject /*jobj*/,
325 jlong handle, jboolean shouldRelease,
326 jlong internalBufferOffset) {
327 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
328 if (shouldRelease == JNI_TRUE) {
329 const char* buf = slice->data_ - internalBufferOffset;
330 delete[] buf;
331 }
332 slice->clear();
333 }
334
335 /*
336 * Class: org_rocksdb_DirectSlice
337 * Method: removePrefix0
338 * Signature: (JI)V
339 */
Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv *,jobject,jlong handle,jint length)340 void Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv* /*env*/,
341 jobject /*jobj*/, jlong handle,
342 jint length) {
343 auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
344 slice->remove_prefix(length);
345 }
346
347 /*
348 * Class: org_rocksdb_DirectSlice
349 * Method: disposeInternalBuf
350 * Signature: (JJ)V
351 */
Java_org_rocksdb_DirectSlice_disposeInternalBuf(JNIEnv *,jobject,jlong handle,jlong internalBufferOffset)352 void Java_org_rocksdb_DirectSlice_disposeInternalBuf(
353 JNIEnv* /*env*/, jobject /*jobj*/, jlong handle,
354 jlong internalBufferOffset) {
355 const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
356 const char* buf = slice->data_ - internalBufferOffset;
357 delete[] buf;
358 }
359
360 // </editor-fold>
361