xrpld
Loading...
Searching...
No Matches
TaggedCache.h
1#pragma once
2
3#include <xrpl/basics/SharedWeakCachePointer.h>
4#include <xrpl/basics/SharedWeakCachePointer.ipp> // IWYU pragma: keep
5#include <xrpl/basics/UnorderedContainers.h>
6#include <xrpl/basics/hardened_hash.h>
7#include <xrpl/beast/clock/abstract_clock.h>
8#include <xrpl/beast/insight/Collector.h>
9#include <xrpl/beast/insight/Gauge.h>
10#include <xrpl/beast/insight/Hook.h>
11#include <xrpl/beast/insight/NullCollector.h>
12#include <xrpl/beast/utility/Journal.h>
13
14#include <atomic>
15#include <chrono>
16#include <cstddef>
17#include <cstdint>
18#include <functional>
19#include <memory>
20#include <mutex>
21#include <string>
22#include <thread>
23#include <type_traits>
24#include <vector>
25
26namespace xrpl {
27
28namespace detail {
29
30// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
31// collision when the key already exists (defined in TaggedCache.ipp):
32// - ReplaceCached: always replace the cached value with `data`. `data` is
33// never written back and may be const.
34// - ReplaceClient: keep the cached value and write it back into `data` (the
35// client's pointer), which must therefore be writable.
36// - ReplaceDynamically: call the supplied callback to decide per call; `data`
37// is written back when the cached value is kept, so it must be writable.
38struct ReplaceCached;
39struct ReplaceClient;
40struct ReplaceDynamically;
41
42} // namespace detail
43
57template <
58 class Key,
59 class T,
60 bool IsKeyCache = false,
61 class SharedWeakUnionPointerType = SharedWeakCachePointer<T>,
62 class SharedPointerType = std::shared_ptr<T>,
63 class Hash = HardenedHash<>,
64 class KeyEqual = std::equal_to<Key>,
65 class Mutex = std::recursive_mutex>
67{
68public:
69 using mutex_type = Mutex;
70 using key_type = Key;
71 using mapped_type = T;
73 using shared_weak_combo_pointer_type = SharedWeakUnionPointerType;
74 using shared_pointer_type = SharedPointerType;
75
76public:
78 std::string const& name,
79 int size,
80 clock_type::duration expiration,
82 beast::Journal journal,
84
85public:
91
96 size() const;
97
98 int
99 getCacheSize() const;
100
101 int
103
104 float
106
107 void
109
110 void
112
117 template <class KeyComparable>
118 bool
119 touchIfExists(KeyComparable const& key);
120
122
123 void
125
126 bool
127 del(key_type const& key, bool valid);
128
129private:
130 // Selects the `data` parameter type of canonicalizeImpl from the replace
131 // policy: const for detail::ReplaceCached (never written back), otherwise
132 // writable.
133 template <typename Policy>
136 SharedPointerType const&,
137 SharedPointerType&>;
138
148 template <class Policy, class Callback = std::nullptr_t>
149 bool
151 key_type const& key,
153 Policy policy,
154 Callback&& replaceCallback = nullptr);
155
156public:
177 template <class Callback>
178 bool
179 canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback);
180
195 bool
196 canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data);
197
213 bool
214 canonicalizeReplaceClient(key_type const& key, SharedPointerType& data);
215
216 SharedPointerType
217 fetch(key_type const& key);
218
224 template <class ReturnType = bool>
225 auto
226 insert(key_type const& key, T const& value) -> ReturnType
227 requires(!IsKeyCache);
228
229 template <class ReturnType = bool>
230 auto
231 insert(key_type const& key) -> ReturnType
232 requires IsKeyCache;
233
234 // VFALCO NOTE It looks like this returns a copy of the data in
235 // the output parameter 'data'. This could be expensive.
236 // Perhaps it should work like standard containers, which
237 // simply return an iterator.
238 //
239 bool
240 retrieve(key_type const& key, T& data);
241
244
246 getKeys() const;
247
248 // CachedSLEs functions.
252 double
253 rate() const;
254
261 template <class Handler>
262 SharedPointerType
263 fetch(key_type const& digest, Handler const& h);
264 // End CachedSLEs functions.
265
266private:
267 SharedPointerType
269
270 void
272
273private:
274 struct Stats
275 {
276 template <class Handler>
278 std::string const& prefix,
279 Handler const& handler,
280 beast::insight::Collector::ptr const& collector)
281 : hook(collector->makeHook(handler))
282 , size(collector->makeGauge(prefix, "size"))
283 , hitRate(collector->makeGauge(prefix, "hit_rate"))
284
285 {
286 }
287
291
294 };
295
297 {
298 public:
300
304
305 void
307 {
308 lastAccess = now;
309 }
310 };
311
313 {
314 public:
317
322
323 [[nodiscard]] bool
324 isWeak() const
325 {
326 if (!ptr)
327 return true;
328 return ptr.isWeak();
329 }
330 [[nodiscard]] bool
331 isCached() const
332 {
333 return ptr && ptr.isStrong();
334 }
335 [[nodiscard]] bool
336 isExpired() const
337 {
338 return ptr.expired();
339 }
340 SharedPointerType
342 {
343 return ptr.lock();
344 }
345 void
347 {
348 lastAccess = now;
349 }
350 };
351
353
355
357
359
360 [[nodiscard]] std::thread
362 clock_type::time_point const& whenExpire,
363 [[maybe_unused]] clock_type::time_point const& now,
365 SweptPointersVector& stuffToSweep,
366 std::atomic<int>& allRemovals,
368
369 [[nodiscard]] std::thread
371 clock_type::time_point const& whenExpire,
372 clock_type::time_point const& now,
375 std::atomic<int>& allRemovals,
377
380 Stats stats_;
381
383
384 // Used for logging
386
387 // Desired number of cache entries (0 = ignore)
388 int const targetSize_;
389
390 // Desired maximum cache age
392
393 // Number of items cached
395 cache_type cache_; // Hold strong reference to recent objects
398};
399
400} // namespace xrpl
Abstract interface to a clock.
std::chrono::steady_clock::duration duration
std::chrono::steady_clock::time_point time_point
A generic endpoint for log messages.
Definition Journal.h:44
std::shared_ptr< Collector > ptr
Definition Collector.h:29
A metric for measuring an integral value.
Definition Gauge.h:21
A reference to a handler for performing polled collection.
Definition Hook.h:14
static std::shared_ptr< Collector > make()
Seed functor once per construction.
std::unordered_map< key_type, mapped_type, hasher, key_equal, allocator_type > map_type
A combination of a std::shared_ptr and a std::weak_pointer.
void touch(clock_type::time_point const &now)
clock_type::time_point lastAccess
KeyOnlyEntry(clock_type::time_point const &lastAccess)
clock_type::time_point lastAccess
SharedPointerType lock()
void touch(clock_type::time_point const &now)
shared_weak_combo_pointer_type ptr
ValueEntry(clock_type::time_point const &lastAccess, shared_pointer_type const &ptr)
std::shared_ptr< int > shared_pointer_type
Definition TaggedCache.h:74
std::vector< key_type > getKeys() const
hardened_partitioned_hash_map< key_type, ValueEntry, HardenedHash<>, std::equal_to< uint256 > > KeyValueCacheType
bool del(key_type const &key, bool valid)
bool retrieve(key_type const &key, T &data)
int getTrackSize() const
int getCacheSize() const
bool canonicalizeReplaceClient(key_type const &key, SharedPointerType &data)
Insert the canonical entry for key, keeping any existing cached value.
std::thread sweepHelper(clock_type::time_point const &whenExpire, clock_type::time_point const &now, KeyOnlyCacheType::map_type &partition, SweptPointersVector &, std::atomic< int > &allRemovals, std::scoped_lock< std::recursive_mutex > const &)
bool touchIfExists(KeyComparable const &key)
Refresh the last access time on a key if present.
SharedWeakCachePointer< int > shared_weak_combo_pointer_type
Definition TaggedCache.h:73
beast::AbstractClock< std::chrono::steady_clock > clock_type
Definition TaggedCache.h:72
SharedPointerType fetch(key_type const &digest, Handler const &h)
Fetch an item from the cache.
hardened_partitioned_hash_map< key_type, KeyOnlyEntry, HardenedHash<>, std::equal_to< uint256 > > KeyOnlyCacheType
std::thread sweepHelper(clock_type::time_point const &whenExpire, clock_type::time_point const &now, KeyValueCacheType::map_type &partition, SweptPointersVector &stuffToSweep, std::atomic< int > &allRemovals, std::scoped_lock< std::recursive_mutex > const &)
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::make())
std::conditional_t< std::is_same_v< detail::ReplaceCached, Policy >, std::shared_ptr< int > const &, std::shared_ptr< int > & > CanonicalizeClientPointerType
hardened_partitioned_hash_map< key_type, Entry, HardenedHash<>, std::equal_to< uint256 > > cache_type
bool canonicalizeImpl(key_type const &key, CanonicalizeClientPointerType< Policy > data, Policy policy, Callback &&replaceCallback=nullptr)
Shared implementation of the canonicalize family.
SharedPointerType initialFetch(key_type const &key, std::scoped_lock< mutex_type > const &l)
bool canonicalize(key_type const &key, SharedPointerType &data, Callback &&replaceCallback)
Replace aliased objects with originals.
std::vector< SharedWeakCachePointer< int > > SweptPointersVector
bool canonicalizeReplaceCache(key_type const &key, SharedPointerType const &data)
Insert/update the canonical entry for key, always replacing the cached value with data.
clock_type::duration const targetAge_
SharedPointerType fetch(key_type const &key)
double rate() const
Returns the fraction of cache hits.
std::conditional_t< IsKeyCache, KeyOnlyEntry, ValueEntry > Entry
auto insert(key_type const &key, T const &value) -> ReturnType requires(!IsKeyCache)
Insert the element into the container.
auto insert(key_type const &key) -> ReturnType
mutex_type & peekMutex()
T is_same_v
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition tokens.cpp:140
PartitionedUnorderedMap< Key, Value, Hash, Pred, Allocator > hardened_partitioned_hash_map
Stats(std::string const &prefix, Handler const &handler, beast::insight::Collector::ptr const &collector)
beast::insight::Gauge size
beast::insight::Hook hook
beast::insight::Gauge hitRate