Skip to content

Commit 86a315d

Browse files
committed
utilities: Add support for registering use cases
1 parent 8db41e0 commit 86a315d

2 files changed

Lines changed: 217 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ set(SOURCES
10051005
utilities/transactions/write_unprepared_txn.cc
10061006
utilities/transactions/write_unprepared_txn_db.cc
10071007
utilities/ttl/db_ttl_impl.cc
1008+
utilities/use_cases.cc
10081009
utilities/wal_filter.cc
10091010
utilities/write_batch_with_index/write_batch_with_index.cc
10101011
utilities/write_batch_with_index/write_batch_with_index_internal.cc)

utilities/use_cases.cc

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#include <iostream>
2+
#include <memory>
3+
#include <set>
4+
#include <string>
5+
#include <vector>
6+
7+
#include "options/configurable_helper.h"
8+
#include "options/options_helper.h"
9+
#include "rocksdb/db_crashtest_use_case.h"
10+
#include "rocksdb/options.h"
11+
#include "rocksdb/use_case.h"
12+
#include "rocksdb/utilities/customizable_util.h"
13+
#include "rocksdb/utilities/options_type.h"
14+
15+
namespace ROCKSDB_NAMESPACE {
16+
Status ToUseCases(const ConfigOptions& cfg_opts, const std::string& value,
17+
std::vector<std::shared_ptr<UseCase>>& use_cases) {
18+
Status status;
19+
for (size_t start = 0, end = 0;
20+
status.ok() && start < value.size() && end != std::string::npos;
21+
start = end + 1) {
22+
std::string token;
23+
status = OptionTypeInfo::NextToken(value, ',', start, &end, &token);
24+
if (status.ok()) {
25+
if (token.find('*') == std::string::npos) {
26+
std::shared_ptr<UseCase> use_case;
27+
status = UseCase::CreateFromString(cfg_opts, token, &use_case);
28+
if (status.ok() && use_case) {
29+
use_cases.push_back(use_case);
30+
}
31+
} else {
32+
// TODO: Pattern match on the factory names in factories to match the
33+
// token
34+
// std::vector<std::string> factories;
35+
// ObjectRegistry::Default()->GetFactoryNames(UseCase::Type(), &factories);
36+
// return bad status (some sort)
37+
}
38+
}
39+
}
40+
return status;
41+
}
42+
43+
static int RegisterBuiltinDBCrashtestUseCases(ObjectLibrary& library,
44+
const std::string& arg) {
45+
library.AddFactory<UseCase>(
46+
SimpleDefaultParams::kClassName(),
47+
[](const std::string& /*uri*/,
48+
std::unique_ptr<UseCase>* guard,
49+
std::string* /*errmsg*/) {
50+
guard->reset(new SimpleDefaultParams());
51+
return guard->get();
52+
});
53+
library.AddFactory<UseCase>(
54+
TxnParams::kClassName(),
55+
[](const std::string& /*uri*/,
56+
std::unique_ptr<UseCase>* guard,
57+
std::string* /*errmsg*/) {
58+
guard->reset(new TxnParams());
59+
return guard->get();
60+
});
61+
library.AddFactory<UseCase>(
62+
BestEffortsRecoveryParams::kClassName(),
63+
[](const std::string& /*uri*/,
64+
std::unique_ptr<UseCase>* guard,
65+
std::string* /*errmsg*/) {
66+
guard->reset(new BestEffortsRecoveryParams());
67+
return guard->get();
68+
});
69+
library.AddFactory<UseCase>(
70+
BlobParams::kClassName(),
71+
[](const std::string& /*uri*/,
72+
std::unique_ptr<UseCase>* guard,
73+
std::string* /*errmsg*/) {
74+
guard->reset(new BlobParams());
75+
return guard->get();
76+
});
77+
library.AddFactory<UseCase>(
78+
TieredParams::kClassName(),
79+
[](const std::string& /*uri*/,
80+
std::unique_ptr<UseCase>* guard,
81+
std::string* /*errmsg*/) {
82+
guard->reset(new TieredParams());
83+
return guard->get();
84+
});
85+
library.AddFactory<DBCrashtestUseCase>(
86+
MultiopsTxnDefaultParams::kClassName(),
87+
[](const std::string& /*uri*/,
88+
std::unique_ptr<DBCrashtestUseCase>* guard,
89+
std::string* /*errmsg*/) {
90+
guard->reset(new MultiopsTxnDefaultParams());
91+
return guard->get();
92+
});
93+
return 1;
94+
}
95+
96+
static int RegisterBuiltinUseCases(ObjectLibrary& library,
97+
const std::string& arg) {
98+
library.AddFactory<UseCase>(
99+
DBCrashtestUseCase::kClassName(),
100+
[](const std::string& /*uri*/,
101+
std::unique_ptr<UseCase>* guard,
102+
std::string* /*errmsg*/) {
103+
guard->reset(new DBCrashtestUseCase());
104+
return guard->get();
105+
});
106+
RegisterBuiltinDBCrashtestUseCases(library, arg);
107+
return 1;
108+
}
109+
110+
Status UseCase::CreateFromString(const ConfigOptions& cfg_opts,
111+
const std::string& value,
112+
std::shared_ptr<UseCase>* result) {
113+
static std::once_flag once;
114+
std::call_once(once, [&]() {
115+
RegisterBuiltinUseCases(*(ObjectLibrary::Default().get()), "");
116+
});
117+
Status status =
118+
LoadSharedObject<UseCase>(cfg_opts, value, result);
119+
return status;
120+
}
121+
122+
void UseCase::RegisterUseCaseDBOptionsConfig(
123+
std::unordered_map<std::string, UseCaseConfig>* config) {
124+
uses_db_options_.push_back(config);
125+
}
126+
127+
void UseCase::RegisterUseCaseCFOptionsConfig(
128+
std::unordered_map<std::string, UseCaseConfig>* config) {
129+
uses_cf_options_.push_back(config);
130+
}
131+
132+
bool UseCase::Validate(const ConfigOptions& cfg_opts, const DBOptions& db_opts,
133+
std::set<std::string>& valid_opts,
134+
std::set<std::string>& invalid_opts) {
135+
auto db_config = DBOptionsAsConfigurable(db_opts);
136+
return ConfigurableHelper::CheckUseCases(cfg_opts, *(db_config.get()),
137+
uses_db_options_, valid_opts,
138+
invalid_opts, nullptr) == 0;
139+
}
140+
141+
bool UseCase::Validate(const ConfigOptions& cfg_opts,
142+
const ColumnFamilyOptions& cf_opts,
143+
std::set<std::string>& valid_opts,
144+
std::set<std::string>& invalid_opts) {
145+
auto cf_config = CFOptionsAsConfigurable(cf_opts);
146+
return ConfigurableHelper::CheckUseCases(cfg_opts, *(cf_config.get()),
147+
uses_cf_options_, valid_opts,
148+
invalid_opts, nullptr) == 0;
149+
}
150+
151+
bool UseCase::Validate(const ConfigOptions& cfg_opts, const Options& opts,
152+
std::set<std::string>& valid_opts,
153+
std::set<std::string>& invalid_opts) {
154+
DBOptions db_options(opts);
155+
ColumnFamilyOptions cf_options(opts);
156+
if (Validate(cfg_opts, db_options, valid_opts, invalid_opts) == 0) {
157+
return Validate(cfg_opts, cf_options, valid_opts, invalid_opts) == 0;
158+
} else {
159+
return false;
160+
}
161+
}
162+
163+
Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
164+
const std::string& validate_against,
165+
const DBOptions& db_opts,
166+
std::set<std::string>& valid_opts,
167+
std::set<std::string>& invalid_opts) {
168+
std::vector<std::shared_ptr<UseCase>> use_cases;
169+
Status s = ToUseCases(cfg_opts, validate_against, use_cases);
170+
if (s.ok()) {
171+
for (const auto& use_case : use_cases) {
172+
use_case->Validate(cfg_opts, db_opts, valid_opts, invalid_opts);
173+
}
174+
if (!invalid_opts.empty()) {
175+
s = Status::InvalidArgument();
176+
}
177+
}
178+
return s;
179+
}
180+
181+
Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
182+
const std::string& validate_against,
183+
const ColumnFamilyOptions& cf_opts,
184+
std::set<std::string>& valid_opts,
185+
std::set<std::string>& invalid_opts) {
186+
std::vector<std::shared_ptr<UseCase>> use_cases;
187+
Status s = ToUseCases(cfg_opts, validate_against, use_cases);
188+
if (s.ok()) {
189+
for (const auto& use_case : use_cases) {
190+
use_case->Validate(cfg_opts, cf_opts, valid_opts, invalid_opts);
191+
}
192+
if (!invalid_opts.empty()) {
193+
s = Status::InvalidArgument();
194+
}
195+
}
196+
return s;
197+
}
198+
199+
Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
200+
const std::string& validate_against,
201+
const Options& opts,
202+
std::set<std::string>& valid_opts,
203+
std::set<std::string>& invalid_opts) {
204+
std::vector<std::shared_ptr<UseCase>> use_cases;
205+
Status s = ToUseCases(cfg_opts, validate_against, use_cases);
206+
if (s.ok()) {
207+
for (const auto& use_case : use_cases) {
208+
use_case->Validate(cfg_opts, opts, valid_opts, invalid_opts);
209+
}
210+
if (!invalid_opts.empty()) {
211+
s = Status::InvalidArgument();
212+
}
213+
}
214+
return s;
215+
}
216+
} // namespace ROCKSDB_NAMESPACE

0 commit comments

Comments
 (0)