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