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