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