]> git.ipfire.org Git - thirdparty/squid.git/blame - src/refresh.cc
make --disable-http-violations actually work
[thirdparty/squid.git] / src / refresh.cc
CommitLineData
e4e6a8db 1
cbe3a719 2
e4e6a8db 3/*
92695e5e 4 * $Id: refresh.cc,v 1.33 1998/08/21 03:15:23 wessels Exp $
e4e6a8db 5 *
6 * DEBUG: section 22 Refresh Calculation
7 * AUTHOR: Harvest Derived
8 *
42c04c16 9 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 10 * ----------------------------------------------------------
e4e6a8db 11 *
12 * Squid is the result of efforts by numerous individuals from the
13 * Internet community. Development is led by Duane Wessels of the
e25c139f 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.
e4e6a8db 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
cbdec147 33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 34 *
e4e6a8db 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
1c3e77cd 43struct {
44 int total;
45 int revalidate_stale;
46 int request_max_age_stale;
47 int response_expires_stale;
48 int response_expires_fresh;
49 int conf_max_age_stale;
50 int last_modified_factor_fresh;
51 int last_modified_factor_stale;
52 int conf_min_age_fresh;
53 int default_stale;
54} refreshCounts;
55
e4e6a8db 56/*
57 * Defaults:
58 * MIN NONE
59 * PCT 20%
60 * MAX 3 days
61 */
48f44632 62#define REFRESH_DEFAULT_MIN (time_t)0
c3f6d204 63#define REFRESH_DEFAULT_PCT 0.20
48f44632 64#define REFRESH_DEFAULT_MAX (time_t)259200
e4e6a8db 65
0cdcddb9 66static const refresh_t *refreshLimits(const char *);
2b5133db 67static const refresh_t *refreshUncompiledPattern(const char *);
1c3e77cd 68static OBJH refreshStats;
2b5133db 69
6018f0de 70static const refresh_t *
71refreshLimits(const char *url)
72{
73 const refresh_t *R;
74 for (R = Config.Refresh; R; R = R->next) {
75 if (!regexec(&(R->compiled_pattern), url, 0, 0, 0))
76 return R;
77 }
78 return NULL;
79}
80
2b5133db 81static const refresh_t *
82refreshUncompiledPattern(const char *pat)
83{
84 const refresh_t *R;
85 for (R = Config.Refresh; R; R = R->next) {
86 if (0 == strcmp(R->pattern, pat))
87 return R;
88 }
89 return NULL;
90}
91
e4e6a8db 92/*
93 * refreshCheck():
94 * return 1 if its time to revalidate this entry, 0 otherwise
95 */
96int
2a24c297 97refreshCheck(const StoreEntry * entry, request_t * request, time_t delta)
e4e6a8db 98{
6018f0de 99 const refresh_t *R;
9b5d1d21 100 const char *uri;
e4e6a8db 101 time_t min = REFRESH_DEFAULT_MIN;
c3f6d204 102 double pct = REFRESH_DEFAULT_PCT;
e4e6a8db 103 time_t max = REFRESH_DEFAULT_MAX;
1dfa1d81 104 int override_expire = 0;
105 int override_lastmod = 0;
cbe3a719 106 int reload_into_ims = 0;
107 int ignore_reload = 0;
0ee4272b 108 const char *pattern = ".";
e4e6a8db 109 time_t age;
c3f6d204 110 double factor;
a207429f 111 time_t check_time = squid_curtime + delta;
9b5d1d21 112 if (entry->mem_obj)
113 uri = entry->mem_obj->url;
114 else
115 uri = urlCanonical(request);
116 debug(22, 3) ("refreshCheck: '%s'\n", uri);
1c3e77cd 117 refreshCounts.total++;
79a15e0a 118 if (EBIT_TEST(entry->flag, ENTRY_REVALIDATE)) {
a47b9029 119 debug(22, 3) ("refreshCheck: YES: Required Authorization\n");
1c3e77cd 120 refreshCounts.revalidate_stale++;
c54e9052 121 return 1;
122 }
9b5d1d21 123 if ((R = refreshLimits(uri))) {
e4e6a8db 124 min = R->min;
125 pct = R->pct;
126 max = R->max;
127 pattern = R->pattern;
1dfa1d81 128 override_expire = R->flags.override_expire;
129 override_lastmod = R->flags.override_lastmod;
cbe3a719 130 reload_into_ims = R->flags.reload_into_ims;
131 ignore_reload = R->flags.ignore_reload;
e4e6a8db 132 }
cbe3a719 133 if (!reload_into_ims)
134 reload_into_ims = Config.onoff.reload_into_ims;
a3d5953d 135 debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
c3f6d204 136 pattern, (int) min, (int) (100.0 * pct), (int) max);
a207429f 137 age = check_time - entry->timestamp;
a3d5953d 138 debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
49d3fcb0 139 debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
140 debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));
92695e5e 141 if (request->flags.nocache_hack) {
cbe3a719 142 if (ignore_reload) {
143 /* The clients no-cache header is ignored */
144 debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n");
145 } else if (reload_into_ims) {
146 /* The clients no-cache header is changed into a IMS query */
147 debug(22, 3) ("refreshCheck: YES: reload-into-ims\n");
148 return 1;
149 } else {
150 /* The clients no-cache header is not overridden on this request */
151 debug(22, 3) ("refreshCheck: YES: client reload\n");
92695e5e 152 request->flags.nocache = 1;
cbe3a719 153 return 1;
154 }
155 }
48f44632 156 if (request->max_age > -1) {
157 if (age > request->max_age) {
a3d5953d 158 debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
1c3e77cd 159 refreshCounts.request_max_age_stale++;
48f44632 160 return 1;
161 }
162 }
1dfa1d81 163 if (override_expire && age <= min) {
164 debug(22, 3) ("refreshCheck: NO: age < min && override_expire\n");
165 return 0;
166 }
1c3e77cd 167 if (entry->expires > -1) {
a207429f 168 if (entry->expires <= check_time) {
a3d5953d 169 debug(22, 3) ("refreshCheck: YES: expires <= curtime\n");
1c3e77cd 170 refreshCounts.response_expires_stale++;
34308e0f 171 return 1;
172 } else {
a3d5953d 173 debug(22, 3) ("refreshCheck: NO: expires > curtime\n");
1c3e77cd 174 refreshCounts.response_expires_fresh++;
34308e0f 175 return 0;
176 }
e4e6a8db 177 }
178 if (age > max) {
a3d5953d 179 debug(22, 3) ("refreshCheck: YES: age > max\n");
1c3e77cd 180 refreshCounts.conf_max_age_stale++;
e4e6a8db 181 return 1;
182 }
1dfa1d81 183 if (override_lastmod && age <= min) {
184 debug(22, 3) ("refreshCheck: NO: age < min && override_lastmod\n");
185 return 0;
186 }
1c3e77cd 187 if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) {
188 factor = (double) age / (double) (entry->timestamp - entry->lastmod);
189 debug(22, 3) ("refreshCheck: factor = %f\n", factor);
190 if (factor < pct) {
191 debug(22, 3) ("refreshCheck: NO: factor < pct\n");
192 refreshCounts.last_modified_factor_fresh++;
0d508d5b 193 return 0;
1c3e77cd 194 } else {
195 debug(22, 3) ("refreshCheck: YES: factor >= pct\n");
196 refreshCounts.last_modified_factor_stale++;
197 return 1;
0d508d5b 198 }
e4e6a8db 199 }
1c3e77cd 200 if (age <= min) {
201 debug(22, 3) ("refreshCheck: NO: age < min\n");
202 refreshCounts.conf_min_age_fresh++;
0d508d5b 203 return 0;
e4e6a8db 204 }
5c1c8975 205 debug(22, 3) ("refreshCheck: YES: default stale\n");
1c3e77cd 206 refreshCounts.default_stale++;
0d508d5b 207 return 1;
e4e6a8db 208}
48f44632 209
6018f0de 210/* returns an approximate time when refreshCheck() may return true */
211time_t
212refreshWhen(const StoreEntry * entry)
213{
214 const refresh_t *R;
215 time_t refresh_time = squid_curtime;
216 time_t min = REFRESH_DEFAULT_MIN;
217 time_t max = REFRESH_DEFAULT_MAX;
c3f6d204 218 double pct = REFRESH_DEFAULT_PCT;
6018f0de 219 const char *pattern = ".";
2b5133db 220 if (entry->mem_obj) {
221 assert(entry->mem_obj->url);
222 debug(22, 3) ("refreshWhen: key '%s'\n", storeKeyText(entry->key));
223 debug(22, 3) ("refreshWhen: url '%s'\n", entry->mem_obj->url);
224 if (EBIT_TEST(entry->flag, ENTRY_REVALIDATE)) {
225 debug(22, 3) ("refreshWhen: NOW: Required Authorization\n");
226 return refresh_time;
227 }
228 debug(22, 3) ("refreshWhen: entry: exp: %d, tstamp: %d, lmt: %d\n",
229 entry->expires, entry->timestamp, entry->lastmod);
230 R = refreshLimits(entry->mem_obj->url);
231 } else {
232 R = refreshUncompiledPattern(".");
6018f0de 233 }
2b5133db 234 if (R != NULL) {
6018f0de 235 min = R->min;
236 max = R->max;
237 pct = R->pct;
238 pattern = R->pattern;
239 }
240 debug(22, 3) ("refreshWhen: Matched '%s %d %d%% %d'\n",
c3f6d204 241 pattern, (int) min, (int) (100.0 * pct), (int) max);
6018f0de 242 /* convert to absolute numbers */
243 min += entry->timestamp;
244 max += entry->timestamp;
245 if (-1 < entry->expires) {
246 debug(22, 3) ("refreshWhen: expires set\n");
247 refresh_time = entry->expires;
4b4cd312 248 } else if (entry->timestamp <= entry->lastmod) {
6018f0de 249 debug(22, 3) ("refreshWhen: lastvalid <= lastmod\n");
250 refresh_time = squid_curtime;
251 } else {
c3f6d204 252 refresh_time = (entry->timestamp - entry->lastmod) * pct + entry->timestamp;
6018f0de 253 debug(22, 3) ("refreshWhen: using refresh pct\n");
254 }
255 /* take min/max into account, max takes priority over min */
256 if (refresh_time < min)
257 refresh_time = min;
258 if (refresh_time > max)
259 refresh_time = max;
260 debug(22, 3) ("refreshWhen: answer: %d (in %d secs)\n",
4b4cd312 261 refresh_time, (int) (refresh_time - squid_curtime));
6018f0de 262 return refresh_time;
263}
264
48f44632 265time_t
266getMaxAge(const char *url)
267{
6018f0de 268 const refresh_t *R;
a3d5953d 269 debug(22, 3) ("getMaxAge: '%s'\n", url);
6018f0de 270 if ((R = refreshLimits(url)))
271 return R->max;
272 else
273 return REFRESH_DEFAULT_MAX;
48f44632 274}
1c3e77cd 275
276static void
277refreshStats(StoreEntry * sentry)
278{
279 storeAppendPrintf(sentry, "refreshCounts.total\t%d\n",
280 refreshCounts.total);
281 storeAppendPrintf(sentry, "refreshCounts.revalidate_stale\t%d\n",
282 refreshCounts.revalidate_stale);
283 storeAppendPrintf(sentry, "refreshCounts.request_max_age_stale\t%d\n",
284 refreshCounts.request_max_age_stale);
285 storeAppendPrintf(sentry, "refreshCounts.response_expires_stale\t%d\n",
286 refreshCounts.response_expires_stale);
287 storeAppendPrintf(sentry, "refreshCounts.response_expires_fresh\t%d\n",
288 refreshCounts.response_expires_fresh);
289 storeAppendPrintf(sentry, "refreshCounts.conf_max_age_stale\t%d\n",
290 refreshCounts.conf_max_age_stale);
291 storeAppendPrintf(sentry, "refreshCounts.last_modified_factor_fresh\t%d\n",
292 refreshCounts.last_modified_factor_fresh);
293 storeAppendPrintf(sentry, "refreshCounts.last_modified_factor_stale\t%d\n",
294 refreshCounts.last_modified_factor_stale);
295 storeAppendPrintf(sentry, "refreshCounts.conf_min_age_fresh\t%d\n",
296 refreshCounts.conf_min_age_fresh);
297 storeAppendPrintf(sentry, "refreshCounts.default_stale\t%d\n",
298 refreshCounts.default_stale);
299}
300
301void
302refreshInit(void)
303{
304 cachemgrRegister("refresh",
305 "Refresh Algorithm Statistics",
306 refreshStats,
307 0,
308 1);
309}