22#if HAVE_DISKIO_MODULE_IPCIO
70#define REBUILD_TIMESTAMP_DELTA_MAX 2
72#define STORE_IN_MEM_BUCKETS (229)
139#if HAVE_DISKIO_MODULE_IPCIO
149StoreEntry::operator
new (
size_t bytecount)
157 return pool->alloc();
161StoreEntry::operator
delete (
void *address)
163 pool->freeOne(address);
218#if URL_CHECKSUM_DEBUG
236 debugs(20, 7, reply.hdr_sz);
303 debugs(20, 7,
"STORE_OK STORE_DISK_CLIENT");
334 debugs(20, 7,
"STORE_PENDING STORE_DISK_CLIENT");
354 shareableWhenPrivate(false)
356 debugs(20, 5,
"StoreEntry constructed, this=" <<
this);
361 debugs(20, 5,
"StoreEntry destructed, this=" <<
this);
371 debugs(20, 5,
"Deferred producer call is already set to: " <<
405 debugs(20, 3,
"destroyStoreEntry: destroying " << data);
426 debugs(20, 3,
"StoreEntry::hashInsert: Inserting Entry " << *
this <<
" key '" <<
storeKeyText(someKey) <<
"'");
460 debugs(20, 3, shareable <<
' ' << *
this);
471 debugs(20, 3, (context ? context :
"somebody") <<
472 " unlocking key " <<
getMD5Text() <<
' ' << *
this);
488 debugs(20, 5, *
this <<
" via " << (context ? context :
"somebody"));
530 static int key_counter = 0;
532 if (++key_counter < 0)
550 debugs(20, 3, shareable << permanent <<
' ' << *
this);
602 }
catch (
const std::exception &ex) {
603 debugs(20, 2,
"for " << *
this <<
" failed: " << ex.what());
633 debugs(20, 3,
"releasing clashing " << *e2);
703 pe->
unlock(
"StoreEntry::adjustVary+failed_makePublic");
704 throw TexcHere(
"failed to make Vary marker public");
717#if X_ACCELERATOR_VARY
720 if (vary.size() > 0) {
744 debugs(20, 3,
"storeCreateEntry: '" << url <<
"'");
762 e->
lock(
"storeCreateEntry");
794 debugs(20, 3,
"allow Store clients to get entry content after buffering too much for " << *
this);
810 tempBuffer.
data = (
char *)buf;
834 if ((x = vsnprintf(buf,
sizeof(buf), fmt, ap)) < 0) {
840 if (x <
static_cast<int>(
sizeof(buf))) {
846 char *buf2 =
new char[x+1];
847 int y = vsnprintf(buf2, x+1, fmt, vargs);
939 debugs(20, 2,
"StoreEntry::checkCachable: NO: not cachable");
945 debugs(20, 2,
"StoreEntry::checkCachable: NO: wrong content-length");
950 debugs(20, 2,
"StoreEntry::checkCachable: NO: missing parts: " << *
this);
953 debugs(20, 2,
"StoreEntry::checkCachable: NO: too big");
956 debugs(20, 2,
"StoreEntry::checkCachable: NO: too small");
959 debugs(20, 3,
"StoreEntry::checkCachable: NO: private key");
968 debugs(20, 2,
"StoreEntry::checkCachable: NO: too many disk files open");
971 debugs(20, 2,
"StoreEntry::checkCachable: NO: too many FD's open");
1011 debugs(20, 3,
"because " << reason <<
": " << *
this);
1019 debugs(20, 3, whyWeAreSure <<
"; " << *
this);
1057#if USE_CACHE_DIGESTS
1084 lock(
"StoreEntry::abort");
1114 unlock(
"StoreEntry::abort");
1142#define MAINTAIN_MAX_SCAN 1024
1143#define MAINTAIN_MAX_REMOVE 64
1161 lock(
"storeLateRelease");
1184 for (
int i = 0; i < 10; ++i) {
1186 debugs(20,
Important(30),
"storeLateRelease: released " << n <<
" objects");
1193 e->
unlock(
"storeLateRelease");
1210 debugs(20, 5,
"storeEntryValidLength: object_len = " <<
1212 debugs(20, 5,
"storeEntryValidLength: hdr_sz = " << reply->hdr_sz);
1213 debugs(20, 5,
"storeEntryValidLength: content_length = " << reply->content_length);
1215 if (reply->content_length < 0) {
1216 debugs(20, 5,
"storeEntryValidLength: Unspecified content length: " <<
getMD5Text());
1220 if (reply->hdr_sz == 0) {
1221 debugs(20, 5,
"storeEntryValidLength: Zero header size: " <<
getMD5Text());
1236 diff = reply->hdr_sz + reply->content_length -
objectLen();
1241 debugs(20, 3,
"storeEntryValidLength: " << (diff < 0 ? -diff : diff) <<
" bytes too " << (diff < 0 ?
"big" :
"small") <<
"; '" <<
getMD5Text() <<
"'" );
1326#if USE_HTTP_VIOLATIONS
1394 time_t served_date = reply->
date;
1422 struct timeval responseTime;
1424 served_date -= responseTime.tv_sec;
1428 if (reply->expires > 0 && reply->date > -1)
1429 exp = served_date + (reply->expires - reply->date);
1431 exp = reply->expires;
1437 if (reply->last_modified < 0 || reply->last_modified ==
lastModified())
1463 updatedReply->prefixLen(),
"-byte header would exceed ",
1475 debugs(20, 5,
"updated basics in " << *
this <<
" with " << e304);
1544 debugs(20, 4,
"not inserting special " << *
this <<
" into policy");
1553 debugs(20, 4,
"not removing special " << *
this <<
" from policy");
1556 debugs(20, 4,
"removed " << *
this);
1569 return "[null_mem_obj]";
1652 debugs(20,
DBG_IMPORTANT,
"WARNING: Trying to load store replacement policy " << type <<
" twice.");
1683 fatalf(
"ERROR: Unknown policy %s\n", settings->
type);
1690 lock(
"StoreEntry::storeErrorResponse");
1697 unlock(
"StoreEntry::storeErrorResponse");
1707 debugs(20, 3,
"StoreEntry::replaceHttpReply: " <<
url());
1710 debugs(20,
DBG_CRITICAL,
"Attempt to replace object with no in-memory representation");
1716 if (andStartWriting)
1737 rep->packHeadersUsingSlowPacker(*
this);
1745 rep->body.packInto(
this);
1772 debugs(20, 7,
"not done with mem-caching " << *
this);
1776 const auto doneWithDiskCache =
1781 if (!doneWithDiskCache) {
1782 debugs(20, 7,
"not done with disk-caching " << *
this);
1786 debugs(20, 7,
"done with writing " << *
this);
1793 if (!willCacheInRam)
1827 if (preserveSwappable)
1840 debugs(88, 3,
"modifiedSince: '" <<
url() <<
"'");
1842 debugs(88, 3,
"modifiedSince: mod_time = " << mod_time);
1849 if (mod_time > ims) {
1850 debugs(88, 3,
"--> YES: entry newer than client");
1852 }
else if (mod_time < ims) {
1853 debugs(88, 3,
"--> NO: entry older than client");
1856 debugs(88, 3,
"--> NO: same LMT");
1895 static SBuf asterisk(
"*", 1);
1899 bool matched =
false;
1900 const char *pos =
nullptr;
1903 while (!matched &&
strListGetItem(&reqETags,
',', &item, &ilen, &pos)) {
1904 if (!strncmp(item,
"*", ilen))
1932 if (dirn < 0 && filen < 0)
1935 const bool matchingDisk = (
swap_dirn == dirn);
1936 return filen < 0 ? matchingDisk : (matchingDisk &&
swap_filen == filen);
1944 asHex(fno).upperCase().minDigits(8));
2003 snprintf(buf, 256,
"LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
2017 debugs(20, 5, (required ?
"adding to " :
"removing from ") << *
this);
2024static std::ostream &
2050 os <<
't' << xitTable.
io << xitTable.index;
2055 os <<
'm' << memCache.
io << memCache.index <<
'@' << memCache.offset;
2096 return os <<
'/' << &e <<
'*' << e.
locks();
#define ScheduleCallHere(call)
void storeDirSwapLog(const StoreEntry *e, int op)
bool etagIsWeakEqual(const ETag &tag1, const ETag &tag2)
whether etags are weak-equal
int etagParseInit(ETag *etag, const char *str)
bool etagIsStrongEqual(const ETag &tag1, const ETag &tag2)
whether etags are strong-equal
#define Here()
source code location of the caller
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
RemovalPolicy * mem_policy
#define memPoolCreate
Creates a named MemPool of elements with the given size.
RemovalPolicy * REMOVALPOLICYCREATE(wordlist *args)
void storeGetMemSpace(int size)
int storeTooManyDiskFilesOpen(void)
StoreEntry * storeGetPublic(const char *uri, const HttpRequestMethod &method)
const char * storeEntryFlags(const StoreEntry *)
StoreEntry * storeCreateEntry(const char *, const char *, const RequestFlags &, const HttpRequestMethod &)
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
int strListIsMember(const String *list, const SBuf &m, char del)
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
#define SWALLOW_EXCEPTIONS(code)
bool cancel(const char *reason)
static void StatQueue(std::ostream &)
prints IPC message queue state; suitable for cache manager reports
const char * str
quoted-string
struct timeval store_complete_stop
bool peerResponseTime(struct timeval &responseTime)
void setHeaders(Http::StatusCode status, const char *reason, const char *ctype, int64_t clen, time_t lmt, time_t expires)
Pointer recreateOnNotModified(const HttpReply &reply304) const
SBuf vary_headers
The variant second-stage cache key. Generated from Vary header pattern for this request.
static void StatQueue(std::ostream &)
prints IPC message queue state; suitable for cache manager reports
Store::IoStatus io
current I/O state
Decision decision
current decision state
Decision
Decision states for StoreEntry::swapoutPossible() and related code.
Store::IoStatus io
current I/O state
void replaceBaseReply(const HttpReplyPointer &r)
HttpRequestPointer request
void setNoDelay(bool const newValue)
XitTable xitTable
current [shared] memory caching state for the entry
const HttpReplyPointer & updatedReply() const
AsyncCallPointer abortCallback
used for notifying StoreEntry writers about 3rd-party initiated aborts
void updateReply(const HttpReply &r)
(re)sets updated reply;
const HttpReply & freshestReply() const
void markEndOfReplyHeaders()
sets baseReply().hdr_sz (i.e. written reply headers size) to endOffset()
void write(const StoreIOBuffer &buf)
int mostBytesWanted(int max, bool ignoreDelayPools) const
MemCache memCache
current [shared] memory caching state for the entry
int64_t endOffset() const
void setUris(char const *aStoreId, char const *aLogUri, const HttpRequestMethod &aMethod)
const char * storeId() const
const HttpReply & baseReply() const
bool hasUris() const
whether setUris() has been called
const char * logUri() const
client request URI used for logging; storeId() by default
bool readAheadPolicyCanRead() const
static bool Enabled()
whether Squid is correctly configured to use a shared memory cache
int getInUseCount() const
the difference between the number of alloc() and freeOne() calls
static Pointer Create(const CommandPointer &cmd)
void(* Add)(RemovalPolicy *policy, StoreEntry *entry, RemovalPolicyNode *node)
void(* Remove)(RemovalPolicy *policy, StoreEntry *entry, RemovalPolicyNode *node)
SupportOrVeto cachable
whether the response may be stored in the cache
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
size_t maxReplyHeaderSize
Store::DiskConfig cacheSwap
RemovalPolicySettings * memPolicy
struct SquidConfig::@90 onoff
struct SquidConfig::@88 Store
void storeWritingCheckpoint()
int locks() const
returns a local concurrent use counter, for debugging
void completeSuccessfully(const char *whyWeAreSureWeStoredTheWholeReply)
void hashInsert(const cache_key *)
void doAbandon(const char *context)
size_t bytesWanted(Range< size_t > const aRange, bool ignoreDelayPool=false) const
void unregisterAbortCallback(const char *reason)
const cache_key * calcPublicKey(const KeyScope keyScope)
bool swappedOut() const
whether the entire entry is now on disk (possibly marked for deletion)
bool shareableWhenPrivate
StoreEntry * adjustVary()
unsigned short lock_count
bool hasIfMatchEtag(const HttpRequest &request) const
has ETag matching at least one of the If-Match etags
void setCollapsingRequirement(const bool required)
allow or forbid collapsed requests feeding
const char * getSerialisedMetaData(size_t &length) const
void ensureMemObject(const char *storeId, const char *logUri, const HttpRequestMethod &aMethod)
initialize mem_obj (if needed) and set URIs/method (if missing)
bool hasIfNoneMatchEtag(const HttpRequest &request) const
has ETag matching at least one of the If-None-Match etags
void dump(int debug_lvl) const
void checkDisk() const
does nothing except throwing if disk-associated data members are inconsistent
void completeTruncated(const char *whyWeConsiderTheReplyTruncated)
int unlock(const char *context)
bool hasMemStore() const
whether there is a corresponding locked shared memory table entry
time_t lastModified() const
bool hasEtag(ETag &etag) const
whether this entry has an ETag; if yes, puts ETag value into parameter
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
swap_status_t swap_status
bool hasParsedReplyHeader() const
whether this entry has access to [deserialized] [HTTP] response headers
void write(StoreIOBuffer)
void lock(const char *context)
bool checkDeferRead(int fd) const
void swapOutDecision(const MemObject::SwapOut::Decision &decision)
bool makePublic(const KeyScope keyScope=ksDefault)
void clearPublicKeyScope()
void memOutDecision(const bool willCacheInRam)
void abandon(const char *context)
bool swappingOut() const
whether we are in the process of writing this entry to disk
void lengthWentBad(const char *reason)
flags [truncated or too big] entry with ENTRY_BAD_LENGTH and releases it
bool updateOnNotModified(const StoreEntry &e304)
time_t lastModified_
received Last-Modified value or -1; use lastModified()
void registerAbortCallback(const AsyncCall::Pointer &)
notify the StoreEntry writer of a 3rd-party initiated StoreEntry abort
const char * describeTimestamps() const
Store::Disk & disk() const
the disk this entry is [being] cached on; asserts for entries w/o a disk
void forcePublicKey(const cache_key *newkey)
void storeErrorResponse(HttpReply *reply)
Store a prepared error response. MemObject locks the reply object.
const char * getMD5Text() const
sfileno swap_filen
unique ID inside a cache_dir for swapped out entries; -1 for others
void storeWriterDone()
called when a store writer ends its work (successfully or not)
void setPrivateKey(const bool shareable, const bool permanent)
void makePrivate(const bool shareable)
int checkNegativeHit() const
void attachToDisk(const sdirno, const sfileno, const swap_status_t)
void kickProducer()
calls back producer registered with deferProducer
AsyncCall::Pointer deferredProducer
producer callback registered with deferProducer
static size_t inUseCount()
void replaceHttpReply(const HttpReplyPointer &, const bool andStartWriting=true)
bool hasOneOfEtags(const String &reqETags, const bool allowWeakMatch) const
whether at least one of the request ETags matches entity ETag
void vappendf(const char *, va_list) override
ping_status_t ping_status
void setNoDelay(bool const)
bool modifiedSince(const time_t ims, const int imslen=-1) const
void append(char const *, int) override
Appends a c-string to existing packed data.
void trimMemory(const bool preserveSwappable)
int64_t objectLen() const
store_status_t store_status
void releaseRequest(const bool shareable=false)
store_client_t storeClientType() const
static Mem::Allocator * pool
void touch()
update last reference timestamp and related Store metadata
bool swapoutFailed() const
whether we failed to write this entry to disk
bool setPublicKey(const KeyScope keyScope=ksDefault)
void deferProducer(const AsyncCall::Pointer &producer)
call back producer when more buffer space is available
const HttpReply * hasFreshestReply() const
bool hasTransients() const
whether there is a corresponding locked transients table entry
void swapOutFileClose(int how)
bool hittingRequiresCollapsing() const
whether this entry can feed collapsed requests and only them
void setMemStatus(mem_status_t)
@ writerGone
failure: caller left before swapping out everything
void configure()
update configuration, including limits (re)calculation
void noteStoppedSharedWriting(StoreEntry &)
adjust shared state after this worker stopped changing the entry
void addWriting(StoreEntry *, const cache_key *)
void handleIdleEntry(StoreEntry &)
called when the entry is no longer needed by any transaction
void stat(StoreEntry &) const override
void freeMemorySpace(const int spaceRequired)
void maintain() override
perform regular periodic maintenance; TODO: move to UFSSwapDir::Maintain
void memoryDisconnect(StoreEntry &)
disassociates the entry from the memory cache, preserving cached data
void transientsDisconnect(StoreEntry &)
disassociates the entry from the intransit table
static int store_dirs_rebuilding
the number of cache_dirs being rebuilt; TODO: move to Disks::Rebuilding
void evictCached(StoreEntry &) override
StoreEntry * find(const cache_key *)
manages a single cache_dir
virtual void disconnect(StoreEntry &)
called when the entry is about to forget its association with cache_dir
Entry * entry_
the guarded Entry or nil
const char * context_
default unlock() message
void onException() noexcept
void unlockAndReset(const char *resetContext=nullptr)
char const * termedBuf() const
void append(char const *buf, int len)
an std::runtime_error with thrower location info
#define debugs(SECTION, LEVEL, CONTENT)
#define EBIT_CLR(flag, bit)
#define EBIT_SET(flag, bit)
#define EBIT_TEST(flag, bit)
@ ENTRY_REQUIRES_COLLAPSING
@ RELEASE_REQUEST
prohibits making the key public
@ ENTRY_REVALIDATE_ALWAYS
@ PING_NONE
Has not considered whether to send ICP queries to peers yet.
enum _mem_status_t mem_status_t
swap_status_t
StoreEntry relationship with a disk cache.
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
void fatal(const char *message)
void fatalf(const char *fmt,...)
const char * swapStatusStr[]
int neighbors_do_private_keys
hash_link * hash_lookup(hash_table *, const void *)
void hash_join(hash_table *, hash_link *)
void hash_remove_link(hash_table *, hash_link *)
RefCount< HttpReply > HttpReplyPointer
SBuf httpMakeVaryMark(HttpRequest *request, HttpReply const *reply)
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
Controller & Root()
safely access controller singleton
IoStatus
cache "I/O" direction and status
void Maintain(void *unused)
void Stats(StoreEntry *output)
AllocedBuf PackSwapMeta(const StoreEntry &, size_t &size)
void storeReplSetup(void)
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
#define LOCAL_ARRAY(type, name, size)
unsigned char cache_key
Store key.
static EVH storeLateRelease
const char * swapStatusStr[]
static std::ostream & operator<<(std::ostream &os, const Store::IoStatus &io)
int expiresMoreThan(time_t expires, time_t when)
static void StatQueues(StoreEntry *e)
reports the current state of Store-related queues
void storeGetMemSpace(int size)
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
void storeConfigure(void)
struct _store_check_cachable_hist store_check_cachable_hist
void storeAppendVPrintf(StoreEntry *e, const char *fmt, va_list vargs)
int storeTooManyDiskFilesOpen(void)
const char * pingStatusStr[]
const char * memStatusStr[]
StoreEntry * storeGetPublicByRequestMethod(HttpRequest *req, const HttpRequestMethod &method, const KeyScope keyScope)
StoreEntry * storeGetPublicByRequest(HttpRequest *req, const KeyScope keyScope)
static int getKeyCounter(void)
StoreEntry * storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod &method)
StoreEntry * storeGetPublic(const char *uri, const HttpRequestMethod &method)
static storerepl_entry_t * storerepl_list
const char * storeStatusStr[]
StoreEntry * storeCreatePureEntry(const char *url, const char *log_url, const HttpRequestMethod &method)
RemovalPolicy * createRemovalPolicy(RemovalPolicySettings *settings)
static OBJH storeCheckCachableStats
void storeReplAdd(const char *type, REMOVALPOLICYCREATE *create)
static std::stack< StoreEntry * > LateReleaseStack
static void storeRegisterWithCacheManager(void)
int storePendingNClients(const StoreEntry *e)
void storeDigestInit(void)
const cache_key * storeKeyPublicByRequest(HttpRequest *request, const KeyScope keyScope)
const cache_key * storeKeyPublic(const char *url, const HttpRequestMethod &method, const KeyScope keyScope)
const cache_key * storeKeyPublicByRequestMethod(HttpRequest *request, const HttpRequestMethod &method, const KeyScope keyScope)
const cache_key * storeKeyPrivate()
cache_key * storeKeyDup(const cache_key *key)
void storeKeyFree(const cache_key *key)
const char * storeKeyText(const cache_key *key)
void storeLog(int tag, const StoreEntry *e)
void storeRebuildStart(void)
struct _store_check_cachable_hist::@121 yes
struct _store_check_cachable_hist::@120 no
REMOVALPOLICYCREATE * create
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
void * xrealloc(void *s, size_t sz)
const char * xstrerr(int error)