2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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.
12 #include "base/Packable.h"
13 #include "base/Range.h"
14 #include "base/RefCount.h"
15 #include "comm/forward.h"
18 #include "http/forward.h"
19 #include "http/RequestMethod.h"
20 #include "HttpReply.h"
21 #include "MemObject.h"
22 #include "RemovalPolicy.h"
23 #include "store/Controller.h"
24 #include "store/forward.h"
25 #include "store_key_md5.h"
26 #include "StoreIOBuffer.h"
27 #include "StoreStats.h"
30 #include "esi/Element.h"
39 extern StoreIoStats store_io_stats
;
41 class StoreEntry
: public hash_link
, public Packable
45 static DeferredRead::DeferrableRead DeferReader
;
46 bool checkDeferRead(int fd
) const;
48 virtual const char *getMD5Text() const;
50 virtual ~StoreEntry();
52 virtual HttpReply
const *getReply() const;
53 virtual void write (StoreIOBuffer
);
55 /** Check if the Store entry is emtpty
56 * \retval true Store contains 0 bytes of data.
57 * \retval false Store contains 1 or more bytes of data.
58 * \retval false Store contains negative content !!!!!!
60 virtual bool isEmpty() const {
62 return mem_obj
->endOffset() == 0;
64 virtual bool isAccepting() const;
65 virtual size_t bytesWanted(Range
<size_t> const aRange
, bool ignoreDelayPool
= false) const;
66 /// flags [truncated or too big] entry with ENTRY_BAD_LENGTH and releases it
67 void lengthWentBad(const char *reason
);
68 virtual void complete();
69 virtual store_client_t
storeClientType() const;
70 virtual char const *getSerialisedMetaData();
71 /// Store a prepared error response. MemObject locks the reply object.
72 void storeErrorResponse(HttpReply
*reply
);
73 void replaceHttpReply(HttpReply
*, bool andStartWriting
= true);
74 void startWriting(); ///< pack and write reply headers and, maybe, body
75 /// whether we may start writing to disk (now or in the future)
76 virtual bool mayStartSwapOut();
77 virtual void trimMemory(const bool preserveSwappable
);
79 // called when a decision to cache in memory has been made
80 void memOutDecision(const bool willCacheInRam
);
81 // called when a decision to cache on disk has been made
82 void swapOutDecision(const MemObject::SwapOut::Decision
&decision
);
85 void makePublic(const KeyScope keyScope
= ksDefault
);
86 void makePrivate(const bool shareable
);
87 /// A low-level method just resetting "private key" flags.
88 /// To avoid key inconsistency please use forcePublicKey()
89 /// or similar instead.
91 void setPublicKey(const KeyScope keyScope
= ksDefault
);
92 /// Resets existing public key to a public key with default scope,
93 /// releasing the old default-scope entry (if any).
94 /// Does nothing if the existing public key already has default scope.
95 void clearPublicKeyScope();
96 void setPrivateKey(const bool shareable
);
98 void releaseRequest(const bool shareable
= false);
100 void cacheNegatively(); /** \todo argh, why both? */
101 void invokeHandlers();
103 void cacheInMemory(); ///< start or continue storing in memory cache
105 /// whether we are in the process of writing this entry to disk
106 bool swappingOut() const { return swap_status
== SWAPOUT_WRITING
; }
107 void swapOutFileClose(int how
);
108 const char *url() const;
109 /// Satisfies cachability requirements shared among disk and RAM caches.
110 /// Encapsulates common checks of mayStartSwapOut() and memoryCachable().
111 /// TODO: Rename and make private so only those two methods can call this.
112 bool checkCachable();
113 int checkNegativeHit() const;
115 int validToSend() const;
116 bool memoryCachable(); ///< checkCachable() and can be cached in memory
118 /// initialize mem_obj; assert if mem_obj already exists
119 /// avoid this method in favor of createMemObject(trio)!
120 void createMemObject();
122 /// initialize mem_obj with URIs/method; assert if mem_obj already exists
123 void createMemObject(const char *storeId
, const char *logUri
, const HttpRequestMethod
&aMethod
);
125 /// initialize mem_obj (if needed) and set URIs/method (if missing)
126 void ensureMemObject(const char *storeId
, const char *logUri
, const HttpRequestMethod
&aMethod
);
128 void dump(int debug_lvl
) const;
130 void hashInsert(const cache_key
*);
131 void registerAbort(STABH
* cb
, void *);
133 void setMemStatus(mem_status_t
);
134 bool timestampsSet();
135 void unregisterAbort();
136 void destroyMemObject();
139 void delayAwareRead(const Comm::ConnectionPointer
&conn
, char *buf
, int len
, AsyncCall::Pointer callback
);
141 void setNoDelay (bool const);
142 void lastModified(const time_t when
) { lastModified_
= when
; }
143 /// \returns entry's 'effective' modification time
144 time_t lastModified() const {
145 // may still return -1 if timestamp is not set
146 return lastModified_
< 0 ? timestamp
: lastModified_
;
148 /// \returns a formatted string with entry's timestamps
149 const char *describeTimestamps() const;
150 // TODO: consider removing currently unsupported imslen parameter
151 bool modifiedSince(const time_t ims
, const int imslen
= -1) const;
152 /// has ETag matching at least one of the If-Match etags
153 bool hasIfMatchEtag(const HttpRequest
&request
) const;
154 /// has ETag matching at least one of the If-None-Match etags
155 bool hasIfNoneMatchEtag(const HttpRequest
&request
) const;
156 /// whether this entry has an ETag; if yes, puts ETag value into parameter
157 bool hasEtag(ETag
&etag
) const;
159 /// the disk this entry is [being] cached on; asserts for entries w/o a disk
160 Store::Disk
&disk() const;
163 RemovalPolicyNode repl
;
164 /* START OF ON-DISK STORE_META_STD TLV field */
169 time_t lastModified_
; ///< received Last-Modified value or -1; use lastModified()
171 uint64_t swap_file_sz
;
174 /* END OF ON-DISK STORE_META_STD */
176 /// unique ID inside a cache_dir for swapped out entries; -1 for others
177 sfileno swap_filen
:25; // keep in sync with SwapFilenMax
181 mem_status_t mem_status
:3;
183 ping_status_t ping_status
:3;
185 store_status_t store_status
:3;
187 swap_status_t swap_status
:3;
190 static size_t inUseCount();
191 static void getPublicByRequestMethod(StoreClient
* aClient
, HttpRequest
* request
, const HttpRequestMethod
& method
);
192 static void getPublicByRequest(StoreClient
* aClient
, HttpRequest
* request
);
193 static void getPublic(StoreClient
* aClient
, const char *uri
, const HttpRequestMethod
& method
);
195 virtual bool isNull() {
199 void *operator new(size_t byteCount
);
200 void operator delete(void *address
);
201 void setReleaseFlag();
204 ESIElement::Pointer cachedESITree
;
206 virtual int64_t objectLen() const;
207 virtual int64_t contentLen() const;
209 /// claim shared ownership of this entry (for use in a given context)
210 /// matching lock() and unlock() contexts eases leak triage but is optional
211 void lock(const char *context
);
213 /// disclaim shared ownership; may remove entry from store and delete it
214 /// returns remaning lock level (zero for unlocked and possibly gone entry)
215 int unlock(const char *context
);
217 /// returns a local concurrent use counter, for debugging
218 int locks() const { return static_cast<int>(lock_count
); }
220 /// update last reference timestamp and related Store metadata
223 virtual void release(const bool shareable
= false);
225 /// May the caller commit to treating this [previously locked]
226 /// entry as a cache hit?
227 bool mayStartHitting() const {
228 return !EBIT_TEST(flags
, KEY_PRIVATE
) || shareableWhenPrivate
;
232 /// call back producer when more buffer space is available
233 void deferProducer(const AsyncCall::Pointer
&producer
);
234 /// calls back producer registered with deferProducer
239 virtual void append(char const *, int);
240 virtual void vappendf(const char *, va_list);
241 virtual void buffer();
242 virtual void flush();
245 void transientsAbandonmentCheck();
248 bool checkTooBig() const;
249 void forcePublicKey(const cache_key
*newkey
);
251 const cache_key
*calcPublicKey(const KeyScope keyScope
);
253 static MemAllocator
*pool
;
255 unsigned short lock_count
; /* Assume < 65536! */
257 /// Nobody can find/lock KEY_PRIVATE entries, but some transactions
258 /// (e.g., collapsed requests) find/lock a public entry before it becomes
259 /// private. May such transactions start using the now-private entry
260 /// they previously locked? This member should not affect transactions
261 /// that already started reading from the entry.
262 bool shareableWhenPrivate
;
265 /// producer callback registered with deferProducer
266 AsyncCall::Pointer deferredProducer
;
269 bool validLength() const;
270 bool hasOneOfEtags(const String
&reqETags
, const bool allowWeakMatch
) const;
272 friend std::ostream
&operator <<(std::ostream
&os
, const StoreEntry
&e
);
275 std::ostream
&operator <<(std::ostream
&os
, const StoreEntry
&e
);
277 /// \ingroup StoreAPI
278 class NullStoreEntry
:public StoreEntry
282 static NullStoreEntry
*getInstance();
287 const char *getMD5Text() const;
288 HttpReply
const *getReply() const { return NULL
; }
289 void write (StoreIOBuffer
) {}
291 bool isEmpty () const {return true;}
293 virtual size_t bytesWanted(Range
<size_t> const aRange
, bool) const { return aRange
.end
; }
295 void operator delete(void *address
);
299 store_client_t
storeClientType() const {return STORE_MEM_CLIENT
;}
301 char const *getSerialisedMetaData();
302 virtual bool mayStartSwapOut() { return false; }
304 void trimMemory(const bool) {}
306 static NullStoreEntry _instance
;
309 /// \ingroup StoreAPI
310 typedef void (*STOREGETCLIENT
) (StoreEntry
*, void *cbdata
);
313 void Stats(StoreEntry
*output
);
314 void Maintain(void *unused
);
317 /// \ingroup StoreAPI
318 size_t storeEntryInUse();
320 /// \ingroup StoreAPI
321 const char *storeEntryFlags(const StoreEntry
*);
323 /// \ingroup StoreAPI
324 void storeEntryReplaceObject(StoreEntry
*, HttpReply
*);
326 /// \ingroup StoreAPI
327 StoreEntry
*storeGetPublic(const char *uri
, const HttpRequestMethod
& method
);
329 /// \ingroup StoreAPI
330 StoreEntry
*storeGetPublicByRequest(HttpRequest
* request
, const KeyScope keyScope
= ksDefault
);
332 /// \ingroup StoreAPI
333 StoreEntry
*storeGetPublicByRequestMethod(HttpRequest
* request
, const HttpRequestMethod
& method
, const KeyScope keyScope
= ksDefault
);
335 /// \ingroup StoreAPI
336 /// Like storeCreatePureEntry(), but also locks the entry and sets entry key.
337 StoreEntry
*storeCreateEntry(const char *, const char *, const RequestFlags
&, const HttpRequestMethod
&);
339 /// \ingroup StoreAPI
340 /// Creates a new StoreEntry with mem_obj and sets initial flags/states.
341 StoreEntry
*storeCreatePureEntry(const char *storeId
, const char *logUrl
, const RequestFlags
&, const HttpRequestMethod
&);
343 /// \ingroup StoreAPI
344 void storeInit(void);
346 /// \ingroup StoreAPI
347 void storeConfigure(void);
349 /// \ingroup StoreAPI
350 void storeFreeMemory(void);
352 /// \ingroup StoreAPI
353 int expiresMoreThan(time_t, time_t);
355 /// \ingroup StoreAPI
356 void storeAppendPrintf(StoreEntry
*, const char *,...) PRINTF_FORMAT_ARG2
;
358 /// \ingroup StoreAPI
359 void storeAppendVPrintf(StoreEntry
*, const char *, va_list ap
);
361 /// \ingroup StoreAPI
362 int storeTooManyDiskFilesOpen(void);
364 /// \ingroup StoreAPI
365 void storeHeapPositionUpdate(StoreEntry
*, SwapDir
*);
367 /// \ingroup StoreAPI
368 void storeSwapFileNumberSet(StoreEntry
* e
, sfileno filn
);
370 /// \ingroup StoreAPI
371 void storeFsInit(void);
373 /// \ingroup StoreAPI
374 void storeFsDone(void);
376 /// \ingroup StoreAPI
377 void storeReplAdd(const char *, REMOVALPOLICYCREATE
*);
379 /// \ingroup StoreAPI
380 extern FREE destroyStoreEntry
;
382 /// \ingroup StoreAPI
383 void storeGetMemSpace(int size
);
385 #endif /* SQUID_STORE_H */