Skip to content

Commit

Permalink
utilities: Add support for registering use cases
Browse files Browse the repository at this point in the history
  • Loading branch information
AmnonHanuhov committed Aug 13, 2023
1 parent 78f527f commit 296a03c
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ set(SOURCES
utilities/transactions/write_unprepared_txn.cc
utilities/transactions/write_unprepared_txn_db.cc
utilities/ttl/db_ttl_impl.cc
utilities/use_cases.cc
utilities/wal_filter.cc
utilities/write_batch_with_index/write_batch_with_index.cc
utilities/write_batch_with_index/write_batch_with_index_internal.cc)
Expand Down
169 changes: 169 additions & 0 deletions utilities/use_cases.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <iostream>

#include "rocksdb/db_crashtest_use_case.h"
#include "rocksdb/options.h"
#include "rocksdb/use_case.h"
#include "rocksdb/utilities/customizable_util.h"
#include "rocksdb/utilities/options_type.h"

namespace ROCKSDB_NAMESPACE {
Status ToUseCases(const ConfigOptions& cfg_opts, const std::string& value,
std::vector<std::shared_ptr<UseCase>>& use_cases) {
Status status;
for (size_t start = 0, end = 0;
status.ok() && start < value.size() && end != std::string::npos;
start = end + 1) {
std::string token;
status = OptionTypeInfo::NextToken(value, ',', start, &end, &token);
if (status.ok()) {
if (token.find('*') == std::string::npos) {
std::shared_ptr<UseCase> use_case;
status = UseCase::CreateFromString(cfg_opts, token, &use_case);
if (status.ok() && use_case) {
use_cases.push_back(use_case);
}
} else {
// TODO: Pattern match on the factory names in factories to match the
// token
// std::vector<std::string> factories;
// ObjectRegistry::Default()->GetFactoryNames(UseCase::Type(), &factories);
// return bad status (some sort)
}
}
}
return status;
}

static int RegisterBuiltinDBCrashtestUseCases(ObjectLibrary& library,
const std::string& arg) {
library.AddFactory<UseCase>(
SimpleDefaultParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new SimpleDefaultParams());
return guard->get();
});
library.AddFactory<UseCase>(
TxnParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new TxnParams());
return guard->get();
});
library.AddFactory<UseCase>(
BestEffortsRecoveryParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new BestEffortsRecoveryParams());
return guard->get();
});
library.AddFactory<UseCase>(
BlobParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new BlobParams());
return guard->get();
});
library.AddFactory<UseCase>(
TieredParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new TieredParams());
return guard->get();
});
library.AddFactory<DBCrashtestUseCase>(
MultiopsTxnDefaultParams::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<DBCrashtestUseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new MultiopsTxnDefaultParams());
return guard->get();
});
return 1;
}

static int RegisterBuiltinUseCases(ObjectLibrary& library,
const std::string& arg) {
library.AddFactory<UseCase>(
DBCrashtestUseCase::kClassName(),
[](const std::string& /*uri*/,
std::unique_ptr<UseCase>* guard,
std::string* /*errmsg*/) {
guard->reset(new DBCrashtestUseCase());
return guard->get();
});
RegisterBuiltinDBCrashtestUseCases(library, arg);
return 1;
}

Status UseCase::CreateFromString(const ConfigOptions& cfg_opts,
const std::string& value,
std::shared_ptr<UseCase>* result) {
static std::once_flag once;
std::call_once(once, [&]() {
RegisterBuiltinUseCases(*(ObjectLibrary::Default().get()), "");
});
Status status =
LoadSharedObject<UseCase>(cfg_opts, value, result);
return status;
}

Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
const std::string& validate_against,
const DBOptions& db_opts,
std::set<std::string>& valid_opts,
std::set<std::string>& invalid_opts) {
std::vector<std::shared_ptr<UseCase>> use_cases;
Status s = ToUseCases(cfg_opts, validate_against, use_cases);
if (s.ok()) {
for (const auto& use_case : use_cases) {
use_case->Validate(cfg_opts, db_opts, valid_opts, invalid_opts);
}
if (!invalid_opts.empty()) {
s = Status::InvalidArgument();
}
}
return s;
}

Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
const std::string& validate_against,
const ColumnFamilyOptions& cf_opts,
std::set<std::string>& valid_opts,
std::set<std::string>& invalid_opts) {
std::vector<std::shared_ptr<UseCase>> use_cases;
Status s = ToUseCases(cfg_opts, validate_against, use_cases);
if (s.ok()) {
for (const auto& use_case : use_cases) {
use_case->Validate(cfg_opts, cf_opts, valid_opts, invalid_opts);
}
if (!invalid_opts.empty()) {
s = Status::InvalidArgument();
}
}
return s;
}

Status UseCase::ValidateOptions(const ConfigOptions& cfg_opts,
const std::string& validate_against,
const Options& opts,
std::set<std::string>& valid_opts,
std::set<std::string>& invalid_opts) {
const DBOptions* db_opts = &opts;
const ColumnFamilyOptions* cf_opts = &opts;
Status s = ValidateOptions(cfg_opts, validate_against, *db_opts, valid_opts, invalid_opts);
if (s.ok()) {
s = ValidateOptions(cfg_opts, validate_against, *cf_opts, valid_opts, invalid_opts);
}
return s;
}
} // namespace ROCKSDB_NAMESPACE

0 comments on commit 296a03c

Please sign in to comment.