diff --git a/src/ripple/app/rdb/backend/MemoryDatabase.h b/src/ripple/app/rdb/backend/MemoryDatabase.h new file mode 100644 index 000000000..24c8ea315 --- /dev/null +++ b/src/ripple/app/rdb/backend/MemoryDatabase.h @@ -0,0 +1,143 @@ +#ifndef RIPPLE_APP_RDB_BACKEND_MEMORYDATABASE_H_INCLUDED +#define RIPPLE_APP_RDB_BACKEND_MEMORYDATABASE_H_INCLUDED +#include +#include +#include + +namespace ripple { + +class MemoryDatabase : public RelationalDatabase +{ +private: + mutable std::shared_mutex mutex_; + boost::container::flat_map ledgers_; + boost::container::flat_map ledgersByHash_; + boost::container::flat_map ledgerHashes_; + std::vector> txHistory_; + +public: + MemoryDatabase(ripple::Application& app, ripple::Config const& conf, ripple::JobQueue& jq) + { + } + + std::optional getMinLedgerSeq() override + { + std::shared_lock lock(mutex_); + if (ledgers_.empty()) + return {}; + return ledgers_.begin()->first; + } + + std::optional getMaxLedgerSeq() override + { + std::shared_lock lock(mutex_); + if (ledgers_.empty()) + return {}; + return ledgers_.rbegin()->first; + } + + std::optional getLedgerInfoByIndex(LedgerIndex ledgerSeq) override + { + std::shared_lock lock(mutex_); + auto it = ledgers_.find(ledgerSeq); + if (it == ledgers_.end()) + return {}; + return it->second; + } + + std::optional getNewestLedgerInfo() override + { + std::shared_lock lock(mutex_); + if (ledgers_.empty()) + return {}; + return ledgers_.rbegin()->second; + } + + std::optional getLedgerInfoByHash(uint256 const& ledgerHash) override + { + std::shared_lock lock(mutex_); + auto it = ledgersByHash_.find(ledgerHash); + if (it == ledgersByHash_.end()) + return {}; + return it->second; + } + + uint256 getHashByIndex(LedgerIndex ledgerIndex) override + { + std::shared_lock lock(mutex_); + auto it = ledgerHashes_.find(ledgerIndex); + if (it == ledgerHashes_.end()) + return {}; + return it->second.ledgerHash; + } + + std::optional getHashesByIndex(LedgerIndex ledgerIndex) override + { + std::shared_lock lock(mutex_); + auto it = ledgerHashes_.find(ledgerIndex); + if (it == ledgerHashes_.end()) + return {}; + return it->second; + } + + std::map getHashesByIndex(LedgerIndex minSeq, LedgerIndex maxSeq) override + { + std::shared_lock lock(mutex_); + std::map result; + auto it = ledgerHashes_.lower_bound(minSeq); + auto end = ledgerHashes_.upper_bound(maxSeq); + for (; it != end; ++it) + { + result[it->first] = it->second; + } + return result; + } + + std::vector> getTxHistory(LedgerIndex startIndex) override + { + std::shared_lock lock(mutex_); + if (startIndex >= txHistory_.size()) + return {}; + return std::vector>( + txHistory_.begin() + startIndex, + txHistory_.begin() + std::min(static_cast(startIndex + 20), txHistory_.size())); + } + + bool ledgerDbHasSpace(Config const& config) override + { + // In-memory database always has space + return true; + } + + bool transactionDbHasSpace(Config const& config) override + { + // In-memory database always has space + return true; + } + + // Add methods to insert data (these would be called when saving ledgers/transactions) + void insertLedger(LedgerInfo const& ledgerInfo) + { + std::unique_lock lock(mutex_); + ledgers_[ledgerInfo.seq] = ledgerInfo; + ledgersByHash_[ledgerInfo.hash] = ledgerInfo; + ledgerHashes_[ledgerInfo.seq] = {ledgerInfo.hash, ledgerInfo.parentHash}; + } + + void insertTransaction(std::shared_ptr const& tx) + { + std::unique_lock lock(mutex_); + txHistory_.push_back(tx); + } +}; + +std::unique_ptr +getMemoryDatabase(Application& app, Config const& config, JobQueue& jobQueue) +{ + return std::make_unique(app, config, jobQueue); +} + + + +} // namespace ripple +#endif diff --git a/src/ripple/app/rdb/impl/RelationalDatabase.cpp b/src/ripple/app/rdb/impl/RelationalDatabase.cpp index 8a3ce5b01..d7104d3b8 100644 --- a/src/ripple/app/rdb/impl/RelationalDatabase.cpp +++ b/src/ripple/app/rdb/impl/RelationalDatabase.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace ripple { @@ -38,6 +39,7 @@ RelationalDatabase::init( { bool use_sqlite = false; bool use_postgres = false; + bool use_memory = false; if (config.reporting()) { @@ -52,6 +54,10 @@ RelationalDatabase::init( { use_sqlite = true; } + else if (boost::iequals(get(rdb_section, "backend"), "memory")) + { + use_memory = true; + } else { Throw( @@ -73,6 +79,10 @@ RelationalDatabase::init( { return getPostgresDatabase(app, config, jobQueue); } + else if (use_memory) + { + return getMemoryDatabase(app, config, jobQueue); + } return std::unique_ptr(); }