]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/LruMap.h
cert validation cache
[thirdparty/squid.git] / src / base / LruMap.h
CommitLineData
14798e73
CT
1
2/*
3 */
4
5#ifndef SQUID_LRUMAP_H
6#define SQUID_LRUMAP_H
7
8#include "SquidTime.h"
9#if HAVE_LIST
10#include <list>
11#endif
12#if HAVE_MAP
13#include <map>
14#endif
15
16template <class EntryValue, size_t EntryCost = sizeof(EntryValue)> class LruMap
17{
18public:
19 class Entry
20 {
21 public:
22 Entry(const char *aKey, EntryValue *t): key(aKey), value(t), date(squid_curtime) {}
23 ~Entry() {delete value;}
24 private:
25 Entry(LruMap<EntryValue, EntryCost>::Entry &);
26 LruMap<EntryValue, EntryCost>::Entry & operator = (LruMap<EntryValue, EntryCost>::Entry &);
27 public:
28 std::string key; ///< the key of entry
29 EntryValue *value; ///< A pointer to the stored value
30 time_t date; ///< The date the entry created
31 };
32 typedef std::list<Entry *> Queue;
33 typedef typename std::list<Entry *>::iterator QueueIterator;
34
35 /// key:queue_item mapping for fast lookups by key
36 typedef std::map<std::string, QueueIterator> Map;
37 typedef typename Map::iterator MapIterator;
38 typedef std::pair<std::string, QueueIterator> MapPair;
39
40
41 LruMap(int ttl, size_t size);
42 ~LruMap();
43 /// Search for an entry, and return a pointer
44 EntryValue *get(const char *key);
45 /// Add an entry to the map
46 bool add(const char *key, EntryValue *t);
47 /// Delete an entry from the map
48 bool del(const char *key);
49 /// (Re-)set the maximum size for this map
50 void setMemLimit(size_t aSize);
51 /// The available size for the map
52 size_t memLimit() const {return memLimit_;}
53 /// The free space of the map
54 size_t freeMem() const { return (memLimit() - size());}
55 /// The current size of the map
56 size_t size() const {return (entries_ * EntryCost);}
57 /// The number of stored entries
58 int entries() const {return entries_;}
59private:
60 LruMap(LruMap<EntryValue, EntryCost> const &);
61 LruMap<EntryValue, EntryCost> & operator = (LruMap<EntryValue, EntryCost> const &);
62
63 bool expired(Entry &e);
64 void trim();
65 void touch(const MapIterator &i);
66 bool del(const MapIterator &i);
67 void findEntry(const char *key, LruMap::MapIterator &i);
68
69 Map storage; ///< The Key/value * pairs
70 Queue index; ///< LRU cache index
71 int ttl;///< >0 ttl for caching, == 0 cache is disabled, < 0 store for ever
72 size_t memLimit_; ///< The maximum memory to use
73 int entries_; ///< The stored entries
74};
75
76template <class EntryValue, size_t EntryCost>
77LruMap<EntryValue, EntryCost>::LruMap(int aTtl, size_t aSize): entries_(0)
78{
79 ttl = aTtl;
80
81 setMemLimit(aSize);
82}
83
84template <class EntryValue, size_t EntryCost>
85LruMap<EntryValue, EntryCost>::~LruMap()
86{
87 for (QueueIterator i = index.begin(); i != index.end(); ++i) {
88 delete *i;
89 }
90}
91
92template <class EntryValue, size_t EntryCost>
93void
94LruMap<EntryValue, EntryCost>::setMemLimit(size_t aSize)
95{
96 if (aSize > 0)
97 memLimit_ = aSize;
98 else
99 memLimit_ = 0;
100}
101
102template <class EntryValue, size_t EntryCost>
103void
104LruMap<EntryValue, EntryCost>::findEntry(const char *key, LruMap::MapIterator &i)
105{
106 i = storage.find(key);
107 if (i == storage.end()) {
108 return;
109 }
110 index.push_front(*(i->second));
111 index.erase(i->second);
112 i->second = index.begin();
113
114 LruMap::Entry *e = *i->second;
115
116 if (e && expired(*e)) {
117 del(i);
118 e = NULL;
119 }
120}
121
122template <class EntryValue, size_t EntryCost>
123EntryValue *
124LruMap<EntryValue, EntryCost>::get(const char *key)
125{
126 LruMap::MapIterator i;
127 findEntry(key, i);
128 LruMap::Entry *e = *i->second;
129 if (i != storage.end()) {
130 touch(i);
131 return e->value;
132 }
133 return NULL;
134}
135
136template <class EntryValue, size_t EntryCost>
137bool
138LruMap<EntryValue, EntryCost>::add(const char *key, EntryValue *t)
139{
140 if (ttl == 0)
141 return false;
142
143 del(key);
144 trim();
145 index.push_front(new Entry(key, t));
146 storage.insert(MapPair(key, index.begin()));
147
148 ++entries_;
149 return true;
150}
151
152template <class EntryValue, size_t EntryCost>
153bool
154LruMap<EntryValue, EntryCost>::expired(LruMap::Entry &entry)
155{
156 if (ttl < 0)
157 return false;
158
159 return (entry.date + ttl < squid_curtime);
160}
161
162template <class EntryValue, size_t EntryCost>
163bool
164LruMap<EntryValue, EntryCost>::del(LruMap::MapIterator const &i)
165{
166 if (i != storage.end()) {
167 delete *(i->second);
168 index.erase(i->second);
169 storage.erase(i);
170 --entries_;
171 return true;
172 }
173 return false;
174}
175
176template <class EntryValue, size_t EntryCost>
177bool
178LruMap<EntryValue, EntryCost>::del(const char *key)
179{
180 LruMap::MapIterator i;
181 findEntry(key, i);
182 return del(i);
183}
184
185template <class EntryValue, size_t EntryCost>
186void
187LruMap<EntryValue, EntryCost>::trim()
188{
189 while(memLimit() > 0 && size() >= memLimit()) {
190 LruMap::QueueIterator i = index.end();
191 --i;
192 if (i != index.end()) {
193 del((*i)->key.c_str());
194 }
195 }
196}
197
198template <class EntryValue, size_t EntryCost>
199void
200LruMap<EntryValue, EntryCost>::touch(LruMap::MapIterator const &i)
201{
202 // this must not be done when nothing is being cached.
203 if (ttl == 0)
204 return;
205
206 index.push_front(*(i->second));
207 index.erase(i->second);
208 i->second = index.begin();
209}
210
211#endif