]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/db_stress_tool/db_stress_listener.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / db_stress_tool / db_stress_listener.h
CommitLineData
f67539c2
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#ifdef GFLAGS
7#pragma once
8
9#include "rocksdb/listener.h"
10#include "util/gflags_compat.h"
11
12DECLARE_int32(compact_files_one_in);
13
14namespace ROCKSDB_NAMESPACE {
15class DbStressListener : public EventListener {
16 public:
17 DbStressListener(const std::string& db_name,
18 const std::vector<DbPath>& db_paths,
19 const std::vector<ColumnFamilyDescriptor>& column_families)
20 : db_name_(db_name),
21 db_paths_(db_paths),
22 column_families_(column_families),
23 num_pending_file_creations_(0) {}
24#ifndef ROCKSDB_LITE
25 ~DbStressListener() override { assert(num_pending_file_creations_ == 0); }
26 void OnFlushCompleted(DB* /*db*/, const FlushJobInfo& info) override {
27 assert(IsValidColumnFamilyName(info.cf_name));
28 VerifyFilePath(info.file_path);
29 // pretending doing some work here
30 RandomSleep();
31 }
32
33 void OnFlushBegin(DB* /*db*/,
34 const FlushJobInfo& /*flush_job_info*/) override {
35 RandomSleep();
36 }
37
38 void OnTableFileDeleted(const TableFileDeletionInfo& /*info*/) override {
39 RandomSleep();
40 }
41
42 void OnCompactionBegin(DB* /*db*/, const CompactionJobInfo& /*ci*/) override {
43 RandomSleep();
44 }
45
46 void OnCompactionCompleted(DB* /*db*/, const CompactionJobInfo& ci) override {
47 assert(IsValidColumnFamilyName(ci.cf_name));
48 assert(ci.input_files.size() + ci.output_files.size() > 0U);
49 for (const auto& file_path : ci.input_files) {
50 VerifyFilePath(file_path);
51 }
52 for (const auto& file_path : ci.output_files) {
53 VerifyFilePath(file_path);
54 }
55 // pretending doing some work here
56 RandomSleep();
57 }
58
59 void OnTableFileCreationStarted(
60 const TableFileCreationBriefInfo& /*info*/) override {
61 ++num_pending_file_creations_;
62 }
63
64 void OnTableFileCreated(const TableFileCreationInfo& info) override {
65 assert(info.db_name == db_name_);
66 assert(IsValidColumnFamilyName(info.cf_name));
67 if (info.file_size) {
68 VerifyFilePath(info.file_path);
69 }
70 assert(info.job_id > 0 || FLAGS_compact_files_one_in > 0);
71 if (info.status.ok() && info.file_size > 0) {
72 assert(info.table_properties.data_size > 0 ||
73 info.table_properties.num_range_deletions > 0);
74 assert(info.table_properties.raw_key_size > 0);
75 assert(info.table_properties.num_entries > 0);
76 }
77 --num_pending_file_creations_;
78 }
79
80 void OnMemTableSealed(const MemTableInfo& /*info*/) override {
81 RandomSleep();
82 }
83
84 void OnColumnFamilyHandleDeletionStarted(
85 ColumnFamilyHandle* /*handle*/) override {
86 RandomSleep();
87 }
88
89 void OnExternalFileIngested(
90 DB* /*db*/, const ExternalFileIngestionInfo& /*info*/) override {
91 RandomSleep();
92 }
93
94 void OnBackgroundError(BackgroundErrorReason /* reason */,
95 Status* /* bg_error */) override {
96 RandomSleep();
97 }
98
99 void OnStallConditionsChanged(const WriteStallInfo& /*info*/) override {
100 RandomSleep();
101 }
102
103 void OnFileReadFinish(const FileOperationInfo& info) override {
104 // Even empty callback is valuable because sometimes some locks are
105 // released in order to make the callback.
106
107 // Sleep carefully here as it is a frequent operation and we don't want
108 // to slow down the tests. We always sleep when the read is large.
109 // When read is small, sleep in a small chance.
110 size_t length_read = info.length;
111 if (length_read >= 1000000 || Random::GetTLSInstance()->OneIn(1000)) {
112 RandomSleep();
113 }
114 }
115
116 void OnFileWriteFinish(const FileOperationInfo& info) override {
117 // Even empty callback is valuable because sometimes some locks are
118 // released in order to make the callback.
119
120 // Sleep carefully here as it is a frequent operation and we don't want
121 // to slow down the tests. When the write is large, always sleep.
122 // Otherwise, sleep in a relatively small chance.
123 size_t length_write = info.length;
124 if (length_write >= 1000000 || Random::GetTLSInstance()->OneIn(64)) {
125 RandomSleep();
126 }
127 }
128
129 bool ShouldBeNotifiedOnFileIO() override {
130 RandomSleep();
131 return static_cast<bool>(Random::GetTLSInstance()->OneIn(1));
132 }
133
134 void OnErrorRecoveryBegin(BackgroundErrorReason /* reason */,
135 Status /* bg_error */,
136 bool* /* auto_recovery */) override {
137 RandomSleep();
138 }
139
140 void OnErrorRecoveryCompleted(Status /* old_bg_error */) override {
141 RandomSleep();
142 }
143
144 protected:
145 bool IsValidColumnFamilyName(const std::string& cf_name) const {
146 if (cf_name == kDefaultColumnFamilyName) {
147 return true;
148 }
149 // The column family names in the stress tests are numbers.
150 for (size_t i = 0; i < cf_name.size(); ++i) {
151 if (cf_name[i] < '0' || cf_name[i] > '9') {
152 return false;
153 }
154 }
155 return true;
156 }
157
158 void VerifyFileDir(const std::string& file_dir) {
159#ifndef NDEBUG
160 if (db_name_ == file_dir) {
161 return;
162 }
163 for (const auto& db_path : db_paths_) {
164 if (db_path.path == file_dir) {
165 return;
166 }
167 }
168 for (auto& cf : column_families_) {
169 for (const auto& cf_path : cf.options.cf_paths) {
170 if (cf_path.path == file_dir) {
171 return;
172 }
173 }
174 }
175 assert(false);
176#else
177 (void)file_dir;
178#endif // !NDEBUG
179 }
180
181 void VerifyFileName(const std::string& file_name) {
182#ifndef NDEBUG
183 uint64_t file_number;
184 FileType file_type;
185 bool result = ParseFileName(file_name, &file_number, &file_type);
186 assert(result);
187 assert(file_type == kTableFile);
188#else
189 (void)file_name;
190#endif // !NDEBUG
191 }
192
193 void VerifyFilePath(const std::string& file_path) {
194#ifndef NDEBUG
195 size_t pos = file_path.find_last_of("/");
196 if (pos == std::string::npos) {
197 VerifyFileName(file_path);
198 } else {
199 if (pos > 0) {
200 VerifyFileDir(file_path.substr(0, pos));
201 }
202 VerifyFileName(file_path.substr(pos));
203 }
204#else
205 (void)file_path;
206#endif // !NDEBUG
207 }
208
209 void RandomSleep() {
210 std::this_thread::sleep_for(
211 std::chrono::microseconds(Random::GetTLSInstance()->Uniform(5000)));
212 }
213#endif // !ROCKSDB_LITE
214
215 private:
216 std::string db_name_;
217 std::vector<DbPath> db_paths_;
218 std::vector<ColumnFamilyDescriptor> column_families_;
219 std::atomic<int> num_pending_file_creations_;
220};
221} // namespace ROCKSDB_NAMESPACE
222#endif // GFLAGS