diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/mgr/TTLCache.h | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/mgr/TTLCache.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/mgr/TTLCache.h b/src/mgr/TTLCache.h new file mode 100644 index 000000000..a6d5ddf2e --- /dev/null +++ b/src/mgr/TTLCache.h @@ -0,0 +1,124 @@ +#pragma once + +#include <atomic> +#include <chrono> +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "PyUtil.h" + +using namespace std; + +template <class Key, class Value> class Cache { + private: + std::atomic<uint64_t> hits, misses; + + protected: + unsigned int capacity; + Cache(unsigned int size = UINT16_MAX) : hits{0}, misses{0}, capacity{size} {}; + std::map<Key, Value> content; + std::vector<string> allowed_keys = {"osd_map", "pg_dump", "pg_stats"}; + + void mark_miss() { + misses++; + } + + void mark_hit() { + hits++; + } + + unsigned int get_misses() { return misses; } + unsigned int get_hits() { return hits; } + void throw_key_not_found(Key key) { + std::stringstream ss; + ss << "Key " << key << " couldn't be found\n"; + throw std::out_of_range(ss.str()); + } + + public: + void insert(Key key, Value value) { + mark_miss(); + if (content.size() < capacity) { + content.insert({key, value}); + } + } + Value get(Key key, bool count_hit = true) { + if (count_hit) { + mark_hit(); + } + return content[key]; + } + void erase(Key key) { content.erase(content.find(key)); } + void clear() { content.clear(); } + bool exists(Key key) { return content.find(key) != content.end(); } + std::pair<uint64_t, uint64_t> get_hit_miss_ratio() { + return std::make_pair(hits.load(), misses.load()); + } + bool is_cacheable(Key key) { + for (auto k : allowed_keys) { + if (key == k) return true; + } + return false; + } + int size() { return content.size(); } + + ~Cache(){}; +}; + +using ttl_time_point = std::chrono::time_point<std::chrono::steady_clock>; +template <class Key, class Value> +class TTLCacheBase : public Cache<Key, std::pair<Value, ttl_time_point>> { + private: + uint16_t ttl; + float ttl_spread_ratio; + using value_type = std::pair<Value, ttl_time_point>; + using cache = Cache<Key, value_type>; + + protected: + Value get_value(Key key, bool count_hit = true); + ttl_time_point get_value_time_point(Key key); + bool exists(Key key); + bool expired(Key key); + void finish_get(Key key); + void finish_erase(Key key); + void throw_key_not_found(Key key); + + public: + TTLCacheBase(uint16_t ttl_ = 0, uint16_t size = UINT16_MAX, + float spread = 0.25) + : Cache<Key, value_type>(size), ttl{ttl_}, ttl_spread_ratio{spread} {} + ~TTLCacheBase(){}; + void insert(Key key, Value value); + Value get(Key key); + void erase(Key key); + void clear(); + uint16_t get_ttl() { return ttl; }; + void set_ttl(uint16_t ttl); +}; + +template <class Key, class Value> +class TTLCache : public TTLCacheBase<Key, Value> { + public: + TTLCache(uint16_t ttl_ = 0, uint16_t size = UINT16_MAX, float spread = 0.25) + : TTLCacheBase<Key, Value>(ttl_, size, spread) {} + ~TTLCache(){}; +}; + +template <class Key> +class TTLCache<Key, PyObject*> : public TTLCacheBase<Key, PyObject*> { + public: + TTLCache(uint16_t ttl_ = 0, uint16_t size = UINT16_MAX, float spread = 0.25) + : TTLCacheBase<Key, PyObject*>(ttl_, size, spread) {} + ~TTLCache(){}; + PyObject* get(Key key); + void erase(Key key); + + private: + using ttl_base = TTLCacheBase<Key, PyObject*>; +}; + +#include "TTLCache.cc" + |