ttl.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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::TtlDB methods.
  8. // from Java side.
  9. #include <jni.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <memory>
  13. #include <string>
  14. #include <vector>
  15. #include "include/org_rocksdb_TtlDB.h"
  16. #include "rocksdb/utilities/db_ttl.h"
  17. #include "rocksjni/cplusplus_to_java_convert.h"
  18. #include "rocksjni/portal.h"
  19. /*
  20. * Class: org_rocksdb_TtlDB
  21. * Method: open
  22. * Signature: (JLjava/lang/String;IZ)J
  23. */
  24. jlong Java_org_rocksdb_TtlDB_open(JNIEnv* env, jclass, jlong joptions_handle,
  25. jstring jdb_path, jint jttl,
  26. jboolean jread_only) {
  27. const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
  28. if (db_path == nullptr) {
  29. // exception thrown: OutOfMemoryError
  30. return 0;
  31. }
  32. auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions_handle);
  33. ROCKSDB_NAMESPACE::DBWithTTL* db = nullptr;
  34. ROCKSDB_NAMESPACE::Status s =
  35. ROCKSDB_NAMESPACE::DBWithTTL::Open(*opt, db_path, &db, jttl, jread_only);
  36. env->ReleaseStringUTFChars(jdb_path, db_path);
  37. // as TTLDB extends RocksDB on the java side, we can reuse
  38. // the RocksDB portal here.
  39. if (s.ok()) {
  40. return GET_CPLUSPLUS_POINTER(db);
  41. } else {
  42. ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
  43. return 0;
  44. }
  45. }
  46. /*
  47. * Class: org_rocksdb_TtlDB
  48. * Method: openCF
  49. * Signature: (JLjava/lang/String;[[B[J[IZ)[J
  50. */
  51. jlongArray Java_org_rocksdb_TtlDB_openCF(JNIEnv* env, jclass, jlong jopt_handle,
  52. jstring jdb_path,
  53. jobjectArray jcolumn_names,
  54. jlongArray jcolumn_options,
  55. jintArray jttls, jboolean jread_only) {
  56. const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
  57. if (db_path == nullptr) {
  58. // exception thrown: OutOfMemoryError
  59. return 0;
  60. }
  61. const jsize len_cols = env->GetArrayLength(jcolumn_names);
  62. jlong* jco = env->GetLongArrayElements(jcolumn_options, nullptr);
  63. if (jco == nullptr) {
  64. // exception thrown: OutOfMemoryError
  65. env->ReleaseStringUTFChars(jdb_path, db_path);
  66. return nullptr;
  67. }
  68. std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> column_families;
  69. jboolean has_exception = JNI_FALSE;
  70. ROCKSDB_NAMESPACE::JniUtil::byteStrings<std::string>(
  71. env, jcolumn_names,
  72. [](const char* str_data, const size_t str_len) {
  73. return std::string(str_data, str_len);
  74. },
  75. [&jco, &column_families](size_t idx, std::string cf_name) {
  76. ROCKSDB_NAMESPACE::ColumnFamilyOptions* cf_options =
  77. reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(jco[idx]);
  78. column_families.push_back(
  79. ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(cf_name, *cf_options));
  80. },
  81. &has_exception);
  82. env->ReleaseLongArrayElements(jcolumn_options, jco, JNI_ABORT);
  83. if (has_exception == JNI_TRUE) {
  84. // exception occurred
  85. env->ReleaseStringUTFChars(jdb_path, db_path);
  86. return nullptr;
  87. }
  88. std::vector<int32_t> ttl_values;
  89. jint* jttlv = env->GetIntArrayElements(jttls, nullptr);
  90. if (jttlv == nullptr) {
  91. // exception thrown: OutOfMemoryError
  92. env->ReleaseStringUTFChars(jdb_path, db_path);
  93. return nullptr;
  94. }
  95. const jsize len_ttls = env->GetArrayLength(jttls);
  96. for (jsize i = 0; i < len_ttls; i++) {
  97. ttl_values.push_back(jttlv[i]);
  98. }
  99. env->ReleaseIntArrayElements(jttls, jttlv, JNI_ABORT);
  100. auto* opt = reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jopt_handle);
  101. std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> handles;
  102. ROCKSDB_NAMESPACE::DBWithTTL* db = nullptr;
  103. ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::DBWithTTL::Open(
  104. *opt, db_path, column_families, &handles, &db, ttl_values, jread_only);
  105. // we have now finished with db_path
  106. env->ReleaseStringUTFChars(jdb_path, db_path);
  107. // check if open operation was successful
  108. if (s.ok()) {
  109. const jsize resultsLen = 1 + len_cols; // db handle + column family handles
  110. std::unique_ptr<jlong[]> results =
  111. std::unique_ptr<jlong[]>(new jlong[resultsLen]);
  112. results[0] = GET_CPLUSPLUS_POINTER(db);
  113. for (int i = 1; i <= len_cols; i++) {
  114. results[i] = GET_CPLUSPLUS_POINTER(handles[i - 1]);
  115. }
  116. jlongArray jresults = env->NewLongArray(resultsLen);
  117. if (jresults == nullptr) {
  118. // exception thrown: OutOfMemoryError
  119. return nullptr;
  120. }
  121. env->SetLongArrayRegion(jresults, 0, resultsLen, results.get());
  122. if (env->ExceptionCheck()) {
  123. // exception thrown: ArrayIndexOutOfBoundsException
  124. env->DeleteLocalRef(jresults);
  125. return nullptr;
  126. }
  127. return jresults;
  128. } else {
  129. ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
  130. return nullptr;
  131. }
  132. }
  133. /*
  134. * Class: org_rocksdb_TtlDB
  135. * Method: disposeInternal
  136. * Signature: (J)V
  137. */
  138. void Java_org_rocksdb_TtlDB_disposeInternalJni(JNIEnv*, jclass, jlong jhandle) {
  139. auto* ttl_db = reinterpret_cast<ROCKSDB_NAMESPACE::DBWithTTL*>(jhandle);
  140. assert(ttl_db != nullptr);
  141. delete ttl_db;
  142. }
  143. /*
  144. * Class: org_rocksdb_TtlDB
  145. * Method: closeDatabase
  146. * Signature: (J)V
  147. */
  148. void Java_org_rocksdb_TtlDB_closeDatabase(JNIEnv* /* env */, jclass,
  149. jlong /* jhandle */) {
  150. // auto* ttl_db = reinterpret_cast<ROCKSDB_NAMESPACE::DBWithTTL*>(jhandle);
  151. // assert(ttl_db != nullptr);
  152. // ROCKSDB_NAMESPACE::Status s = ttl_db->Close();
  153. // ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
  154. // TODO(AR) this is disabled until
  155. // https://github.com/facebook/rocksdb/issues/4818 is resolved!
  156. }
  157. /*
  158. * Class: org_rocksdb_TtlDB
  159. * Method: createColumnFamilyWithTtl
  160. * Signature: (JLorg/rocksdb/ColumnFamilyDescriptor;[BJI)J;
  161. */
  162. jlong Java_org_rocksdb_TtlDB_createColumnFamilyWithTtl(JNIEnv* env, jclass,
  163. jlong jdb_handle,
  164. jbyteArray jcolumn_name,
  165. jlong jcolumn_options,
  166. jint jttl) {
  167. jbyte* cfname = env->GetByteArrayElements(jcolumn_name, nullptr);
  168. if (cfname == nullptr) {
  169. // exception thrown: OutOfMemoryError
  170. return 0;
  171. }
  172. const jsize len = env->GetArrayLength(jcolumn_name);
  173. auto* cfOptions = reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyOptions*>(
  174. jcolumn_options);
  175. auto* db_handle = reinterpret_cast<ROCKSDB_NAMESPACE::DBWithTTL*>(jdb_handle);
  176. ROCKSDB_NAMESPACE::ColumnFamilyHandle* handle;
  177. ROCKSDB_NAMESPACE::Status s = db_handle->CreateColumnFamilyWithTtl(
  178. *cfOptions, std::string(reinterpret_cast<char*>(cfname), len), &handle,
  179. jttl);
  180. env->ReleaseByteArrayElements(jcolumn_name, cfname, JNI_ABORT);
  181. if (s.ok()) {
  182. return GET_CPLUSPLUS_POINTER(handle);
  183. }
  184. ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s);
  185. return 0;
  186. }