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