#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl::NodeStore { struct MemoryDB { explicit MemoryDB() = default; std::mutex mutex; bool open = false; std::map> table; }; class MemoryFactory : public Factory { private: std::mutex mutex_; std::map map_; Manager& manager_; public: explicit MemoryFactory(Manager& manager); [[nodiscard]] std::string getName() const override; std::unique_ptr createInstance( size_t keyBytes, Section const& keyValues, std::size_t burstSize, Scheduler& scheduler, beast::Journal journal) override; MemoryDB& open(std::string const& path) { std::scoped_lock const _(mutex_); auto const result = map_.emplace(std::piecewise_construct, std::make_tuple(path), std::make_tuple()); MemoryDB& db = result.first->second; if (db.open) Throw("already open"); return db; } }; MemoryFactory* gMemoryFactory = nullptr; void registerMemoryFactory(Manager& manager) { static MemoryFactory kInstance{manager}; gMemoryFactory = &kInstance; } //------------------------------------------------------------------------------ class MemoryBackend : public Backend { private: using Map = std::map>; std::string name_; beast::Journal const journal_; MemoryDB* db_{nullptr}; public: MemoryBackend(size_t keyBytes, Section const& keyValues, beast::Journal journal) : name_(get(keyValues, "path")), journal_(journal) { boost::ignore_unused(journal_); // Keep unused journal_ just in case. if (name_.empty()) Throw("Missing path in Memory backend"); } ~MemoryBackend() override { close(); } std::string getName() override { return name_; } void open(bool) override { db_ = &gMemoryFactory->open(name_); } bool isOpen() override { return static_cast(db_); } void close() override { db_ = nullptr; } //-------------------------------------------------------------------------- Status fetch(uint256 const& hash, std::shared_ptr* pObject) override { XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database"); std::scoped_lock const _(db_->mutex); Map::iterator const iter = db_->table.find(hash); if (iter == db_->table.end()) { pObject->reset(); return Status::NotFound; } *pObject = iter->second; return Status::Ok; } void store(std::shared_ptr const& object) override { XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::store : non-null database"); std::scoped_lock const _(db_->mutex); db_->table.emplace(object->getHash(), object); } void storeBatch(Batch const& batch) override { for (auto const& e : batch) store(e); } void sync() override { } void forEach(std::function)> f) override { XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::forEach : non-null database"); for (auto const& e : db_->table) f(e.second); } int getWriteLoad() override { return 0; } void setDeletePath() override { } [[nodiscard]] int fdRequired() const override { return 0; } }; //------------------------------------------------------------------------------ MemoryFactory::MemoryFactory(Manager& manager) : manager_(manager) { manager_.insert(*this); } std::string MemoryFactory::getName() const { return "Memory"; } std::unique_ptr MemoryFactory::createInstance( size_t keyBytes, Section const& keyValues, std::size_t, Scheduler& scheduler, beast::Journal journal) { return std::make_unique(keyBytes, keyValues, journal); } } // namespace xrpl::NodeStore