#pragma once #include "data/LedgerCacheInterface.hpp" #include "data/Types.hpp" #include "etl/Models.hpp" #include "util/prometheus/Bool.hpp" #include "util/prometheus/Counter.hpp" #include "util/prometheus/Label.hpp" #include "util/prometheus/Prometheus.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace data { /** * @brief Cache for an entire ledger. */ class LedgerCache : public LedgerCacheInterface { public: /** @brief An entry of the cache */ struct CacheEntry { uint32_t seq = 0; Blob blob; }; using CacheMap = std::map; private: // counters for fetchLedgerObject(s) hit rate std::reference_wrapper objectReqCounter_{ PrometheusService::counterInt( "ledger_cache_counter_total_number", util::prometheus::Labels({{"type", "request"}, {"fetch", "ledger_objects"}}), "LedgerCache statistics" ) }; std::reference_wrapper objectHitCounter_{ PrometheusService::counterInt( "ledger_cache_counter_total_number", util::prometheus::Labels({{"type", "cache_hit"}, {"fetch", "ledger_objects"}}) ) }; // counters for fetchSuccessorKey hit rate std::reference_wrapper successorReqCounter_{ PrometheusService::counterInt( "ledger_cache_counter_total_number", util::prometheus::Labels({{"type", "request"}, {"fetch", "successor_key"}}), "ledgerCache" ) }; std::reference_wrapper successorHitCounter_{ PrometheusService::counterInt( "ledger_cache_counter_total_number", util::prometheus::Labels({{"type", "cache_hit"}, {"fetch", "successor_key"}}) ) }; CacheMap map_; CacheMap deleted_; mutable std::shared_mutex mtx_; std::condition_variable_any cv_; uint32_t latestSeq_ = 0; util::prometheus::Bool full_{PrometheusService::boolMetric( "ledger_cache_full", util::prometheus::Labels{}, "Whether ledger cache full or not" )}; util::prometheus::Bool disabled_{PrometheusService::boolMetric( "ledger_cache_disabled", util::prometheus::Labels{}, "Whether ledger cache is disabled or not" )}; util::prometheus::Bool isCurrentlyLoading_{ PrometheusService::boolMetric( "ledger_cache_is_currently_loading", util::prometheus::Labels{}, "Whether ledger cache is currently loading or not" ) }; // temporary set to prevent background thread from writing already deleted data. not used when // cache is full std::unordered_set> deletes_; public: void update(std::vector const& objs, uint32_t seq, bool isBackground) override; void update(std::vector const& objs, uint32_t seq) override; std::optional get(xrpl::uint256 const& key, uint32_t seq) const override; std::optional getDeleted(xrpl::uint256 const& key, uint32_t seq) const override; std::optional getSuccessor(xrpl::uint256 const& key, uint32_t seq) const override; std::optional getPredecessor(xrpl::uint256 const& key, uint32_t seq) const override; void setDisabled() override; bool isDisabled() const override; void setFull() override; uint32_t latestLedgerSequence() const override; bool isFull() const override; size_t size() const override; float getObjectHitRate() const override; float getSuccessorHitRate() const override; void waitUntilCacheContainsSeq(uint32_t seq) override; std::expected saveToFile(std::string const& path) const override; std::expected loadFromFile(std::string const& path, uint32_t minLatestSequence) override; void startLoading() override; [[nodiscard]] bool isCurrentlyLoading() const override; }; } // namespace data