]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/db/periodic_work_scheduler_test.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / db / periodic_work_scheduler_test.cc
CommitLineData
20effc67
TL
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/periodic_work_scheduler.h"
7
8#include "db/db_test_util.h"
9
10namespace ROCKSDB_NAMESPACE {
11
12#ifndef ROCKSDB_LITE
13class PeriodicWorkSchedulerTest : public DBTestBase {
14 public:
15 PeriodicWorkSchedulerTest()
16 : DBTestBase("/periodic_work_scheduler_test", /*env_do_fsync=*/true) {
17 mock_env_.reset(new MockTimeEnv(env_));
18 }
19
20 protected:
21 std::unique_ptr<MockTimeEnv> mock_env_;
22
23 void SetUp() override {
24 mock_env_->InstallTimedWaitFixCallback();
25 SyncPoint::GetInstance()->SetCallBack(
26 "DBImpl::StartPeriodicWorkScheduler:Init", [&](void* arg) {
27 auto* periodic_work_scheduler_ptr =
28 reinterpret_cast<PeriodicWorkScheduler**>(arg);
29 *periodic_work_scheduler_ptr =
30 PeriodicWorkTestScheduler::Default(mock_env_.get());
31 });
32 }
33};
34
35TEST_F(PeriodicWorkSchedulerTest, Basic) {
36 constexpr unsigned int kPeriodSec =
37 PeriodicWorkScheduler::kDefaultFlushInfoLogPeriodSec;
38 Close();
39 Options options;
40 options.stats_dump_period_sec = kPeriodSec;
41 options.stats_persist_period_sec = kPeriodSec;
42 options.create_if_missing = true;
43 options.env = mock_env_.get();
44
45 int dump_st_counter = 0;
46 SyncPoint::GetInstance()->SetCallBack("DBImpl::DumpStats:StartRunning",
47 [&](void*) { dump_st_counter++; });
48
49 int pst_st_counter = 0;
50 SyncPoint::GetInstance()->SetCallBack("DBImpl::PersistStats:StartRunning",
51 [&](void*) { pst_st_counter++; });
52
53 int flush_info_log_counter = 0;
54 SyncPoint::GetInstance()->SetCallBack(
55 "DBImpl::FlushInfoLog:StartRunning",
56 [&](void*) { flush_info_log_counter++; });
57 SyncPoint::GetInstance()->EnableProcessing();
58
59 Reopen(options);
60
61 ASSERT_EQ(kPeriodSec, dbfull()->GetDBOptions().stats_dump_period_sec);
62 ASSERT_EQ(kPeriodSec, dbfull()->GetDBOptions().stats_persist_period_sec);
63
64 ASSERT_GT(kPeriodSec, 1u);
65 dbfull()->TEST_WaitForStatsDumpRun([&] {
66 mock_env_->MockSleepForSeconds(static_cast<int>(kPeriodSec) - 1);
67 });
68
69 auto scheduler = dbfull()->TEST_GetPeriodicWorkScheduler();
70 ASSERT_NE(nullptr, scheduler);
71 ASSERT_EQ(3, scheduler->TEST_GetValidTaskNum());
72
73 ASSERT_EQ(1, dump_st_counter);
74 ASSERT_EQ(1, pst_st_counter);
75 ASSERT_EQ(1, flush_info_log_counter);
76
77 dbfull()->TEST_WaitForStatsDumpRun(
78 [&] { mock_env_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
79
80 ASSERT_EQ(2, dump_st_counter);
81 ASSERT_EQ(2, pst_st_counter);
82 ASSERT_EQ(2, flush_info_log_counter);
83
84 dbfull()->TEST_WaitForStatsDumpRun(
85 [&] { mock_env_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
86
87 ASSERT_EQ(3, dump_st_counter);
88 ASSERT_EQ(3, pst_st_counter);
89 ASSERT_EQ(3, flush_info_log_counter);
90
91 // Disable scheduler with SetOption
92 ASSERT_OK(dbfull()->SetDBOptions(
93 {{"stats_dump_period_sec", "0"}, {"stats_persist_period_sec", "0"}}));
94 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_dump_period_sec);
95 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_persist_period_sec);
96
97 // Info log flush should still run.
98 dbfull()->TEST_WaitForStatsDumpRun(
99 [&] { mock_env_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
100 ASSERT_EQ(3, dump_st_counter);
101 ASSERT_EQ(3, pst_st_counter);
102 ASSERT_EQ(4, flush_info_log_counter);
103
104 scheduler = dbfull()->TEST_GetPeriodicWorkScheduler();
105 ASSERT_EQ(1u, scheduler->TEST_GetValidTaskNum());
106
107 // Re-enable one task
108 ASSERT_OK(dbfull()->SetDBOptions({{"stats_dump_period_sec", "5"}}));
109 ASSERT_EQ(5u, dbfull()->GetDBOptions().stats_dump_period_sec);
110 ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_persist_period_sec);
111
112 scheduler = dbfull()->TEST_GetPeriodicWorkScheduler();
113 ASSERT_NE(nullptr, scheduler);
114 ASSERT_EQ(2, scheduler->TEST_GetValidTaskNum());
115
116 dbfull()->TEST_WaitForStatsDumpRun(
117 [&] { mock_env_->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
125TEST_F(PeriodicWorkSchedulerTest, 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 auto scheduler = dbi->TEST_GetPeriodicWorkScheduler();
153 ASSERT_EQ(kInstanceNum * 3, scheduler->TEST_GetValidTaskNum());
154
155 int expected_run = kInstanceNum;
156 dbi->TEST_WaitForStatsDumpRun(
157 [&] { mock_env_->MockSleepForSeconds(kPeriodSec - 1); });
158 ASSERT_EQ(expected_run, dump_st_counter);
159 ASSERT_EQ(expected_run, pst_st_counter);
160
161 expected_run += kInstanceNum;
162 dbi->TEST_WaitForStatsDumpRun(
163 [&] { mock_env_->MockSleepForSeconds(kPeriodSec); });
164 ASSERT_EQ(expected_run, dump_st_counter);
165 ASSERT_EQ(expected_run, pst_st_counter);
166
167 expected_run += kInstanceNum;
168 dbi->TEST_WaitForStatsDumpRun(
169 [&] { mock_env_->MockSleepForSeconds(kPeriodSec); });
170 ASSERT_EQ(expected_run, dump_st_counter);
171 ASSERT_EQ(expected_run, pst_st_counter);
172
173 int half = kInstanceNum / 2;
174 for (int i = 0; i < half; i++) {
175 delete dbs[i];
176 }
177
178 expected_run += (kInstanceNum - half) * 2;
179
180 dbi->TEST_WaitForStatsDumpRun(
181 [&] { mock_env_->MockSleepForSeconds(kPeriodSec); });
182 dbi->TEST_WaitForStatsDumpRun(
183 [&] { mock_env_->MockSleepForSeconds(kPeriodSec); });
184 ASSERT_EQ(expected_run, dump_st_counter);
185 ASSERT_EQ(expected_run, pst_st_counter);
186
187 for (int i = half; i < kInstanceNum; i++) {
188 dbs[i]->Close();
189 delete dbs[i];
190 }
191}
192
193TEST_F(PeriodicWorkSchedulerTest, MultiEnv) {
194 constexpr int kDumpPeriodSec = 5;
195 constexpr int kPersistPeriodSec = 10;
196 Close();
197 Options options1;
198 options1.stats_dump_period_sec = kDumpPeriodSec;
199 options1.stats_persist_period_sec = kPersistPeriodSec;
200 options1.create_if_missing = true;
201 options1.env = mock_env_.get();
202
203 Reopen(options1);
204
205 std::unique_ptr<MockTimeEnv> mock_env2(new MockTimeEnv(Env::Default()));
206 Options options2;
207 options2.stats_dump_period_sec = kDumpPeriodSec;
208 options2.stats_persist_period_sec = kPersistPeriodSec;
209 options2.create_if_missing = true;
210 options1.env = mock_env2.get();
211
212 std::string dbname = test::PerThreadDBPath("multi_env_test");
213 DB* db;
214 ASSERT_OK(DB::Open(options2, dbname, &db));
215 DBImpl* dbi = static_cast_with_check<DBImpl>(db);
216
217 ASSERT_EQ(dbi->TEST_GetPeriodicWorkScheduler(),
218 dbfull()->TEST_GetPeriodicWorkScheduler());
219
220 db->Close();
221 delete db;
222 Close();
223}
224#endif // !ROCKSDB_LITE
225} // namespace ROCKSDB_NAMESPACE
226
227int main(int argc, char** argv) {
228 ::testing::InitGoogleTest(&argc, argv);
229
230 return RUN_ALL_TESTS();
231}