]>
Commit | Line | Data |
---|---|---|
d3b3ab85 | 1 | /* |
262a0e14 | 2 | * $Id$ |
d3b3ab85 | 3 | * |
507d0a78 | 4 | * DEBUG: section 20 Swap Dir base object |
d3b3ab85 | 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. | |
26ac0430 | 23 | * |
d3b3ab85 | 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. | |
26ac0430 | 28 | * |
d3b3ab85 | 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 | ||
582c2af2 | 35 | #include "squid.h" |
27bc2077 | 36 | #include "compat/strtoll.h" |
b9ae18aa | 37 | #include "ConfigOption.h" |
582c2af2 FC |
38 | #include "protos.h" |
39 | #include "StoreFileSystem.h" | |
40 | #include "SwapDir.h" | |
d3b3ab85 | 41 | |
e2851fe7 | 42 | SwapDir::SwapDir(char const *aType): theType(aType), |
a86ff82a | 43 | max_size(0), |
3b581957 | 44 | path(NULL), index(-1), disker(-1), min_objsize(0), max_objsize (-1), |
e2851fe7 AR |
45 | repl(NULL), removals(0), scanned(0), |
46 | cleanLog(NULL) | |
47 | { | |
48 | fs.blksize = 1024; | |
49 | } | |
50 | ||
62e76326 | 51 | SwapDir::~SwapDir() |
52 | { | |
e2851fe7 | 53 | // TODO: should we delete repl? |
d3b3ab85 | 54 | xfree(path); |
55 | } | |
56 | ||
57 | void | |
26ac0430 | 58 | SwapDir::create() {} |
d3b3ab85 | 59 | |
60 | void | |
26ac0430 | 61 | SwapDir::dump(StoreEntry &)const {} |
d3b3ab85 | 62 | |
63 | bool | |
64 | SwapDir::doubleCheck(StoreEntry &) | |
65 | { | |
66 | return false; | |
67 | } | |
68 | ||
69 | void | |
26ac0430 | 70 | SwapDir::unlink(StoreEntry &) {} |
d3b3ab85 | 71 | |
93bc1434 AR |
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 | ||
c8f4eac4 | 83 | void |
84 | SwapDir::stat(StoreEntry &output) const | |
85 | { | |
39c1e1d9 DK |
86 | if (!doReportStat()) |
87 | return; | |
88 | ||
c8f4eac4 | 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 | ||
d3b3ab85 | 103 | void |
104 | SwapDir::statfs(StoreEntry &)const {} | |
105 | ||
106 | void | |
26ac0430 | 107 | SwapDir::maintain() {} |
c8f4eac4 | 108 | |
12e11a5c | 109 | uint64_t |
c8f4eac4 | 110 | SwapDir::minSize() const |
111 | { | |
12e11a5c | 112 | return ((maxSize() * Config.Swap.lowWaterMark) / 100); |
c8f4eac4 | 113 | } |
d3b3ab85 | 114 | |
115 | void | |
26ac0430 | 116 | SwapDir::reference(StoreEntry &) {} |
d3b3ab85 | 117 | |
4c973beb AR |
118 | bool |
119 | SwapDir::dereference(StoreEntry &) | |
120 | { | |
121 | return true; // keep in global store_table | |
122 | } | |
d3b3ab85 | 123 | |
124 | int | |
125 | SwapDir::callback() | |
126 | { | |
127 | return 0; | |
128 | } | |
129 | ||
aa1a691e AR |
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 | ||
cc34568d | 145 | if (currentSize() > maxSize()) |
aa1a691e AR |
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 | ||
d3b3ab85 | 154 | void |
26ac0430 | 155 | SwapDir::sync() {} |
d3b3ab85 | 156 | |
157 | /* Move to StoreEntry ? */ | |
158 | bool | |
159 | SwapDir::canLog(StoreEntry const &e)const | |
160 | { | |
161 | if (e.swap_filen < 0) | |
62e76326 | 162 | return false; |
163 | ||
d3b3ab85 | 164 | if (e.swap_status != SWAPOUT_DONE) |
62e76326 | 165 | return false; |
166 | ||
d3b3ab85 | 167 | if (e.swap_file_sz <= 0) |
62e76326 | 168 | return false; |
169 | ||
d3b3ab85 | 170 | if (EBIT_TEST(e.flags, RELEASE_REQUEST)) |
62e76326 | 171 | return false; |
172 | ||
d3b3ab85 | 173 | if (EBIT_TEST(e.flags, KEY_PRIVATE)) |
62e76326 | 174 | return false; |
175 | ||
d3b3ab85 | 176 | if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) |
62e76326 | 177 | return false; |
178 | ||
d3b3ab85 | 179 | return true; |
180 | } | |
181 | ||
182 | void | |
26ac0430 | 183 | SwapDir::openLog() {} |
d3b3ab85 | 184 | |
185 | void | |
26ac0430 | 186 | SwapDir::closeLog() {} |
d3b3ab85 | 187 | |
188 | int | |
189 | SwapDir::writeCleanStart() | |
190 | { | |
191 | return 0; | |
192 | } | |
193 | ||
194 | void | |
26ac0430 | 195 | SwapDir::writeCleanDone() {} |
d3b3ab85 | 196 | |
197 | void | |
26ac0430 | 198 | SwapDir::logEntry(const StoreEntry & e, int op) const {} |
59b2d47f | 199 | |
200 | char const * | |
201 | SwapDir::type() const | |
202 | { | |
203 | return theType; | |
204 | } | |
205 | ||
14911a4e AR |
206 | bool |
207 | SwapDir::active() const | |
208 | { | |
209 | if (IamWorkerProcess()) | |
210 | return true; | |
211 | ||
212 | // we are inside a disker dedicated to this disk | |
3b581957 | 213 | if (KidIdentifier == disker) |
14911a4e AR |
214 | return true; |
215 | ||
216 | return false; // Coordinator, wrong disker, etc. | |
217 | } | |
218 | ||
219 | bool | |
220 | SwapDir::needsDiskStrand() const | |
221 | { | |
222 | return false; | |
223 | } | |
224 | ||
59b2d47f | 225 | /* NOT performance critical. Really. Don't bother optimising for speed |
26ac0430 | 226 | * - RBC 20030718 |
59b2d47f | 227 | */ |
b9ae18aa | 228 | ConfigOption * |
59b2d47f | 229 | SwapDir::getOptionTree() const |
230 | { | |
b9ae18aa | 231 | ConfigOptionVector *result = new ConfigOptionVector; |
232 | result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionReadOnlyParse, &SwapDir::optionReadOnlyDump)); | |
a8a33c46 | 233 | result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionObjectSizeParse, &SwapDir::optionObjectSizeDump)); |
59b2d47f | 234 | return result; |
235 | } | |
236 | ||
237 | void | |
e053c141 | 238 | SwapDir::parseOptions(int isaReconfig) |
59b2d47f | 239 | { |
240 | unsigned int old_read_only = flags.read_only; | |
241 | char *name, *value; | |
242 | ||
b9ae18aa | 243 | ConfigOption *newOption = getOptionTree(); |
59b2d47f | 244 | |
245 | while ((name = strtok(NULL, w_space)) != NULL) { | |
246 | value = strchr(name, '='); | |
247 | ||
f412b2d6 FC |
248 | if (value) { |
249 | *value = '\0'; /* cut on = */ | |
250 | ++value; | |
251 | } | |
59b2d47f | 252 | |
d9e04dc7 | 253 | debugs(3,2, "SwapDir::parseOptions: parsing store option '" << name << "'='" << (value ? value : "") << "'"); |
254 | ||
59b2d47f | 255 | if (newOption) |
e053c141 | 256 | if (!newOption->parse(name, value, isaReconfig)) |
59b2d47f | 257 | self_destruct(); |
258 | } | |
259 | ||
260 | delete newOption; | |
261 | ||
262 | /* | |
263 | * Handle notifications about reconfigured single-options with no value | |
264 | * where the removal of the option cannot be easily detected in the | |
265 | * parsing... | |
266 | */ | |
267 | ||
e053c141 | 268 | if (isaReconfig) { |
59b2d47f | 269 | if (old_read_only != flags.read_only) { |
e0236918 | 270 | debugs(3, DBG_IMPORTANT, "Cache dir '" << path << "' now " << (flags.read_only ? "No-Store" : "Read-Write")); |
59b2d47f | 271 | } |
272 | } | |
273 | } | |
274 | ||
275 | void | |
276 | SwapDir::dumpOptions(StoreEntry * entry) const | |
277 | { | |
b9ae18aa | 278 | ConfigOption *newOption = getOptionTree(); |
59b2d47f | 279 | |
280 | if (newOption) | |
281 | newOption->dump(entry); | |
282 | ||
283 | delete newOption; | |
284 | } | |
285 | ||
286 | bool | |
e053c141 | 287 | SwapDir::optionReadOnlyParse(char const *option, const char *value, int isaReconfig) |
59b2d47f | 288 | { |
7f42bc3e | 289 | if (strcmp(option, "no-store") != 0 && strcmp(option, "read-only") != 0) |
59b2d47f | 290 | return false; |
291 | ||
292 | int read_only = 0; | |
293 | ||
294 | if (value) | |
295 | read_only = xatoi(value); | |
296 | else | |
297 | read_only = 1; | |
298 | ||
299 | flags.read_only = read_only; | |
300 | ||
301 | return true; | |
302 | } | |
303 | ||
304 | void | |
305 | SwapDir::optionReadOnlyDump(StoreEntry * e) const | |
306 | { | |
307 | if (flags.read_only) | |
7f42bc3e | 308 | storeAppendPrintf(e, " no-store"); |
59b2d47f | 309 | } |
310 | ||
311 | bool | |
a8a33c46 | 312 | SwapDir::optionObjectSizeParse(char const *option, const char *value, int isaReconfig) |
59b2d47f | 313 | { |
a8a33c46 A |
314 | int64_t *val; |
315 | if (strcmp(option, "max-size") == 0) { | |
316 | val = &max_objsize; | |
317 | } else if (strcmp(option, "min-size") == 0) { | |
318 | val = &min_objsize; | |
319 | } else | |
59b2d47f | 320 | return false; |
321 | ||
322 | if (!value) | |
323 | self_destruct(); | |
324 | ||
47f6e231 | 325 | int64_t size = strtoll(value, NULL, 10); |
59b2d47f | 326 | |
24063512 DK |
327 | if (isaReconfig && *val != size) { |
328 | if (allowOptionReconfigure(option)) { | |
329 | debugs(3, DBG_IMPORTANT, "cache_dir '" << path << "' object " << | |
330 | option << " now " << size << " Bytes"); | |
331 | } else { | |
332 | debugs(3, DBG_IMPORTANT, "WARNING: cache_dir '" << path << "' " | |
333 | "object " << option << " cannot be changed dynamically, " << | |
334 | "value left unchanged (" << *val << " Bytes)"); | |
335 | return true; | |
336 | } | |
337 | } | |
59b2d47f | 338 | |
a8a33c46 | 339 | *val = size; |
59b2d47f | 340 | |
341 | return true; | |
342 | } | |
343 | ||
344 | void | |
a8a33c46 | 345 | SwapDir::optionObjectSizeDump(StoreEntry * e) const |
59b2d47f | 346 | { |
b6662ffd | 347 | if (min_objsize != 0) |
c91ca3ce | 348 | storeAppendPrintf(e, " min-size=%" PRId64, min_objsize); |
a8a33c46 | 349 | |
59b2d47f | 350 | if (max_objsize != -1) |
c91ca3ce | 351 | storeAppendPrintf(e, " max-size=%" PRId64, max_objsize); |
59b2d47f | 352 | } |
c8f4eac4 | 353 | |
44def0f9 | 354 | // some SwapDirs may maintain their indexes and be able to lookup an entry key |
c8f4eac4 | 355 | StoreEntry * |
6ca34f6f | 356 | SwapDir::get(const cache_key *key) |
c8f4eac4 | 357 | { |
44def0f9 | 358 | return NULL; |
c8f4eac4 | 359 | } |
360 | ||
361 | void | |
6ca34f6f | 362 | SwapDir::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData) |
c8f4eac4 | 363 | { |
364 | fatal("not implemented"); | |
365 | } |