20 #ifndef RIPPLE_BASICS_TAGGEDCACHE_H_INCLUDED
21 #define RIPPLE_BASICS_TAGGEDCACHE_H_INCLUDED
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/UnorderedContainers.h>
25 #include <ripple/basics/hardened_hash.h>
26 #include <ripple/beast/clock/abstract_clock.h>
27 #include <ripple/beast/insight/Insight.h>
52 bool IsKeyCache =
false,
53 class Hash = hardened_hash<>,
183 template <
class KeyComparable>
229 if (when_expire > (now - minimumAge))
230 when_expire = now - minimumAge;
235 << (now - when_expire).count() <<
" of "
261 <<
m_name <<
" TaggedCache sweep lock duration "
262 << std::chrono::duration_cast<std::chrono::milliseconds>(
280 Entry& entry = cit->second;
284 if (entry.isCached())
291 if (!valid || entry.isExpired())
326 std::piecewise_construct,
333 Entry& entry = cit->second;
336 if (entry.isCached())
338 if (replace(entry.ptr))
341 entry.weak_ptr = data;
351 auto cachedData = entry.lock();
355 if (replace(entry.ptr))
358 entry.weak_ptr = data;
362 entry.ptr = cachedData;
371 entry.weak_ptr = data;
409 template <
class ReturnType =
bool>
414 auto p = std::make_shared<T>(
std::cref(value));
418 template <
class ReturnType =
bool>
425 std::piecewise_construct,
429 it->second.last_access = now;
442 auto entry =
fetch(key);
481 return double(
m_hits) / tot;
489 template <
class Handler>
505 auto const [it, inserted] =
509 return it->second.ptr;
521 Entry& entry = cit->second;
522 if (entry.isCached())
528 entry.ptr = entry.lock();
529 if (entry.isCached())
552 hit_rate = (
m_hits * 100) / total;
561 template <
class Handler>
564 Handler
const& handler,
566 :
hook(collector->make_hook(handler))
567 ,
size(collector->make_gauge(prefix,
"size"))
568 ,
hit_rate(collector->make_gauge(prefix,
"hit_rate"))
616 return ptr ==
nullptr;
621 return ptr !=
nullptr;
663 int cacheRemovals = 0;
668 stuffToSweep.
first.reserve(partition.size());
669 stuffToSweep.
second.reserve(partition.size());
671 auto cit = partition.begin();
672 while (cit != partition.end())
674 if (cit->second.isWeak())
677 if (cit->second.isExpired())
679 stuffToSweep.second.push_back(
680 std::move(cit->second.weak_ptr));
682 cit = partition.erase(cit);
689 else if (cit->second.last_access <= when_expire)
693 if (cit->second.ptr.use_count() == 1)
695 stuffToSweep.first.push_back(
696 std::move(cit->second.ptr));
698 cit = partition.erase(cit);
703 cit->second.ptr.reset();
715 if (mapRemovals || cacheRemovals)
718 <<
"TaggedCache partition sweep " <<
m_name
719 <<
": cache = " << partition.size() <<
"-" << cacheRemovals
720 <<
", map-=" << mapRemovals;
723 allRemovals += cacheRemovals;
737 int cacheRemovals = 0;
743 auto cit = partition.begin();
744 while (cit != partition.end())
746 if (cit->second.last_access > now)
748 cit->second.last_access = now;
751 else if (cit->second.last_access <= when_expire)
753 cit = partition.erase(cit);
762 if (mapRemovals || cacheRemovals)
764 JLOG(m_journal.debug())
765 <<
"TaggedCache partition sweep " << m_name
766 <<
": cache = " << partition.size() <<
"-" << cacheRemovals
767 <<
", map-=" << mapRemovals;
770 allRemovals += cacheRemovals;
std::vector< key_type > getKeys() const
std::shared_ptr< T > fetch(key_type const &digest, Handler const &h)
Fetch an item from the cache.
bool del(const key_type &key, bool valid)
bool retrieve(const key_type &key, T &data)
ValueEntry(clock_type::time_point const &last_access_, std::shared_ptr< mapped_type > const &ptr_)
Stream trace() const
Severity stream access functions.
partition_map_type & map()
auto insert(key_type const &key) -> std::enable_if_t< IsKeyCache, ReturnType >
std::pair< std::vector< std::shared_ptr< mapped_type > >, std::vector< std::weak_ptr< mapped_type > >> SweptPointersVector
beast::insight::Hook hook
void find(key_type const &key, T &it) const
std::size_t partitions() const
void touch(clock_type::time_point const &now)
std::weak_ptr< mapped_type > weak_ptr
bool canonicalize_replace_cache(const key_type &key, std::shared_ptr< T > const &data)
beast::insight::Gauge size
virtual time_point now() const =0
Returns the current time.
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
std::thread sweepHelper(clock_type::time_point const &when_expire, clock_type::time_point const &now, typename KeyOnlyCacheType::map_type &partition, SweptPointersVector &, std::atomic< int > &allRemovals, std::lock_guard< std::recursive_mutex > const &)
clock_type::time_point last_access
bool canonicalize(const key_type &key, std::shared_ptr< T > &data, std::function< bool(std::shared_ptr< T > const &)> &&replace)
Replace aliased objects with originals.
void setTargetSize(int s)
clock_type::duration m_target_age
void setTargetAge(clock_type::duration s)
auto insert(key_type const &key, T const &value) -> std::enable_if_t<!IsKeyCache, ReturnType >
Insert the element into the container.
beast::insight::Gauge hit_rate
std::shared_ptr< mapped_type > lock()
A generic endpoint for log messages.
void touch(clock_type::time_point const &now)
T forward_as_tuple(T... args)
Stats(std::string const &prefix, Handler const &handler, beast::insight::Collector::ptr const &collector)
double rate() const
Returns the fraction of cache hits.
std::pair< iterator, bool > emplace(std::piecewise_construct_t const &, T &&keyTuple, U &&valueTuple)
iterator erase(const_iterator position)
std::size_t size() const
Returns the number of items in the container.
A metric for measuring an integral value.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
beast::abstract_clock< std::chrono::steady_clock > clock_type
std::conditional< false, KeyOnlyEntry, ValueEntry >::type Entry
std::shared_ptr< T > fetch(const key_type &key)
std::thread sweepHelper(clock_type::time_point const &when_expire, [[maybe_unused]] clock_type::time_point const &now, typename KeyValueCacheType::map_type &partition, SweptPointersVector &stuffToSweep, std::atomic< int > &allRemovals, std::lock_guard< std::recursive_mutex > const &)
clock_type::time_point last_access
KeyOnlyEntry(clock_type::time_point const &last_access_)
bool touch_if_exists(KeyComparable const &key)
Refresh the last access time on a key if present.
bool canonicalize_replace_client(const key_type &key, std::shared_ptr< T > &data)
std::shared_ptr< mapped_type > ptr
std::shared_ptr< T > initialFetch(key_type const &key, std::lock_guard< mutex_type > const &l)
clock_type::duration getTargetAge() const
typename std::chrono::steady_clock ::time_point time_point
A reference to a handler for performing polled collection.
static std::shared_ptr< Collector > New()
typename std::chrono::steady_clock ::duration duration
void set(value_type value) const
Set the value on the gauge.
clock_type & clock()
Return the clock associated with the cache.
TaggedCache(std::string const &name, int size, clock_type::duration expiration, clock_type &clock, beast::Journal journal, beast::insight::Collector::ptr const &collector=beast::insight::NullCollector::New())