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