#include #include namespace xrpl { namespace detail { bool CachedViewImpl::exists(Keylet const& k) const { return read(k) != nullptr; } std::shared_ptr CachedViewImpl::read(Keylet const& k) const { static CountedObjects::Counter hits{"CachedView::hit"}; static CountedObjects::Counter hitsexpired{"CachedView::hitExpired"}; static CountedObjects::Counter misses{"CachedView::miss"}; bool cacheHit = false; bool baseRead = false; auto const digest = [&]() -> std::optional { { std::lock_guard const lock(mutex_); auto const iter = map_.find(k.key); if (iter != map_.end()) { cacheHit = true; return iter->second; } } return base_.digest(k.key); }(); if (!digest) return nullptr; auto sle = cache_.fetch(*digest, [&]() { baseRead = true; return base_.read(k); }); // If the sle is null, then a failure must have occurred in base_.read() XRPL_ASSERT(sle || baseRead, "xrpl::CachedView::read : null SLE result from base"); if (cacheHit && baseRead) { hitsexpired.increment(); } else if (cacheHit) { hits.increment(); } else { misses.increment(); } if (!cacheHit) { // Avoid acquiring this lock unless necessary. It is only necessary if // the key was not found in the map_. The lock is needed to add the key // and digest. std::lock_guard const lock(mutex_); map_.emplace(k.key, *digest); } if (!sle || !k.check(*sle)) return nullptr; return sle; } } // namespace detail } // namespace xrpl