]> git.ipfire.org Git - thirdparty/squid.git/blob - src/refresh.cc
change FSF address
[thirdparty/squid.git] / src / refresh.cc
1
2 /*
3 * $Id: refresh.cc,v 1.25 1998/07/20 17:20:03 wessels Exp $
4 *
5 * DEBUG: section 22 Refresh Calculation
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 *
30 */
31
32 #ifndef USE_POSIX_REGEX
33 #define USE_POSIX_REGEX /* put before includes; always use POSIX */
34 #endif
35
36 #include "squid.h"
37
38 /*
39 * Defaults:
40 * MIN NONE
41 * PCT 20%
42 * MAX 3 days
43 */
44 #define REFRESH_DEFAULT_MIN (time_t)0
45 #define REFRESH_DEFAULT_PCT 0.20
46 #define REFRESH_DEFAULT_MAX (time_t)259200
47
48 static const refresh_t * refreshLimits(const char *);
49 static const refresh_t *refreshUncompiledPattern(const char *);
50
51 static const refresh_t *
52 refreshLimits(const char *url)
53 {
54 const refresh_t *R;
55 for (R = Config.Refresh; R; R = R->next) {
56 if (!regexec(&(R->compiled_pattern), url, 0, 0, 0))
57 return R;
58 }
59 return NULL;
60 }
61
62 static const refresh_t *
63 refreshUncompiledPattern(const char *pat)
64 {
65 const refresh_t *R;
66 for (R = Config.Refresh; R; R = R->next) {
67 if (0 == strcmp(R->pattern, pat))
68 return R;
69 }
70 return NULL;
71 }
72
73 /*
74 * refreshCheck():
75 * return 1 if its time to revalidate this entry, 0 otherwise
76 */
77 int
78 refreshCheck(const StoreEntry * entry, request_t * request, time_t delta)
79 {
80 const refresh_t *R;
81 const char *uri;
82 time_t min = REFRESH_DEFAULT_MIN;
83 double pct = REFRESH_DEFAULT_PCT;
84 time_t max = REFRESH_DEFAULT_MAX;
85 const char *pattern = ".";
86 time_t age;
87 double factor;
88 time_t check_time = squid_curtime + delta;
89 if (entry->mem_obj)
90 uri = entry->mem_obj->url;
91 else
92 uri = urlCanonical(request);
93 debug(22, 3) ("refreshCheck: '%s'\n", uri);
94 if (EBIT_TEST(entry->flag, ENTRY_REVALIDATE)) {
95 debug(22, 3) ("refreshCheck: YES: Required Authorization\n");
96 return 1;
97 }
98 if ((R = refreshLimits(uri))) {
99 min = R->min;
100 pct = R->pct;
101 max = R->max;
102 pattern = R->pattern;
103 }
104 debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
105 pattern, (int) min, (int) (100.0 * pct), (int) max);
106 age = check_time - entry->timestamp;
107 debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
108 debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
109 debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));
110 if (request->max_age > -1) {
111 if (age > request->max_age) {
112 debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
113 return 1;
114 }
115 }
116 if (age <= min) {
117 debug(22, 3) ("refreshCheck: NO: age < min\n");
118 return 0;
119 }
120 if (-1 < entry->expires) {
121 if (entry->expires <= check_time) {
122 debug(22, 3) ("refreshCheck: YES: expires <= curtime\n");
123 return 1;
124 } else {
125 debug(22, 3) ("refreshCheck: NO: expires > curtime\n");
126 return 0;
127 }
128 }
129 if (age > max) {
130 debug(22, 3) ("refreshCheck: YES: age > max\n");
131 return 1;
132 }
133 if (entry->timestamp <= entry->lastmod) {
134 if (request->protocol != PROTO_HTTP) {
135 debug(22, 3) ("refreshCheck: NO: non-HTTP request\n");
136 return 0;
137 }
138 debug(22, 3) ("refreshCheck: YES: lastvalid <= lastmod (%d <= %d)\n",
139 (int) entry->timestamp, (int) entry->lastmod);
140 return 1;
141 }
142 factor = (double) age / (double) (entry->timestamp - entry->lastmod);
143 debug(22, 3) ("refreshCheck: factor = %f\n", factor);
144 if (factor < pct) {
145 debug(22, 3) ("refreshCheck: NO: factor < pct\n");
146 return 0;
147 }
148 return 1;
149 }
150
151 /* returns an approximate time when refreshCheck() may return true */
152 time_t
153 refreshWhen(const StoreEntry * entry)
154 {
155 const refresh_t *R;
156 time_t refresh_time = squid_curtime;
157 time_t min = REFRESH_DEFAULT_MIN;
158 time_t max = REFRESH_DEFAULT_MAX;
159 double pct = REFRESH_DEFAULT_PCT;
160 const char *pattern = ".";
161 if (entry->mem_obj) {
162 assert(entry->mem_obj->url);
163 debug(22, 3) ("refreshWhen: key '%s'\n", storeKeyText(entry->key));
164 debug(22, 3) ("refreshWhen: url '%s'\n", entry->mem_obj->url);
165 if (EBIT_TEST(entry->flag, ENTRY_REVALIDATE)) {
166 debug(22, 3) ("refreshWhen: NOW: Required Authorization\n");
167 return refresh_time;
168 }
169 debug(22, 3) ("refreshWhen: entry: exp: %d, tstamp: %d, lmt: %d\n",
170 entry->expires, entry->timestamp, entry->lastmod);
171 R = refreshLimits(entry->mem_obj->url);
172 } else {
173 R = refreshUncompiledPattern(".");
174 }
175 if (R != NULL) {
176 min = R->min;
177 max = R->max;
178 pct = R->pct;
179 pattern = R->pattern;
180 }
181 debug(22, 3) ("refreshWhen: Matched '%s %d %d%% %d'\n",
182 pattern, (int) min, (int) (100.0 * pct), (int) max);
183 /* convert to absolute numbers */
184 min += entry->timestamp;
185 max += entry->timestamp;
186 if (-1 < entry->expires) {
187 debug(22, 3) ("refreshWhen: expires set\n");
188 refresh_time = entry->expires;
189 } else if (entry->timestamp <= entry->lastmod) {
190 debug(22, 3) ("refreshWhen: lastvalid <= lastmod\n");
191 refresh_time = squid_curtime;
192 } else {
193 refresh_time = (entry->timestamp - entry->lastmod) * pct + entry->timestamp;
194 debug(22, 3) ("refreshWhen: using refresh pct\n");
195 }
196 /* take min/max into account, max takes priority over min */
197 if (refresh_time < min)
198 refresh_time = min;
199 if (refresh_time > max)
200 refresh_time = max;
201 debug(22, 3) ("refreshWhen: answer: %d (in %d secs)\n",
202 refresh_time, (int) (refresh_time - squid_curtime));
203 return refresh_time;
204 }
205
206 time_t
207 getMaxAge(const char *url)
208 {
209 const refresh_t *R;
210 debug(22, 3) ("getMaxAge: '%s'\n", url);
211 if ((R = refreshLimits(url)))
212 return R->max;
213 else
214 return REFRESH_DEFAULT_MAX;
215 }