9#ifndef SQUID__SRC_BASE_CLPMAP_H
10#define SQUID__SRC_BASE_CLPMAP_H
20#include <unordered_map>
39template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &) = DefaultMemoryUsage>
53 Entry(
const Key &,
const Value &,
const Ttl);
66 using Entries = std::list<Entry, PoolingAllocator<Entry> >;
71 ClpMap(uint64_t capacity,
Ttl defaultTtl);
83 const Value *
get(
const Key &);
88 bool add(
const Key &,
const Value &,
Ttl);
94 void del(
const Key &);
121 using IndexItem = std::pair<const Key, EntriesIterator>;
126 static std::optional<uint64_t>
MemoryCountedFor(
const Key &,
const Value &);
128 void trim(uint64_t wantSpace);
148template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
150 defaultTtl_(defaultTtl)
156template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
160 if (memUsed_ > newLimit)
161 trim(memLimit_ - newLimit);
162 memLimit_ = newLimit;
166template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
170 const auto i = index_.find(key);
171 if (i == index_.end())
174 const auto entryPosition = i->second;
175 if (!entryPosition->expired()) {
176 if (entryPosition != entries_.begin())
177 entries_.splice(entries_.begin(), entries_, entryPosition);
186template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
190 const auto i = find(key);
191 if (i != index_.end()) {
192 const auto &entry = *(i->second);
198template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
199std::optional<uint64_t>
206 const auto keySz = k.length();
209 return NaturalSum<uint64_t>(
212 sizeof(
typename Entries::value_type),
215 sizeof(
typename Index::value_type));
218template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
231 const auto memoryRequirements = MemoryCountedFor(key, v);
232 if (!memoryRequirements)
235 const auto wantSpace = memoryRequirements.value();
236 if (wantSpace > memLimit() || wantSpace == 0)
240 auto &
addedEntry = entries_.emplace_front(key, v, ttl);
241 index_.emplace(key, entries_.begin());
244 memUsed_ += wantSpace;
245 assert(memUsed_ >= wantSpace);
250template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
254 assert(i != index_.end());
255 const auto entryPosition = i->second;
257 assert(entryPosition != entries_.end());
258 const auto sz = entryPosition->memCounted;
263 entries_.erase(entryPosition);
266template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
270 const auto i = find(key);
271 if (i != index_.end())
276template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
280 assert(wantSpace <= memLimit());
281 while (freeMem() < wantSpace) {
282 assert(!entries_.empty());
285 del(entries_.rbegin()->key);
289template <
class Key,
class Value, u
int64_t MemoryUsedBy(const Value &)>
uint64_t DefaultMemoryUsage(const Value &e)
static char const * trim(char const *s)
S SetToNaturalSumOrMax(S &var, const Args... args)
the keeper of cache entry Key, Value, and caching-related entry metadata
bool expired() const
whether the entry is stale
Value value
cached value provided by the map user
time_t expires
get() stops returning the entry after this time
uint64_t memCounted
memory accounted for this entry in our ClpMap
Key key
the entry search key; see ClpMap::get()
Entry(const Key &, const Value &, const Ttl)
ConstEntriesIterator cbegin() const
const Value * get(const Key &)
std::pair< const Key, EntriesIterator > IndexItem
ClpMap(const ClpMap &)=delete
ConstEntriesIterator end() const
ClpMap(const uint64_t capacity)
void del(const Key &)
Remove the corresponding entry (if any)
void trim(uint64_t wantSpace)
purges entries to make free memory large enough to fit wantSpace bytes
typename Entries::iterator EntriesIterator
uint64_t memLimit() const
The memory capacity for the map.
uint64_t freeMem() const
The free space of the map.
ClpMap & operator=(const ClpMap &)=delete
Ttl defaultTtl_
entry TTL to use if none provided to add()
typename Index::iterator IndexIterator
uint64_t memUsed_
the total amount of memory we currently use for all cached entries
void erase(const IndexIterator &)
removes the cached entry (identified by its index) from the map
Index index_
entries_ positions indexed by the entry key
static std::optional< uint64_t > MemoryCountedFor(const Key &, const Value &)
uint64_t memLimit_
the maximum memory we are allowed to use for all cached entries
IndexIterator find(const Key &)
std::unordered_map< Key, EntriesIterator, std::hash< Key >, std::equal_to< Key >, PoolingAllocator< IndexItem > > Index
key:entry_position mapping for fast entry lookups by key
int Ttl
maximum desired entry caching duration (a.k.a. TTL), in seconds
typename Entries::const_iterator ConstEntriesIterator
ConstEntriesIterator begin() const
range-based for loop support;
void setMemLimit(uint64_t newLimit)
Reset the memory capacity for this map, purging if needed.
size_t entries() const
The number of currently stored entries, including expired ones.
bool add(const Key &, const Value &, Ttl)
ConstEntriesIterator cend() const
uint64_t memoryUsed() const
The current (approximate) memory usage of the map.
Entries entries_
cached entries, including expired ones, in LRU order
std::list< Entry, PoolingAllocator< Entry > > Entries
Entries in LRU order.
bool add(const Key &key, const Value &v)
Copy the given value into the map (with the given key and default TTL)
STL Allocator that uses Squid memory pools for memory management.
A const & max(A const &lhs, A const &rhs)
static StoreEntry * addedEntry(Store::Disk *aStore, String name, String, String)