write_batch_test.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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::WriteBatch methods testing from Java side.
  8. #include <memory>
  9. #include "db/memtable.h"
  10. #include "db/write_batch_internal.h"
  11. #include "include/org_rocksdb_WriteBatch.h"
  12. #include "include/org_rocksdb_WriteBatchTest.h"
  13. #include "include/org_rocksdb_WriteBatchTestInternalHelper.h"
  14. #include "include/org_rocksdb_WriteBatch_Handler.h"
  15. #include "options/cf_options.h"
  16. #include "rocksdb/db.h"
  17. #include "rocksdb/env.h"
  18. #include "rocksdb/memtablerep.h"
  19. #include "rocksdb/status.h"
  20. #include "rocksdb/write_batch.h"
  21. #include "rocksdb/write_buffer_manager.h"
  22. #include "rocksjni/portal.h"
  23. #include "table/scoped_arena_iterator.h"
  24. #include "test_util/testharness.h"
  25. #include "util/string_util.h"
  26. /*
  27. * Class: org_rocksdb_WriteBatchTest
  28. * Method: getContents
  29. * Signature: (J)[B
  30. */
  31. jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(JNIEnv* env,
  32. jclass /*jclazz*/,
  33. jlong jwb_handle) {
  34. auto* b = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
  35. assert(b != nullptr);
  36. // todo: Currently the following code is directly copied from
  37. // db/write_bench_test.cc. It could be implemented in java once
  38. // all the necessary components can be accessed via jni api.
  39. ROCKSDB_NAMESPACE::InternalKeyComparator cmp(
  40. ROCKSDB_NAMESPACE::BytewiseComparator());
  41. auto factory = std::make_shared<ROCKSDB_NAMESPACE::SkipListFactory>();
  42. ROCKSDB_NAMESPACE::Options options;
  43. ROCKSDB_NAMESPACE::WriteBufferManager wb(options.db_write_buffer_size);
  44. options.memtable_factory = factory;
  45. ROCKSDB_NAMESPACE::MemTable* mem = new ROCKSDB_NAMESPACE::MemTable(
  46. cmp, ROCKSDB_NAMESPACE::ImmutableCFOptions(options),
  47. ROCKSDB_NAMESPACE::MutableCFOptions(options), &wb,
  48. ROCKSDB_NAMESPACE::kMaxSequenceNumber, 0 /* column_family_id */);
  49. mem->Ref();
  50. std::string state;
  51. ROCKSDB_NAMESPACE::ColumnFamilyMemTablesDefault cf_mems_default(mem);
  52. ROCKSDB_NAMESPACE::Status s =
  53. ROCKSDB_NAMESPACE::WriteBatchInternal::InsertInto(b, &cf_mems_default,
  54. nullptr, nullptr);
  55. unsigned int count = 0;
  56. ROCKSDB_NAMESPACE::Arena arena;
  57. ROCKSDB_NAMESPACE::ScopedArenaIterator iter(
  58. mem->NewIterator(ROCKSDB_NAMESPACE::ReadOptions(), &arena));
  59. for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
  60. ROCKSDB_NAMESPACE::ParsedInternalKey ikey;
  61. ikey.clear();
  62. bool parsed = ROCKSDB_NAMESPACE::ParseInternalKey(iter->key(), &ikey);
  63. if (!parsed) {
  64. assert(parsed);
  65. }
  66. switch (ikey.type) {
  67. case ROCKSDB_NAMESPACE::kTypeValue:
  68. state.append("Put(");
  69. state.append(ikey.user_key.ToString());
  70. state.append(", ");
  71. state.append(iter->value().ToString());
  72. state.append(")");
  73. count++;
  74. break;
  75. case ROCKSDB_NAMESPACE::kTypeMerge:
  76. state.append("Merge(");
  77. state.append(ikey.user_key.ToString());
  78. state.append(", ");
  79. state.append(iter->value().ToString());
  80. state.append(")");
  81. count++;
  82. break;
  83. case ROCKSDB_NAMESPACE::kTypeDeletion:
  84. state.append("Delete(");
  85. state.append(ikey.user_key.ToString());
  86. state.append(")");
  87. count++;
  88. break;
  89. case ROCKSDB_NAMESPACE::kTypeSingleDeletion:
  90. state.append("SingleDelete(");
  91. state.append(ikey.user_key.ToString());
  92. state.append(")");
  93. count++;
  94. break;
  95. case ROCKSDB_NAMESPACE::kTypeRangeDeletion:
  96. state.append("DeleteRange(");
  97. state.append(ikey.user_key.ToString());
  98. state.append(", ");
  99. state.append(iter->value().ToString());
  100. state.append(")");
  101. count++;
  102. break;
  103. case ROCKSDB_NAMESPACE::kTypeLogData:
  104. state.append("LogData(");
  105. state.append(ikey.user_key.ToString());
  106. state.append(")");
  107. count++;
  108. break;
  109. default:
  110. assert(false);
  111. state.append("Err:Expected(");
  112. state.append(std::to_string(ikey.type));
  113. state.append(")");
  114. count++;
  115. break;
  116. }
  117. state.append("@");
  118. state.append(ROCKSDB_NAMESPACE::NumberToString(ikey.sequence));
  119. }
  120. if (!s.ok()) {
  121. state.append(s.ToString());
  122. } else if (ROCKSDB_NAMESPACE::WriteBatchInternal::Count(b) != count) {
  123. state.append("Err:CountMismatch(expected=");
  124. state.append(
  125. std::to_string(ROCKSDB_NAMESPACE::WriteBatchInternal::Count(b)));
  126. state.append(", actual=");
  127. state.append(std::to_string(count));
  128. state.append(")");
  129. }
  130. delete mem->Unref();
  131. jbyteArray jstate = env->NewByteArray(static_cast<jsize>(state.size()));
  132. if (jstate == nullptr) {
  133. // exception thrown: OutOfMemoryError
  134. return nullptr;
  135. }
  136. env->SetByteArrayRegion(
  137. jstate, 0, static_cast<jsize>(state.size()),
  138. const_cast<jbyte*>(reinterpret_cast<const jbyte*>(state.c_str())));
  139. if (env->ExceptionCheck()) {
  140. // exception thrown: ArrayIndexOutOfBoundsException
  141. env->DeleteLocalRef(jstate);
  142. return nullptr;
  143. }
  144. return jstate;
  145. }
  146. /*
  147. * Class: org_rocksdb_WriteBatchTestInternalHelper
  148. * Method: setSequence
  149. * Signature: (JJ)V
  150. */
  151. void Java_org_rocksdb_WriteBatchTestInternalHelper_setSequence(
  152. JNIEnv* /*env*/, jclass /*jclazz*/, jlong jwb_handle, jlong jsn) {
  153. auto* wb = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
  154. assert(wb != nullptr);
  155. ROCKSDB_NAMESPACE::WriteBatchInternal::SetSequence(
  156. wb, static_cast<ROCKSDB_NAMESPACE::SequenceNumber>(jsn));
  157. }
  158. /*
  159. * Class: org_rocksdb_WriteBatchTestInternalHelper
  160. * Method: sequence
  161. * Signature: (J)J
  162. */
  163. jlong Java_org_rocksdb_WriteBatchTestInternalHelper_sequence(JNIEnv* /*env*/,
  164. jclass /*jclazz*/,
  165. jlong jwb_handle) {
  166. auto* wb = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
  167. assert(wb != nullptr);
  168. return static_cast<jlong>(
  169. ROCKSDB_NAMESPACE::WriteBatchInternal::Sequence(wb));
  170. }
  171. /*
  172. * Class: org_rocksdb_WriteBatchTestInternalHelper
  173. * Method: append
  174. * Signature: (JJ)V
  175. */
  176. void Java_org_rocksdb_WriteBatchTestInternalHelper_append(JNIEnv* /*env*/,
  177. jclass /*jclazz*/,
  178. jlong jwb_handle_1,
  179. jlong jwb_handle_2) {
  180. auto* wb1 = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle_1);
  181. assert(wb1 != nullptr);
  182. auto* wb2 = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle_2);
  183. assert(wb2 != nullptr);
  184. ROCKSDB_NAMESPACE::WriteBatchInternal::Append(wb1, wb2);
  185. }