ttl.cc 6.6 KB

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