Disk.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 20 Swap Dir base object */
10 
11 #include "squid.h"
12 #include "cache_cf.h"
13 #include "compat/strtoll.h"
14 #include "ConfigOption.h"
15 #include "ConfigParser.h"
16 #include "globals.h"
17 #include "Parsing.h"
18 #include "SquidConfig.h"
19 #include "Store.h"
20 #include "store/Disk.h"
21 #include "StoreFileSystem.h"
22 #include "tools.h"
23 
24 Store::Disk::Disk(char const *aType): theType(aType),
25  max_size(0), min_objsize(-1), max_objsize (-1),
26  path(nullptr), index(-1), disker(-1),
27  repl(nullptr), removals(0), scanned(0),
28  cleanLog(nullptr)
29 {
30  fs.blksize = 1024;
31 }
32 
34 {
35  // TODO: should we delete repl?
36  xfree(path);
37 }
38 
39 void
41 
42 void
44 
45 bool
47 {
48  return false;
49 }
50 
51 void
53 {
54  if (!doReportStat())
55  return;
56 
57  stats.swap.size = currentSize();
58  stats.swap.capacity = maxSize();
59  stats.swap.count = currentCount();
60 }
61 
62 void
64 {
65  if (!doReportStat())
66  return;
67 
68  storeAppendPrintf(&output, "Store Directory #%d (%s): %s\n", index, type(),
69  path);
70  storeAppendPrintf(&output, "FS Block Size %d Bytes\n",
71  fs.blksize);
72  statfs(output);
73 
74  if (repl) {
75  storeAppendPrintf(&output, "Removal policy: %s\n", repl->_type);
76 
77  if (repl->Stats)
78  repl->Stats(repl, &output);
79  }
80 }
81 
82 void
84 
85 void
87 
88 uint64_t
90 {
91  // XXX: Not all disk stores use Config.Swap.lowWaterMark
92  return ((maxSize() * Config.Swap.lowWaterMark) / 100);
93 }
94 
95 int64_t
97 {
98  // per-store min-size=N value is authoritative
99  return min_objsize > -1 ? min_objsize : Config.Store.minObjectSize;
100 }
101 
102 int64_t
104 {
105  // per-store max-size=N value is authoritative
106  if (max_objsize > -1)
107  return max_objsize;
108 
109  // store with no individual max limit is limited by configured maximum_object_size
110  // or the total store size, whichever is smaller
111  return min(static_cast<int64_t>(maxSize()), Config.Store.maxObjectSize);
112 }
113 
114 void
116 {
117  // negative values mean no limit (-1)
118  if (newMax < 0) {
119  max_objsize = -1; // set explicitly in case it had a non-default value previously
120  return;
121  }
122 
123  // prohibit values greater than total storage area size
124  // but set max_objsize to the maximum allowed to override maximum_object_size global config
125  if (static_cast<uint64_t>(newMax) > maxSize()) {
126  debugs(47, DBG_PARSE_NOTE(2), "WARNING: Ignoring 'max-size' option for " << path <<
127  " which is larger than total cache_dir size of " << maxSize() << " bytes.");
128  max_objsize = maxSize();
129  return;
130  }
131 
132  max_objsize = newMax;
133 }
134 
135 void
137 
138 bool
140 {
141  return true; // keep in global store_table
142 }
143 
144 void
146 {
147  if (currentSize() >= maxSize())
148  return;
149 
150  max_size = currentSize();
151 
152  debugs(20, DBG_IMPORTANT, "WARNING: Shrinking cache_dir #" << index << " to " << currentSize() / 1024.0 << " KB");
153 }
154 
155 bool
157 {
158  // need either the expected or the already accumulated object size
159  assert(objsize >= 0);
160  return minObjectSize() <= objsize && objsize <= maxObjectSize();
161 }
162 
163 bool
164 Store::Disk::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const
165 {
166  debugs(47,8, "cache_dir[" << index << "]: needs " <<
167  diskSpaceNeeded << " <? " << max_objsize);
168 
169  if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
170  return false; // we do not store Squid-generated entries
171 
172  if (!objectSizeIsAcceptable(diskSpaceNeeded))
173  return false; // does not satisfy size limits
174 
175  if (flags.read_only)
176  return false; // cannot write at all
177 
178  if (currentSize() > maxSize())
179  return false; // already overflowing
180 
181  /* Return 999 (99.9%) constant load; TODO: add a named constant for this */
182  load = 999;
183  return true; // kids may provide more tests and should report true load
184 }
185 
186 /* Move to StoreEntry ? */
187 bool
189 {
190  if (!e.hasDisk())
191  return false;
192 
193  if (!e.swappedOut())
194  return false;
195 
196  if (e.swap_file_sz <= 0)
197  return false;
198 
200  return false;
201 
202  if (EBIT_TEST(e.flags, KEY_PRIVATE))
203  return false;
204 
205  if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
206  return false;
207 
208  return true;
209 }
210 
211 void
213 
214 void
216 
217 int
219 {
220  return 0;
221 }
222 
223 void
225 
226 void
227 Store::Disk::logEntry(const StoreEntry &, int) const {}
228 
229 char const *
231 {
232  return theType;
233 }
234 
235 bool
237 {
238  if (IamWorkerProcess())
239  return true;
240 
241  // we are inside a disker dedicated to this disk
242  if (KidIdentifier == disker)
243  return true;
244 
245  return false; // Coordinator, wrong disker, etc.
246 }
247 
248 bool
250 {
251  return false;
252 }
253 
254 /* NOT performance critical. Really. Don't bother optimising for speed
255  * - RBC 20030718
256  */
257 ConfigOption *
259 {
263  return result;
264 }
265 
266 void
268 {
269  const bool old_read_only = flags.read_only;
270  char *name, *value;
271 
272  ConfigOption *newOption = getOptionTree();
273 
274  while ((name = ConfigParser::NextToken()) != nullptr) {
275  value = strchr(name, '=');
276 
277  if (value) {
278  *value = '\0'; /* cut on = */
279  ++value;
280  }
281 
282  debugs(3,2, "cache_dir " << name << '=' << (value ? value : ""));
283 
284  if (newOption)
285  if (!newOption->parse(name, value, isaReconfig)) {
286  self_destruct();
287  return;
288  }
289  }
290 
291  delete newOption;
292 
293  /*
294  * Handle notifications about reconfigured single-options with no value
295  * where the removal of the option cannot be easily detected in the
296  * parsing...
297  */
298 
299  if (isaReconfig) {
300  if (old_read_only != flags.read_only) {
301  debugs(3, DBG_IMPORTANT, "Cache dir '" << path << "' now " << (flags.read_only ? "No-Store" : "Read-Write"));
302  }
303  }
304 }
305 
306 void
308 {
309  ConfigOption *newOption = getOptionTree();
310 
311  if (newOption)
312  newOption->dump(entry);
313 
314  delete newOption;
315 }
316 
317 bool
318 Store::Disk::optionReadOnlyParse(char const *option, const char *value, int)
319 {
320  if (strcmp(option, "no-store") != 0 && strcmp(option, "read-only") != 0)
321  return false;
322 
323  if (strcmp(option, "read-only") == 0) {
324  debugs(3, DBG_PARSE_NOTE(3), "UPGRADE WARNING: Replace cache_dir option 'read-only' with 'no-store'.");
325  }
326 
327  bool read_only = 0;
328 
329  if (value)
330  read_only = (xatoi(value) != 0);
331  else
332  read_only = true;
333 
334  flags.read_only = read_only;
335 
336  return true;
337 }
338 
339 void
341 {
342  if (flags.read_only)
343  storeAppendPrintf(e, " no-store");
344 }
345 
346 bool
347 Store::Disk::optionObjectSizeParse(char const *option, const char *value, int isaReconfig)
348 {
349  int64_t *val;
350  if (strcmp(option, "max-size") == 0) {
351  val = &max_objsize;
352  } else if (strcmp(option, "min-size") == 0) {
353  val = &min_objsize;
354  } else
355  return false;
356 
357  if (!value) {
358  self_destruct();
359  return false;
360  }
361 
362  int64_t size = strtoll(value, nullptr, 10);
363 
364  if (isaReconfig && *val != size) {
365  if (allowOptionReconfigure(option)) {
366  debugs(3, DBG_IMPORTANT, "cache_dir '" << path << "' object " <<
367  option << " now " << size << " Bytes");
368  } else {
369  debugs(3, DBG_IMPORTANT, "WARNING: cache_dir '" << path << "' "
370  "object " << option << " cannot be changed dynamically, " <<
371  "value left unchanged (" << *val << " Bytes)");
372  return true;
373  }
374  }
375 
376  *val = size;
377 
378  return true;
379 }
380 
381 void
383 {
384  if (min_objsize != -1)
385  storeAppendPrintf(e, " min-size=%" PRId64, min_objsize);
386 
387  if (max_objsize != -1)
388  storeAppendPrintf(e, " max-size=%" PRId64, max_objsize);
389 }
390 
391 // some SwapDirs may maintain their indexes and be able to lookup an entry key
392 StoreEntry *
394 {
395  return nullptr;
396 }
397 
virtual void dump(StoreEntry &) const
Definition: Disk.cc:43
virtual bool doubleCheck(StoreEntry &)
Definition: Disk.cc:46
int64_t minObjectSize
Definition: SquidConfig.h:267
virtual bool parse(char const *option, const char *value, int reconfiguring)=0
virtual bool active() const
Definition: Disk.cc:236
void stat(StoreEntry &) const override
Definition: Disk.cc:63
virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const =0
check whether we can store the entry; if we can, report current load
Definition: Disk.cc:164
void reference(StoreEntry &e) override
somebody needs this entry (many cache replacement policies need to know)
Definition: Disk.cc:136
virtual void logEntry(const StoreEntry &e, int op) const
Definition: Disk.cc:227
manages a single cache_dir
Definition: Disk.h:21
unsigned char cache_key
Store key.
Definition: forward.h:29
double count
number of cached objects
Definition: StoreStats.h:21
int KidIdentifier
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:855
@ KEY_PRIVATE
Definition: enums.h:97
StoreEntry * get(const cache_key *) override
Definition: Disk.cc:393
virtual void dump(StoreEntry *e) const =0
virtual void closeLog()
Definition: Disk.cc:215
double capacity
the size limit
Definition: StoreStats.h:22
int64_t maxObjectSize() const override
the maximum size of a storable object; -1 if unlimited
Definition: Disk.cc:103
uint16_t flags
Definition: Store.h:231
bool IamWorkerProcess()
whether the current process handles HTTP transactions and such
Definition: stub_tools.cc:47
virtual void statfs(StoreEntry &) const
Definition: Disk.cc:83
int64_t minObjectSize() const
the size of the smallest entry this cache_dir can store
Definition: Disk.cc:96
struct SquidConfig::@82 Swap
void self_destruct(void)
Definition: cache_cf.cc:276
double size
bytes currently in use
Definition: StoreStats.h:20
virtual void openLog()
Definition: Disk.cc:212
std::vector< ConfigOption * > options
Definition: ConfigOption.h:74
int size
Definition: ModDevPoll.cc:69
bool dereference(StoreEntry &e) override
Definition: Disk.cc:139
#define DBG_PARSE_NOTE(x)
Definition: Stream.h:42
@ RELEASE_REQUEST
prohibits making the key public
Definition: enums.h:93
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1929
Swap swap
cache_mem stats
Definition: StoreStats.h:47
#define EBIT_TEST(flag, bit)
Definition: defines.h:67
const char * type() const
Definition: Disk.cc:230
virtual void diskFull()
Definition: Disk.cc:145
virtual bool needsDiskStrand() const
needs a dedicated kid process
Definition: Disk.cc:249
int xatoi(const char *token)
Definition: Parsing.cc:44
struct SquidConfig::@95 Store
#define assert(EX)
Definition: assert.h:17
Disk(char const *aType)
Definition: Disk.cc:24
bool objectSizeIsAcceptable(int64_t objSize) const
Definition: Disk.cc:156
bool canLog(StoreEntry const &e) const
Definition: Disk.cc:188
void optionReadOnlyDump(StoreEntry *e) const
Definition: Disk.cc:340
~Disk() override
Definition: Disk.cc:33
int64_t strtoll(const char *nptr, char **endptr, int base)
Definition: strtoll.c:61
virtual ConfigOption * getOptionTree() const
Definition: Disk.cc:258
void optionObjectSizeDump(StoreEntry *e) const
Definition: Disk.cc:382
void parseOptions(int reconfiguring)
Definition: Disk.cc:267
#define xfree
static char * NextToken()
void dumpOptions(StoreEntry *e) const
Definition: Disk.cc:307
int lowWaterMark
Definition: SquidConfig.h:86
virtual int writeCleanStart()
Definition: Disk.cc:218
void maintain() override
perform regular periodic maintenance; TODO: move to UFSSwapDir::Maintain
Definition: Disk.cc:86
virtual void writeCleanDone()
Definition: Disk.cc:224
bool optionObjectSizeParse(char const *option, const char *value, int reconfiguring)
Definition: Disk.cc:347
struct Store::Disk::@125 fs
uint64_t minSize() const override
the minimum size the store will shrink to via normal housekeeping
Definition: Disk.cc:89
uint64_t swap_file_sz
Definition: Store.h:229
@ ENTRY_SPECIAL
Definition: enums.h:79
#define DBG_IMPORTANT
Definition: Stream.h:38
int64_t maxObjectSize
Definition: SquidConfig.h:266
#define PRId64
Definition: types.h:104
void getStats(StoreInfoStats &stats) const override
collect statistics
Definition: Disk.cc:52
bool swappedOut() const
whether the entire entry is now on disk (possibly marked for deletion)
Definition: Store.h:135
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
const A & min(A const &lhs, A const &rhs)
void create() override
create system resources needed for this store to operate in the future
Definition: Disk.cc:40
High-level store statistics used by mgr:info action. Used inside PODs!
Definition: StoreStats.h:13
bool optionReadOnlyParse(char const *option, const char *value, int reconfiguring)
Definition: Disk.cc:318
class SquidConfig Config
Definition: SquidConfig.cc:12

 

Introduction

Documentation

Support

Miscellaneous