slice.cc 12 KB

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