]> git.ipfire.org Git - thirdparty/squid.git/blob - src/refresh.cc
- fixed typos in refreshCountsStats
[thirdparty/squid.git] / src / refresh.cc
1
2
3 /*
4 * $Id: refresh.cc,v 1.38 1998/10/17 04:41:48 rousskov Exp $
5 *
6 * DEBUG: section 22 Refresh Calculation
7 * AUTHOR: Harvest Derived
8 *
9 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
10 * ----------------------------------------------------------
11 *
12 * Squid is the result of efforts by numerous individuals from the
13 * Internet community. Development is led by Duane Wessels of the
14 * National Laboratory for Applied Network Research and funded by the
15 * National Science Foundation. Squid is Copyrighted (C) 1998 by
16 * Duane Wessels and the University of California San Diego. Please
17 * see the COPYRIGHT file for full details. Squid incorporates
18 * software developed and/or copyrighted by other sources. Please see
19 * the CREDITS file for full details.
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
34 *
35 */
36
37 #ifndef USE_POSIX_REGEX
38 #define USE_POSIX_REGEX /* put before includes; always use POSIX */
39 #endif
40
41 #include "squid.h"
42
43 typedef enum { rcHTTP, rcICP, rcCDigest, rcCount } refreshCountsEnum;
44
45 static struct RefreshCounts {
46 const char *proto;
47 int total;
48 int revalidate_stale;
49 int request_max_age_stale;
50 int response_expires_stale;
51 int response_expires_fresh;
52 int conf_max_age_stale;
53 int last_modified_factor_fresh;
54 int last_modified_factor_stale;
55 int conf_min_age_fresh;
56 int default_stale;
57 } refreshCounts[rcCount];
58
59 /*
60 * Defaults:
61 * MIN NONE
62 * PCT 20%
63 * MAX 3 days
64 */
65 #define REFRESH_DEFAULT_MIN (time_t)0
66 #define REFRESH_DEFAULT_PCT 0.20
67 #define REFRESH_DEFAULT_MAX (time_t)259200
68
69 static const refresh_t *refreshLimits(const char *);
70 static const refresh_t *refreshUncompiledPattern(const char *);
71 static OBJH refreshStats;
72
73 static const refresh_t *
74 refreshLimits(const char *url)
75 {
76 const refresh_t *R;
77 for (R = Config.Refresh; R; R = R->next) {
78 if (!regexec(&(R->compiled_pattern), url, 0, 0, 0))
79 return R;
80 }
81 return NULL;
82 }
83
84 static const refresh_t *
85 refreshUncompiledPattern(const char *pat)
86 {
87 const refresh_t *R;
88 for (R = Config.Refresh; R; R = R->next) {
89 if (0 == strcmp(R->pattern, pat))
90 return R;
91 }
92 return NULL;
93 }
94
95 /* return 1 if the entry must be revalidated within delta seconds
96 * 0 otherwise
97 *
98 * note: request maybe null (e.g. for cache digests build)
99 */
100 static int
101 refreshCheck(const StoreEntry * entry, request_t * request, time_t delta, struct RefreshCounts *rc)
102 {
103 const refresh_t *R;
104 const char *uri = NULL;
105 time_t min = REFRESH_DEFAULT_MIN;
106 double pct = REFRESH_DEFAULT_PCT;
107 time_t max = REFRESH_DEFAULT_MAX;
108 #if HTTP_VIOLATIONS
109 int override_expire = 0;
110 int override_lastmod = 0;
111 int reload_into_ims = 0;
112 int ignore_reload = 0;
113 #endif
114 const char *pattern = "<none>";
115 time_t age;
116 double factor;
117 time_t check_time = squid_curtime + delta;
118 if (entry->mem_obj)
119 uri = entry->mem_obj->url;
120 else
121 if (request)
122 uri = urlCanonical(request);
123
124 debug(22, 3) ("refreshCheck(%s): '%s'\n", rc->proto, uri ? uri : "<none>");
125 rc->total++;
126 if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE)) {
127 debug(22, 3) ("refreshCheck: YES: Required Authorization\n");
128 rc->revalidate_stale++;
129 return 1;
130 }
131 if ((R = uri ? refreshLimits(uri) : refreshUncompiledPattern("."))) {
132 min = R->min;
133 pct = R->pct;
134 max = R->max;
135 pattern = R->pattern;
136 #if HTTP_VIOLATIONS
137 override_expire = R->flags.override_expire;
138 override_lastmod = R->flags.override_lastmod;
139 reload_into_ims = R->flags.reload_into_ims;
140 ignore_reload = R->flags.ignore_reload;
141 #endif
142 }
143 #if HTTP_VIOLATIONS
144 if (!reload_into_ims)
145 reload_into_ims = Config.onoff.reload_into_ims;
146 #endif
147 debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
148 pattern, (int) min, (int) (100.0 * pct), (int) max);
149 age = check_time - entry->timestamp;
150 debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
151 debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
152 debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));
153 /* request-specific checks */
154 if (request) {
155 #if HTTP_VIOLATIONS
156 if (request->flags.nocache_hack) {
157 if (ignore_reload) {
158 /* The clients no-cache header is ignored */
159 debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n");
160 } else if (reload_into_ims) {
161 /* The clients no-cache header is changed into a IMS query */
162 debug(22, 3) ("refreshCheck: YES: reload-into-ims\n");
163 return 1;
164 } else {
165 /* The clients no-cache header is not overridden on this request */
166 debug(22, 3) ("refreshCheck: YES: client reload\n");
167 request->flags.nocache = 1;
168 return 1;
169 }
170 }
171 #endif
172 if (request->max_age > -1) {
173 if (age > request->max_age) {
174 debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
175 rc->request_max_age_stale++;
176 return 1;
177 }
178 }
179 }
180 #if HTTP_VIOLATIONS
181 if (override_expire && age <= min) {
182 debug(22, 3) ("refreshCheck: NO: age < min && override_expire\n");
183 return 0;
184 }
185 #endif
186 if (entry->expires > -1) {
187 if (entry->expires <= check_time) {
188 debug(22, 3) ("refreshCheck: YES: expires <= curtime\n");
189 rc->response_expires_stale++;
190 return 1;
191 } else {
192 debug(22, 3) ("refreshCheck: NO: expires > curtime\n");
193 rc->response_expires_fresh++;
194 return 0;
195 }
196 }
197 if (age > max) {
198 debug(22, 3) ("refreshCheck: YES: age > max\n");
199 rc->conf_max_age_stale++;
200 return 1;
201 }
202 #if HTTP_VIOLATIONS
203 if (override_lastmod && age <= min) {
204 debug(22, 3) ("refreshCheck: NO: age < min && override_lastmod\n");
205 return 0;
206 }
207 #endif
208 if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) {
209 factor = (double) age / (double) (entry->timestamp - entry->lastmod);
210 debug(22, 3) ("refreshCheck: factor = %f\n", factor);
211 if (factor < pct) {
212 debug(22, 3) ("refreshCheck: NO: factor < pct\n");
213 rc->last_modified_factor_fresh++;
214 return 0;
215 } else {
216 debug(22, 3) ("refreshCheck: YES: factor >= pct\n");
217 rc->last_modified_factor_stale++;
218 return 1;
219 }
220 }
221 if (age <= min) {
222 debug(22, 3) ("refreshCheck: NO: age < min\n");
223 rc->conf_min_age_fresh++;
224 return 0;
225 }
226 debug(22, 3) ("refreshCheck: YES: default stale\n");
227 rc->default_stale++;
228 return 1;
229 }
230
231 /* refreshCheck... functions below are protocol-specific wrappers around
232 * refreshCheck() function above */
233
234 int
235 refreshCheckHTTP(const StoreEntry * entry, request_t * request) {
236 return refreshCheck(entry, request, 0, refreshCounts + rcHTTP);
237 }
238
239 int
240 refreshCheckICP(const StoreEntry * entry, request_t * request) {
241 return refreshCheck(entry, request, 30, refreshCounts + rcICP);
242 }
243
244 int
245 refreshCheckDigest(const StoreEntry * entry, time_t delta) {
246 return refreshCheck(entry, NULL, delta, refreshCounts + rcCDigest);
247 }
248
249 time_t
250 getMaxAge(const char *url)
251 {
252 const refresh_t *R;
253 debug(22, 3) ("getMaxAge: '%s'\n", url);
254 if ((R = refreshLimits(url)))
255 return R->max;
256 else
257 return REFRESH_DEFAULT_MAX;
258 }
259
260 static void
261 refreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc)
262 {
263 storeAppendPrintf(sentry, "\n\n%s histogram:\n", rc->proto);
264 storeAppendPrintf(sentry, "Category\tCount\t%%Total\n");
265
266 storeAppendPrintf(sentry, "revalidate_stale\t%6d\t%6.2f\n",
267 rc->revalidate_stale, xpercent(rc->revalidate_stale, rc->total));
268 storeAppendPrintf(sentry, "request_max_age_stale\t%6d\t%6.2f\n",
269 rc->request_max_age_stale, xpercent(rc->request_max_age_stale, rc->total));
270 storeAppendPrintf(sentry, "response_expires_stale\t%6d\t%6.2f\n",
271 rc->response_expires_stale, xpercent(rc->response_expires_stale, rc->total));
272 storeAppendPrintf(sentry, "response_expires_fresh\t%6d\t%6.2f\n",
273 rc->response_expires_fresh, xpercent(rc->response_expires_fresh, rc->total));
274 storeAppendPrintf(sentry, "conf_max_age_stale\t%6d\t%6.2f\n",
275 rc->conf_max_age_stale, xpercent(rc->conf_max_age_stale, rc->total));
276 storeAppendPrintf(sentry, "last_modified_factor_fresh\t%6d\t%6.2f\n",
277 rc->last_modified_factor_fresh, xpercent(rc->last_modified_factor_fresh, rc->total));
278 storeAppendPrintf(sentry, "last_modified_factor_stale\t%6d\t%6.2f\n",
279 rc->last_modified_factor_stale, xpercent(rc->last_modified_factor_stale, rc->total));
280 storeAppendPrintf(sentry, "conf_min_age_fresh\t%6d\t%6.2f\n",
281 rc->conf_min_age_fresh, xpercent(rc->conf_min_age_fresh, rc->total));
282 storeAppendPrintf(sentry, "default_stale\t%6d\t%6.2f\n",
283 rc->default_stale, xpercent(rc->default_stale, rc->total));
284 storeAppendPrintf(sentry, "total\t%6d\t%6.2f\n",
285 rc->total, xpercent(rc->total, rc->total));
286 }
287
288 static void
289 refreshStats(StoreEntry * sentry)
290 {
291 int i;
292 int total = 0;
293
294 /* get total usage count */
295 for (i = 0; i < rcCount; ++i)
296 total += refreshCounts[i].total;
297
298 /* protocol usage histogram */
299 storeAppendPrintf(sentry, "\nRefreshCheck calls per protocol\n\n");
300 storeAppendPrintf(sentry, "Protocol\t#Calls\t%%Calls\n");
301 for (i = 0; i < rcCount; ++i)
302 storeAppendPrintf(sentry, "%10s\t%6d\t%6.2f\n",
303 refreshCounts[i].proto,
304 refreshCounts[i].total,
305 xpercent(refreshCounts[i].total, total));
306
307 /* per protocol histograms */
308 storeAppendPrintf(sentry, "\n\nRefreshCheck histograms for various protocols\n");
309 for (i = 0; i < rcCount; ++i)
310 refreshCountsStats(sentry, refreshCounts + i);
311 }
312
313 void
314 refreshInit()
315 {
316 memset(refreshCounts, 0, sizeof(refreshCounts));
317 refreshCounts[rcHTTP].proto = "HTTP";
318 refreshCounts[rcICP].proto = "ICP";
319 refreshCounts[rcCDigest].proto = "Cache Digests";
320
321 cachemgrRegister("refresh",
322 "Refresh Algorithm Statistics",
323 refreshStats,
324 0,
325 1);
326 }