rippled
TaggedCache.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_BASICS_TAGGEDCACHE_H_INCLUDED
21 #define RIPPLE_BASICS_TAGGEDCACHE_H_INCLUDED
22 
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>
28 #include <atomic>
29 #include <functional>
30 #include <mutex>
31 #include <thread>
32 #include <type_traits>
33 #include <vector>
34 
35 namespace ripple {
36 
49 template <
50  class Key,
51  class T,
52  bool IsKeyCache = false,
53  class Hash = hardened_hash<>,
54  class KeyEqual = std::equal_to<Key>,
55  class Mutex = std::recursive_mutex>
56 class TaggedCache
57 {
58 public:
59  using mutex_type = Mutex;
60  using key_type = Key;
61  using mapped_type = T;
63 
64 public:
66  std::string const& name,
67  int size,
68  clock_type::duration expiration,
70  beast::Journal journal,
71  beast::insight::Collector::ptr const& collector =
73  : m_journal(journal)
74  , m_clock(clock)
75  , m_stats(
76  name,
77  std::bind(&TaggedCache::collect_metrics, this),
78  collector)
79  , m_name(name)
81  , m_target_age(expiration)
82  , m_cache_count(0)
83  , m_hits(0)
84  , m_misses(0)
85  {
86  }
87 
88 public:
90  clock_type&
92  {
93  return m_clock;
94  }
95 
98  size() const
99  {
100  std::lock_guard lock(m_mutex);
101  return m_cache.size();
102  }
103 
104  void
106  {
107  std::lock_guard lock(m_mutex);
108  m_target_size = s;
109 
110  if (s > 0)
111  {
112  for (auto& partition : m_cache.map())
113  {
114  partition.rehash(static_cast<std::size_t>(
115  (s + (s >> 2)) /
116  (partition.max_load_factor() * m_cache.partitions()) +
117  1));
118  }
119  }
120 
121  JLOG(m_journal.debug()) << m_name << " target size set to " << s;
122  }
123 
125  getTargetAge() const
126  {
127  std::lock_guard lock(m_mutex);
128  return m_target_age;
129  }
130 
131  void
133  {
134  std::lock_guard lock(m_mutex);
135  m_target_age = s;
136  JLOG(m_journal.debug())
137  << m_name << " target age set to " << m_target_age.count();
138  }
139 
140  int
141  getCacheSize() const
142  {
143  std::lock_guard lock(m_mutex);
144  return m_cache_count;
145  }
146 
147  int
148  getTrackSize() const
149  {
150  std::lock_guard lock(m_mutex);
151  return m_cache.size();
152  }
153 
154  float
156  {
157  std::lock_guard lock(m_mutex);
158  auto const total = static_cast<float>(m_hits + m_misses);
159  return m_hits * (100.0f / std::max(1.0f, total));
160  }
161 
162  void
164  {
165  std::lock_guard lock(m_mutex);
166  m_cache.clear();
167  m_cache_count = 0;
168  }
169 
170  void
172  {
173  std::lock_guard lock(m_mutex);
174  m_cache.clear();
175  m_cache_count = 0;
176  m_hits = 0;
177  m_misses = 0;
178  }
179 
183  template <class KeyComparable>
184  bool
185  touch_if_exists(KeyComparable const& key)
186  {
187  std::lock_guard lock(m_mutex);
188  auto const iter(m_cache.find(key));
189  if (iter == m_cache.end())
190  {
191  ++m_stats.misses;
192  return false;
193  }
194  iter->second.touch(m_clock.now());
195  ++m_stats.hits;
196  return true;
197  }
198 
202 
203  void
205  {
206  // Keep references to all the stuff we sweep
207  // For performance, each worker thread should exit before the swept data
208  // is destroyed but still within the main cache lock.
210 
211  clock_type::time_point const now(m_clock.now());
212  clock_type::time_point when_expire;
213 
214  auto const start = std::chrono::steady_clock::now();
215  {
216  std::lock_guard lock(m_mutex);
217 
218  if (m_target_size == 0 ||
219  (static_cast<int>(m_cache.size()) <= m_target_size))
220  {
221  when_expire = now - m_target_age;
222  }
223  else
224  {
225  when_expire =
227 
228  clock_type::duration const minimumAge(std::chrono::seconds(1));
229  if (when_expire > (now - minimumAge))
230  when_expire = now - minimumAge;
231 
232  JLOG(m_journal.trace())
233  << m_name << " is growing fast " << m_cache.size() << " of "
234  << m_target_size << " aging at "
235  << (now - when_expire).count() << " of "
236  << m_target_age.count();
237  }
238 
239  std::vector<std::thread> workers;
240  workers.reserve(m_cache.partitions());
241  std::atomic<int> allRemovals = 0;
242 
243  for (std::size_t p = 0; p < m_cache.partitions(); ++p)
244  {
245  workers.push_back(sweepHelper(
246  when_expire,
247  now,
248  m_cache.map()[p],
249  allStuffToSweep[p],
250  allRemovals,
251  lock));
252  }
253  for (std::thread& worker : workers)
254  worker.join();
255 
256  m_cache_count -= allRemovals;
257  }
258  // At this point allStuffToSweep will go out of scope outside the lock
259  // and decrement the reference count on each strong pointer.
260  JLOG(m_journal.debug())
261  << m_name << " TaggedCache sweep lock duration "
262  << std::chrono::duration_cast<std::chrono::milliseconds>(
264  .count()
265  << "ms";
266  }
267 
268  bool
269  del(const key_type& key, bool valid)
270  {
271  // Remove from cache, if !valid, remove from map too. Returns true if
272  // removed from cache
273  std::lock_guard lock(m_mutex);
274 
275  auto cit = m_cache.find(key);
276 
277  if (cit == m_cache.end())
278  return false;
279 
280  Entry& entry = cit->second;
281 
282  bool ret = false;
283 
284  if (entry.isCached())
285  {
286  --m_cache_count;
287  entry.ptr.reset();
288  ret = true;
289  }
290 
291  if (!valid || entry.isExpired())
292  m_cache.erase(cit);
293 
294  return ret;
295  }
296 
310 public:
311  bool
313  const key_type& key,
314  std::shared_ptr<T>& data,
315  std::function<bool(std::shared_ptr<T> const&)>&& replace)
316  {
317  // Return canonical value, store if needed, refresh in cache
318  // Return values: true=we had the data already
319  std::lock_guard lock(m_mutex);
320 
321  auto cit = m_cache.find(key);
322 
323  if (cit == m_cache.end())
324  {
326  std::piecewise_construct,
329  ++m_cache_count;
330  return false;
331  }
332 
333  Entry& entry = cit->second;
334  entry.touch(m_clock.now());
335 
336  if (entry.isCached())
337  {
338  if (replace(entry.ptr))
339  {
340  entry.ptr = data;
341  entry.weak_ptr = data;
342  }
343  else
344  {
345  data = entry.ptr;
346  }
347 
348  return true;
349  }
350 
351  auto cachedData = entry.lock();
352 
353  if (cachedData)
354  {
355  if (replace(entry.ptr))
356  {
357  entry.ptr = data;
358  entry.weak_ptr = data;
359  }
360  else
361  {
362  entry.ptr = cachedData;
363  data = cachedData;
364  }
365 
366  ++m_cache_count;
367  return true;
368  }
369 
370  entry.ptr = data;
371  entry.weak_ptr = data;
372  ++m_cache_count;
373 
374  return false;
375  }
376 
377  bool
379  const key_type& key,
380  std::shared_ptr<T> const& data)
381  {
382  return canonicalize(
383  key,
384  const_cast<std::shared_ptr<T>&>(data),
385  [](std::shared_ptr<T> const&) { return true; });
386  }
387 
388  bool
390  {
391  return canonicalize(
392  key, data, [](std::shared_ptr<T> const&) { return false; });
393  }
394 
396  fetch(const key_type& key)
397  {
399  auto ret = initialFetch(key, l);
400  if (!ret)
401  ++m_misses;
402  return ret;
403  }
404 
409  template <class ReturnType = bool>
410  auto
411  insert(key_type const& key, T const& value)
413  {
414  auto p = std::make_shared<T>(std::cref(value));
415  return canonicalize_replace_client(key, p);
416  }
417 
418  template <class ReturnType = bool>
419  auto
421  {
422  std::lock_guard lock(m_mutex);
423  clock_type::time_point const now(m_clock.now());
424  auto [it, inserted] = m_cache.emplace(
425  std::piecewise_construct,
427  std::forward_as_tuple(now));
428  if (!inserted)
429  it->second.last_access = now;
430  return inserted;
431  }
432 
433  // VFALCO NOTE It looks like this returns a copy of the data in
434  // the output parameter 'data'. This could be expensive.
435  // Perhaps it should work like standard containers, which
436  // simply return an iterator.
437  //
438  bool
439  retrieve(const key_type& key, T& data)
440  {
441  // retrieve the value of the stored data
442  auto entry = fetch(key);
443 
444  if (!entry)
445  return false;
446 
447  data = *entry;
448  return true;
449  }
450 
451  mutex_type&
453  {
454  return m_mutex;
455  }
456 
458  getKeys() const
459  {
461 
462  {
463  std::lock_guard lock(m_mutex);
464  v.reserve(m_cache.size());
465  for (auto const& _ : m_cache)
466  v.push_back(_.first);
467  }
468 
469  return v;
470  }
471 
472  // CachedSLEs functions.
474  double
475  rate() const
476  {
477  std::lock_guard lock(m_mutex);
478  auto const tot = m_hits + m_misses;
479  if (tot == 0)
480  return 0;
481  return double(m_hits) / tot;
482  }
483 
489  template <class Handler>
491  fetch(key_type const& digest, Handler const& h)
492  {
493  {
495  if (auto ret = initialFetch(digest, l))
496  return ret;
497  }
498 
499  auto sle = h();
500  if (!sle)
501  return {};
502 
504  ++m_misses;
505  auto const [it, inserted] =
506  m_cache.emplace(digest, Entry(m_clock.now(), std::move(sle)));
507  if (!inserted)
508  it->second.touch(m_clock.now());
509  return it->second.ptr;
510  }
511  // End CachedSLEs functions.
512 
513 private:
516  {
517  auto cit = m_cache.find(key);
518  if (cit == m_cache.end())
519  return {};
520 
521  Entry& entry = cit->second;
522  if (entry.isCached())
523  {
524  ++m_hits;
525  entry.touch(m_clock.now());
526  return entry.ptr;
527  }
528  entry.ptr = entry.lock();
529  if (entry.isCached())
530  {
531  // independent of cache size, so not counted as a hit
532  ++m_cache_count;
533  entry.touch(m_clock.now());
534  return entry.ptr;
535  }
536 
537  m_cache.erase(cit);
538  return {};
539  }
540 
541  void
543  {
545 
546  {
548  {
549  std::lock_guard lock(m_mutex);
550  auto const total(m_hits + m_misses);
551  if (total != 0)
552  hit_rate = (m_hits * 100) / total;
553  }
554  m_stats.hit_rate.set(hit_rate);
555  }
556  }
557 
558 private:
559  struct Stats
560  {
561  template <class Handler>
563  std::string const& prefix,
564  Handler const& handler,
565  beast::insight::Collector::ptr const& collector)
566  : hook(collector->make_hook(handler))
567  , size(collector->make_gauge(prefix, "size"))
568  , hit_rate(collector->make_gauge(prefix, "hit_rate"))
569  , hits(0)
570  , misses(0)
571  {
572  }
573 
577 
580  };
581 
583  {
584  public:
586 
587  explicit KeyOnlyEntry(clock_type::time_point const& last_access_)
588  : last_access(last_access_)
589  {
590  }
591 
592  void
594  {
595  last_access = now;
596  }
597  };
598 
600  {
601  public:
605 
607  clock_type::time_point const& last_access_,
608  std::shared_ptr<mapped_type> const& ptr_)
609  : ptr(ptr_), weak_ptr(ptr_), last_access(last_access_)
610  {
611  }
612 
613  bool
614  isWeak() const
615  {
616  return ptr == nullptr;
617  }
618  bool
619  isCached() const
620  {
621  return ptr != nullptr;
622  }
623  bool
624  isExpired() const
625  {
626  return weak_ptr.expired();
627  }
630  {
631  return weak_ptr.lock();
632  }
633  void
635  {
636  last_access = now;
637  }
638  };
639 
640  typedef
643 
644  using KeyOnlyCacheType =
646 
647  using KeyValueCacheType =
649 
650  using cache_type =
652 
653  [[nodiscard]] std::thread
655  clock_type::time_point const& when_expire,
656  [[maybe_unused]] clock_type::time_point const& now,
657  typename KeyValueCacheType::map_type& partition,
658  SweptPointersVector& stuffToSweep,
659  std::atomic<int>& allRemovals,
661  {
662  return std::thread([&, this]() {
663  int cacheRemovals = 0;
664  int mapRemovals = 0;
665 
666  // Keep references to all the stuff we sweep
667  // so that we can destroy them outside the lock.
668  stuffToSweep.first.reserve(partition.size());
669  stuffToSweep.second.reserve(partition.size());
670  {
671  auto cit = partition.begin();
672  while (cit != partition.end())
673  {
674  if (cit->second.isWeak())
675  {
676  // weak
677  if (cit->second.isExpired())
678  {
679  stuffToSweep.second.push_back(
680  std::move(cit->second.weak_ptr));
681  ++mapRemovals;
682  cit = partition.erase(cit);
683  }
684  else
685  {
686  ++cit;
687  }
688  }
689  else if (cit->second.last_access <= when_expire)
690  {
691  // strong, expired
692  ++cacheRemovals;
693  if (cit->second.ptr.use_count() == 1)
694  {
695  stuffToSweep.first.push_back(
696  std::move(cit->second.ptr));
697  ++mapRemovals;
698  cit = partition.erase(cit);
699  }
700  else
701  {
702  // remains weakly cached
703  cit->second.ptr.reset();
704  ++cit;
705  }
706  }
707  else
708  {
709  // strong, not expired
710  ++cit;
711  }
712  }
713  }
714 
715  if (mapRemovals || cacheRemovals)
716  {
717  JLOG(m_journal.debug())
718  << "TaggedCache partition sweep " << m_name
719  << ": cache = " << partition.size() << "-" << cacheRemovals
720  << ", map-=" << mapRemovals;
721  }
722 
723  allRemovals += cacheRemovals;
724  });
725  }
726 
727  [[nodiscard]] std::thread
729  clock_type::time_point const& when_expire,
730  clock_type::time_point const& now,
731  typename KeyOnlyCacheType::map_type& partition,
733  std::atomic<int>& allRemovals,
735  {
736  return std::thread([&, this]() {
737  int cacheRemovals = 0;
738  int mapRemovals = 0;
739 
740  // Keep references to all the stuff we sweep
741  // so that we can destroy them outside the lock.
742  {
743  auto cit = partition.begin();
744  while (cit != partition.end())
745  {
746  if (cit->second.last_access > now)
747  {
748  cit->second.last_access = now;
749  ++cit;
750  }
751  else if (cit->second.last_access <= when_expire)
752  {
753  cit = partition.erase(cit);
754  }
755  else
756  {
757  ++cit;
758  }
759  }
760  }
761 
762  if (mapRemovals || cacheRemovals)
763  {
764  JLOG(m_journal.debug())
765  << "TaggedCache partition sweep " << m_name
766  << ": cache = " << partition.size() << "-" << cacheRemovals
767  << ", map-=" << mapRemovals;
768  }
769 
770  allRemovals += cacheRemovals;
771  });
772  };
773 
774  beast::Journal m_journal;
776  Stats m_stats;
777 
779 
780  // Used for logging
782 
783  // Desired number of cache entries (0 = ignore)
785 
786  // Desired maximum cache age
788 
789  // Number of items cached
791  cache_type m_cache; // Hold strong reference to recent objects
794 };
795 
796 } // namespace ripple
797 
798 #endif
ripple::TaggedCache::getKeys
std::vector< key_type > getKeys() const
Definition: TaggedCache.h:458
ripple::TaggedCache::m_mutex
mutex_type m_mutex
Definition: TaggedCache.h:778
ripple::TaggedCache::fetch
std::shared_ptr< T > fetch(key_type const &digest, Handler const &h)
Fetch an item from the cache.
Definition: TaggedCache.h:491
ripple::TaggedCache::reset
void reset()
Definition: TaggedCache.h:171
std::weak_ptr::lock
T lock(T... args)
ripple::TaggedCache::mutex_type
Mutex mutex_type
Definition: TaggedCache.h:59
ripple::TaggedCache::sweep
void sweep()
Definition: TaggedCache.h:204
ripple::TaggedCache::del
bool del(const key_type &key, bool valid)
Definition: TaggedCache.h:269
ripple::TaggedCache::retrieve
bool retrieve(const key_type &key, T &data)
Definition: TaggedCache.h:439
ripple::TaggedCache::ValueEntry::ValueEntry
ValueEntry(clock_type::time_point const &last_access_, std::shared_ptr< mapped_type > const &ptr_)
Definition: TaggedCache.h:606
ripple::partitioned_unordered_map::size
std::size_t size() const
Definition: partitioned_unordered_map.h:389
std::string
STL class.
std::shared_ptr< Collector >
ripple::TaggedCache
Map/cache combination.
Definition: Application.h:64
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::partitioned_unordered_map::clear
void clear()
Definition: partitioned_unordered_map.h:364
ripple::partitioned_unordered_map::map
partition_map_type & map()
Definition: partitioned_unordered_map.h:259
functional
ripple::TaggedCache::ValueEntry::isCached
bool isCached() const
Definition: TaggedCache.h:619
ripple::TaggedCache::insert
auto insert(key_type const &key) -> std::enable_if_t< IsKeyCache, ReturnType >
Definition: TaggedCache.h:420
ripple::partitioned_unordered_map::end
static void end(T &it)
Definition: partitioned_unordered_map.h:219
std::pair
std::vector::reserve
T reserve(T... args)
vector
ripple::TaggedCache::clear
void clear()
Definition: TaggedCache.h:163
ripple::TaggedCache::SweptPointersVector
std::pair< std::vector< std::shared_ptr< mapped_type > >, std::vector< std::weak_ptr< mapped_type > >> SweptPointersVector
Definition: TaggedCache.h:201
ripple::TaggedCache::m_cache
cache_type m_cache
Definition: TaggedCache.h:791
std::chrono::seconds
std::recursive_mutex
STL class.
ripple::TaggedCache::m_cache_count
int m_cache_count
Definition: TaggedCache.h:790
std::lock_guard
STL class.
ripple::TaggedCache::ValueEntry
Definition: TaggedCache.h:599
ripple::TaggedCache::collect_metrics
void collect_metrics()
Definition: TaggedCache.h:542
ripple::TaggedCache::Stats::hook
beast::insight::Hook hook
Definition: TaggedCache.h:574
ripple::partitioned_unordered_map
Definition: partitioned_unordered_map.h:43
std::function
ripple::TaggedCache< uint256, SLE const >::mapped_type
SLE const mapped_type
Definition: TaggedCache.h:61
ripple::partitioned_unordered_map::find
void find(key_type const &key, T &it) const
Definition: partitioned_unordered_map.h:311
ripple::partitioned_unordered_map::partitions
std::size_t partitions() const
Definition: partitioned_unordered_map.h:253
ripple::TaggedCache::ValueEntry::touch
void touch(clock_type::time_point const &now)
Definition: TaggedCache.h:634
ripple::TaggedCache::ValueEntry::weak_ptr
std::weak_ptr< mapped_type > weak_ptr
Definition: TaggedCache.h:603
ripple::TaggedCache::m_misses
std::uint64_t m_misses
Definition: TaggedCache.h:793
ripple::TaggedCache::canonicalize_replace_cache
bool canonicalize_replace_cache(const key_type &key, std::shared_ptr< T > const &data)
Definition: TaggedCache.h:378
ripple::TaggedCache::Stats::size
beast::insight::Gauge size
Definition: TaggedCache.h:575
std::weak_ptr::expired
T expired(T... args)
beast::abstract_clock::now
virtual time_point now() const =0
Returns the current time.
std::vector::push_back
T push_back(T... args)
ripple::digest
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition: tokens.cpp:47
ripple::TaggedCache::getHitRate
float getHitRate()
Definition: TaggedCache.h:155
ripple::TaggedCache::sweepHelper
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 &)
Definition: TaggedCache.h:728
ripple::base_uint< 256 >
ripple::TaggedCache::KeyOnlyEntry::last_access
clock_type::time_point last_access
Definition: TaggedCache.h:585
ripple::TaggedCache::canonicalize
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.
Definition: TaggedCache.h:312
ripple::TaggedCache::setTargetSize
void setTargetSize(int s)
Definition: TaggedCache.h:105
ripple::TaggedCache::m_target_age
clock_type::duration m_target_age
Definition: TaggedCache.h:787
ripple::TaggedCache::getTrackSize
int getTrackSize() const
Definition: TaggedCache.h:148
thread
ripple::TaggedCache::setTargetAge
void setTargetAge(clock_type::duration s)
Definition: TaggedCache.h:132
std::enable_if_t
ripple::TaggedCache::insert
auto insert(key_type const &key, T const &value) -> std::enable_if_t<!IsKeyCache, ReturnType >
Insert the element into the container.
Definition: TaggedCache.h:411
ripple::TaggedCache::Stats::misses
std::size_t misses
Definition: TaggedCache.h:579
ripple::TaggedCache::Stats::hit_rate
beast::insight::Gauge hit_rate
Definition: TaggedCache.h:576
ripple::TaggedCache::ValueEntry::isExpired
bool isExpired() const
Definition: TaggedCache.h:624
ripple::TaggedCache::Stats::hits
std::size_t hits
Definition: TaggedCache.h:578
ripple::TaggedCache::ValueEntry::lock
std::shared_ptr< mapped_type > lock()
Definition: TaggedCache.h:629
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint64_t
ripple::TaggedCache::KeyOnlyEntry::touch
void touch(clock_type::time_point const &now)
Definition: TaggedCache.h:593
ripple::TaggedCache::Stats
Definition: TaggedCache.h:559
atomic
std::forward_as_tuple
T forward_as_tuple(T... args)
ripple::TaggedCache::Stats::Stats
Stats(std::string const &prefix, Handler const &handler, beast::insight::Collector::ptr const &collector)
Definition: TaggedCache.h:562
ripple::TaggedCache::rate
double rate() const
Returns the fraction of cache hits.
Definition: TaggedCache.h:475
ripple::partitioned_unordered_map::emplace
std::pair< iterator, bool > emplace(std::piecewise_construct_t const &, T &&keyTuple, U &&valueTuple)
Definition: partitioned_unordered_map.h:338
ripple::partitioned_unordered_map::erase
iterator erase(const_iterator position)
Definition: partitioned_unordered_map.h:371
ripple::TaggedCache::getCacheSize
int getCacheSize() const
Definition: TaggedCache.h:141
beast::abstract_clock< std::chrono::steady_clock >
ripple::TaggedCache::size
std::size_t size() const
Returns the number of items in the container.
Definition: TaggedCache.h:98
beast::insight::Gauge
A metric for measuring an integral value.
Definition: Gauge.h:39
std::weak_ptr< mapped_type >
std::equal_to
ripple::TaggedCache::m_hits
std::uint64_t m_hits
Definition: TaggedCache.h:792
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::TaggedCache::clock_type
beast::abstract_clock< std::chrono::steady_clock > clock_type
Definition: TaggedCache.h:62
ripple::TaggedCache< uint256, SLE const >::Entry
std::conditional< false, KeyOnlyEntry, ValueEntry >::type Entry
Definition: TaggedCache.h:642
ripple::TaggedCache::m_name
std::string m_name
Definition: TaggedCache.h:781
ripple::TaggedCache::KeyOnlyEntry
Definition: TaggedCache.h:582
ripple::TaggedCache::fetch
std::shared_ptr< T > fetch(const key_type &key)
Definition: TaggedCache.h:396
ripple::TaggedCache::sweepHelper
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 &)
Definition: TaggedCache.h:654
std
STL namespace.
ripple::TaggedCache::ValueEntry::last_access
clock_type::time_point last_access
Definition: TaggedCache.h:604
ripple::TaggedCache::m_journal
beast::Journal m_journal
Definition: TaggedCache.h:772
ripple::TaggedCache::KeyOnlyEntry::KeyOnlyEntry
KeyOnlyEntry(clock_type::time_point const &last_access_)
Definition: TaggedCache.h:587
mutex
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::size_t
ripple::TaggedCache::touch_if_exists
bool touch_if_exists(KeyComparable const &key)
Refresh the last access time on a key if present.
Definition: TaggedCache.h:185
ripple::TaggedCache::canonicalize_replace_client
bool canonicalize_replace_client(const key_type &key, std::shared_ptr< T > &data)
Definition: TaggedCache.h:389
ripple::TaggedCache::peekMutex
mutex_type & peekMutex()
Definition: TaggedCache.h:452
std::conditional
std::max
T max(T... args)
ripple::TaggedCache::ValueEntry::ptr
std::shared_ptr< mapped_type > ptr
Definition: TaggedCache.h:602
ripple::TaggedCache::initialFetch
std::shared_ptr< T > initialFetch(key_type const &key, std::lock_guard< mutex_type > const &l)
Definition: TaggedCache.h:515
ripple::TaggedCache::getTargetAge
clock_type::duration getTargetAge() const
Definition: TaggedCache.h:125
ripple::TaggedCache::m_target_size
int m_target_size
Definition: TaggedCache.h:784
std::unordered_map
STL class.
ripple::TaggedCache::m_stats
Stats m_stats
Definition: TaggedCache.h:776
beast::abstract_clock< std::chrono::steady_clock >::time_point
typename std::chrono::steady_clock ::time_point time_point
Definition: abstract_clock.h:63
beast::insight::Hook
A reference to a handler for performing polled collection.
Definition: Hook.h:31
type_traits
beast::insight::NullCollector::New
static std::shared_ptr< Collector > New()
Definition: NullCollector.cpp:152
beast::abstract_clock< std::chrono::steady_clock >::duration
typename std::chrono::steady_clock ::duration duration
Definition: abstract_clock.h:62
ripple::TaggedCache::m_clock
clock_type & m_clock
Definition: TaggedCache.h:775
std::cref
T cref(T... args)
std::thread::join
T join(T... args)
beast::insight::Gauge::set
void set(value_type value) const
Set the value on the gauge.
Definition: Gauge.h:68
ripple::TaggedCache::clock
clock_type & clock()
Return the clock associated with the cache.
Definition: TaggedCache.h:91
ripple::TaggedCache::TaggedCache
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())
Definition: TaggedCache.h:65
ripple::TaggedCache::ValueEntry::isWeak
bool isWeak() const
Definition: TaggedCache.h:614
std::chrono::steady_clock::now
T now(T... args)