ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
CircuitCache.h
Go to the documentation of this file.
1/**
2 * @file CircuitCache.h
3 * @brief LRU in-process cache for recently created provenance circuit gates.
4 *
5 * Reading gates from the mmap-backed persistent storage is relatively
6 * expensive. The @c CircuitCache stores the most recently created gates
7 * in an in-memory Boost multi-index container so that subsequent lookups
8 * within the same backend can skip the IPC round-trip to the background
9 * worker.
10 *
11 * The cache is bounded by a fixed byte budget. When inserting a new
12 * gate would exceed the budget the oldest entry (FIFO order) is
13 * evicted. Eviction simply drops the entry: the cache is a read
14 * accelerator on top of a write-through design (every @c create_gate
15 * goes to the worker via IPC regardless of cache state, see
16 * @c provsql_mmap.c), so the worker already holds every gate the cache
17 * ever did and no flush hook is required.
18 *
19 * The C-linkage wrapper functions in @c circuit_cache.h provide the
20 * interface used by the C portions of the extension.
21 */
22#ifndef CIRCUIT_CACHE_CPP_H
23#define CIRCUIT_CACHE_CPP_H
24
25#include "provsql_utils_cpp.h"
26
27#include <optional>
28#include <utility>
29#include <vector>
30
31#include <boost/multi_index_container.hpp>
32#include <boost/multi_index/hashed_index.hpp>
33#include <boost/multi_index/member.hpp>
34#include <boost/multi_index/sequenced_index.hpp>
35
36using namespace boost::multi_index;
37
38/**
39 * @brief All information stored for a single gate in the circuit cache.
40 *
41 * Each cache entry tracks the gate's UUID token, its type, and the list
42 * of its children (also as UUIDs).
43 */
45{
46 pg_uuid_t token; ///< UUID identifying this gate
47 gate_type type; ///< Kind of gate (input, plus, times, …)
48 std::vector<pg_uuid_t> children; ///< Ordered list of child gate UUIDs
49
50 /**
51 * @brief Estimated memory footprint of this entry in bytes.
52 *
53 * Used by @c CircuitCache to track the total size of the cache so that
54 * it can enforce its byte budget.
55 *
56 * @return Size of @c CircuitCacheInfos plus the children array.
57 */
58 inline unsigned size() const {
59 return sizeof(CircuitCacheInfos)+children.size()*sizeof(pg_uuid_t);
60 }
61};
62
63/**
64 * @brief Bounded LRU cache mapping gate UUIDs to their @c CircuitCacheInfos.
65 *
66 * Internally a Boost @c multi_index_container provides two views of the
67 * same data:
68 * - A sequenced (insertion-order) index used to evict the oldest entry
69 * when the cache is full.
70 * - A hashed-unique index keyed on @c token for O(1) lookup.
71 *
72 * The cache is not thread-safe; each backend process maintains its own
73 * instance.
74 */
76{
77/** @brief Boost multi-index container type for cache entries. */
78typedef multi_index_container<
80 indexed_by<
81 sequenced<>,
82 hashed_unique<member<CircuitCacheInfos, pg_uuid_t, &CircuitCacheInfos::token> >
83 >
85item_list il; ///< The container holding cached entries
86unsigned current_size; ///< Current total byte usage of cached entries
87
88public:
89/** @brief The value type stored in the cache. */
91/** @brief Iterator type for iterating over cache entries in FIFO order. */
92typedef typename item_list::iterator iterator;
93
94/** @brief Construct an empty cache. */
97
98/**
99 * @brief Insert a new gate into the cache, evicting the oldest if necessary.
100 *
101 * If @p infos.token is already present in the cache the existing entry
102 * is bumped to the LRU front and, when @p infos carries strictly more
103 * information than the existing entry (a real @c gate_type replacing a
104 * stored @c gate_invalid placeholder, or a non-empty children list
105 * replacing an empty one), its contents are overwritten in place.
106 * Otherwise the entry is added and, if the cache then exceeds its size
107 * budget, the oldest entry (FIFO tail) is removed.
108 *
109 * @param infos Gate information to cache.
110 * @return @c true if the entry was newly inserted, @c false if it was
111 * already present (regardless of whether it was upgraded).
112 */
113bool insert(const CircuitCacheInfos& infos);
114
115/**
116 * @brief Look up a gate by UUID.
117 *
118 * @param token UUID of the gate to find.
119 * @return An @c std::optional containing the @c CircuitCacheInfos if
120 * found, or @c std::nullopt on a cache miss.
121 */
122std::optional<CircuitCacheInfos> get(pg_uuid_t token) const;
123
124/**
125 * @brief Iterator to the first cached entry (oldest).
126 * @return Iterator pointing to the oldest cache entry.
127 */
129 return il.begin();
130}
131/**
132 * @brief Past-the-end iterator for the cache.
133 * @return Iterator one past the last cache entry.
134 */
135inline iterator end(){
136 return il.end();
137}
138};
139
140#endif /* CIRCUIT_CACHE_CPP_H */
CircuitCache()
Construct an empty cache.
multi_index_container< CircuitCacheInfos, indexed_by< sequenced<>, hashed_unique< member< CircuitCacheInfos, pg_uuid_t, &CircuitCacheInfos::token > > > > item_list
Boost multi-index container type for cache entries.
item_list il
The container holding cached entries.
item_list::iterator iterator
Iterator type for iterating over cache entries in FIFO order.
unsigned current_size
Current total byte usage of cached entries.
CircuitCacheInfos item_type
The value type stored in the cache.
iterator end()
Past-the-end iterator for the cache.
iterator begin()
Iterator to the first cached entry (oldest).
bool insert(const CircuitCacheInfos &infos)
Insert a new gate into the cache, evicting the oldest if necessary.
std::optional< CircuitCacheInfos > get(pg_uuid_t token) const
Look up a gate by UUID.
C++ utility functions for UUID manipulation.
All information stored for a single gate in the circuit cache.
std::vector< pg_uuid_t > children
Ordered list of child gate UUIDs.
unsigned size() const
Estimated memory footprint of this entry in bytes.
gate_type type
Kind of gate (input, plus, times, …).
pg_uuid_t token
UUID identifying this gate.
UUID structure.