rippled
KeyCache.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_KEYCACHE_H_INCLUDED
21 #define RIPPLE_BASICS_KEYCACHE_H_INCLUDED
22 
23 #include <ripple/basics/hardened_hash.h>
24 #include <ripple/basics/UnorderedContainers.h>
25 #include <ripple/beast/clock/abstract_clock.h>
26 #include <ripple/beast/insight/Insight.h>
27 #include <mutex>
28 
29 namespace ripple {
30 
37 template <
38  class Key,
39  class Hash = hardened_hash <>,
40  class KeyEqual = std::equal_to <Key>,
41  //class Allocator = std::allocator <std::pair <Key const, Entry>>,
42  class Mutex = std::mutex
43 >
44 class KeyCache
45 {
46 public:
47  using key_type = Key;
49 
50 private:
51  struct Stats
52  {
53  template <class Handler>
54  Stats (std::string const& prefix, Handler const& handler,
55  beast::insight::Collector::ptr const& collector)
56  : hook (collector->make_hook (handler))
57  , size (collector->make_gauge (prefix, "size"))
58  , hit_rate (collector->make_gauge (prefix, "hit_rate"))
59  , hits (0)
60  , misses (0)
61  { }
62 
66 
69  };
70 
71  struct Entry
72  {
73  explicit Entry (clock_type::time_point const& last_access_)
74  : last_access (last_access_)
75  {
76  }
77 
79  };
80 
82  using iterator = typename map_type::iterator;
83 
84 public:
85  using size_type = typename map_type::size_type;
86 
87 private:
88  Mutex mutable m_mutex;
90  Stats mutable m_stats;
95 
96 public:
103  beast::insight::Collector::ptr const& collector, size_type target_size = 0,
105  : m_stats (name,
107  collector)
108  , m_clock (clock)
109  , m_name (name)
110  , m_target_size (target_size)
111  , m_target_age (expiration)
112  {
113  }
114 
115  // VFALCO TODO Use a forwarding constructor call here
117  size_type target_size = 0,
119  : m_stats (name,
122  , m_clock (clock)
123  , m_name (name)
124  , m_target_size (target_size)
125  , m_target_age (expiration)
126  {
127  }
128 
129  //--------------------------------------------------------------------------
130 
132  std::string const& name () const
133  {
134  return m_name;
135  }
136 
139  {
140  return m_clock;
141  }
142 
144  size_type size () const
145  {
146  std::lock_guard lock (m_mutex);
147  return m_map.size ();
148  }
149 
151  void clear ()
152  {
153  std::lock_guard lock (m_mutex);
154  m_map.clear ();
155  }
156 
157  void reset ()
158  {
159  std::lock_guard lock(m_mutex);
160  m_map.clear();
161  m_stats.hits = 0;
162  m_stats.misses = 0;
163  }
164 
166  {
167  std::lock_guard lock (m_mutex);
168  m_target_size = s;
169  }
170 
172  {
173  std::lock_guard lock (m_mutex);
174  m_target_age = s;
175  }
176 
180  template <class KeyComparable>
181  bool exists (KeyComparable const& key) const
182  {
183  std::lock_guard lock (m_mutex);
184  typename map_type::const_iterator const iter (m_map.find (key));
185  if (iter != m_map.end ())
186  {
187  ++m_stats.hits;
188  return true;
189  }
190  ++m_stats.misses;
191  return false;
192  }
193 
198  bool insert (Key const& key)
199  {
200  std::lock_guard lock (m_mutex);
201  clock_type::time_point const now (m_clock.now ());
202  auto [it, inserted] = m_map.emplace (
203  std::piecewise_construct, std::forward_as_tuple (key),
204  std::forward_as_tuple (now));
205  if (!inserted)
206  {
207  it->second.last_access = now;
208  return false;
209  }
210  return true;
211  }
212 
216  template <class KeyComparable>
217  bool touch_if_exists (KeyComparable const& key)
218  {
219  std::lock_guard lock (m_mutex);
220  iterator const iter (m_map.find (key));
221  if (iter == m_map.end ())
222  {
223  ++m_stats.misses;
224  return false;
225  }
226  iter->second.last_access = m_clock.now ();
227  ++m_stats.hits;
228  return true;
229  }
230 
235  bool erase (key_type const& key)
236  {
237  std::lock_guard lock (m_mutex);
238  if (m_map.erase (key) > 0)
239  {
240  ++m_stats.hits;
241  return true;
242  }
243  ++m_stats.misses;
244  return false;
245  }
246 
248  void sweep ()
249  {
250  clock_type::time_point const now (m_clock.now ());
251  clock_type::time_point when_expire;
252 
253  std::lock_guard lock (m_mutex);
254 
255  if (m_target_size == 0 ||
256  (m_map.size () <= m_target_size))
257  {
258  when_expire = now - m_target_age;
259  }
260  else
261  {
262  when_expire = now -
264 
265  clock_type::duration const minimumAge (
267  if (when_expire > (now - minimumAge))
268  when_expire = now - minimumAge;
269  }
270 
271  iterator it = m_map.begin ();
272 
273  while (it != m_map.end ())
274  {
275  if (it->second.last_access > now)
276  {
277  it->second.last_access = now;
278  ++it;
279  }
280  else if (it->second.last_access <= when_expire)
281  {
282  it = m_map.erase (it);
283  }
284  else
285  {
286  ++it;
287  }
288  }
289  }
290 
291 private:
293  {
294  m_stats.size.set (size ());
295 
296  {
298  {
299  std::lock_guard lock (m_mutex);
300  auto const total (m_stats.hits + m_stats.misses);
301  if (total != 0)
302  hit_rate = (m_stats.hits * 100) / total;
303  }
304  m_stats.hit_rate.set (hit_rate);
305  }
306  }
307 };
308 
309 }
310 
311 #endif
ripple::KeyCache::m_mutex
Mutex m_mutex
Definition: KeyCache.h:88
ripple::KeyCache::m_stats
Stats m_stats
Definition: KeyCache.h:90
ripple::KeyCache< uint256 >::iterator
typename map_type::iterator iterator
Definition: KeyCache.h:82
ripple::KeyCache::size
size_type size() const
Returns the number of items in the container.
Definition: KeyCache.h:144
std::bind
T bind(T... args)
std::string
STL class.
std::shared_ptr< Collector >
ripple::KeyCache::erase
bool erase(key_type const &key)
Remove the specified cache entry.
Definition: KeyCache.h:235
ripple::KeyCache::m_map
map_type m_map
Definition: KeyCache.h:89
ripple::KeyCache::Stats::Stats
Stats(std::string const &prefix, Handler const &handler, beast::insight::Collector::ptr const &collector)
Definition: KeyCache.h:54
ripple::KeyCache::m_name
const std::string m_name
Definition: KeyCache.h:92
std::unordered_map::find
T find(T... args)
std::unordered_map::size
T size(T... args)
ripple::KeyCache::Stats::size
beast::insight::Gauge size
Definition: KeyCache.h:64
std::chrono::seconds
ripple::KeyCache::collect_metrics
void collect_metrics()
Definition: KeyCache.h:292
ripple::KeyCache::Stats::hits
std::size_t hits
Definition: KeyCache.h:67
std::unordered_map::emplace
T emplace(T... args)
std::lock_guard
STL class.
ripple::KeyCache::reset
void reset()
Definition: KeyCache.h:157
std::unordered_map::clear
T clear(T... args)
beast::abstract_clock::now
virtual time_point now() const =0
Returns the current time.
ripple::KeyCache::touch_if_exists
bool touch_if_exists(KeyComparable const &key)
Refresh the last access time on a key if present.
Definition: KeyCache.h:217
ripple::KeyCache::m_clock
clock_type & m_clock
Definition: KeyCache.h:91
ripple::KeyCache::m_target_size
size_type m_target_size
Definition: KeyCache.h:93
ripple::base_uint< 256 >
ripple::KeyCache::KeyCache
KeyCache(std::string const &name, clock_type &clock, beast::insight::Collector::ptr const &collector, size_type target_size=0, std::chrono::seconds expiration=std::chrono::minutes{2})
Construct with the specified name.
Definition: KeyCache.h:102
ripple::KeyCache::insert
bool insert(Key const &key)
Insert the specified key.
Definition: KeyCache.h:198
ripple::KeyCache::Stats::hit_rate
beast::insight::Gauge hit_rate
Definition: KeyCache.h:65
std::unordered_map::erase
T erase(T... args)
ripple::KeyCache::exists
bool exists(KeyComparable const &key) const
Returns true if the key was found.
Definition: KeyCache.h:181
ripple::KeyCache::m_target_age
clock_type::duration m_target_age
Definition: KeyCache.h:94
std::uint64_t
std::forward_as_tuple
T forward_as_tuple(T... args)
ripple::KeyCache::sweep
void sweep()
Remove stale entries from the cache.
Definition: KeyCache.h:248
beast::abstract_clock< std::chrono::steady_clock >
ripple::KeyCache::Entry::Entry
Entry(clock_type::time_point const &last_access_)
Definition: KeyCache.h:73
beast::insight::Gauge
A metric for measuring an integral value.
Definition: Gauge.h:39
ripple::KeyCache::KeyCache
KeyCache(std::string const &name, clock_type &clock, size_type target_size=0, std::chrono::seconds expiration=std::chrono::minutes{2})
Definition: KeyCache.h:116
std::equal_to
ripple::KeyCache::clear
void clear()
Empty the cache.
Definition: KeyCache.h:151
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::KeyCache::Entry::last_access
clock_type::time_point last_access
Definition: KeyCache.h:78
ripple::KeyCache::setTargetSize
void setTargetSize(size_type s)
Definition: KeyCache.h:165
std::unordered_map::begin
T begin(T... args)
ripple::KeyCache< uint256 >::size_type
typename map_type::size_type size_type
Definition: KeyCache.h:85
ripple::KeyCache::Entry
Definition: KeyCache.h:71
ripple::KeyCache::setTargetAge
void setTargetAge(std::chrono::seconds s)
Definition: KeyCache.h:171
ripple::KeyCache::name
std::string const & name() const
Retrieve the name of this object.
Definition: KeyCache.h:132
ripple::KeyCache::Stats
Definition: KeyCache.h:51
ripple::KeyCache::Stats::misses
std::size_t misses
Definition: KeyCache.h:68
mutex
std::size_t
std::unordered_map::end
T end(T... args)
ripple::KeyCache::clock
clock_type & clock()
Return the clock associated with the cache.
Definition: KeyCache.h:138
ripple::KeyCache
Maintains a cache of keys with no associated data.
Definition: KeyCache.h:44
std::unordered_map
STL class.
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
beast::insight::NullCollector::New
static std::shared_ptr< Collector > New()
Definition: NullCollector.cpp:140
beast::abstract_clock< std::chrono::steady_clock >::duration
typename std::chrono::steady_clock ::duration duration
Definition: abstract_clock.h:62
ripple::KeyCache::Stats::hook
beast::insight::Hook hook
Definition: KeyCache.h:63
beast::insight::Gauge::set
void set(value_type value) const
Set the value on the gauge.
Definition: Gauge.h:68