Files
rippled/src/libxrpl/nodestore/ManagerImp.cpp
2026-05-15 15:32:19 +00:00

134 lines
3.3 KiB
C++

#include <xrpl/nodestore/detail/ManagerImp.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/Manager.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/Scheduler.h>
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
#include <boost/algorithm/string/predicate.hpp>
#include <algorithm>
#include <cstddef>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <utility>
namespace xrpl::NodeStore {
ManagerImp&
ManagerImp::instance()
{
static ManagerImp kInst;
return kInst;
}
void
ManagerImp::missingBackend()
{
Throw<std::runtime_error>(
"Your xrpld.cfg is missing a [node_db] entry, "
"please see the xrpld-example.cfg file!");
}
// We shouldn't rely on global variables for lifetime management because their
// lifetime is not well-defined. ManagerImp may get destroyed before the Factory
// classes, and then, calling Manager::instance().erase() in the destructors of
// the Factory classes is an undefined behaviour.
void
registerNuDBFactory(Manager& manager);
void
registerRocksDBFactory(Manager& manager);
void
registerNullFactory(Manager& manager);
void
registerMemoryFactory(Manager& manager);
ManagerImp::ManagerImp()
{
registerNuDBFactory(*this);
registerRocksDBFactory(*this);
registerNullFactory(*this);
registerMemoryFactory(*this);
}
std::unique_ptr<Backend>
ManagerImp::makeBackend(
Section const& parameters,
std::size_t burstSize,
Scheduler& scheduler,
beast::Journal journal)
{
std::string const type{get(parameters, "type")};
if (type.empty())
missingBackend();
auto factory{find(type)};
if (factory == nullptr)
{
missingBackend();
}
return factory->createInstance(
NodeObject::kKeyBytes, parameters, burstSize, scheduler, journal);
}
std::unique_ptr<Database>
ManagerImp::makeDatabase(
std::size_t burstSize,
Scheduler& scheduler,
int readThreads,
Section const& config,
beast::Journal journal)
{
auto backend{makeBackend(config, burstSize, scheduler, journal)};
backend->open();
return std::make_unique<DatabaseNodeImp>(
scheduler, readThreads, std::move(backend), config, journal);
}
void
ManagerImp::insert(Factory& factory)
{
std::scoped_lock const _(mutex_);
list_.push_back(&factory);
}
void
ManagerImp::erase(Factory& factory)
{
std::scoped_lock const _(mutex_);
auto const iter =
std::ranges::find_if(list_, [&factory](Factory* other) { return other == &factory; });
XRPL_ASSERT(iter != list_.end(), "xrpl::NodeStore::ManagerImp::erase : valid input");
list_.erase(iter);
}
Factory*
ManagerImp::find(std::string const& name)
{
std::scoped_lock const _(mutex_);
auto const iter = std::ranges::find_if(
list_, [&name](Factory* other) { return boost::iequals(name, other->getName()); });
if (iter == list_.end())
return nullptr;
return *iter;
}
//------------------------------------------------------------------------------
Manager&
Manager::instance()
{
return ManagerImp::instance();
}
} // namespace xrpl::NodeStore