reduce_levels_test.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #ifndef ROCKSDB_LITE
  7. #include "db/db_impl/db_impl.h"
  8. #include "db/version_set.h"
  9. #include "rocksdb/db.h"
  10. #include "rocksdb/utilities/ldb_cmd.h"
  11. #include "test_util/testharness.h"
  12. #include "test_util/testutil.h"
  13. #include "tools/ldb_cmd_impl.h"
  14. #include "util/string_util.h"
  15. namespace ROCKSDB_NAMESPACE {
  16. class ReduceLevelTest : public testing::Test {
  17. public:
  18. ReduceLevelTest() {
  19. dbname_ = test::PerThreadDBPath("db_reduce_levels_test");
  20. DestroyDB(dbname_, Options());
  21. db_ = nullptr;
  22. }
  23. Status OpenDB(bool create_if_missing, int levels);
  24. Status Put(const std::string& k, const std::string& v) {
  25. return db_->Put(WriteOptions(), k, v);
  26. }
  27. std::string Get(const std::string& k) {
  28. ReadOptions options;
  29. std::string result;
  30. Status s = db_->Get(options, k, &result);
  31. if (s.IsNotFound()) {
  32. result = "NOT_FOUND";
  33. } else if (!s.ok()) {
  34. result = s.ToString();
  35. }
  36. return result;
  37. }
  38. Status Flush() {
  39. if (db_ == nullptr) {
  40. return Status::InvalidArgument("DB not opened.");
  41. }
  42. DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_);
  43. return db_impl->TEST_FlushMemTable();
  44. }
  45. void MoveL0FileToLevel(int level) {
  46. DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_);
  47. for (int i = 0; i < level; ++i) {
  48. ASSERT_OK(db_impl->TEST_CompactRange(i, nullptr, nullptr));
  49. }
  50. }
  51. void CloseDB() {
  52. if (db_ != nullptr) {
  53. delete db_;
  54. db_ = nullptr;
  55. }
  56. }
  57. bool ReduceLevels(int target_level);
  58. int FilesOnLevel(int level) {
  59. std::string property;
  60. EXPECT_TRUE(db_->GetProperty(
  61. "rocksdb.num-files-at-level" + NumberToString(level), &property));
  62. return atoi(property.c_str());
  63. }
  64. private:
  65. std::string dbname_;
  66. DB* db_;
  67. };
  68. Status ReduceLevelTest::OpenDB(bool create_if_missing, int num_levels) {
  69. ROCKSDB_NAMESPACE::Options opt;
  70. opt.num_levels = num_levels;
  71. opt.create_if_missing = create_if_missing;
  72. ROCKSDB_NAMESPACE::Status st =
  73. ROCKSDB_NAMESPACE::DB::Open(opt, dbname_, &db_);
  74. if (!st.ok()) {
  75. fprintf(stderr, "Can't open the db:%s\n", st.ToString().c_str());
  76. }
  77. return st;
  78. }
  79. bool ReduceLevelTest::ReduceLevels(int target_level) {
  80. std::vector<std::string> args =
  81. ROCKSDB_NAMESPACE::ReduceDBLevelsCommand::PrepareArgs(
  82. dbname_, target_level, false);
  83. LDBCommand* level_reducer = LDBCommand::InitFromCmdLineArgs(
  84. args, Options(), LDBOptions(), nullptr, LDBCommand::SelectCommand);
  85. level_reducer->Run();
  86. bool is_succeed = level_reducer->GetExecuteState().IsSucceed();
  87. delete level_reducer;
  88. return is_succeed;
  89. }
  90. TEST_F(ReduceLevelTest, Last_Level) {
  91. ASSERT_OK(OpenDB(true, 4));
  92. ASSERT_OK(Put("aaaa", "11111"));
  93. Flush();
  94. MoveL0FileToLevel(3);
  95. ASSERT_EQ(FilesOnLevel(3), 1);
  96. CloseDB();
  97. ASSERT_TRUE(ReduceLevels(3));
  98. ASSERT_OK(OpenDB(true, 3));
  99. ASSERT_EQ(FilesOnLevel(2), 1);
  100. CloseDB();
  101. ASSERT_TRUE(ReduceLevels(2));
  102. ASSERT_OK(OpenDB(true, 2));
  103. ASSERT_EQ(FilesOnLevel(1), 1);
  104. CloseDB();
  105. }
  106. TEST_F(ReduceLevelTest, Top_Level) {
  107. ASSERT_OK(OpenDB(true, 5));
  108. ASSERT_OK(Put("aaaa", "11111"));
  109. Flush();
  110. ASSERT_EQ(FilesOnLevel(0), 1);
  111. CloseDB();
  112. ASSERT_TRUE(ReduceLevels(4));
  113. ASSERT_OK(OpenDB(true, 4));
  114. CloseDB();
  115. ASSERT_TRUE(ReduceLevels(3));
  116. ASSERT_OK(OpenDB(true, 3));
  117. CloseDB();
  118. ASSERT_TRUE(ReduceLevels(2));
  119. ASSERT_OK(OpenDB(true, 2));
  120. CloseDB();
  121. }
  122. TEST_F(ReduceLevelTest, All_Levels) {
  123. ASSERT_OK(OpenDB(true, 5));
  124. ASSERT_OK(Put("a", "a11111"));
  125. ASSERT_OK(Flush());
  126. MoveL0FileToLevel(4);
  127. ASSERT_EQ(FilesOnLevel(4), 1);
  128. CloseDB();
  129. ASSERT_OK(OpenDB(true, 5));
  130. ASSERT_OK(Put("b", "b11111"));
  131. ASSERT_OK(Flush());
  132. MoveL0FileToLevel(3);
  133. ASSERT_EQ(FilesOnLevel(3), 1);
  134. ASSERT_EQ(FilesOnLevel(4), 1);
  135. CloseDB();
  136. ASSERT_OK(OpenDB(true, 5));
  137. ASSERT_OK(Put("c", "c11111"));
  138. ASSERT_OK(Flush());
  139. MoveL0FileToLevel(2);
  140. ASSERT_EQ(FilesOnLevel(2), 1);
  141. ASSERT_EQ(FilesOnLevel(3), 1);
  142. ASSERT_EQ(FilesOnLevel(4), 1);
  143. CloseDB();
  144. ASSERT_OK(OpenDB(true, 5));
  145. ASSERT_OK(Put("d", "d11111"));
  146. ASSERT_OK(Flush());
  147. MoveL0FileToLevel(1);
  148. ASSERT_EQ(FilesOnLevel(1), 1);
  149. ASSERT_EQ(FilesOnLevel(2), 1);
  150. ASSERT_EQ(FilesOnLevel(3), 1);
  151. ASSERT_EQ(FilesOnLevel(4), 1);
  152. CloseDB();
  153. ASSERT_TRUE(ReduceLevels(4));
  154. ASSERT_OK(OpenDB(true, 4));
  155. ASSERT_EQ("a11111", Get("a"));
  156. ASSERT_EQ("b11111", Get("b"));
  157. ASSERT_EQ("c11111", Get("c"));
  158. ASSERT_EQ("d11111", Get("d"));
  159. CloseDB();
  160. ASSERT_TRUE(ReduceLevels(3));
  161. ASSERT_OK(OpenDB(true, 3));
  162. ASSERT_EQ("a11111", Get("a"));
  163. ASSERT_EQ("b11111", Get("b"));
  164. ASSERT_EQ("c11111", Get("c"));
  165. ASSERT_EQ("d11111", Get("d"));
  166. CloseDB();
  167. ASSERT_TRUE(ReduceLevels(2));
  168. ASSERT_OK(OpenDB(true, 2));
  169. ASSERT_EQ("a11111", Get("a"));
  170. ASSERT_EQ("b11111", Get("b"));
  171. ASSERT_EQ("c11111", Get("c"));
  172. ASSERT_EQ("d11111", Get("d"));
  173. CloseDB();
  174. }
  175. } // namespace ROCKSDB_NAMESPACE
  176. int main(int argc, char** argv) {
  177. ::testing::InitGoogleTest(&argc, argv);
  178. return RUN_ALL_TESTS();
  179. }
  180. #else
  181. #include <stdio.h>
  182. int main(int /*argc*/, char** /*argv*/) {
  183. fprintf(stderr, "SKIPPED as LDBCommand is not supported in ROCKSDB_LITE\n");
  184. return 0;
  185. }
  186. #endif // !ROCKSDB_LITE