]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/LruMap.h
POrtability: use 64-bit for X-Cache-Age header
[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"
074d6a40 9
14798e73 10#include <list>
14798e73 11#include <map>
14798e73
CT
12
13template <class EntryValue, size_t EntryCost = sizeof(EntryValue)> class LruMap
14{
15public:
16 class Entry
17 {
18 public:
19 Entry(const char *aKey, EntryValue *t): key(aKey), value(t), date(squid_curtime) {}
20 ~Entry() {delete value;}
21 private:
a70d5f19
CT
22 Entry(Entry &);
23 Entry & operator = (Entry &);
14798e73
CT
24 public:
25 std::string key; ///< the key of entry
26 EntryValue *value; ///< A pointer to the stored value
27 time_t date; ///< The date the entry created
28 };
29 typedef std::list<Entry *> Queue;
30 typedef typename std::list<Entry *>::iterator QueueIterator;
4c304fb9 31
14798e73
CT
32 /// key:queue_item mapping for fast lookups by key
33 typedef std::map<std::string, QueueIterator> Map;
34 typedef typename Map::iterator MapIterator;
35 typedef std::pair<std::string, QueueIterator> MapPair;
36
14798e73
CT
37 LruMap(int ttl, size_t size);
38 ~LruMap();
39 /// Search for an entry, and return a pointer
40 EntryValue *get(const char *key);
41 /// Add an entry to the map
42 bool add(const char *key, EntryValue *t);
43 /// Delete an entry from the map
44 bool del(const char *key);
45 /// (Re-)set the maximum size for this map
46 void setMemLimit(size_t aSize);
47 /// The available size for the map
48 size_t memLimit() const {return memLimit_;}
49 /// The free space of the map
9873e378 50 size_t freeMem() const { return (memLimit() > size() ? memLimit() - size() : 0);}
14798e73
CT
51 /// The current size of the map
52 size_t size() const {return (entries_ * EntryCost);}
53 /// The number of stored entries
54 int entries() const {return entries_;}
55private:
a70d5f19
CT
56 LruMap(LruMap const &);
57 LruMap & operator = (LruMap const &);
4c304fb9 58
0cef2d4b 59 bool expired(const Entry &e) const;
14798e73
CT
60 void trim();
61 void touch(const MapIterator &i);
62 bool del(const MapIterator &i);
63 void findEntry(const char *key, LruMap::MapIterator &i);
64
65 Map storage; ///< The Key/value * pairs
66 Queue index; ///< LRU cache index
67 int ttl;///< >0 ttl for caching, == 0 cache is disabled, < 0 store for ever
68 size_t memLimit_; ///< The maximum memory to use
69 int entries_; ///< The stored entries
70};
71
72template <class EntryValue, size_t EntryCost>
73LruMap<EntryValue, EntryCost>::LruMap(int aTtl, size_t aSize): entries_(0)
74{
75 ttl = aTtl;
76
77 setMemLimit(aSize);
78}
79
80template <class EntryValue, size_t EntryCost>
81LruMap<EntryValue, EntryCost>::~LruMap()
82{
83 for (QueueIterator i = index.begin(); i != index.end(); ++i) {
84 delete *i;
85 }
86}
87
88template <class EntryValue, size_t EntryCost>
89void
90LruMap<EntryValue, EntryCost>::setMemLimit(size_t aSize)
91{
92 if (aSize > 0)
93 memLimit_ = aSize;
94 else
95 memLimit_ = 0;
96}
97
98template <class EntryValue, size_t EntryCost>
99void
100LruMap<EntryValue, EntryCost>::findEntry(const char *key, LruMap::MapIterator &i)
101{
102 i = storage.find(key);
103 if (i == storage.end()) {
104 return;
105 }
106 index.push_front(*(i->second));
107 index.erase(i->second);
108 i->second = index.begin();
4c304fb9 109
0cef2d4b
CT
110 if (const Entry *e = *i->second) {
111 if (!expired(*e))
112 return;
113 // else fall through to cleanup
14798e73 114 }
0cef2d4b
CT
115
116 del(i);
117 i = storage.end();
14798e73
CT
118}
119
120template <class EntryValue, size_t EntryCost>
121EntryValue *
122LruMap<EntryValue, EntryCost>::get(const char *key)
123{
9aea094e 124 MapIterator i;
14798e73 125 findEntry(key, i);
14798e73
CT
126 if (i != storage.end()) {
127 touch(i);
0cef2d4b 128 Entry *e = *i->second;
14798e73
CT
129 return e->value;
130 }
131 return NULL;
132}
133
134template <class EntryValue, size_t EntryCost>
135bool
136LruMap<EntryValue, EntryCost>::add(const char *key, EntryValue *t)
137{
138 if (ttl == 0)
139 return false;
140
141 del(key);
142 trim();
143 index.push_front(new Entry(key, t));
144 storage.insert(MapPair(key, index.begin()));
145
146 ++entries_;
147 return true;
148}
149
150template <class EntryValue, size_t EntryCost>
151bool
0cef2d4b 152LruMap<EntryValue, EntryCost>::expired(const LruMap::Entry &entry) const
14798e73
CT
153{
154 if (ttl < 0)
155 return false;
156
157 return (entry.date + ttl < squid_curtime);
158}
159
160template <class EntryValue, size_t EntryCost>
161bool
162LruMap<EntryValue, EntryCost>::del(LruMap::MapIterator const &i)
163{
4c304fb9 164 if (i != storage.end()) {
e5ec7440 165 Entry *e = *i->second;
14798e73
CT
166 index.erase(i->second);
167 storage.erase(i);
0cef2d4b 168 delete e;
14798e73
CT
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