]> git.ipfire.org Git - thirdparty/squid.git/blame - src/repl/lru/store_repl_lru.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / repl / lru / store_repl_lru.cc
CommitLineData
6a566b9c 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
6a566b9c 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
6a566b9c 7 */
8
bbc27441
AJ
9/* DEBUG: none LRU Removal Policy */
10
582c2af2 11#include "squid.h"
528b2c61 12#include "MemObject.h"
985c86bc 13#include "SquidTime.h"
602d9612 14#include "Store.h"
6a566b9c 15
ed6e9fb9
AJ
16/* because LruNode use explicit memory alloc()/freeOne() calls.
17 * XXX: convert to MEMPROXY_CLASS() API
18 */
19#include "mem/Pool.h"
20
6a566b9c 21REMOVALPOLICYCREATE createRemovalPolicy_lru;
22
26ac0430 23struct LruPolicyData {
e6ccf245 24 void setPolicyNode (StoreEntry *, void *) const;
6a566b9c 25 RemovalPolicy *policy;
26 dlink_list list;
27 int count;
28 int nwalkers;
9f913cf1 29 enum heap_entry_type {
62e76326 30 TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
9f913cf1 31 } type;
6a566b9c 32};
33
34/* Hack to avoid having to remember the RemovalPolicyNode location.
35 * Needed by the purge walker to clear the policy information
36 */
e6ccf245 37static enum LruPolicyData::heap_entry_type
6a566b9c 38repl_guessType(StoreEntry * entry, RemovalPolicyNode * node)
39{
40 if (node == &entry->repl)
62e76326 41 return LruPolicyData::TYPE_STORE_ENTRY;
42
6a566b9c 43 if (entry->mem_obj && node == &entry->mem_obj->repl)
62e76326 44 return LruPolicyData::TYPE_STORE_MEM;
45
6a566b9c 46 fatal("Heap Replacement: Unknown StoreEntry node type");
62e76326 47
e6ccf245 48 return LruPolicyData::TYPE_UNKNOWN;
6a566b9c 49}
e6ccf245 50
51void
52LruPolicyData::setPolicyNode (StoreEntry *entry, void *value) const
53{
54 switch (type) {
62e76326 55
56 case TYPE_STORE_ENTRY:
57 entry->repl.data = value;
58 break ;
59
60 case TYPE_STORE_MEM:
61 entry->mem_obj->repl.data = value ;
62 break ;
63
64 default:
65 break;
6a566b9c 66 }
e6ccf245 67}
6a566b9c 68
69typedef struct _LruNode LruNode;
62e76326 70
26ac0430 71struct _LruNode {
6a566b9c 72 /* Note: the dlink_node MUST be the first member of the LruNode
73 * structure. This member is later pointer typecasted to LruNode *.
74 */
75 dlink_node node;
76};
77
04eb0689 78static MemAllocator *lru_node_pool = NULL;
6a566b9c 79static int nr_lru_policies = 0;
80
81static void
82lru_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
83{
e6ccf245 84 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 85 LruNode *lru_node;
86 assert(!node->data);
b001e822 87 node->data = lru_node = (LruNode *)lru_node_pool->alloc();
6a566b9c 88 dlinkAddTail(entry, &lru_node->node, &lru->list);
89 lru->count += 1;
62e76326 90
6a566b9c 91 if (!lru->type)
62e76326 92 lru->type = repl_guessType(entry, node);
6a566b9c 93}
94
95static void
96lru_remove(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
97{
e6ccf245 98 LruPolicyData *lru = (LruPolicyData *)policy->_data;
99 LruNode *lru_node = (LruNode *)node->data;
62e76326 100
6a566b9c 101 if (!lru_node)
62e76326 102 return;
103
75240ca9 104 /*
105 * It seems to be possible for an entry to exist in the hash
106 * but not be in the LRU list, so check for that case rather
107 * than suffer a NULL pointer access.
108 */
109 if (NULL == lru_node->node.data)
62e76326 110 return;
111
6a566b9c 112 assert(lru_node->node.data == entry);
62e76326 113
6a566b9c 114 node->data = NULL;
62e76326 115
6a566b9c 116 dlinkDelete(&lru_node->node, &lru->list);
62e76326 117
dc47f531 118 lru_node_pool->freeOne(lru_node);
62e76326 119
6a566b9c 120 lru->count -= 1;
121}
122
123static void
124lru_referenced(RemovalPolicy * policy, const StoreEntry * entry,
62e76326 125 RemovalPolicyNode * node)
6a566b9c 126{
e6ccf245 127 LruPolicyData *lru = (LruPolicyData *)policy->_data;
128 LruNode *lru_node = (LruNode *)node->data;
62e76326 129
6a566b9c 130 if (!lru_node)
62e76326 131 return;
132
6a566b9c 133 dlinkDelete(&lru_node->node, &lru->list);
62e76326 134
6a566b9c 135 dlinkAddTail((void *) entry, &lru_node->node, &lru->list);
136}
137
138/** RemovalPolicyWalker **/
139
140typedef struct _LruWalkData LruWalkData;
62e76326 141
26ac0430 142struct _LruWalkData {
6a566b9c 143 LruNode *current;
144};
145
2d72d4fd 146static const StoreEntry *
6a566b9c 147lru_walkNext(RemovalPolicyWalker * walker)
148{
e6ccf245 149 LruWalkData *lru_walk = (LruWalkData *)walker->_data;
6a566b9c 150 LruNode *lru_node = lru_walk->current;
62e76326 151
6a566b9c 152 if (!lru_node)
62e76326 153 return NULL;
154
6a566b9c 155 lru_walk->current = (LruNode *) lru_node->node.next;
62e76326 156
6a566b9c 157 return (StoreEntry *) lru_node->node.data;
158}
159
160static void
161lru_walkDone(RemovalPolicyWalker * walker)
162{
163 RemovalPolicy *policy = walker->_policy;
e6ccf245 164 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 165 assert(strcmp(policy->_type, "lru") == 0);
166 assert(lru->nwalkers > 0);
167 lru->nwalkers -= 1;
168 safe_free(walker->_data);
aa839030 169 delete walker;
6a566b9c 170}
171
172static RemovalPolicyWalker *
173lru_walkInit(RemovalPolicy * policy)
174{
e6ccf245 175 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 176 RemovalPolicyWalker *walker;
177 LruWalkData *lru_walk;
178 lru->nwalkers += 1;
aa839030 179 walker = new RemovalPolicyWalker;
e6ccf245 180 lru_walk = (LruWalkData *)xcalloc(1, sizeof(*lru_walk));
6a566b9c 181 walker->_policy = policy;
182 walker->_data = lru_walk;
183 walker->Next = lru_walkNext;
184 walker->Done = lru_walkDone;
185 lru_walk->current = (LruNode *) lru->list.head;
6a566b9c 186 return walker;
187}
188
189/** RemovalPurgeWalker **/
190
191typedef struct _LruPurgeData LruPurgeData;
62e76326 192
26ac0430 193struct _LruPurgeData {
6a566b9c 194 LruNode *current;
195 LruNode *start;
196};
197
198static StoreEntry *
199lru_purgeNext(RemovalPurgeWalker * walker)
200{
e6ccf245 201 LruPurgeData *lru_walker = (LruPurgeData *)walker->_data;
6a566b9c 202 RemovalPolicy *policy = walker->_policy;
e6ccf245 203 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 204 LruNode *lru_node;
205 StoreEntry *entry;
62e76326 206
207try_again:
6a566b9c 208 lru_node = lru_walker->current;
62e76326 209
6a566b9c 210 if (!lru_node || walker->scanned >= walker->max_scan)
62e76326 211 return NULL;
212
6a566b9c 213 walker->scanned += 1;
62e76326 214
6a566b9c 215 lru_walker->current = (LruNode *) lru_node->node.next;
62e76326 216
6a566b9c 217 if (lru_walker->current == lru_walker->start) {
62e76326 218 /* Last node found */
219 lru_walker->current = NULL;
6a566b9c 220 }
62e76326 221
6a566b9c 222 entry = (StoreEntry *) lru_node->node.data;
223 dlinkDelete(&lru_node->node, &lru->list);
62e76326 224
3900307b 225 if (entry->locked()) {
62e76326 226 /* Shit, it is locked. we can't return this one */
d7ae3534 227 ++ walker->locked;
62e76326 228 dlinkAddTail(entry, &lru_node->node, &lru->list);
229 goto try_again;
6a566b9c 230 }
62e76326 231
dc47f531 232 lru_node_pool->freeOne(lru_node);
6a566b9c 233 lru->count -= 1;
e6ccf245 234 lru->setPolicyNode(entry, NULL);
6a566b9c 235 return entry;
236}
237
238static void
239lru_purgeDone(RemovalPurgeWalker * walker)
240{
241 RemovalPolicy *policy = walker->_policy;
e6ccf245 242 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 243 assert(strcmp(policy->_type, "lru") == 0);
244 assert(lru->nwalkers > 0);
245 lru->nwalkers -= 1;
246 safe_free(walker->_data);
aa839030 247 delete walker;
6a566b9c 248}
249
250static RemovalPurgeWalker *
251lru_purgeInit(RemovalPolicy * policy, int max_scan)
252{
e6ccf245 253 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 254 RemovalPurgeWalker *walker;
255 LruPurgeData *lru_walk;
256 lru->nwalkers += 1;
aa839030 257 walker = new RemovalPurgeWalker;
e6ccf245 258 lru_walk = (LruPurgeData *)xcalloc(1, sizeof(*lru_walk));
6a566b9c 259 walker->_policy = policy;
260 walker->_data = lru_walk;
261 walker->max_scan = max_scan;
262 walker->Next = lru_purgeNext;
263 walker->Done = lru_purgeDone;
264 lru_walk->start = lru_walk->current = (LruNode *) lru->list.head;
6a566b9c 265 return walker;
266}
267
8a3e7d9e 268static void
269lru_stats(RemovalPolicy * policy, StoreEntry * sentry)
270{
e6ccf245 271 LruPolicyData *lru = (LruPolicyData *)policy->_data;
b671cc68 272 LruNode *lru_node = (LruNode *) lru->list.head;
8a3e7d9e 273
62e76326 274again:
275
8a3e7d9e 276 if (lru_node) {
62e76326 277 StoreEntry *entry = (StoreEntry *) lru_node->node.data;
278
3900307b 279 if (entry->locked()) {
62e76326 280 lru_node = (LruNode *) lru_node->node.next;
281 goto again;
282 }
283
284 storeAppendPrintf(sentry, "LRU reference age: %.2f days\n", (double) (squid_curtime - entry->lastref) / (double) (24 * 60 * 60));
8a3e7d9e 285 }
286}
287
6a566b9c 288static void
289lru_free(RemovalPolicy * policy)
290{
e6ccf245 291 LruPolicyData *lru = (LruPolicyData *)policy->_data;
6a566b9c 292 /* Make some verification of the policy state */
293 assert(strcmp(policy->_type, "lru") == 0);
294 assert(lru->nwalkers);
295 assert(lru->count);
296 /* Ok, time to destroy this policy */
e4a67a80 297 safe_free(lru);
6a566b9c 298 memset(policy, 0, sizeof(*policy));
aa839030 299 delete policy;
6a566b9c 300}
301
302RemovalPolicy *
9f913cf1 303createRemovalPolicy_lru(wordlist * args)
6a566b9c 304{
305 RemovalPolicy *policy;
306 LruPolicyData *lru_data;
307 /* no arguments expected or understood */
308 assert(!args);
309 /* Initialize */
62e76326 310
d96ceb8e 311 if (!lru_node_pool) {
b001e822 312 /* Must be chunked */
04eb0689 313 lru_node_pool = memPoolCreate("LRU policy node", sizeof(LruNode));
b001e822 314 lru_node_pool->setChunkSize(512 * 1024);
d96ceb8e 315 }
62e76326 316
6a566b9c 317 /* Allocate the needed structures */
e6ccf245 318 lru_data = (LruPolicyData *)xcalloc(1, sizeof(*lru_data));
62e76326 319
aa839030 320 policy = new RemovalPolicy;
62e76326 321
6a566b9c 322 /* Initialize the URL data */
323 lru_data->policy = policy;
62e76326 324
6a566b9c 325 /* Populate the policy structure */
326 policy->_type = "lru";
62e76326 327
6a566b9c 328 policy->_data = lru_data;
62e76326 329
6a566b9c 330 policy->Free = lru_free;
62e76326 331
6a566b9c 332 policy->Add = lru_add;
62e76326 333
6a566b9c 334 policy->Remove = lru_remove;
62e76326 335
6a566b9c 336 policy->Referenced = lru_referenced;
62e76326 337
6a566b9c 338 policy->Dereferenced = lru_referenced;
62e76326 339
6a566b9c 340 policy->WalkInit = lru_walkInit;
62e76326 341
6a566b9c 342 policy->PurgeInit = lru_purgeInit;
62e76326 343
8a3e7d9e 344 policy->Stats = lru_stats;
62e76326 345
6a566b9c 346 /* Increase policy usage count */
347 nr_lru_policies += 0;
62e76326 348
6a566b9c 349 return policy;
350}
f53969cc 351