]> git.ipfire.org Git - thirdparty/squid.git/blob - src/SwapDir.cc
Merged from trunk
[thirdparty/squid.git] / src / SwapDir.cc
1 /*
2 * $Id$
3 *
4 * DEBUG: section 20 Swap Dir base object
5 * AUTHOR: Robert Collins
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35 #include "squid.h"
36 #include "cache_cf.h"
37 #include "compat/strtoll.h"
38 #include "ConfigOption.h"
39 #include "Parsing.h"
40 #include "protos.h"
41 #include "StoreFileSystem.h"
42 #include "SwapDir.h"
43
44 SwapDir::SwapDir(char const *aType): theType(aType),
45 max_size(0),
46 path(NULL), index(-1), disker(-1), min_objsize(0), max_objsize (-1),
47 repl(NULL), removals(0), scanned(0),
48 cleanLog(NULL)
49 {
50 fs.blksize = 1024;
51 }
52
53 SwapDir::~SwapDir()
54 {
55 // TODO: should we delete repl?
56 xfree(path);
57 }
58
59 void
60 SwapDir::create() {}
61
62 void
63 SwapDir::dump(StoreEntry &)const {}
64
65 bool
66 SwapDir::doubleCheck(StoreEntry &)
67 {
68 return false;
69 }
70
71 void
72 SwapDir::unlink(StoreEntry &) {}
73
74 void
75 SwapDir::getStats(StoreInfoStats &stats) const
76 {
77 if (!doReportStat())
78 return;
79
80 stats.swap.size = currentSize();
81 stats.swap.capacity = maxSize();
82 stats.swap.count = currentCount();
83 }
84
85 void
86 SwapDir::stat(StoreEntry &output) const
87 {
88 if (!doReportStat())
89 return;
90
91 storeAppendPrintf(&output, "Store Directory #%d (%s): %s\n", index, type(),
92 path);
93 storeAppendPrintf(&output, "FS Block Size %d Bytes\n",
94 fs.blksize);
95 statfs(output);
96
97 if (repl) {
98 storeAppendPrintf(&output, "Removal policy: %s\n", repl->_type);
99
100 if (repl->Stats)
101 repl->Stats(repl, &output);
102 }
103 }
104
105 void
106 SwapDir::statfs(StoreEntry &)const {}
107
108 void
109 SwapDir::maintain() {}
110
111 uint64_t
112 SwapDir::minSize() const
113 {
114 return ((maxSize() * Config.Swap.lowWaterMark) / 100);
115 }
116
117 void
118 SwapDir::reference(StoreEntry &) {}
119
120 bool
121 SwapDir::dereference(StoreEntry &)
122 {
123 return true; // keep in global store_table
124 }
125
126 int
127 SwapDir::callback()
128 {
129 return 0;
130 }
131
132 bool
133 SwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const
134 {
135 debugs(47,8, HERE << "cache_dir[" << index << "]: needs " <<
136 diskSpaceNeeded << " <? " << max_objsize);
137
138 if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
139 return false; // we do not store Squid-generated entries
140
141 if (!objectSizeIsAcceptable(diskSpaceNeeded))
142 return false; // does not satisfy size limits
143
144 if (flags.read_only)
145 return false; // cannot write at all
146
147 if (currentSize() > maxSize())
148 return false; // already overflowing
149
150 /* Return 999 (99.9%) constant load; TODO: add a named constant for this */
151 load = 999;
152 return true; // kids may provide more tests and should report true load
153 }
154
155
156 void
157 SwapDir::sync() {}
158
159 /* Move to StoreEntry ? */
160 bool
161 SwapDir::canLog(StoreEntry const &e)const
162 {
163 if (e.swap_filen < 0)
164 return false;
165
166 if (e.swap_status != SWAPOUT_DONE)
167 return false;
168
169 if (e.swap_file_sz <= 0)
170 return false;
171
172 if (EBIT_TEST(e.flags, RELEASE_REQUEST))
173 return false;
174
175 if (EBIT_TEST(e.flags, KEY_PRIVATE))
176 return false;
177
178 if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
179 return false;
180
181 return true;
182 }
183
184 void
185 SwapDir::openLog() {}
186
187 void
188 SwapDir::closeLog() {}
189
190 int
191 SwapDir::writeCleanStart()
192 {
193 return 0;
194 }
195
196 void
197 SwapDir::writeCleanDone() {}
198
199 void
200 SwapDir::logEntry(const StoreEntry & e, int op) const {}
201
202 char const *
203 SwapDir::type() const
204 {
205 return theType;
206 }
207
208 bool
209 SwapDir::active() const
210 {
211 if (IamWorkerProcess())
212 return true;
213
214 // we are inside a disker dedicated to this disk
215 if (KidIdentifier == disker)
216 return true;
217
218 return false; // Coordinator, wrong disker, etc.
219 }
220
221 bool
222 SwapDir::needsDiskStrand() const
223 {
224 return false;
225 }
226
227 /* NOT performance critical. Really. Don't bother optimising for speed
228 * - RBC 20030718
229 */
230 ConfigOption *
231 SwapDir::getOptionTree() const
232 {
233 ConfigOptionVector *result = new ConfigOptionVector;
234 result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionReadOnlyParse, &SwapDir::optionReadOnlyDump));
235 result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionObjectSizeParse, &SwapDir::optionObjectSizeDump));
236 return result;
237 }
238
239 void
240 SwapDir::parseOptions(int isaReconfig)
241 {
242 unsigned int old_read_only = flags.read_only;
243 char *name, *value;
244
245 ConfigOption *newOption = getOptionTree();
246
247 while ((name = strtok(NULL, w_space)) != NULL) {
248 value = strchr(name, '=');
249
250 if (value) {
251 *value = '\0'; /* cut on = */
252 ++value;
253 }
254
255 debugs(3,2, "SwapDir::parseOptions: parsing store option '" << name << "'='" << (value ? value : "") << "'");
256
257 if (newOption)
258 if (!newOption->parse(name, value, isaReconfig))
259 self_destruct();
260 }
261
262 delete newOption;
263
264 /*
265 * Handle notifications about reconfigured single-options with no value
266 * where the removal of the option cannot be easily detected in the
267 * parsing...
268 */
269
270 if (isaReconfig) {
271 if (old_read_only != flags.read_only) {
272 debugs(3, DBG_IMPORTANT, "Cache dir '" << path << "' now " << (flags.read_only ? "No-Store" : "Read-Write"));
273 }
274 }
275 }
276
277 void
278 SwapDir::dumpOptions(StoreEntry * entry) const
279 {
280 ConfigOption *newOption = getOptionTree();
281
282 if (newOption)
283 newOption->dump(entry);
284
285 delete newOption;
286 }
287
288 bool
289 SwapDir::optionReadOnlyParse(char const *option, const char *value, int isaReconfig)
290 {
291 if (strcmp(option, "no-store") != 0 && strcmp(option, "read-only") != 0)
292 return false;
293
294 int read_only = 0;
295
296 if (value)
297 read_only = xatoi(value);
298 else
299 read_only = 1;
300
301 flags.read_only = read_only;
302
303 return true;
304 }
305
306 void
307 SwapDir::optionReadOnlyDump(StoreEntry * e) const
308 {
309 if (flags.read_only)
310 storeAppendPrintf(e, " no-store");
311 }
312
313 bool
314 SwapDir::optionObjectSizeParse(char const *option, const char *value, int isaReconfig)
315 {
316 int64_t *val;
317 if (strcmp(option, "max-size") == 0) {
318 val = &max_objsize;
319 } else if (strcmp(option, "min-size") == 0) {
320 val = &min_objsize;
321 } else
322 return false;
323
324 if (!value)
325 self_destruct();
326
327 int64_t size = strtoll(value, NULL, 10);
328
329 if (isaReconfig && *val != size) {
330 if (allowOptionReconfigure(option)) {
331 debugs(3, DBG_IMPORTANT, "cache_dir '" << path << "' object " <<
332 option << " now " << size << " Bytes");
333 } else {
334 debugs(3, DBG_IMPORTANT, "WARNING: cache_dir '" << path << "' "
335 "object " << option << " cannot be changed dynamically, " <<
336 "value left unchanged (" << *val << " Bytes)");
337 return true;
338 }
339 }
340
341 *val = size;
342
343 return true;
344 }
345
346 void
347 SwapDir::optionObjectSizeDump(StoreEntry * e) const
348 {
349 if (min_objsize != 0)
350 storeAppendPrintf(e, " min-size=%" PRId64, min_objsize);
351
352 if (max_objsize != -1)
353 storeAppendPrintf(e, " max-size=%" PRId64, max_objsize);
354 }
355
356 // some SwapDirs may maintain their indexes and be able to lookup an entry key
357 StoreEntry *
358 SwapDir::get(const cache_key *key)
359 {
360 return NULL;
361 }
362
363 void
364 SwapDir::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
365 {
366 fatal("not implemented");
367 }