TARAXA
Loading...
Searching...
No Matches
cache.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include <map>
5#include <mutex>
6#include <optional>
7#include <shared_mutex>
8#include <unordered_map>
9#include <vector>
10
11namespace taraxa {
12
13// TODO: could it be somehow prettier?
14// partial specialization is not allowed for functions, so make it with structs
15namespace {
16template <class T>
17struct is_empty {
18 is_empty(const T &v) : v_(v) {}
19 operator bool() const { return !v_; }
20 const T &v_;
21};
22template <class T>
23struct is_empty<std::vector<T>> {
24 is_empty(const std::vector<T> &v) : v_(v) {}
25 operator bool() const { return v_.empty(); }
26 const std::vector<T> &v_;
27};
28} // namespace
29
30template <class Key, class Value>
32 public:
33 using GetterFn = std::function<Value(uint64_t, const Key &)>;
34 using ValueMap = std::unordered_map<Key, Value>;
35 using DataMap = std::map<uint64_t, ValueMap>;
36
41
42 MapByBlockCache(uint64_t blocks_to_save, GetterFn &&getter_fn)
43 : kBlocksToKeep(blocks_to_save), getter_fn_(std::move(getter_fn)) {}
44
45 void append(uint64_t block_num, const Key &key, const Value &value) const {
46 std::unique_lock lock(mutex_);
47
48 auto blk_entry = data_by_block_.find(block_num);
49 if (blk_entry == data_by_block_.end()) {
50 blk_entry = data_by_block_.emplace(block_num, ValueMap()).first;
51 }
52 blk_entry->second.emplace(key, value);
53
54 // Remove older element after we added one more
55 if (data_by_block_.size() > kBlocksToKeep) {
56 data_by_block_.erase(data_by_block_.begin());
57 }
58 }
59
60 Value get(uint64_t blk_num, const Key &key) const {
61 {
62 std::shared_lock lock(mutex_);
63 auto blk_entry = data_by_block_.find(blk_num);
64 if (blk_entry != data_by_block_.end()) {
65 auto e = blk_entry->second.find(key);
66 if (e != blk_entry->second.end()) {
67 return e->second;
68 }
69 }
70 }
71
72 auto value = getter_fn_(blk_num, key);
73 if (is_empty(value)) {
74 return {};
75 }
76 // Not save old values in cache
77 auto last_num = lastBlockNum();
78 if (last_num < kBlocksToKeep || blk_num >= last_num - kBlocksToKeep) {
79 append(blk_num, key, value);
80 }
81 return value;
82 }
83
84 uint64_t lastBlockNum() const {
85 std::shared_lock lock(mutex_);
86 if (data_by_block_.empty()) {
87 return 0;
88 }
89 return data_by_block_.rbegin()->first;
90 }
91
92 protected:
93 const uint64_t kBlocksToKeep;
95
96 // cache is used from const methods in other class, so should be mutable
97 mutable std::shared_mutex mutex_;
99};
100
101template <class Value>
103 public:
104 using GetterFn = std::function<Value(uint64_t)>;
105 using DataMap = std::map<uint64_t, Value>;
106
111
112 ValueByBlockCache(uint64_t blocks_to_save, GetterFn &&getter_fn)
113 : kBlocksToKeep(blocks_to_save), getter_fn_(std::move(getter_fn)) {}
114
115 void append(uint64_t block_num, Value value) const {
116 std::unique_lock lock(mutex_);
117 data_by_block_.emplace(block_num, value);
118
119 // Remove older element after we added one more
120 if (data_by_block_.size() > kBlocksToKeep) {
121 data_by_block_.erase(data_by_block_.begin());
122 }
123 }
124
125 std::optional<Value> getFromCache(uint64_t block_num) const {
126 std::shared_lock lock(mutex_);
127 auto blk_entry = data_by_block_.find(block_num);
128 if (blk_entry != data_by_block_.end()) {
129 return blk_entry->second;
130 }
131 return {};
132 }
133
134 Value get(uint64_t block_num) const {
135 auto blk_entry = getFromCache(block_num);
136 if (blk_entry) {
137 return *blk_entry;
138 }
139
140 auto value = getter_fn_(block_num);
141 if (is_empty(value)) {
142 return {};
143 }
144 // Not save old values in cache
145 auto last_num = lastBlockNum();
146 if (last_num < kBlocksToKeep || block_num >= last_num - kBlocksToKeep) {
147 append(block_num, value);
148 }
149 return value;
150 }
151
152 Value last() const {
153 std::shared_lock lock(mutex_);
154 if (data_by_block_.empty()) {
155 return {};
156 }
157 return data_by_block_.rbegin()->second;
158 }
159
160 uint64_t lastBlockNum() const {
161 std::shared_lock lock(mutex_);
162 if (data_by_block_.empty()) {
163 return 0;
164 }
165 return data_by_block_.rbegin()->first;
166 }
167
168 protected:
169 const uint64_t kBlocksToKeep;
171
172 // cache is used from const methods in other class, so should be mutable
173 mutable std::shared_mutex mutex_;
175};
176
177} // namespace taraxa
Definition cache.hpp:31
Value get(uint64_t blk_num, const Key &key) const
Definition cache.hpp:60
const uint64_t kBlocksToKeep
Definition cache.hpp:93
MapByBlockCache & operator=(MapByBlockCache &&)=delete
std::map< uint64_t, ValueMap > DataMap
Definition cache.hpp:35
DataMap data_by_block_
Definition cache.hpp:98
MapByBlockCache & operator=(const MapByBlockCache &)=delete
MapByBlockCache(uint64_t blocks_to_save, GetterFn &&getter_fn)
Definition cache.hpp:42
std::unordered_map< Key, Value > ValueMap
Definition cache.hpp:34
std::shared_mutex mutex_
Definition cache.hpp:97
std::function< Value(uint64_t, const Key &)> GetterFn
Definition cache.hpp:33
void append(uint64_t block_num, const Key &key, const Value &value) const
Definition cache.hpp:45
MapByBlockCache(MapByBlockCache &&)=delete
uint64_t lastBlockNum() const
Definition cache.hpp:84
GetterFn getter_fn_
Definition cache.hpp:94
MapByBlockCache(const MapByBlockCache &)=delete
Definition cache.hpp:102
Value get(uint64_t block_num) const
Definition cache.hpp:134
std::shared_mutex mutex_
Definition cache.hpp:173
ValueByBlockCache(uint64_t blocks_to_save, GetterFn &&getter_fn)
Definition cache.hpp:112
const uint64_t kBlocksToKeep
Definition cache.hpp:169
std::map< uint64_t, Value > DataMap
Definition cache.hpp:105
ValueByBlockCache(const ValueByBlockCache &)=delete
uint64_t lastBlockNum() const
Definition cache.hpp:160
void append(uint64_t block_num, Value value) const
Definition cache.hpp:115
Value last() const
Definition cache.hpp:152
std::function< Value(uint64_t)> GetterFn
Definition cache.hpp:104
ValueByBlockCache(ValueByBlockCache &&)=delete
ValueByBlockCache & operator=(const ValueByBlockCache &)=delete
GetterFn getter_fn_
Definition cache.hpp:170
std::optional< Value > getFromCache(uint64_t block_num) const
Definition cache.hpp:125
ValueByBlockCache & operator=(ValueByBlockCache &&)=delete
DataMap data_by_block_
Definition cache.hpp:174
std::hash for asio::adress
Definition FixedHash.h:483
Definition app.hpp:16