MemStore.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 Memory Cache */
10 
11 #include "squid.h"
12 #include "base/RunnersRegistry.h"
13 #include "CollapsedForwarding.h"
14 #include "HttpReply.h"
15 #include "ipc/mem/Page.h"
16 #include "ipc/mem/Pages.h"
17 #include "MemObject.h"
18 #include "MemStore.h"
19 #include "mime_header.h"
20 #include "SquidConfig.h"
21 #include "SquidMath.h"
22 #include "StoreStats.h"
23 #include "tools.h"
24 
26 static const SBuf MapLabel("cache_mem_map");
28 static const char *SpaceLabel = "cache_mem_space";
30 static const char *ExtrasLabel = "cache_mem_ex";
31 // TODO: sync with Rock::SwapDir::*Path()
32 
33 // We store free slot IDs (i.e., "space") as Page objects so that we can use
34 // Ipc::Mem::PageStack. Pages require pool IDs. The value here is not really
35 // used except for a positivity test. A unique value is handy for debugging.
36 static const uint32_t SpacePoolId = 510716;
37 
40 class ShmWriter: public Packable
41 {
42 public:
43  ShmWriter(MemStore &aStore, StoreEntry *anEntry, const sfileno aFileNo, Ipc::StoreMapSliceId aFirstSlice = -1);
44 
45  /* Packable API */
46  virtual void append(const char *aBuf, int aSize) override;
47  virtual void vappendf(const char *fmt, va_list ap) override;
48 
49 public:
51 
55 
58 
59  uint64_t totalWritten;
60 
61 protected:
62  void copyToShm();
64 
65 private:
67  const sfileno fileNo;
68 
69  /* set by (and only valid during) append calls */
70  const char *buf;
71  int bufSize;
72  int bufWritten;
73 };
74 
75 /* ShmWriter */
76 
77 ShmWriter::ShmWriter(MemStore &aStore, StoreEntry *anEntry, const sfileno aFileNo, Ipc::StoreMapSliceId aFirstSlice):
78  entry(anEntry),
79  firstSlice(aFirstSlice),
80  lastSlice(firstSlice),
81  totalWritten(0),
82  store(aStore),
83  fileNo(aFileNo),
84  buf(nullptr),
85  bufSize(0),
86  bufWritten(0)
87 {
88  Must(entry);
89 }
90 
91 void
92 ShmWriter::append(const char *aBuf, int aBufSize)
93 {
94  Must(!buf);
95  buf = aBuf;
96  bufSize = aBufSize;
97  if (bufSize) {
98  Must(buf);
99  bufWritten = 0;
100  copyToShm();
101  }
102  buf = nullptr;
103  bufSize = 0;
104  bufWritten = 0;
105 }
106 
107 void
108 ShmWriter::vappendf(const char *fmt, va_list ap)
109 {
110  SBuf vaBuf;
111 #if defined(VA_COPY)
112  va_list apCopy;
113  VA_COPY(apCopy, ap);
114  vaBuf.vappendf(fmt, apCopy);
115  va_end(apCopy);
116 #else
117  vaBuf.vappendf(fmt, ap);
118 #endif
119  append(vaBuf.rawContent(), vaBuf.length());
120 }
121 
123 void
125 {
126  Must(bufSize > 0); // do not use up shared memory pages for nothing
127  Must(firstSlice < 0 || lastSlice >= 0);
128 
129  // fill, skip slices that are already full
130  while (bufWritten < bufSize) {
132  if (firstSlice < 0)
134  copyToShmSlice(slice);
135  }
136 
137  debugs(20, 7, "stored " << bufWritten << '/' << totalWritten << " header bytes of " << *entry);
138 }
139 
141 void
143 {
145  debugs(20, 7, "entry " << *entry << " slice " << lastSlice << " has " <<
146  page);
147 
148  Must(bufWritten <= bufSize);
149  const int64_t writingDebt = bufSize - bufWritten;
150  const int64_t pageSize = Ipc::Mem::PageSize();
151  const int64_t sliceOffset = totalWritten % pageSize;
152  const int64_t copySize = std::min(writingDebt, pageSize - sliceOffset);
153  memcpy(static_cast<char*>(PagePointer(page)) + sliceOffset, buf + bufWritten,
154  copySize);
155 
156  debugs(20, 7, "copied " << slice.size << '+' << copySize << " bytes of " <<
157  entry << " from " << sliceOffset << " in " << page);
158 
159  slice.size += copySize;
160  bufWritten += copySize;
161  totalWritten += copySize;
162  // fresh anchor.basics.swap_file_sz is already set [to the stale value]
163 
164  // either we wrote everything or we filled the entire slice
165  Must(bufWritten == bufSize || sliceOffset + copySize == pageSize);
166 }
167 
168 /* MemStore */
169 
170 MemStore::MemStore(): map(NULL), lastWritingSlice(-1)
171 {
172 }
173 
175 {
176  delete map;
177 }
178 
179 void
181 {
182  const int64_t entryLimit = EntryLimit();
183  if (entryLimit <= 0)
184  return; // no memory cache configured or a misconfiguration
185 
186  // check compatibility with the disk cache, if any
187  if (Config.cacheSwap.n_configured > 0) {
188  const int64_t diskMaxSize = Store::Root().maxObjectSize();
189  const int64_t memMaxSize = maxObjectSize();
190  if (diskMaxSize == -1) {
191  debugs(20, DBG_IMPORTANT, "WARNING: disk-cache maximum object size "
192  "is unlimited but mem-cache maximum object size is " <<
193  memMaxSize / 1024.0 << " KB");
194  } else if (diskMaxSize > memMaxSize) {
195  debugs(20, DBG_IMPORTANT, "WARNING: disk-cache maximum object size "
196  "is too large for mem-cache: " <<
197  diskMaxSize / 1024.0 << " KB > " <<
198  memMaxSize / 1024.0 << " KB");
199  }
200  }
201 
204 
205  Must(!map);
206  map = new MemStoreMap(MapLabel);
207  map->cleaner = this;
208 }
209 
210 void
212 {
213  const size_t pageSize = Ipc::Mem::PageSize();
214 
215  stats.mem.shared = true;
216  stats.mem.capacity =
218  stats.mem.size =
220  stats.mem.count = currentCount();
221 }
222 
223 void
225 {
226  storeAppendPrintf(&e, "\n\nShared Memory Cache\n");
227 
228  storeAppendPrintf(&e, "Maximum Size: %.0f KB\n", maxSize()/1024.0);
229  storeAppendPrintf(&e, "Current Size: %.2f KB %.2f%%\n",
230  currentSize() / 1024.0,
232 
233  if (map) {
234  const int entryLimit = map->entryLimit();
235  const int slotLimit = map->sliceLimit();
236  storeAppendPrintf(&e, "Maximum entries: %9d\n", entryLimit);
237  if (entryLimit > 0) {
238  storeAppendPrintf(&e, "Current entries: %" PRId64 " %.2f%%\n",
239  currentCount(), (100.0 * currentCount() / entryLimit));
240  }
241 
242  storeAppendPrintf(&e, "Maximum slots: %9d\n", slotLimit);
243  if (slotLimit > 0) {
244  const unsigned int slotsFree =
246  if (slotsFree <= static_cast<const unsigned int>(slotLimit)) {
247  const int usedSlots = slotLimit - static_cast<const int>(slotsFree);
248  storeAppendPrintf(&e, "Used slots: %9d %.2f%%\n",
249  usedSlots, (100.0 * usedSlots / slotLimit));
250  }
251 
252  if (slotLimit < 100) { // XXX: otherwise too expensive to count
254  map->updateStats(stats);
255  stats.dump(e);
256  }
257  }
258  }
259 }
260 
261 void
263 {
264 }
265 
266 uint64_t
268 {
269  return 0; // XXX: irrelevant, but Store parent forces us to implement this
270 }
271 
272 uint64_t
274 {
275  return Config.memMaxSize;
276 }
277 
278 uint64_t
280 {
283 }
284 
285 uint64_t
287 {
288  return map ? map->entryCount() : 0;
289 }
290 
291 int64_t
293 {
295 }
296 
297 void
299 {
300 }
301 
302 bool
304 {
305  // no need to keep e in the global store_table for us; we have our own map
306  return false;
307 }
308 
309 StoreEntry *
311 {
312  if (!map)
313  return NULL;
314 
315  sfileno index;
316  const Ipc::StoreMapAnchor *const slot = map->openForReading(key, index);
317  if (!slot)
318  return NULL;
319 
320  // create a brand new store entry and initialize it with stored info
321  StoreEntry *e = new StoreEntry();
322 
323  // XXX: We do not know the URLs yet, only the key, but we need to parse and
324  // store the response for the Root().get() callers to be happy because they
325  // expect IN_MEMORY entries to already have the response headers and body.
326  e->createMemObject();
327 
328  anchorEntry(*e, index, *slot);
329 
330  const bool copied = copyFromShm(*e, index, *slot);
331 
332  if (copied) {
333  e->hashInsert(key);
334  return e;
335  }
336 
337  debugs(20, 3, HERE << "mem-loading failed; freeing " << index);
338  map->freeEntry(index); // do not let others into the same trap
339  return NULL;
340 }
341 
342 void
344 {
345  if (!map)
346  return;
347 
348  Ipc::StoreMapUpdate update(updatedE);
349  assert(updatedE);
350  assert(updatedE->mem_obj);
351  if (!map->openForUpdating(update, updatedE->mem_obj->memCache.index))
352  return;
353 
354  try {
355  updateHeadersOrThrow(update);
356  } catch (const std::exception &ex) {
357  debugs(20, 2, "error starting to update entry " << *updatedE << ": " << ex.what());
358  map->abortUpdating(update);
359  }
360 }
361 
362 void
364 {
365  // our +/- hdr_sz math below does not work if the chains differ [in size]
367 
368  const HttpReply *rawReply = update.entry->getReply();
369  Must(rawReply);
370  const HttpReply &reply = *rawReply;
371  const uint64_t staleHdrSz = reply.hdr_sz;
372  debugs(20, 7, "stale hdr_sz: " << staleHdrSz);
373 
374  /* we will need to copy same-slice payload after the stored headers later */
375  Must(staleHdrSz > 0);
376  update.stale.splicingPoint = map->sliceContaining(update.stale.fileNo, staleHdrSz);
377  Must(update.stale.splicingPoint >= 0);
378  Must(update.stale.anchor->basics.swap_file_sz >= staleHdrSz);
379 
380  Must(update.stale.anchor);
381  ShmWriter writer(*this, update.entry, update.fresh.fileNo);
382  reply.packHeadersInto(&writer);
383  const uint64_t freshHdrSz = writer.totalWritten;
384  debugs(20, 7, "fresh hdr_sz: " << freshHdrSz << " diff: " << (freshHdrSz - staleHdrSz));
385 
386  /* copy same-slice payload remaining after the stored headers */
387  const Ipc::StoreMapSlice &slice = map->readableSlice(update.stale.fileNo, update.stale.splicingPoint);
388  const Ipc::StoreMapSlice::Size sliceCapacity = Ipc::Mem::PageSize();
389  const Ipc::StoreMapSlice::Size headersInLastSlice = staleHdrSz % sliceCapacity;
390  Must(headersInLastSlice > 0); // or sliceContaining() would have stopped earlier
391  Must(slice.size >= headersInLastSlice);
392  const Ipc::StoreMapSlice::Size payloadInLastSlice = slice.size - headersInLastSlice;
393  const MemStoreMapExtras::Item &extra = extras->items[update.stale.splicingPoint];
394  char *page = static_cast<char*>(PagePointer(extra.page));
395  debugs(20, 5, "appending same-slice payload: " << payloadInLastSlice);
396  writer.append(page + headersInLastSlice, payloadInLastSlice);
397  update.fresh.splicingPoint = writer.lastSlice;
398 
399  update.fresh.anchor->basics.swap_file_sz -= staleHdrSz;
400  update.fresh.anchor->basics.swap_file_sz += freshHdrSz;
401 
402  map->closeForUpdating(update);
403 }
404 
405 bool
406 MemStore::anchorCollapsed(StoreEntry &collapsed, bool &inSync)
407 {
408  if (!map)
409  return false;
410 
411  sfileno index;
412  const Ipc::StoreMapAnchor *const slot = map->openForReading(
413  reinterpret_cast<cache_key*>(collapsed.key), index);
414  if (!slot)
415  return false;
416 
417  anchorEntry(collapsed, index, *slot);
418  inSync = updateCollapsedWith(collapsed, index, *slot);
419  return true; // even if inSync is false
420 }
421 
422 bool
424 {
425  assert(collapsed.mem_obj);
426 
427  const sfileno index = collapsed.mem_obj->memCache.index;
428 
429  // already disconnected from the cache, no need to update
430  if (index < 0)
431  return true;
432 
433  if (!map)
434  return false;
435 
436  const Ipc::StoreMapAnchor &anchor = map->readableEntry(index);
437  return updateCollapsedWith(collapsed, index, anchor);
438 }
439 
441 bool
443 {
444  collapsed.swap_file_sz = anchor.basics.swap_file_sz;
445  const bool copied = copyFromShm(collapsed, index, anchor);
446  return copied;
447 }
448 
450 void
452 {
453  const Ipc::StoreMapAnchor::Basics &basics = anchor.basics;
454 
455  e.swap_file_sz = basics.swap_file_sz;
456  e.lastref = basics.lastref;
457  e.timestamp = basics.timestamp;
458  e.expires = basics.expires;
459  e.lastModified(basics.lastmod);
460  e.refcount = basics.refcount;
461  e.flags = basics.flags;
462 
463  assert(e.mem_obj);
464  if (anchor.complete()) {
468  } else {
470  assert(e.mem_obj->object_sz < 0);
472  }
473  assert(e.swap_status == SWAPOUT_NONE); // set in StoreEntry constructor
475 
477  e.clearPrivate();
479 
481  mc.index = index;
483 }
484 
486 bool
488 {
489  debugs(20, 7, "mem-loading entry " << index << " from " << anchor.start);
490  assert(e.mem_obj);
491 
492  // emulate the usual Store code but w/o inapplicable checks and callbacks:
493 
494  Ipc::StoreMapSliceId sid = anchor.start; // optimize: remember the last sid
495  bool wasEof = anchor.complete() && sid < 0;
496  int64_t sliceOffset = 0;
497  while (sid >= 0) {
498  const Ipc::StoreMapSlice &slice = map->readableSlice(index, sid);
499  // slice state may change during copying; take snapshots now
500  wasEof = anchor.complete() && slice.next < 0;
501  const Ipc::StoreMapSlice::Size wasSize = slice.size;
502 
503  debugs(20, 9, "entry " << index << " slice " << sid << " eof " <<
504  wasEof << " wasSize " << wasSize << " <= " <<
505  anchor.basics.swap_file_sz << " sliceOffset " << sliceOffset <<
506  " mem.endOffset " << e.mem_obj->endOffset());
507 
508  if (e.mem_obj->endOffset() < sliceOffset + wasSize) {
509  // size of the slice data that we already copied
510  const size_t prefixSize = e.mem_obj->endOffset() - sliceOffset;
511  assert(prefixSize <= wasSize);
512 
513  const MemStoreMapExtras::Item &extra = extras->items[sid];
514 
515  char *page = static_cast<char*>(PagePointer(extra.page));
516  const StoreIOBuffer sliceBuf(wasSize - prefixSize,
517  e.mem_obj->endOffset(),
518  page + prefixSize);
519  if (!copyFromShmSlice(e, sliceBuf, wasEof))
520  return false;
521  debugs(20, 9, "entry " << index << " copied slice " << sid <<
522  " from " << extra.page << '+' << prefixSize);
523  }
524  // else skip a [possibly incomplete] slice that we copied earlier
525 
526  // careful: the slice may have grown _and_ gotten the next slice ID!
527  if (slice.next >= 0) {
528  assert(!wasEof);
529  // here we know that slice.size may not change any more
530  if (wasSize >= slice.size) { // did not grow since we started copying
531  sliceOffset += wasSize;
532  sid = slice.next;
533  }
534  } else if (wasSize >= slice.size) { // did not grow
535  break;
536  }
537  }
538 
539  if (!wasEof) {
540  debugs(20, 7, "mem-loaded " << e.mem_obj->endOffset() << '/' <<
541  anchor.basics.swap_file_sz << " bytes of " << e);
542  return true;
543  }
544 
545  debugs(20, 7, "mem-loaded all " << e.mem_obj->object_sz << '/' <<
546  anchor.basics.swap_file_sz << " bytes of " << e);
547 
548  // from StoreEntry::complete()
552 
553  assert(e.mem_obj->object_sz >= 0);
554  assert(static_cast<uint64_t>(e.mem_obj->object_sz) == anchor.basics.swap_file_sz);
555  // would be nice to call validLength() here, but it needs e.key
556 
557  // we read the entire response into the local memory; no more need to lock
558  disconnect(e);
559  return true;
560 }
561 
563 bool
565 {
566  debugs(20, 7, "buf: " << buf.offset << " + " << buf.length);
567 
568  // from store_client::readBody()
569  // parse headers if needed; they might span multiple slices!
570  HttpReply *rep = (HttpReply *)e.getReply();
571  if (rep->pstate < Http::Message::psParsed) {
572  // XXX: have to copy because httpMsgParseStep() requires 0-termination
573  MemBuf mb;
574  mb.init(buf.length+1, buf.length+1);
575  mb.append(buf.data, buf.length);
576  mb.terminate();
577  const int result = rep->httpMsgParseStep(mb.buf, buf.length, eof);
578  if (result > 0) {
581  } else if (result < 0) {
582  debugs(20, DBG_IMPORTANT, "Corrupted mem-cached headers: " << e);
583  return false;
584  } else { // more slices are needed
585  assert(!eof);
586  }
587  }
588  debugs(20, 7, "rep pstate: " << rep->pstate);
589 
590  // local memory stores both headers and body so copy regardless of pstate
591  const int64_t offBefore = e.mem_obj->endOffset();
592  assert(e.mem_obj->data_hdr.write(buf)); // from MemObject::write()
593  const int64_t offAfter = e.mem_obj->endOffset();
594  // expect to write the entire buf because StoreEntry::write() never fails
595  assert(offAfter >= 0 && offBefore <= offAfter &&
596  static_cast<size_t>(offAfter - offBefore) == buf.length);
597  return true;
598 }
599 
601 bool
603 {
604  if (e.mem_status == IN_MEMORY) {
605  debugs(20, 5, "already loaded from mem-cache: " << e);
606  return false;
607  }
608 
609  if (e.mem_obj && e.mem_obj->memCache.offset > 0) {
610  debugs(20, 5, "already written to mem-cache: " << e);
611  return false;
612  }
613 
614  if (!e.memoryCachable()) {
615  debugs(20, 7, HERE << "Not memory cachable: " << e);
616  return false; // will not cache due to entry state or properties
617  }
618 
619  assert(e.mem_obj);
620 
621  if (!e.mem_obj->vary_headers.isEmpty()) {
622  // XXX: We must store/load SerialisedMetaData to cache Vary in RAM
623  debugs(20, 5, "Vary not yet supported: " << e.mem_obj->vary_headers);
624  return false;
625  }
626 
627  const int64_t expectedSize = e.mem_obj->expectedReplySize(); // may be < 0
628  const int64_t loadedSize = e.mem_obj->endOffset();
629  const int64_t ramSize = max(loadedSize, expectedSize);
630  if (ramSize > maxObjectSize()) {
631  debugs(20, 5, HERE << "Too big max(" <<
632  loadedSize << ", " << expectedSize << "): " << e);
633  return false; // will not cache due to cachable entry size limits
634  }
635 
636  if (!e.mem_obj->isContiguous()) {
637  debugs(20, 5, "not contiguous");
638  return false;
639  }
640 
641  if (!map) {
642  debugs(20, 5, HERE << "No map to mem-cache " << e);
643  return false;
644  }
645 
646  if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) {
647  debugs(20, 5, "Not mem-caching ENTRY_SPECIAL " << e);
648  return false;
649  }
650 
651  return true;
652 }
653 
655 bool
657 {
658  sfileno index = 0;
659  Ipc::StoreMapAnchor *slot = map->openForWriting(reinterpret_cast<const cache_key *>(e.key), index);
660  if (!slot) {
661  debugs(20, 5, HERE << "No room in mem-cache map to index " << e);
662  return false;
663  }
664 
665  assert(e.mem_obj);
666  e.mem_obj->memCache.index = index;
668  slot->set(e);
669  // Do not allow others to feed off an unknown-size entry because we will
670  // stop swapping it out if it grows too large.
671  if (e.mem_obj->expectedReplySize() >= 0)
672  map->startAppending(index);
673  e.memOutDecision(true);
674  return true;
675 }
676 
678 void
680 {
681  // prevents remote readers from getting ENTRY_FWD_HDR_WAIT entries and
682  // not knowing when the wait is over
684  debugs(20, 5, "postponing copying " << e << " for ENTRY_FWD_HDR_WAIT");
685  return;
686  }
687 
688  assert(map);
689  assert(e.mem_obj);
690 
691  const int64_t eSize = e.mem_obj->endOffset();
692  if (e.mem_obj->memCache.offset >= eSize) {
693  debugs(20, 5, "postponing copying " << e << " for lack of news: " <<
694  e.mem_obj->memCache.offset << " >= " << eSize);
695  return; // nothing to do (yet)
696  }
697 
698  // throw if an accepted unknown-size entry grew too big or max-size changed
699  Must(eSize <= maxObjectSize());
700 
701  const int32_t index = e.mem_obj->memCache.index;
702  assert(index >= 0);
703  Ipc::StoreMapAnchor &anchor = map->writeableEntry(index);
704  lastWritingSlice = anchor.start;
705 
706  // fill, skip slices that are already full
707  // Optimize: remember lastWritingSlice in e.mem_obj
708  while (e.mem_obj->memCache.offset < eSize) {
711  if (anchor.start < 0)
712  anchor.start = lastWritingSlice;
713  copyToShmSlice(e, anchor, slice);
714  }
715 
716  debugs(20, 7, "mem-cached available " << eSize << " bytes of " << e);
717 }
718 
720 void
722 {
724  debugs(20, 7, "entry " << e << " slice " << lastWritingSlice << " has " <<
725  page);
726 
727  const int64_t bufSize = Ipc::Mem::PageSize();
728  const int64_t sliceOffset = e.mem_obj->memCache.offset % bufSize;
729  StoreIOBuffer sharedSpace(bufSize - sliceOffset, e.mem_obj->memCache.offset,
730  static_cast<char*>(PagePointer(page)) + sliceOffset);
731 
732  // check that we kept everything or purge incomplete/sparse cached entry
733  const ssize_t copied = e.mem_obj->data_hdr.copy(sharedSpace);
734  if (copied <= 0) {
735  debugs(20, 2, "Failed to mem-cache " << (bufSize - sliceOffset) <<
736  " bytes of " << e << " from " << e.mem_obj->memCache.offset <<
737  " in " << page);
738  throw TexcHere("data_hdr.copy failure");
739  }
740 
741  debugs(20, 7, "mem-cached " << copied << " bytes of " << e <<
742  " from " << e.mem_obj->memCache.offset << " in " << page);
743 
744  slice.size += copied;
745  e.mem_obj->memCache.offset += copied;
747 }
748 
752 MemStore::nextAppendableSlice(const sfileno fileNo, sfileno &sliceOffset)
753 {
754  // allocate the very first slot for the entry if needed
755  if (sliceOffset < 0) {
756  Ipc::StoreMapAnchor &anchor = map->writeableEntry(fileNo);
757  Must(anchor.start < 0);
758  Ipc::Mem::PageId page;
759  sliceOffset = reserveSapForWriting(page); // throws
760  extras->items[sliceOffset].page = page;
761  anchor.start = sliceOffset;
762  }
763 
764  const size_t sliceCapacity = Ipc::Mem::PageSize();
765  do {
766  Ipc::StoreMap::Slice &slice = map->writeableSlice(fileNo, sliceOffset);
767 
768  if (slice.size >= sliceCapacity) {
769  if (slice.next >= 0) {
770  sliceOffset = slice.next;
771  continue;
772  }
773 
774  Ipc::Mem::PageId page;
775  slice.next = sliceOffset = reserveSapForWriting(page);
776  extras->items[sliceOffset].page = page;
777  debugs(20, 7, "entry " << fileNo << " new slice: " << sliceOffset);
778  continue; // to get and return the slice at the new sliceOffset
779  }
780 
781  return slice;
782  } while (true);
783  /* not reached */
784 }
785 
789 {
790  Must(extras);
791  Must(sliceId >= 0);
792  Ipc::Mem::PageId page = extras->items[sliceId].page;
793  Must(page);
794  return page;
795 }
796 
798 sfileno
800 {
801  Ipc::Mem::PageId slot;
802  if (freeSlots->pop(slot)) {
803  debugs(20, 5, "got a previously free slot: " << slot);
804 
806  debugs(20, 5, "and got a previously free page: " << page);
807  return slot.number - 1;
808  } else {
809  debugs(20, 3, "but there is no free page, returning " << slot);
810  freeSlots->push(slot);
811  }
812  }
813 
814  // catch free slots delivered to noteFreeMapSlice()
815  assert(!waitingFor);
816  waitingFor.slot = &slot;
817  waitingFor.page = &page;
818  if (map->purgeOne()) {
819  assert(!waitingFor); // noteFreeMapSlice() should have cleared it
820  assert(slot.set());
821  assert(page.set());
822  debugs(20, 5, "got previously busy " << slot << " and " << page);
823  return slot.number - 1;
824  }
825  assert(waitingFor.slot == &slot && waitingFor.page == &page);
826  waitingFor.slot = NULL;
827  waitingFor.page = NULL;
828 
829  debugs(47, 3, "cannot get a slice; entries: " << map->entryCount());
830  throw TexcHere("ran out of mem-cache slots");
831 }
832 
833 void
835 {
836  Ipc::Mem::PageId &pageId = extras->items[sliceId].page;
837  debugs(20, 9, "slice " << sliceId << " freed " << pageId);
838  assert(pageId);
839  Ipc::Mem::PageId slotId;
840  slotId.pool = SpacePoolId;
841  slotId.number = sliceId + 1;
842  if (!waitingFor) {
843  // must zero pageId before we give slice (and pageId extras!) to others
844  Ipc::Mem::PutPage(pageId);
845  freeSlots->push(slotId);
846  } else {
847  *waitingFor.slot = slotId;
848  *waitingFor.page = pageId;
849  waitingFor.slot = NULL;
850  waitingFor.page = NULL;
851  pageId = Ipc::Mem::PageId();
852  }
853 }
854 
855 void
857 {
858  assert(e.mem_obj);
859 
860  debugs(20, 7, "entry " << e);
861 
862  switch (e.mem_obj->memCache.io) {
864  if (!shouldCache(e) || !startCaching(e)) {
866  e.memOutDecision(false);
867  return;
868  }
869  break;
870 
871  case MemObject::ioDone:
873  return; // we should not write in all of the above cases
874 
876  break; // already decided to write and still writing
877  }
878 
879  try {
880  copyToShm(e);
881  if (e.store_status == STORE_OK) // done receiving new content
882  completeWriting(e);
883  else
885  return;
886  } catch (const std::exception &x) { // TODO: should we catch ... as well?
887  debugs(20, 2, "mem-caching error writing entry " << e << ": " << x.what());
888  // fall through to the error handling code
889  }
890 
891  disconnect(e);
892 }
893 
894 void
896 {
897  assert(e.mem_obj);
898  const int32_t index = e.mem_obj->memCache.index;
899  assert(index >= 0);
900  assert(map);
901 
902  debugs(20, 5, "mem-cached all " << e.mem_obj->memCache.offset << " bytes of " << e);
903 
904  e.mem_obj->memCache.index = -1;
906  map->closeForWriting(index, false);
907 
908  CollapsedForwarding::Broadcast(e); // before we close our transient entry!
910 }
911 
912 void
914 {
915  assert(e.mem_obj);
916  if (e.mem_obj->memCache.index >= 0)
918 }
919 
920 void
922 {
923  if (e.mem_obj && e.mem_obj->memCache.index >= 0) {
925  disconnect(e);
926  } else if (map) {
927  // the entry may have been loaded and then disconnected from the cache
928  map->freeEntryByKey(reinterpret_cast<cache_key*>(e.key));
929  }
930 
931  e.destroyMemObject(); // XXX: but it may contain useful info such as a client list. The old code used to do that though, right?
932 }
933 
934 void
936 {
937  assert(e.mem_obj);
938  MemObject &mem_obj = *e.mem_obj;
939  if (mem_obj.memCache.index >= 0) {
940  if (mem_obj.memCache.io == MemObject::ioWriting) {
941  map->abortWriting(mem_obj.memCache.index);
942  mem_obj.memCache.index = -1;
943  mem_obj.memCache.io = MemObject::ioDone;
944  Store::Root().transientsAbandon(e); // broadcasts after the change
945  } else {
947  map->closeForReading(mem_obj.memCache.index);
948  mem_obj.memCache.index = -1;
949  mem_obj.memCache.io = MemObject::ioDone;
950  }
951  }
952 }
953 
955 int64_t
957 {
959  return 0; // no memory cache configured
960 
961  const int64_t minEntrySize = Ipc::Mem::PageSize();
962  const int64_t entryLimit = Config.memMaxSize / minEntrySize;
963  return entryLimit;
964 }
965 
970 {
971 public:
972  /* RegisteredRunner API */
974  virtual void finalizeConfig();
975  virtual void claimMemoryNeeds();
976  virtual void useConfig();
977  virtual ~MemStoreRr();
978 
979 protected:
980  /* Ipc::Mem::RegisteredRunner API */
981  virtual void create();
982 
983 private:
987 };
988 
990 
991 void
993 {
995 }
996 
997 void
999 {
1000  // decide whether to use a shared memory cache if the user did not specify
1001  if (!Config.memShared.configured()) {
1003  Config.memMaxSize > 0);
1004  } else if (Config.memShared && !Ipc::Mem::Segment::Enabled()) {
1005  fatal("memory_cache_shared is on, but no support for shared memory detected");
1006  } else if (Config.memShared && !UsingSmp()) {
1007  debugs(20, DBG_IMPORTANT, "WARNING: memory_cache_shared is on, but only"
1008  " a single worker is running");
1009  }
1010 }
1011 
1012 void
1014 {
1017 }
1018 
1019 void
1021 {
1022  if (!Config.memShared)
1023  return;
1024 
1025  const int64_t entryLimit = MemStore::EntryLimit();
1026  if (entryLimit <= 0) {
1027  if (Config.memMaxSize > 0) {
1028  debugs(20, DBG_IMPORTANT, "WARNING: mem-cache size is too small ("
1029  << (Config.memMaxSize / 1024.0) << " KB), should be >= " <<
1030  (Ipc::Mem::PageSize() / 1024.0) << " KB");
1031  }
1032  return; // no memory cache configured or a misconfiguration
1033  }
1034 
1035  Must(!spaceOwner);
1037  entryLimit, 0);
1038  Must(!mapOwner);
1039  mapOwner = MemStoreMap::Init(MapLabel, entryLimit);
1040  Must(!extrasOwner);
1042 }
1043 
1045 {
1046  delete extrasOwner;
1047  delete mapOwner;
1048  delete spaceOwner;
1049 }
1050 
virtual uint64_t minSize() const override
the minimum size the store will shrink to via normal housekeeping
Definition: MemStore.cc:267
sfileno fileNo
StoreMap::fileNos[name], for convenience/speed.
Definition: StoreMap.h:159
virtual void unlink(StoreEntry &e) override
remove the entry from the store
Definition: MemStore.cc:921
virtual void claimMemoryNeeds()
Definition: MemStore.cc:992
virtual void getStats(StoreInfoStats &stats) const override
collect statistics
Definition: MemStore.cc:211
std::atomic< uint64_t > swap_file_sz
Definition: StoreMap.h:89
bool complete() const
Definition: StoreMap.h:72
#define assert(EX)
Definition: assert.h:17
struct Ipc::StoreMapAnchor::Basics basics
virtual bool updateCollapsed(StoreEntry &e) override
Definition: MemStore.cc:423
size_t maxInMemObjSize
Definition: SquidConfig.h:264
virtual uint64_t maxSize() const override
Definition: MemStore.cc:273
void closeForWriting(const sfileno fileno, bool lockForReading=false)
successfully finish creating or updating the entry at fileno pos
Definition: StoreMap.cc:157
std::atomic< StoreMapSliceId > next
ID of the next entry slice.
Definition: StoreMap.h:46
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:225
const char * buf
content being appended now
Definition: MemStore.cc:70
Aggregates information required for updating entry metadata and headers.
Definition: StoreMap.h:146
SlotAndPage waitingFor
a cache for a single "hot" free slot and page
Definition: MemStore.h:113
ParseState pstate
the current parsing state
Definition: Message.h:94
void copyToShm(StoreEntry &e)
copies all local data to shared memory
Definition: MemStore.cc:679
void push(PageId &page)
makes value available as a free page number to future pop() callers
Definition: PageStack.cc:76
int entryLimit() const
maximum entryCount() possible
Definition: StoreMap.cc:622
int hdr_sz
Definition: Message.h:81
double size
bytes currently in use
Definition: StoreStats.h:20
Definition: SBuf.h:87
std::atomic< Size > size
slice contents size
Definition: StoreMap.h:45
Ipc::Mem::Pointer< Ipc::Mem::PageStack > freeSlots
unused map slot IDs
Definition: MemStore.h:95
char * PagePointer(const PageId &page)
converts page handler into a temporary writeable shared memory pointer
Definition: Pages.cc:48
unsigned char cache_key
Store key.
Definition: forward.h:29
#define shm_old(Class)
Definition: Pointer.h:180
virtual ~MemStoreRr()
Definition: MemStore.cc:1044
void completeWriting(StoreEntry &e)
all data has been received; there will be no more write() calls
Definition: MemStore.cc:895
void freeEntryByKey(const cache_key *const key)
Definition: StoreMap.cc:270
int64_t endOffset() const
Definition: MemObject.cc:232
#define PRId64
Definition: types.h:110
static const uint32_t SpacePoolId
Definition: MemStore.cc:36
Ipc::Mem::PageId * slot
local slot variable, waiting to be filled
Definition: MemStore.h:110
ShmWriter(MemStore &aStore, StoreEntry *anEntry, const sfileno aFileNo, Ipc::StoreMapSliceId aFirstSlice=-1)
Definition: MemStore.cc:77
Ipc::StoreMap MemStoreMap
Definition: MemStore.h:23
void lastModified(const time_t when)
Definition: Store.h:142
MemStoreMap * map
index of mem-cached entries
Definition: MemStore.h:96
virtual void init() override
Definition: MemStore.cc:180
YesNoNone memShared
whether the memory cache is shared among workers
Definition: SquidConfig.h:79
void abortUpdating(Update &update)
undoes partial update, unlocks, and cleans up
Definition: StoreMap.cc:221
void updateHeadersOrThrow(Ipc::StoreMapUpdate &update)
Definition: MemStore.cc:363
Io io
current I/O state
Definition: MemObject.h:149
MemStore()
Definition: MemStore.cc:170
bool shouldCache(StoreEntry &e) const
whether we should cache the entry
Definition: MemStore.cc:602
class Ping::pingStats_ stats
bool copyFromShm(StoreEntry &e, const sfileno index, const Ipc::StoreMapAnchor &anchor)
copies the entire entry from shared to local memory
Definition: MemStore.cc:487
virtual void finalizeConfig()
Definition: MemStore.cc:998
virtual uint64_t currentCount() const override
the total number of objects stored right now
Definition: MemStore.cc:286
void NotePageNeed(const int purpose, const int count)
claim the need for a number of pages for a given purpose
Definition: Pages.cc:72
StoreMapCleaner * cleaner
notified before a readable entry is freed
Definition: StoreMap.h:296
approximate stats of a set of ReadWriteLocks
Definition: ReadWriteLock.h:56
struct SquidConfig::@110 Store
uint32_t Size
Definition: StoreMap.h:31
bool GetPage(const PageId::Purpose purpose, PageId &page)
sets page ID and returns true unless no free pages are found
Definition: Pages.cc:34
bool isEmpty() const
Definition: SBuf.h:422
virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId) override
adjust slice-linked state before a locked Readable slice is erased
Definition: MemStore.cc:834
static Owner * Init(const SBuf &path, const int slotLimit)
initialize shared memory
Definition: StoreMap.cc:37
static const SBuf MapLabel("cache_mem_map")
shared memory segment path to use for MemStore maps
bool openForUpdating(Update &update, sfileno fileNoHint)
finds and locks the Update entry for an exclusive metadata update
Definition: StoreMap.cc:409
Controller & Root()
safely access controller singleton
Definition: Controller.cc:619
uint32_t pool
page pool ID within Squid
Definition: Page.h:33
Ipc::Mem::PageId * page
local page variable, waiting to be filled
Definition: MemStore.h:111
High-level store statistics used by mgr:info action. Used inside PODs!
Definition: StoreStats.h:13
virtual int64_t maxObjectSize() const override
the maximum size of a storable object; -1 if unlimited
Definition: MemStore.cc:292
time_t expires
Definition: Store.h:167
RunnerRegistrationEntry(MemStoreRr)
double count
number of cached objects
Definition: StoreStats.h:21
void memOutDecision(const bool willCacheInRam)
Definition: store.cc:1923
void destroyMemObject()
Definition: store.cc:370
A const & max(A const &lhs, A const &rhs)
MemCache memCache
current [shared] memory caching state for the entry
Definition: MemObject.h:151
int32_t index
entry position inside the memory cache
Definition: MemObject.h:146
time_t timestamp
Definition: Store.h:165
virtual bool anchorCollapsed(StoreEntry &e, bool &inSync) override
Definition: MemStore.cc:406
Ipc::StoreMap::Slice & nextAppendableSlice(const sfileno entryIndex, sfileno &sliceOffset)
Definition: MemStore.cc:752
void anchorEntry(StoreEntry &e, const sfileno index, const Ipc::StoreMapAnchor &anchor)
anchors StoreEntry to an already locked map entry
Definition: MemStore.cc:451
static void Broadcast(const StoreEntry &e)
notify other workers about changes in entry state (e.g., new data)
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:105
virtual uint64_t currentSize() const override
current size
Definition: MemStore.cc:279
static bool Enabled()
Whether shared memory support is available.
Definition: Segment.cc:321
double capacity
the size limit
Definition: StoreStats.h:22
bool copyFromShmSlice(StoreEntry &e, const StoreIOBuffer &buf, bool eof)
imports one shared memory slice into local memory
Definition: MemStore.cc:564
double doublePercent(const double, const double)
Definition: SquidMath.cc:25
Mem mem
all cache_dirs stats
Definition: StoreStats.h:49
uint64_t swap_file_sz
Definition: Store.h:171
int bufSize
buf size
Definition: MemStore.cc:71
uint32_t number
page number within the segment
Definition: Page.h:35
ping_status_t ping_status
Definition: Store.h:183
bool startCaching(StoreEntry &e)
locks map anchor and preps to store the entry in shared memory
Definition: MemStore.cc:656
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:405
int64_t offset
Definition: StoreIOBuffer.h:55
void hashInsert(const cache_key *)
Definition: store.cc:413
bool updateCollapsedWith(StoreEntry &collapsed, const sfileno index, const Ipc::StoreMapAnchor &anchor)
updates collapsed entry after its anchor has been located
Definition: MemStore.cc:442
State of an entry with regards to the [shared] memory caching.
Definition: MemObject.h:141
bool write(StoreIOBuffer const &)
Definition: stmem.cc:342
int64_t object_sz
Definition: MemObject.h:169
size_t PagesAvailable()
approximate total number of shared memory pages we can allocate now
Definition: Pages.h:47
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
void startAppending(const sfileno fileno)
restrict opened for writing entry to appending operations; allow reads
Definition: StoreMap.cc:148
virtual ~MemStore()
Definition: MemStore.cc:174
#define DBG_IMPORTANT
Definition: Debug.h:45
bool pop(PageId &page)
sets value and returns true unless no free page numbers are found
Definition: PageStack.cc:40
void write(StoreEntry &e)
copy non-shared entry data of the being-cached entry to our cache
Definition: MemStore.cc:856
bool configured() const
Definition: YesNoNone.h:66
virtual HttpReply const * getReply() const
Definition: store.cc:1742
#define EBIT_CLR(flag, bit)
Definition: defines.h:106
mem_status_t mem_status
Definition: Store.h:181
virtual void vappendf(const char *fmt, va_list ap) override
Definition: MemStore.cc:108
Slice & writeableSlice(const AnchorId anchorId, const SliceId sliceId)
writeable slice within an entry chain created by openForWriting()
Definition: StoreMap.cc:174
virtual bool dereference(StoreEntry &e) override
Definition: MemStore.cc:303
virtual void stat(StoreEntry &e) const override
Definition: MemStore.cc:224
int32_t StoreMapSliceId
Definition: StoreMap.h:24
SliceId sliceContaining(const sfileno fileno, const uint64_t nth) const
Definition: StoreMap.cc:334
void updateStats(ReadWriteLockStats &stats) const
adds approximate current stats to the supplied ones
Definition: StoreMap.cc:640
void fatal(const char *message)
Definition: fatal.cc:39
MemStore & store
Definition: MemStore.cc:66
Anchor & writeableEntry(const AnchorId anchorId)
writeable anchor for the entry created by openForWriting()
Definition: StoreMap.cc:190
void transientsAbandon(StoreEntry &)
calls Root().transients->abandon() if transients are tracked
Definition: Controller.cc:425
void set(const StoreEntry &anEntry)
store StoreEntry key and basics for an inode slot
Definition: StoreMap.cc:747
const sfileno fileNo
Definition: MemStore.cc:67
void abortWriting(const sfileno fileno)
stop writing the entry, freeing its slot for others to use if possible
Definition: StoreMap.cc:204
uint16_t flags
Definition: Store.h:173
void copyToShm()
copies the entire buffer to shared memory
Definition: MemStore.cc:124
ssize_t copy(StoreIOBuffer const &) const
Definition: stmem.cc:226
StoreMapAnchor * anchor
StoreMap::anchors[fileNo], for convenience/speed.
Definition: StoreMap.h:158
void configure(bool beSet)
enables or disables the option; updating to 'configured' state
Definition: YesNoNone.h:52
signed_int32_t sfileno
Definition: forward.h:22
MemObject * mem_obj
Definition: Store.h:162
void disconnect(StoreEntry &e)
called when the entry is about to forget its association with mem cache
Definition: MemStore.cc:935
uint16_t refcount
Definition: Store.h:172
bool UsingSmp()
Whether there should be more than one worker process running.
Definition: tools.cc:658
virtual StoreEntry * get(const cache_key *) override
Retrieve a store entry from the store (blocking)
Definition: MemStore.cc:310
Ipc::Mem::Owner< Ipc::Mem::PageStack > * spaceOwner
free slices Owner
Definition: MemStore.cc:984
void const char * buf
Definition: stub_helper.cc:16
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:147
#define shm_new(Class)
Definition: Pointer.h:179
bool shared
whether memory cache is shared among workers
Definition: StoreStats.h:42
bool set() const
true if and only if both critical components have been initialized
Definition: Page.h:27
#define Must(cond)
Definition: TextException.h:89
void freeEntry(const sfileno fileno)
free the entry if possible or mark it as waiting to be freed if not
Definition: StoreMap.cc:257
static int64_t EntryLimit()
calculates maximum number of entries we need to store and map
Definition: MemStore.cc:956
Definition: enums.h:46
int sliceLimit() const
maximum number of slices possible
Definition: StoreMap.cc:634
SBuf vary_headers
Definition: MemObject.h:176
size_t PageSize()
returns page size in bytes; all pages are assumed to be the same size
Definition: Pages.cc:28
char * buf
Definition: MemBuf.h:134
virtual void maintain() override
perform regular periodic maintenance; TODO: move to UFSSwapDir::Maintain
Definition: MemStore.cc:262
#define EBIT_SET(flag, bit)
Definition: defines.h:105
void transientsCompleteWriting(StoreEntry &)
marks the entry completed for collapsed requests
Definition: Controller.cc:435
store_status_t store_status
Definition: Store.h:185
const Anchor * openForReading(const cache_key *const key, sfileno &fileno)
opens entry (identified by key) for reading, increments read level
Definition: StoreMap.cc:353
const Anchor & readableEntry(const AnchorId anchorId) const
readable anchor for the entry created by openForReading()
Definition: StoreMap.cc:197
Edition stale
old anchor and chain being updated
Definition: StoreMap.h:173
void copyToShmSlice(StoreEntry &e, Ipc::StoreMapAnchor &anchor, Ipc::StoreMap::Slice &slice)
copies at most one slice worth of local memory to shared memory
Definition: MemStore.cc:721
bool memoryCachable()
checkCachable() and can be cached in memory
Definition: store.cc:1410
StoreEntry * entry
the entry being updated
Definition: MemStore.cc:50
Store::DiskConfig cacheSwap
Definition: SquidConfig.h:418
Ipc::StoreMapSliceId lastSlice
the slot keeping the last byte of the appended content (at least)
Definition: MemStore.cc:57
Ipc::Mem::Owner< MemStoreMapExtras > * extrasOwner
PageIds Owner.
Definition: MemStore.cc:986
Edition fresh
new anchor and updated chain prefix
Definition: StoreMap.h:174
virtual void useConfig()
Definition: Segment.cc:376
int bufWritten
buf bytes appended so far
Definition: MemStore.cc:72
aggregates anchor and slice owners for Init() caller convenience
Definition: StoreMap.h:197
Shared memory page identifier, address, or handler.
Definition: Page.h:21
sfileno reserveSapForWriting(Ipc::Mem::PageId &page)
finds a slot and a free page to fill or throws
Definition: MemStore.cc:799
size_t PageLevel()
approximate total number of shared memory pages used now
Definition: Pages.cc:80
Definition: MemBuf.h:23
void packHeadersInto(Packable *p) const
Definition: HttpReply.cc:85
size_t memMaxSize
Definition: SquidConfig.h:81
#define TexcHere(msg)
Definition: TextException.h:81
void const cache_key * key
swap_status_t swap_status
Definition: Store.h:187
int httpMsgParseStep(const char *buf, int len, int atEnd)
Definition: Message.cc:169
static const char * SpaceLabel
shared memory segment path to use for the free slices index
Definition: MemStore.cc:28
void PutPage(PageId &page)
makes identified page available as a free page to future GetPage() callers
Definition: Pages.cc:41
Ipc::Mem::Pointer< Extras > extras
IDs of pages with slice data.
Definition: MemStore.h:99
virtual void reference(StoreEntry &e) override
somebody needs this entry (many cache replacement policies need to know)
Definition: MemStore.cc:298
bool purgeOne()
either finds and frees an entry with at least 1 slice or returns false
Definition: StoreMap.cc:591
void clearPrivate()
Definition: store.cc:158
const Slice & readableSlice(const AnchorId anchorId, const SliceId sliceId) const
readable slice within an entry chain opened by openForReading()
Definition: StoreMap.cc:182
StoreMapSliceId splicingPoint
the last slice in the chain still containing metadata/headers
Definition: StoreMap.h:163
virtual void append(const char *aBuf, int aSize) override
Appends a c-string to existing packed data.
Definition: MemStore.cc:92
time_t lastref
Definition: Store.h:166
static const char * ExtrasLabel
shared memory segment path to use for IDs of shared pages with slice data
Definition: MemStore.cc:30
SBuf & vappendf(const char *fmt, va_list vargs)
Definition: SBuf.cc:261
virtual void markForUnlink(StoreEntry &) override
expect an unlink() call after the entry becomes idle
Definition: MemStore.cc:913
Anchor * openForWriting(const cache_key *const key, sfileno &fileno)
Definition: StoreMap.cc:97
mem_hdr data_hdr
Definition: MemObject.h:101
sfileno lastWritingSlice
the last allocate slice for writing a store entry (during copyToShm)
Definition: MemStore.h:102
const char * rawContent() const
Definition: SBuf.cc:539
bool isContiguous() const
Definition: MemObject.cc:406
Ipc::StoreMapSliceId firstSlice
Definition: MemStore.cc:54
virtual void create()
called when the runner should create a new memory segment
Definition: MemStore.cc:1020
void closeForReading(const sfileno fileno)
closes open entry after reading, decrements read level
Definition: StoreMap.cc:400
std::atomic< StoreMapSliceId > start
where the chain of StoreEntry slices begins [app]
Definition: StoreMap.h:95
uint64_t totalWritten
cumulative number of bytes appended so far
Definition: MemStore.cc:59
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:904
int entryCount() const
number of writeable and readable entries
Definition: StoreMap.cc:628
virtual void updateHeaders(StoreEntry *e) override
make stored metadata and HTTP headers the same as in the given entry
Definition: MemStore.cc:343
MemStoreMap::Owner * mapOwner
primary map Owner
Definition: MemStore.cc:985
#define EBIT_TEST(flag, bit)
Definition: defines.h:107
size_t PageLimit()
the total number of shared memory pages that can be in use at any time
Definition: Pages.cc:55
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
void copyToShmSlice(Ipc::StoreMap::Slice &slice)
copies at most one slice worth of buffer to shared memory
Definition: MemStore.cc:142
virtual int64_t maxObjectSize() const override
the maximum size of a storable object; -1 if unlimited
Definition: Controller.cc:181
Ipc::Mem::PageId pageForSlice(Ipc::StoreMapSliceId sliceId)
safely returns a previously allocated memory page for the given entry slice
Definition: MemStore.cc:788
int64_t expectedReplySize() const
Definition: MemObject.cc:256
A const & min(A const &lhs, A const &rhs)
void closeForUpdating(Update &update)
makes updated info available to others, unlocks, and cleans up
Definition: StoreMap.cc:497
void dump(StoreEntry &e) const
int64_t offset
bytes written/read to/from the memory cache so far
Definition: MemObject.h:147
virtual void useConfig()
Definition: MemStore.cc:1013
StoreEntry * entry
the store entry being updated
Definition: StoreMap.h:172
void setMemStatus(mem_status_t)
Definition: store.cc:1630
void terminate()
Definition: MemBuf.cc:259
void createMemObject()
Definition: store.cc:1681

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors