reduce_levels_test.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. #include "db/db_impl/db_impl.h"
  7. #include "db/version_set.h"
  8. #include "rocksdb/db.h"
  9. #include "rocksdb/utilities/ldb_cmd.h"
  10. #include "test_util/testharness.h"
  11. #include "test_util/testutil.h"
  12. #include "tools/ldb_cmd_impl.h"
  13. #include "util/cast_util.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. EXPECT_OK(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 = static_cast_with_check<DBImpl>(db_);
  43. return db_impl->TEST_FlushMemTable();
  44. }
  45. void MoveL0FileToLevel(int level) {
  46. DBImpl* db_impl = static_cast_with_check<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" + std::to_string(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.level_compaction_dynamic_level_bytes = false;
  71. opt.num_levels = num_levels;
  72. opt.create_if_missing = create_if_missing;
  73. ROCKSDB_NAMESPACE::Status st =
  74. ROCKSDB_NAMESPACE::DB::Open(opt, dbname_, &db_);
  75. if (!st.ok()) {
  76. fprintf(stderr, "Can't open the db:%s\n", st.ToString().c_str());
  77. }
  78. return st;
  79. }
  80. bool ReduceLevelTest::ReduceLevels(int target_level) {
  81. std::vector<std::string> args =
  82. ROCKSDB_NAMESPACE::ReduceDBLevelsCommand::PrepareArgs(
  83. dbname_, target_level, false);
  84. LDBCommand* level_reducer = LDBCommand::InitFromCmdLineArgs(
  85. args, Options(), LDBOptions(), nullptr, LDBCommand::SelectCommand);
  86. level_reducer->Run();
  87. bool is_succeed = level_reducer->GetExecuteState().IsSucceed();
  88. delete level_reducer;
  89. return is_succeed;
  90. }
  91. TEST_F(ReduceLevelTest, Last_Level) {
  92. ASSERT_OK(OpenDB(true, 4));
  93. ASSERT_OK(Put("aaaa", "11111"));
  94. ASSERT_OK(Flush());
  95. MoveL0FileToLevel(3);
  96. ASSERT_EQ(FilesOnLevel(3), 1);
  97. CloseDB();
  98. ASSERT_TRUE(ReduceLevels(3));
  99. ASSERT_OK(OpenDB(true, 3));
  100. ASSERT_EQ(FilesOnLevel(2), 1);
  101. CloseDB();
  102. ASSERT_TRUE(ReduceLevels(2));
  103. ASSERT_OK(OpenDB(true, 2));
  104. ASSERT_EQ(FilesOnLevel(1), 1);
  105. CloseDB();
  106. }
  107. TEST_F(ReduceLevelTest, Top_Level) {
  108. ASSERT_OK(OpenDB(true, 5));
  109. ASSERT_OK(Put("aaaa", "11111"));
  110. ASSERT_OK(Flush());
  111. ASSERT_EQ(FilesOnLevel(0), 1);
  112. CloseDB();
  113. ASSERT_TRUE(ReduceLevels(4));
  114. ASSERT_OK(OpenDB(true, 4));
  115. CloseDB();
  116. ASSERT_TRUE(ReduceLevels(3));
  117. ASSERT_OK(OpenDB(true, 3));
  118. CloseDB();
  119. ASSERT_TRUE(ReduceLevels(2));
  120. ASSERT_OK(OpenDB(true, 2));
  121. CloseDB();
  122. }
  123. TEST_F(ReduceLevelTest, All_Levels) {
  124. ASSERT_OK(OpenDB(true, 5));
  125. ASSERT_OK(Put("a", "a11111"));
  126. ASSERT_OK(Flush());
  127. MoveL0FileToLevel(4);
  128. ASSERT_EQ(FilesOnLevel(4), 1);
  129. CloseDB();
  130. ASSERT_OK(OpenDB(true, 5));
  131. ASSERT_OK(Put("b", "b11111"));
  132. ASSERT_OK(Flush());
  133. MoveL0FileToLevel(3);
  134. ASSERT_EQ(FilesOnLevel(3), 1);
  135. ASSERT_EQ(FilesOnLevel(4), 1);
  136. CloseDB();
  137. ASSERT_OK(OpenDB(true, 5));
  138. ASSERT_OK(Put("c", "c11111"));
  139. ASSERT_OK(Flush());
  140. MoveL0FileToLevel(2);
  141. ASSERT_EQ(FilesOnLevel(2), 1);
  142. ASSERT_EQ(FilesOnLevel(3), 1);
  143. ASSERT_EQ(FilesOnLevel(4), 1);
  144. CloseDB();
  145. ASSERT_OK(OpenDB(true, 5));
  146. ASSERT_OK(Put("d", "d11111"));
  147. ASSERT_OK(Flush());
  148. MoveL0FileToLevel(1);
  149. ASSERT_EQ(FilesOnLevel(1), 1);
  150. ASSERT_EQ(FilesOnLevel(2), 1);
  151. ASSERT_EQ(FilesOnLevel(3), 1);
  152. ASSERT_EQ(FilesOnLevel(4), 1);
  153. CloseDB();
  154. ASSERT_TRUE(ReduceLevels(4));
  155. ASSERT_OK(OpenDB(true, 4));
  156. ASSERT_EQ("a11111", Get("a"));
  157. ASSERT_EQ("b11111", Get("b"));
  158. ASSERT_EQ("c11111", Get("c"));
  159. ASSERT_EQ("d11111", Get("d"));
  160. CloseDB();
  161. ASSERT_TRUE(ReduceLevels(3));
  162. ASSERT_OK(OpenDB(true, 3));
  163. ASSERT_EQ("a11111", Get("a"));
  164. ASSERT_EQ("b11111", Get("b"));
  165. ASSERT_EQ("c11111", Get("c"));
  166. ASSERT_EQ("d11111", Get("d"));
  167. CloseDB();
  168. ASSERT_TRUE(ReduceLevels(2));
  169. ASSERT_OK(OpenDB(true, 2));
  170. ASSERT_EQ("a11111", Get("a"));
  171. ASSERT_EQ("b11111", Get("b"));
  172. ASSERT_EQ("c11111", Get("c"));
  173. ASSERT_EQ("d11111", Get("d"));
  174. CloseDB();
  175. }
  176. } // namespace ROCKSDB_NAMESPACE
  177. int main(int argc, char** argv) {
  178. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  179. ::testing::InitGoogleTest(&argc, argv);
  180. return RUN_ALL_TESTS();
  181. }