38 sharedMemStore(nullptr),
49 assert(!
"Controller is never destroyed");
58 sharedMemStore->
init();
77#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)
82 }
while (
pid > 0 || (
pid < 0 && errno == EINTR));
89 static time_t last_warn_time = 0;
109 sharedMemStore->getStats(stats);
124 disks->getStats(stats);
140 currentSize() / 1024.0);
146 sharedMemStore->stat(output);
156 return disks->maxSize();
163 return disks->minSize();
170 return disks->currentSize();
177 return disks->currentCount();
184 return disks->maxObjectSize();
200 const int64_t disksMax = disks->maxObjectSize();
215 sharedMemStore->sync();
226 return disks->callback();
244 sharedMemStore->reference(e);
266 bool keepInStoreTable =
false;
272 keepInStoreTable = disks->dereference(e) || keepInStoreTable;
276 keepInStoreTable = sharedMemStore->dereference(e) || keepInStoreTable;
284 keepInStoreTable = wantsLocalMemory || keepInStoreTable;
292 keepInStoreTable =
false;
295 return keepInStoreTable;
302 return transients && transients->markedForDeletion(key);
310 return markedForDeletion(
reinterpret_cast<const cache_key*
>(e.
key)) &&
311 transients && !transients->readers(e);
317 return disks->hasReadableEntry(e);
324 checkTransients(entry);
345 if (
const auto entry = peek(key)) {
348 allowSharing(*entry, key);
349 checkFoundCandidate(*entry);
351 referenceBusy(*entry);
353 }
catch (
const std::exception &ex) {
354 debugs(20, 2,
"failed with " << *entry <<
": " << ex.what());
367 addReading(&entry, key);
371 const auto hadWriter = transients->hasWriter(entry);
372 const auto found = anchorToCache(entry);
376 debugs(20,
DBG_IMPORTANT,
"ERROR: Squid BUG: missing ENTRY_REQUIRES_COLLAPSING for " << entry);
377 throw TextException(
"transients entry missing ENTRY_REQUIRES_COLLAPSING",
Here());
425 if (markedForDeletion(key)) {
431 debugs(20, 3,
"got local in-transit entry: " << *e);
438 debugs(20, 3,
"got shared in-transit entry: " << *e);
443 if (sharedMemStore) {
444 if (
StoreEntry *e = sharedMemStore->get(key)) {
445 debugs(20, 3,
"got mem-cached entry: " << *e);
450 if (
const auto e = disks->get(key)) {
451 debugs(20, 3,
"got disk-cached entry: " << *e);
462 return transients && e.
hasTransients() && transients->isReader(e);
468 return transients && e.
hasTransients() && transients->isWriter(e);
474 return disks->accumulateMore(entry);
486 transients->evictCached(e);
487 memoryEvictCached(e);
488 disks->evictCached(e);
497 debugs(20, 5,
"marking local in-transit " << *entry);
498 entry->release(
true);
503 sharedMemStore->evictIfFound(key);
505 disks->evictIfFound(key);
508 transients->evictIfFound(key);
526 if (memoryCacheHasSpaceFor(pagesRequired))
533 static time_t lastWalk = 0;
538 debugs(20, 2,
"need " << pagesRequired <<
" pages");
541 memoryPagesDebt_ = pagesRequired;
547 while (
const auto entry = walker->Next(walker)) {
549 entry->abandon(__func__);
552 if (memoryCacheHasSpaceFor(pagesRequired))
556 debugs(20, 3,
"removed " << removed <<
" out of " <<
hot_obj_count <<
" memory-cached entries");
557 walker->Done(walker);
558 memoryPagesDebt_ = 0;
573 const int64_t ramSize =
max(loadedSize, expectedSize);
574 const int64_t ramLimit =
min(
577 return ramSize <= ramLimit;
583 bool keepInLocalMemory =
false;
585 sharedMemStore->write(e);
586 else if (localMemStore)
587 keepInLocalMemory = keepForLocalMemoryCache(e);
589 debugs(20, 7,
"keepInLocalMemory: " << keepInLocalMemory);
591 if (!keepInLocalMemory)
602 sharedMemStore->evictCached(e);
612 sharedMemStore->disconnect(e);
620 transients->completeWriting(e);
627 transients->readers(e) : 0;
634 transients->disconnect(e);
640 bool keepInLocalMemory =
false;
646 keepInLocalMemory =
true;
647 }
else if (sharedMemStore) {
649 }
else if (localMemStore) {
650 keepInLocalMemory = keepForLocalMemoryCache(e) &&
652 memoryCacheHasSpaceFor(memoryPagesDebt_);
657 if (!dereferenceIdle(e, keepInLocalMemory)) {
658 debugs(20, 5,
"destroying unlocked entry: " << &e <<
' ' << e);
663 debugs(20, 5,
"keepInLocalMemory: " << keepInLocalMemory);
669 if (keepInLocalMemory) {
682 memoryEvictCached(e);
702 debugs(20, 5,
"ignored repeated update of " << *old <<
" with " << e304);
709 debugs(20, 5,
"updated nothing in " << *old <<
" with " << e304);
718 sharedMemStore->updateHeaders(old);
721 disks->updateHeaders(old);
735 "SMP-" :
"locally-") <<
"collapse " << *e);
769 StoreEntry *collapsed = transients->findCollapsed(xitIndex);
771 debugs(20, 7,
"not SMP-syncing not-transient " << xitIndex);
775 if (!collapsed->
locked()) {
776 debugs(20, 3,
"skipping (and may destroy) unlocked " << *collapsed);
777 handleIdleEntry(*collapsed);
784 debugs(20, 3,
"skipping already aborted " << *collapsed);
788 debugs(20, 7,
"syncing " << *collapsed);
791 transients->status(*collapsed, entryStatus);
794 debugs(20, 3,
"will release " << *collapsed <<
" due to waitingToBeFreed");
798 if (transients->isWriter(*collapsed))
801 assert(transients->isReader(*collapsed));
808 debugs(20, 7,
"already handled by memory store: " << *collapsed);
809 }
else if (sharedMemStore && collapsed->
hasMemStore()) {
811 inSync = sharedMemStore->updateAnchored(*collapsed);
813 }
else if (collapsed->
hasDisk()) {
815 inSync = disks->updateAnchored(*collapsed);
818 found = anchorToCache(*collapsed);
829 debugs(20, 3,
"aborting unattached " << *collapsed <<
830 " because it was marked for deletion before we could attach it");
836 debugs(20, 5,
"synced " << *collapsed);
844 debugs(20, 3,
"aborting unsyncable " << *collapsed);
850 debugs(20, 3,
"aborting abandoned-by-writer " << *collapsed);
856 debugs(20, 7,
"waiting " << *collapsed);
867 assert(transientsReader(entry));
873 debugs(20, 5,
"already handled by memory store: " << entry);
875 }
else if (sharedMemStore && entry.
hasMemStore()) {
876 debugs(20, 5,
"already anchored to memory store: " << entry);
879 debugs(20, 5,
"already anchored to disk: " << entry);
883 debugs(20, 7,
"anchoring " << entry);
886 transients->status(entry, entryStatus);
890 found = sharedMemStore->anchorToCache(entry);
892 found = disks->anchorToCache(entry);
895 debugs(20, 7,
"anchored " << entry);
901 throw TextException(
"will never be able to anchor to an already marked entry",
Here());
904 throw TextException(
"will never be able to anchor to an abandoned-by-writer entry",
Here());
906 debugs(20, 7,
"skipping not yet cached " << entry);
#define Here()
source code location of the caller
RemovalPolicy * mem_policy
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
Store::IoStatus io
current I/O state
static size_t inUseCount()
int64_t expectedReplySize() const
MemCache memCache
current [shared] memory caching state for the entry
int64_t endOffset() const
static bool Enabled()
whether Squid is correctly configured to use a shared memory cache
void(* Referenced)(RemovalPolicy *policy, const StoreEntry *entry, RemovalPolicyNode *node)
RemovalPurgeWalker *(* PurgeInit)(RemovalPolicy *policy, int max_scan)
void(* Dereferenced)(RemovalPolicy *policy, const StoreEntry *entry, RemovalPolicyNode *node)
struct SquidConfig::@75 Swap
struct SquidConfig::@88 Store
void hashInsert(const cache_key *)
bool swappedOut() const
whether the entire entry is now on disk (possibly marked for deletion)
void setCollapsingRequirement(const bool required)
allow or forbid collapsed requests feeding
bool hasMemStore() const
whether there is a corresponding locked shared memory table entry
void release(const bool shareable=false)
bool memoryCachable()
checkCachable() and can be cached in memory
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
bool makePublic(const KeyScope keyScope=ksDefault)
bool updateOnNotModified(const StoreEntry &e304)
static size_t inUseCount()
void trimMemory(const bool preserveSwappable)
bool hasTransients() const
whether there is a corresponding locked transients table entry
bool hittingRequiresCollapsing() const
whether this entry can feed collapsed requests and only them
void setMemStatus(mem_status_t)
bool shared
whether memory cache is shared among workers
double capacity
the size limit
double count
number of cached objects
double size
bytes currently in use
High-level store statistics used by mgr:info action. Used inside PODs!
double store_entry_count
number of StoreEntry objects in existence
Mem mem
all cache_dirs stats
double mem_object_count
number of MemObject objects in existence
void memoryOut(StoreEntry &, const bool preserveSwappable)
called to get rid of no longer needed entry data in RAM, if any
void checkFoundCandidate(const StoreEntry &) const
flags problematic entries before find() commits to finalizing/returning them
void configure()
update configuration, including limits (re)calculation
~Controller() override
this destructor is never called because Controller singleton is immortal
StoreEntry * findCallbackXXX(const cache_key *)
bool markedForDeletionAndAbandoned(const StoreEntry &) const
StoreEntry * peekAtLocal(const cache_key *)
void checkTransients(const StoreEntry &) const
int transientReaders(const StoreEntry &) const
number of the transient entry readers some time ago
void noteStoppedSharedWriting(StoreEntry &)
adjust shared state after this worker stopped changing the entry
void addReading(StoreEntry *, const cache_key *)
void addWriting(StoreEntry *, const cache_key *)
uint64_t maxSize() const override
void handleIdleEntry(StoreEntry &)
called when the entry is no longer needed by any transaction
bool allowCollapsing(StoreEntry *, const RequestFlags &, const HttpRequestMethod &)
tries to make the entry available for collapsing future requests
void sync() override
prepare for shutdown
void stat(StoreEntry &) const override
bool transientsReader(const StoreEntry &) const
whether the entry is in "reading from Transients" I/O state
void referenceBusy(StoreEntry &e)
update reference counters of the recently touched entry
void freeMemorySpace(const int spaceRequired)
void maintain() override
perform regular periodic maintenance; TODO: move to UFSSwapDir::Maintain
void syncCollapsed(const sfileno)
Update local intransit entry after changes made by appending worker.
void getStats(StoreInfoStats &stats) const override
collect statistics
uint64_t minSize() const override
the minimum size the store will shrink to via normal housekeeping
void memoryDisconnect(StoreEntry &)
disassociates the entry from the memory cache, preserving cached data
bool hasReadableDiskEntry(const StoreEntry &) const
whether there is a disk entry with e.key
bool markedForDeletion(const cache_key *key) const
bool updateOnNotModified(StoreEntry *old, StoreEntry &e304)
void transientsDisconnect(StoreEntry &)
disassociates the entry from the intransit table
int64_t accumulateMore(StoreEntry &) const
bool memoryCacheHasSpaceFor(const int pagesRequired) const
whether the memory cache is allowed to store that many additional pages
static int store_dirs_rebuilding
the number of cache_dirs being rebuilt; TODO: move to Disks::Rebuilding
int64_t maxObjectSize() const override
the maximum size of a storable object; -1 if unlimited
bool anchorToCache(StoreEntry &)
void memoryEvictCached(StoreEntry &)
static bool SmpAware()
whether there are any SMP-aware storages
bool transientsWriter(const StoreEntry &) const
whether the entry is in "writing to Transients" I/O state
void create() override
create system resources needed for this store to operate in the future
uint64_t currentSize() const override
current size
bool dereferenceIdle(StoreEntry &, bool wantsLocalMemory)
void evictCached(StoreEntry &) override
void allowSharing(StoreEntry &, const cache_key *)
indexes and adds SMP-tracking for an ephemeral peek() result
void evictIfFound(const cache_key *) override
StoreEntry * find(const cache_key *)
uint64_t currentCount() const override
the total number of objects stored right now
int callback() override
called once every main loop iteration; TODO: Move to UFS code.
bool keepForLocalMemoryCache(StoreEntry &e) const
whether e should be kept in local RAM for possible future caching
StoreEntry * peek(const cache_key *)
summary view of all disk caches (cache_dirs) combined
static bool SmpAware()
whether any disk cache is SMP-aware
an std::runtime_error with thrower location info
shared entry metadata, used for synchronization
bool waitingToBeFreed
whether the entry was marked for deletion
bool hasWriter
whether some worker is storing the entry
static bool Enabled()
Can we create and initialize Transients?
static size_t StoreMemSize()
static size_t InUseCount()
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
#define EBIT_TEST(flag, bit)
hash_link * hash_lookup(hash_table *, const void *)
double doublePercent(const double, const double)
Controller & Root()
safely access controller singleton
StoreSearch * NewLocalSearch()
unsigned char cache_key
Store key.
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
const char * storeKeyText(const cache_key *key)