#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl::NodeStore { ManagerImp& ManagerImp::instance() { static ManagerImp kInst; return kInst; } void ManagerImp::missingBackend() { Throw( "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 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 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( 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