]>
Commit | Line | Data |
---|---|---|
e4e6a8db | 1 | |
2 | /* | |
528b2c61 | 3 | * $Id: refresh.cc,v 1.59 2003/01/23 00:37:25 robertc Exp $ |
e4e6a8db | 4 | * |
5 | * DEBUG: section 22 Refresh Calculation | |
6 | * AUTHOR: Harvest Derived | |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
e4e6a8db | 10 | * |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
e4e6a8db | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
e4e6a8db | 34 | */ |
35 | ||
36 | #ifndef USE_POSIX_REGEX | |
37 | #define USE_POSIX_REGEX /* put before includes; always use POSIX */ | |
38 | #endif | |
39 | ||
40 | #include "squid.h" | |
e6ccf245 | 41 | #include "Store.h" |
528b2c61 | 42 | #include "MemObject.h" |
e4e6a8db | 43 | |
7d47d8e6 | 44 | typedef enum { |
65fa5c61 | 45 | rcHTTP, |
46 | rcICP, | |
47 | #if USE_HTCP | |
48 | rcHTCP, | |
49 | #endif | |
50 | #if USE_CACHE_DIGESTS | |
51 | rcCDigest, | |
52 | #endif | |
53 | rcStore, | |
54 | rcCount | |
7d47d8e6 | 55 | } refreshCountsEnum; |
829a9357 | 56 | |
65fa5c61 | 57 | typedef struct { |
58 | unsigned int expires:1; | |
59 | unsigned int min:1; | |
60 | unsigned int lmfactor:1; | |
61 | unsigned int max; | |
62 | } stale_flags; | |
63 | ||
64 | /* | |
65 | * This enumerated list assigns specific values, ala HTTP/FTP status | |
66 | * codes. All Fresh codes are in the range 100-199 and all stale | |
67 | * codes are 200-299. We might want to use these codes in logging, | |
68 | * so best to keep them consistent over time. | |
69 | */ | |
70 | enum { | |
71 | FRESH_REQUEST_MAX_STALE_ALL = 100, | |
72 | FRESH_REQUEST_MAX_STALE_VALUE, | |
73 | FRESH_EXPIRES, | |
74 | FRESH_LMFACTOR_RULE, | |
75 | FRESH_MIN_RULE, | |
76 | FRESH_OVERRIDE_EXPIRES, | |
77 | FRESH_OVERRIDE_LASTMOD, | |
78 | STALE_MUST_REVALIDATE = 200, | |
79 | STALE_RELOAD_INTO_IMS, | |
80 | STALE_FORCED_RELOAD, | |
81 | STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE, | |
82 | STALE_EXPIRES, | |
83 | STALE_MAX_RULE, | |
84 | STALE_LMFACTOR_RULE, | |
85 | STALE_DEFAULT = 299 | |
86 | }; | |
87 | ||
829a9357 | 88 | static struct RefreshCounts { |
89 | const char *proto; | |
1c3e77cd | 90 | int total; |
65fa5c61 | 91 | int status[STALE_DEFAULT + 1]; |
829a9357 | 92 | } refreshCounts[rcCount]; |
1c3e77cd | 93 | |
e4e6a8db | 94 | /* |
95 | * Defaults: | |
96 | * MIN NONE | |
97 | * PCT 20% | |
98 | * MAX 3 days | |
99 | */ | |
48f44632 | 100 | #define REFRESH_DEFAULT_MIN (time_t)0 |
c3f6d204 | 101 | #define REFRESH_DEFAULT_PCT 0.20 |
48f44632 | 102 | #define REFRESH_DEFAULT_MAX (time_t)259200 |
e4e6a8db | 103 | |
0cdcddb9 | 104 | static const refresh_t *refreshLimits(const char *); |
2b5133db | 105 | static const refresh_t *refreshUncompiledPattern(const char *); |
1c3e77cd | 106 | static OBJH refreshStats; |
65fa5c61 | 107 | static int refreshStaleness(const StoreEntry *, time_t, time_t, const refresh_t *, stale_flags *); |
108 | ||
109 | static refresh_t DefaultRefresh; | |
2b5133db | 110 | |
6018f0de | 111 | static const refresh_t * |
112 | refreshLimits(const char *url) | |
113 | { | |
114 | const refresh_t *R; | |
115 | for (R = Config.Refresh; R; R = R->next) { | |
116 | if (!regexec(&(R->compiled_pattern), url, 0, 0, 0)) | |
117 | return R; | |
118 | } | |
119 | return NULL; | |
120 | } | |
121 | ||
2b5133db | 122 | static const refresh_t * |
123 | refreshUncompiledPattern(const char *pat) | |
124 | { | |
125 | const refresh_t *R; | |
126 | for (R = Config.Refresh; R; R = R->next) { | |
127 | if (0 == strcmp(R->pattern, pat)) | |
128 | return R; | |
129 | } | |
130 | return NULL; | |
131 | } | |
132 | ||
65fa5c61 | 133 | /* |
134 | * Calculate how stale the response is (or will be at the check_time). | |
135 | * Staleness calculation is based on the following: (1) response | |
136 | * expiration time, (2) age greater than configured maximum, (3) | |
137 | * last-modified factor, and (4) age less than configured minimum. | |
138 | * | |
139 | * If the response is fresh, return -1. Otherwise return its | |
140 | * staleness. NOTE return value of 0 means the response is stale. | |
141 | * | |
142 | * The 'stale_flags' structure is used to tell the calling function | |
143 | * _why_ this response is fresh or stale. Its used, for example, | |
144 | * when the admin wants to override expiration and last-modified | |
145 | * times. | |
146 | */ | |
147 | static int | |
148 | refreshStaleness(const StoreEntry * entry, time_t check_time, time_t age, const refresh_t * R, stale_flags * sf) | |
149 | { | |
150 | /* | |
151 | * Check for an explicit expiration time. | |
152 | */ | |
153 | if (entry->expires > -1) { | |
154 | sf->expires = 1; | |
155 | if (entry->expires > check_time) { | |
156 | debug(22, 3) ("FRESH: expires %d >= check_time %d \n", | |
157 | (int) entry->expires, (int) check_time); | |
158 | return -1; | |
159 | } else { | |
160 | debug(22, 3) ("STALE: expires %d < check_time %d \n", | |
161 | (int) entry->expires, (int) check_time); | |
162 | return (check_time - entry->expires); | |
163 | } | |
164 | } | |
165 | assert(age >= 0); | |
166 | /* | |
167 | * Use local heuristics to determine staleness. Start with the | |
168 | * max age from the refresh_pattern rule. | |
169 | */ | |
170 | if (age > R->max) { | |
171 | debug(22, 3) ("STALE: age %d > max %d \n", (int) age, (int) R->max); | |
172 | sf->max = 1; | |
173 | return (age - R->max); | |
174 | } | |
175 | /* | |
176 | * Try the last-modified factor algorithm. | |
177 | */ | |
178 | if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) { | |
179 | /* | |
180 | * stale_age is the Age of the response when it became/becomes | |
181 | * stale according to the last-modified factor algorithm. | |
182 | */ | |
e6ccf245 | 183 | time_t stale_age = static_cast<time_t>((entry->timestamp - entry->lastmod) * R->pct); |
65fa5c61 | 184 | sf->lmfactor = 1; |
185 | if (age >= stale_age) { | |
186 | debug(22, 3) ("STALE: age %d > stale_age %d\n", | |
187 | (int) age, (int) stale_age); | |
188 | return (age - stale_age); | |
189 | } else { | |
190 | debug(22, 3) ("FRESH: age %d <= stale_age %d\n", | |
191 | (int) age, (int) stale_age); | |
192 | return -1; | |
193 | } | |
194 | } | |
195 | /* | |
196 | * If we are here, staleness is determined by the refresh_pattern | |
197 | * configured minimum age. | |
198 | */ | |
199 | if (age <= R->min) { | |
200 | debug(22, 3) ("FRESH: age %d <= min %d\n", (int) age, (int) R->min); | |
201 | sf->min = 1; | |
202 | return -1; | |
203 | } | |
204 | debug(22, 3) ("STALE: age %d > min %d\n", (int) age, (int) R->min); | |
205 | return (age - R->min); | |
206 | } | |
207 | ||
829a9357 | 208 | /* return 1 if the entry must be revalidated within delta seconds |
209 | * 0 otherwise | |
210 | * | |
211 | * note: request maybe null (e.g. for cache digests build) | |
e4e6a8db | 212 | */ |
829a9357 | 213 | static int |
65fa5c61 | 214 | refreshCheck(const StoreEntry * entry, request_t * request, time_t delta) |
e4e6a8db | 215 | { |
6018f0de | 216 | const refresh_t *R; |
829a9357 | 217 | const char *uri = NULL; |
65fa5c61 | 218 | time_t age = 0; |
a207429f | 219 | time_t check_time = squid_curtime + delta; |
65fa5c61 | 220 | int staleness; |
221 | stale_flags sf; | |
9b5d1d21 | 222 | if (entry->mem_obj) |
223 | uri = entry->mem_obj->url; | |
7d47d8e6 | 224 | else if (request) |
9b5d1d21 | 225 | uri = urlCanonical(request); |
7d47d8e6 | 226 | |
65fa5c61 | 227 | debug(22, 3) ("refreshCheck: '%s'\n", uri ? uri : "<none>"); |
228 | ||
229 | if (check_time > entry->timestamp) | |
230 | age = check_time - entry->timestamp; | |
231 | R = uri ? refreshLimits(uri) : refreshUncompiledPattern("."); | |
232 | if (NULL == R) | |
233 | R = &DefaultRefresh; | |
234 | memset(&sf, '\0', sizeof(sf)); | |
235 | staleness = refreshStaleness(entry, check_time, age, R, &sf); | |
236 | debug(22, 3) ("Staleness = %d\n", staleness); | |
237 | ||
a3d5953d | 238 | debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n", |
65fa5c61 | 239 | R->pattern, (int) R->min, (int) (100.0 * R->pct), (int) R->max); |
a3d5953d | 240 | debug(22, 3) ("refreshCheck: age = %d\n", (int) age); |
49d3fcb0 | 241 | debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time)); |
242 | debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp)); | |
65fa5c61 | 243 | |
244 | if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1) { | |
245 | debug(22, 3) ("refreshCheck: YES: Must revalidate stale response\n"); | |
246 | return STALE_MUST_REVALIDATE; | |
247 | } | |
829a9357 | 248 | /* request-specific checks */ |
249 | if (request) { | |
65fa5c61 | 250 | HttpHdrCc *cc = request->cache_control; |
9f60cfdf | 251 | #if HTTP_VIOLATIONS |
65fa5c61 | 252 | if (!request->flags.nocache_hack) { |
253 | (void) 0; | |
254 | } else if (R->flags.ignore_reload) { | |
255 | /* The clients no-cache header is ignored */ | |
256 | debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n"); | |
257 | } else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) { | |
258 | /* The clients no-cache header is changed into a IMS query */ | |
259 | debug(22, 3) ("refreshCheck: YES: reload-into-ims\n"); | |
260 | return STALE_RELOAD_INTO_IMS; | |
261 | } else { | |
262 | /* The clients no-cache header is not overridden on this request */ | |
263 | debug(22, 3) ("refreshCheck: YES: client reload\n"); | |
264 | request->flags.nocache = 1; | |
265 | return STALE_FORCED_RELOAD; | |
cbe3a719 | 266 | } |
9f60cfdf | 267 | #endif |
65fa5c61 | 268 | if (NULL != cc) { |
269 | if (cc->max_age > -1) { | |
085008f9 | 270 | #if HTTP_VIOLATIONS |
271 | if (R->flags.ignore_reload && cc->max_age == 0) { | |
272 | } else | |
528b2c61 | 273 | #endif |
274 | { | |
275 | #if 0 | |
276 | if (cc->max_age == 0) { | |
277 | debug (22,3) ("refreshCheck: YES: client-max-age = 0\n"); | |
278 | return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; | |
279 | } | |
085008f9 | 280 | #endif |
65fa5c61 | 281 | if (age > cc->max_age) { |
282 | debug(22, 3) ("refreshCheck: YES: age > client-max-age\n"); | |
283 | return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; | |
284 | } | |
528b2c61 | 285 | } |
65fa5c61 | 286 | } |
287 | if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) { | |
288 | if (cc->max_stale < 0) { | |
289 | /* max-stale directive without a value */ | |
290 | debug(22, 3) ("refreshCheck: NO: max-stale wildcard\n"); | |
291 | return FRESH_REQUEST_MAX_STALE_ALL; | |
292 | } else if (staleness < cc->max_stale) { | |
293 | debug(22, 3) ("refreshCheck: NO: staleness < max-stale\n"); | |
294 | return FRESH_REQUEST_MAX_STALE_VALUE; | |
295 | } | |
829a9357 | 296 | } |
48f44632 | 297 | } |
298 | } | |
65fa5c61 | 299 | if (-1 == staleness) { |
300 | if (sf.expires) | |
301 | return FRESH_EXPIRES; | |
302 | assert(!sf.max); | |
303 | if (sf.lmfactor) | |
304 | return FRESH_LMFACTOR_RULE; | |
305 | assert(sf.min); | |
306 | return FRESH_MIN_RULE; | |
1dfa1d81 | 307 | } |
65fa5c61 | 308 | /* |
309 | * At this point the response is stale, unless one of | |
542c4d60 | 310 | * the override options kicks in. |
65fa5c61 | 311 | */ |
312 | if (sf.expires) { | |
313 | #if HTTP_VIOLATIONS | |
314 | if (R->flags.override_expire && age < R->min) { | |
315 | debug(22, 3) ("refreshCheck: NO: age < min && override-expire\n"); | |
316 | return FRESH_OVERRIDE_EXPIRES; | |
34308e0f | 317 | } |
65fa5c61 | 318 | #endif |
319 | return STALE_EXPIRES; | |
e4e6a8db | 320 | } |
65fa5c61 | 321 | if (sf.max) |
322 | return STALE_MAX_RULE; | |
323 | if (sf.lmfactor) { | |
9f60cfdf | 324 | #if HTTP_VIOLATIONS |
65fa5c61 | 325 | if (R->flags.override_lastmod && age < R->min) { |
326 | debug(22, 3) ("refreshCheck: NO: age < min && override-lastmod\n"); | |
327 | return FRESH_OVERRIDE_LASTMOD; | |
0d508d5b | 328 | } |
65fa5c61 | 329 | #endif |
330 | return STALE_LMFACTOR_RULE; | |
e4e6a8db | 331 | } |
65fa5c61 | 332 | return STALE_DEFAULT; |
e4e6a8db | 333 | } |
48f44632 | 334 | |
cfa9f1cb | 335 | int |
336 | refreshIsCachable(const StoreEntry * entry) | |
337 | { | |
338 | /* | |
339 | * Don't look at the request to avoid no-cache and other nuisances. | |
340 | * the object should have a mem_obj so the URL will be found there. | |
341 | * 60 seconds delta, to avoid objects which expire almost | |
342 | * immediately, and which can't be refreshed. | |
343 | */ | |
65fa5c61 | 344 | int reason = refreshCheck(entry, NULL, 60); |
345 | refreshCounts[rcStore].total++; | |
346 | refreshCounts[rcStore].status[reason]++; | |
347 | if (reason < 200) | |
cfa9f1cb | 348 | /* Does not need refresh. This is certainly cachable */ |
349 | return 1; | |
350 | if (entry->lastmod < 0) | |
351 | /* Last modified is needed to do a refresh */ | |
352 | return 0; | |
353 | if (entry->mem_obj == NULL) | |
354 | /* no mem_obj? */ | |
355 | return 1; | |
528b2c61 | 356 | if (entry->getReply() == NULL) |
cfa9f1cb | 357 | /* no reply? */ |
358 | return 1; | |
528b2c61 | 359 | if (entry->getReply()->content_length == 0) |
cfa9f1cb | 360 | /* No use refreshing (caching?) 0 byte objects */ |
361 | return 0; | |
362 | /* This seems to be refreshable. Cache it */ | |
363 | return 1; | |
364 | } | |
365 | ||
829a9357 | 366 | /* refreshCheck... functions below are protocol-specific wrappers around |
367 | * refreshCheck() function above */ | |
368 | ||
369 | int | |
7d47d8e6 | 370 | refreshCheckHTTP(const StoreEntry * entry, request_t * request) |
371 | { | |
65fa5c61 | 372 | int reason = refreshCheck(entry, request, 0); |
373 | refreshCounts[rcHTTP].total++; | |
374 | refreshCounts[rcHTTP].status[reason]++; | |
375 | return (reason < 200) ? 0 : 1; | |
829a9357 | 376 | } |
377 | ||
378 | int | |
7d47d8e6 | 379 | refreshCheckICP(const StoreEntry * entry, request_t * request) |
380 | { | |
65fa5c61 | 381 | int reason = refreshCheck(entry, request, 30); |
382 | refreshCounts[rcICP].total++; | |
383 | refreshCounts[rcICP].status[reason]++; | |
384 | return (reason < 200) ? 0 : 1; | |
829a9357 | 385 | } |
386 | ||
65fa5c61 | 387 | #if USE_HTCP |
32b3cf93 | 388 | int |
389 | refreshCheckHTCP(const StoreEntry * entry, request_t * request) | |
390 | { | |
65fa5c61 | 391 | int reason = refreshCheck(entry, request, 10); |
392 | refreshCounts[rcHTCP].total++; | |
393 | refreshCounts[rcHTCP].status[reason]++; | |
394 | return (reason < 200) ? 0 : 1; | |
32b3cf93 | 395 | } |
65fa5c61 | 396 | #endif |
32b3cf93 | 397 | |
65fa5c61 | 398 | #if USE_CACHE_DIGESTS |
829a9357 | 399 | int |
7d47d8e6 | 400 | refreshCheckDigest(const StoreEntry * entry, time_t delta) |
401 | { | |
65fa5c61 | 402 | int reason = refreshCheck(entry, |
c68e9c6b | 403 | entry->mem_obj ? entry->mem_obj->request : NULL, |
65fa5c61 | 404 | delta); |
405 | refreshCounts[rcCDigest].total++; | |
406 | refreshCounts[rcCDigest].status[reason]++; | |
407 | return (reason < 200) ? 0 : 1; | |
6018f0de | 408 | } |
65fa5c61 | 409 | #endif |
6018f0de | 410 | |
48f44632 | 411 | time_t |
412 | getMaxAge(const char *url) | |
413 | { | |
6018f0de | 414 | const refresh_t *R; |
a3d5953d | 415 | debug(22, 3) ("getMaxAge: '%s'\n", url); |
6018f0de | 416 | if ((R = refreshLimits(url))) |
417 | return R->max; | |
418 | else | |
419 | return REFRESH_DEFAULT_MAX; | |
48f44632 | 420 | } |
1c3e77cd | 421 | |
829a9357 | 422 | static void |
423 | refreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc) | |
424 | { | |
cc7cfa8e | 425 | int sum = 0; |
426 | int tot = rc->total; | |
427 | ||
829a9357 | 428 | storeAppendPrintf(sentry, "\n\n%s histogram:\n", rc->proto); |
65fa5c61 | 429 | storeAppendPrintf(sentry, "Count\t%%Total\tCategory\n"); |
829a9357 | 430 | |
65fa5c61 | 431 | #define refreshCountsStatsEntry(code,desc) { \ |
432 | storeAppendPrintf(sentry, "%6d\t%6.2f\t%s\n", \ | |
433 | rc->status[code], xpercent(rc->status[code], tot), desc); \ | |
434 | sum += rc->status[code]; \ | |
cc7cfa8e | 435 | } |
65fa5c61 | 436 | |
437 | refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_ALL, | |
438 | "Fresh: request max-stale wildcard"); | |
439 | refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_VALUE, | |
440 | "Fresh: request max-stale value"); | |
441 | refreshCountsStatsEntry(FRESH_EXPIRES, | |
442 | "Fresh: expires time not reached"); | |
443 | refreshCountsStatsEntry(FRESH_LMFACTOR_RULE, | |
444 | "Fresh: refresh_pattern last-mod factor percentage"); | |
445 | refreshCountsStatsEntry(FRESH_MIN_RULE, | |
446 | "Fresh: refresh_pattern min value"); | |
447 | refreshCountsStatsEntry(FRESH_OVERRIDE_EXPIRES, | |
448 | "Fresh: refresh_pattern override expires"); | |
449 | refreshCountsStatsEntry(FRESH_OVERRIDE_LASTMOD, | |
450 | "Fresh: refresh_pattern override lastmod"); | |
451 | refreshCountsStatsEntry(STALE_MUST_REVALIDATE, | |
452 | "Stale: response has must-revalidate"); | |
453 | refreshCountsStatsEntry(STALE_RELOAD_INTO_IMS, | |
454 | "Stale: changed reload into IMS"); | |
455 | refreshCountsStatsEntry(STALE_FORCED_RELOAD, | |
456 | "Stale: request has no-cache directive"); | |
457 | refreshCountsStatsEntry(STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE, | |
458 | "Stale: age exceeds request max-age value"); | |
459 | refreshCountsStatsEntry(STALE_EXPIRES, | |
460 | "Stale: expires time reached"); | |
461 | refreshCountsStatsEntry(STALE_MAX_RULE, | |
462 | "Stale: refresh_pattern max age rule"); | |
463 | refreshCountsStatsEntry(STALE_LMFACTOR_RULE, | |
464 | "Stale: refresh_pattern last-mod factor percentage"); | |
465 | refreshCountsStatsEntry(STALE_DEFAULT, | |
466 | "Stale: by default"); | |
467 | ||
7d47d8e6 | 468 | tot = sum; /* paranoid: "total" line shows 100% if we forgot nothing */ |
65fa5c61 | 469 | storeAppendPrintf(sentry, "%6d\t%6.2f\tTOTAL\n", |
470 | rc->total, xpercent(rc->total, tot)); | |
471 | \ | |
472 | storeAppendPrintf(sentry, "\n"); | |
829a9357 | 473 | } |
474 | ||
1c3e77cd | 475 | static void |
476 | refreshStats(StoreEntry * sentry) | |
477 | { | |
829a9357 | 478 | int i; |
479 | int total = 0; | |
480 | ||
481 | /* get total usage count */ | |
482 | for (i = 0; i < rcCount; ++i) | |
483 | total += refreshCounts[i].total; | |
484 | ||
485 | /* protocol usage histogram */ | |
486 | storeAppendPrintf(sentry, "\nRefreshCheck calls per protocol\n\n"); | |
487 | storeAppendPrintf(sentry, "Protocol\t#Calls\t%%Calls\n"); | |
488 | for (i = 0; i < rcCount; ++i) | |
489 | storeAppendPrintf(sentry, "%10s\t%6d\t%6.2f\n", | |
490 | refreshCounts[i].proto, | |
7d47d8e6 | 491 | refreshCounts[i].total, |
829a9357 | 492 | xpercent(refreshCounts[i].total, total)); |
493 | ||
494 | /* per protocol histograms */ | |
495 | storeAppendPrintf(sentry, "\n\nRefreshCheck histograms for various protocols\n"); | |
496 | for (i = 0; i < rcCount; ++i) | |
42125db6 | 497 | refreshCountsStats(sentry, &refreshCounts[i]); |
1c3e77cd | 498 | } |
499 | ||
500 | void | |
9bc73deb | 501 | refreshInit(void) |
1c3e77cd | 502 | { |
829a9357 | 503 | memset(refreshCounts, 0, sizeof(refreshCounts)); |
504 | refreshCounts[rcHTTP].proto = "HTTP"; | |
505 | refreshCounts[rcICP].proto = "ICP"; | |
65fa5c61 | 506 | #if USE_HTCP |
32b3cf93 | 507 | refreshCounts[rcHTCP].proto = "HTCP"; |
65fa5c61 | 508 | #endif |
cfa9f1cb | 509 | refreshCounts[rcStore].proto = "On Store"; |
65fa5c61 | 510 | #if USE_CACHE_DIGESTS |
829a9357 | 511 | refreshCounts[rcCDigest].proto = "Cache Digests"; |
65fa5c61 | 512 | #endif |
1c3e77cd | 513 | cachemgrRegister("refresh", |
514 | "Refresh Algorithm Statistics", | |
515 | refreshStats, | |
516 | 0, | |
517 | 1); | |
65fa5c61 | 518 | memset(&DefaultRefresh, '\0', sizeof(DefaultRefresh)); |
519 | DefaultRefresh.pattern = "<none>"; | |
520 | DefaultRefresh.min = REFRESH_DEFAULT_MIN; | |
521 | DefaultRefresh.pct = REFRESH_DEFAULT_PCT; | |
522 | DefaultRefresh.max = REFRESH_DEFAULT_MAX; | |
1c3e77cd | 523 | } |