]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/db/periodic_task_scheduler_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / db / periodic_task_scheduler_test.cc
1 // Copyright (c) Meta Platforms, Inc. and affiliates.
2 //
3 // This source code is licensed under both the GPLv2 (found in the
4 // COPYING file in the root directory) and Apache 2.0 License
5 // (found in the LICENSE.Apache file in the root directory).
6
7 #include "db/periodic_task_scheduler.h"
8
9 #include "db/db_test_util.h"
10 #include "env/composite_env_wrapper.h"
11 #include "test_util/mock_time_env.h"
12
13 namespace ROCKSDB_NAMESPACE {
14
15 #ifndef ROCKSDB_LITE
16 class PeriodicTaskSchedulerTest : public DBTestBase {
17 public:
18 PeriodicTaskSchedulerTest()
19 : DBTestBase("periodic_task_scheduler_test", /*env_do_fsync=*/true) {
20 mock_clock_ = std::make_shared<MockSystemClock>(env_->GetSystemClock());
21 mock_env_.reset(new CompositeEnvWrapper(env_, mock_clock_));
22 }
23
24 protected:
25 std::unique_ptr<Env> mock_env_;
26 std::shared_ptr<MockSystemClock> mock_clock_;
27
28 void SetUp() override {
29 mock_clock_->InstallTimedWaitFixCallback();
30 SyncPoint::GetInstance()->SetCallBack(
31 "DBImpl::StartPeriodicTaskScheduler:Init", [&](void* arg) {
32 auto periodic_task_scheduler_ptr =
33 reinterpret_cast<PeriodicTaskScheduler*>(arg);
34 periodic_task_scheduler_ptr->TEST_OverrideTimer(mock_clock_.get());
35 });
36 }
37 };
38
39 TEST_F(PeriodicTaskSchedulerTest, Basic) {
40 constexpr unsigned int kPeriodSec = 10;
41 Close();
42 Options options;
43 options.stats_dump_period_sec = kPeriodSec;
44 options.stats_persist_period_sec = kPeriodSec;
45 options.create_if_missing = true;
46 options.env = mock_env_.get();
47
48 int dump_st_counter = 0;
49 SyncPoint::GetInstance()->SetCallBack("DBImpl::DumpStats:StartRunning",
50 [&](void*) { dump_st_counter++; });
51
52 int pst_st_counter = 0;
53 SyncPoint::GetInstance()->SetCallBack("DBImpl::PersistStats:StartRunning",
54 [&](void*) { pst_st_counter++; });
55
56 int flush_info_log_counter = 0;
57 SyncPoint::GetInstance()->SetCallBack(
58 "DBImpl::FlushInfoLog:StartRunning",
59 [&](void*) { flush_info_log_counter++; });
60 SyncPoint::GetInstance()->EnableProcessing();
61
62 Reopen(options);
63
64 ASSERT_EQ(kPeriodSec, dbfull()->GetDBOptions().stats_dump_period_sec);
65 ASSERT_EQ(kPeriodSec, dbfull()->GetDBOptions().stats_persist_period_sec);
66
67 ASSERT_GT(kPeriodSec, 1u);
68 dbfull()->TEST_WaitForPeridicTaskRun([&] {
69 mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec) - 1);
70 });
71
72 const PeriodicTaskScheduler& scheduler =
73 dbfull()->TEST_GetPeriodicTaskScheduler();
74 ASSERT_EQ(3, scheduler.TEST_GetValidTaskNum());
75
76 ASSERT_EQ(1, dump_st_counter);
77 ASSERT_EQ(1, pst_st_counter);
78 ASSERT_EQ(1, flush_info_log_counter);
79
80 dbfull()->TEST_WaitForPeridicTaskRun(
81 [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
82
83 ASSERT_EQ(2, dump_st_counter);
84 ASSERT_EQ(2, pst_st_counter);
85 ASSERT_EQ(2, flush_info_log_counter);
86
87 dbfull()->TEST_WaitForPeridicTaskRun(
88 [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
89
90 ASSERT_EQ(3, dump_st_counter);
91 ASSERT_EQ(3, pst_st_counter);
92 ASSERT_EQ(3, flush_info_log_counter);
93
94 // Disable scheduler with SetOption
95 ASSERT_OK(dbfull()->SetDBOptions(
96 {{"stats_dump_period_sec", "0"}, {"stats_persist_period_sec", "0"}}));
97 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_dump_period_sec);
98 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_persist_period_sec);
99
100 // Info log flush should still run.
101 dbfull()->TEST_WaitForPeridicTaskRun(
102 [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
103 ASSERT_EQ(3, dump_st_counter);
104 ASSERT_EQ(3, pst_st_counter);
105 ASSERT_EQ(4, flush_info_log_counter);
106
107 ASSERT_EQ(1u, scheduler.TEST_GetValidTaskNum());
108
109 // Re-enable one task
110 ASSERT_OK(dbfull()->SetDBOptions({{"stats_dump_period_sec", "5"}}));
111 ASSERT_EQ(5u, dbfull()->GetDBOptions().stats_dump_period_sec);
112 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_persist_period_sec);
113
114 ASSERT_EQ(2, scheduler.TEST_GetValidTaskNum());
115
116 dbfull()->TEST_WaitForPeridicTaskRun(
117 [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
118 ASSERT_EQ(4, dump_st_counter);
119 ASSERT_EQ(3, pst_st_counter);
120 ASSERT_EQ(5, flush_info_log_counter);
121
122 Close();
123 }
124
125 TEST_F(PeriodicTaskSchedulerTest, MultiInstances) {
126 constexpr int kPeriodSec = 5;
127 const int kInstanceNum = 10;
128
129 Close();
130 Options options;
131 options.stats_dump_period_sec = kPeriodSec;
132 options.stats_persist_period_sec = kPeriodSec;
133 options.create_if_missing = true;
134 options.env = mock_env_.get();
135
136 int dump_st_counter = 0;
137 SyncPoint::GetInstance()->SetCallBack("DBImpl::DumpStats:2",
138 [&](void*) { dump_st_counter++; });
139
140 int pst_st_counter = 0;
141 SyncPoint::GetInstance()->SetCallBack("DBImpl::PersistStats:StartRunning",
142 [&](void*) { pst_st_counter++; });
143 SyncPoint::GetInstance()->EnableProcessing();
144
145 auto dbs = std::vector<DB*>(kInstanceNum);
146 for (int i = 0; i < kInstanceNum; i++) {
147 ASSERT_OK(
148 DB::Open(options, test::PerThreadDBPath(std::to_string(i)), &(dbs[i])));
149 }
150
151 auto dbi = static_cast_with_check<DBImpl>(dbs[kInstanceNum - 1]);
152
153 const PeriodicTaskScheduler& scheduler = dbi->TEST_GetPeriodicTaskScheduler();
154 ASSERT_EQ(kInstanceNum * 3, scheduler.TEST_GetValidTaskNum());
155
156 int expected_run = kInstanceNum;
157 dbi->TEST_WaitForPeridicTaskRun(
158 [&] { mock_clock_->MockSleepForSeconds(kPeriodSec - 1); });
159 ASSERT_EQ(expected_run, dump_st_counter);
160 ASSERT_EQ(expected_run, pst_st_counter);
161
162 expected_run += kInstanceNum;
163 dbi->TEST_WaitForPeridicTaskRun(
164 [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
165 ASSERT_EQ(expected_run, dump_st_counter);
166 ASSERT_EQ(expected_run, pst_st_counter);
167
168 expected_run += kInstanceNum;
169 dbi->TEST_WaitForPeridicTaskRun(
170 [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
171 ASSERT_EQ(expected_run, dump_st_counter);
172 ASSERT_EQ(expected_run, pst_st_counter);
173
174 int half = kInstanceNum / 2;
175 for (int i = 0; i < half; i++) {
176 delete dbs[i];
177 }
178
179 expected_run += (kInstanceNum - half) * 2;
180
181 dbi->TEST_WaitForPeridicTaskRun(
182 [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
183 dbi->TEST_WaitForPeridicTaskRun(
184 [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
185 ASSERT_EQ(expected_run, dump_st_counter);
186 ASSERT_EQ(expected_run, pst_st_counter);
187
188 for (int i = half; i < kInstanceNum; i++) {
189 ASSERT_OK(dbs[i]->Close());
190 delete dbs[i];
191 }
192 }
193
194 TEST_F(PeriodicTaskSchedulerTest, MultiEnv) {
195 constexpr int kDumpPeriodSec = 5;
196 constexpr int kPersistPeriodSec = 10;
197 Close();
198 Options options1;
199 options1.stats_dump_period_sec = kDumpPeriodSec;
200 options1.stats_persist_period_sec = kPersistPeriodSec;
201 options1.create_if_missing = true;
202 options1.env = mock_env_.get();
203
204 Reopen(options1);
205
206 std::unique_ptr<Env> mock_env2(
207 new CompositeEnvWrapper(Env::Default(), mock_clock_));
208 Options options2;
209 options2.stats_dump_period_sec = kDumpPeriodSec;
210 options2.stats_persist_period_sec = kPersistPeriodSec;
211 options2.create_if_missing = true;
212 options1.env = mock_env2.get();
213
214 std::string dbname = test::PerThreadDBPath("multi_env_test");
215 DB* db;
216 ASSERT_OK(DB::Open(options2, dbname, &db));
217
218 ASSERT_OK(db->Close());
219 delete db;
220 Close();
221 }
222
223 #endif // !ROCKSDB_LITE
224 } // namespace ROCKSDB_NAMESPACE
225
226 int main(int argc, char** argv) {
227 ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
228 ::testing::InitGoogleTest(&argc, argv);
229
230 return RUN_ALL_TESTS();
231 }