2 * Copyright (C) 1996-2015 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/RefCount.h"
14 #include "comm/forward.h"
17 #include "http/forward.h"
18 #include "http/RequestMethod.h"
19 #include "HttpReply.h"
20 #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
43 MEMPROXY_CLASS(StoreEntry
);
46 static DeferredRead::DeferrableRead DeferReader
;
47 bool checkDeferRead(int fd
) const;
49 virtual const char *getMD5Text() const;
51 virtual ~StoreEntry();
53 virtual HttpReply
const *getReply() const;
54 virtual void write (StoreIOBuffer
);
56 /** Check if the Store entry is emtpty
57 * \retval true Store contains 0 bytes of data.
58 * \retval false Store contains 1 or more bytes of data.
59 * \retval false Store contains negative content !!!!!!
61 virtual bool isEmpty() const {
63 return mem_obj
->endOffset() == 0;
65 virtual bool isAccepting() const;
66 virtual size_t bytesWanted(Range
<size_t> const aRange
, bool ignoreDelayPool
= false) const;
67 /// flags [truncated or too big] entry with ENTRY_BAD_LENGTH and releases it
68 void lengthWentBad(const char *reason
);
69 virtual void complete();
70 virtual store_client_t
storeClientType() const;
71 virtual char const *getSerialisedMetaData();
72 /// Store a prepared error response. MemObject locks the reply object.
73 void storeErrorResponse(HttpReply
*reply
);
74 void replaceHttpReply(HttpReply
*, bool andStartWriting
= true);
75 void startWriting(); ///< pack and write reply headers and, maybe, body
76 /// whether we may start writing to disk (now or in the future)
77 virtual bool mayStartSwapOut();
78 virtual void trimMemory(const bool preserveSwappable
);
80 // called when a decision to cache in memory has been made
81 void memOutDecision(const bool willCacheInRam
);
82 // called when a decision to cache on disk has been made
83 void swapOutDecision(const MemObject::SwapOut::Decision
&decision
);
91 void releaseRequest();
93 void cacheNegatively(); /** \todo argh, why both? */
94 void invokeHandlers();
96 void cacheInMemory(); ///< start or continue storing in memory cache
98 /// whether we are in the process of writing this entry to disk
99 bool swappingOut() const { return swap_status
== SWAPOUT_WRITING
; }
100 void swapOutFileClose(int how
);
101 const char *url() const;
102 /// Satisfies cachability requirements shared among disk and RAM caches.
103 /// Encapsulates common checks of mayStartSwapOut() and memoryCachable().
104 /// TODO: Rename and make private so only those two methods can call this.
105 bool checkCachable();
106 int checkNegativeHit() const;
108 int validToSend() const;
109 bool memoryCachable(); ///< checkCachable() and can be cached in memory
111 /// if needed, initialize mem_obj member w/o URI-related information
112 MemObject
*makeMemObject();
114 /// initialize mem_obj member (if needed) and supply URI-related info
115 void createMemObject(const char *storeId
, const char *logUri
, const HttpRequestMethod
&aMethod
);
117 void dump(int debug_lvl
) const;
119 void hashInsert(const cache_key
*);
120 void registerAbort(STABH
* cb
, void *);
122 void setMemStatus(mem_status_t
);
123 void timestampsSet();
124 void unregisterAbort();
125 void destroyMemObject();
128 void delayAwareRead(const Comm::ConnectionPointer
&conn
, char *buf
, int len
, AsyncCall::Pointer callback
);
130 void setNoDelay (bool const);
131 bool modifiedSince(HttpRequest
* request
) const;
132 /// has ETag matching at least one of the If-Match etags
133 bool hasIfMatchEtag(const HttpRequest
&request
) const;
134 /// has ETag matching at least one of the If-None-Match etags
135 bool hasIfNoneMatchEtag(const HttpRequest
&request
) const;
136 /// whether this entry has an ETag; if yes, puts ETag value into parameter
137 bool hasEtag(ETag
&etag
) const;
139 /// the disk this entry is [being] cached on; asserts for entries w/o a disk
140 Store::Disk
&disk() const;
143 RemovalPolicyNode repl
;
144 /* START OF ON-DISK STORE_META_STD TLV field */
149 uint64_t swap_file_sz
;
152 /* END OF ON-DISK STORE_META_STD */
154 /// unique ID inside a cache_dir for swapped out entries; -1 for others
155 sfileno swap_filen
:25; // keep in sync with SwapFilenMax
159 mem_status_t mem_status
:3;
161 ping_status_t ping_status
:3;
163 store_status_t store_status
:3;
165 swap_status_t swap_status
:3;
168 static size_t inUseCount();
169 static void getPublicByRequestMethod(StoreClient
* aClient
, HttpRequest
* request
, const HttpRequestMethod
& method
);
170 static void getPublicByRequest(StoreClient
* aClient
, HttpRequest
* request
);
171 static void getPublic(StoreClient
* aClient
, const char *uri
, const HttpRequestMethod
& method
);
173 virtual bool isNull() {
177 void setReleaseFlag();
180 ESIElement::Pointer cachedESITree
;
182 virtual int64_t objectLen() const;
183 virtual int64_t contentLen() const;
185 /// claim shared ownership of this entry (for use in a given context)
186 /// matching lock() and unlock() contexts eases leak triage but is optional
187 void lock(const char *context
);
189 /// disclaim shared ownership; may remove entry from store and delete it
190 /// returns remaning lock level (zero for unlocked and possibly gone entry)
191 int unlock(const char *context
);
193 /// returns a local concurrent use counter, for debugging
194 int locks() const { return static_cast<int>(lock_count
); }
196 /// update last reference timestamp and related Store metadata
199 virtual void release();
202 /// call back producer when more buffer space is available
203 void deferProducer(const AsyncCall::Pointer
&producer
);
204 /// calls back producer registered with deferProducer
209 virtual void append(char const *, int);
210 virtual void vappendf(const char *, va_list);
211 virtual void buffer();
212 virtual void flush();
215 void transientsAbandonmentCheck();
218 bool checkTooBig() const;
220 static MemAllocator
*pool
;
222 unsigned short lock_count
; /* Assume < 65536! */
225 /// producer callback registered with deferProducer
226 AsyncCall::Pointer deferredProducer
;
229 bool validLength() const;
230 bool hasOneOfEtags(const String
&reqETags
, const bool allowWeakMatch
) const;
233 std::ostream
&operator <<(std::ostream
&os
, const StoreEntry
&e
);
235 /// \ingroup StoreAPI
236 class NullStoreEntry
:public StoreEntry
240 static NullStoreEntry
*getInstance();
245 const char *getMD5Text() const;
246 HttpReply
const *getReply() const { return NULL
; }
247 void write (StoreIOBuffer
) {}
249 bool isEmpty () const {return true;}
251 virtual size_t bytesWanted(Range
<size_t> const aRange
, bool) const { return aRange
.end
; }
253 void operator delete(void *address
);
257 store_client_t
storeClientType() const {return STORE_MEM_CLIENT
;}
259 char const *getSerialisedMetaData();
260 virtual bool mayStartSwapOut() { return false; }
262 void trimMemory(const bool) {}
264 static NullStoreEntry _instance
;
267 /// \ingroup StoreAPI
268 typedef void (*STOREGETCLIENT
) (StoreEntry
*, void *cbdata
);
272 void Stats(StoreEntry
*output
);
273 void Maintain(void *unused
);
276 /// \ingroup StoreAPI
277 size_t storeEntryInUse();
279 /// \ingroup StoreAPI
280 const char *storeEntryFlags(const StoreEntry
*);
282 /// \ingroup StoreAPI
283 void storeEntryReplaceObject(StoreEntry
*, HttpReply
*);
285 /// \ingroup StoreAPI
286 StoreEntry
*storeGetPublic(const char *uri
, const HttpRequestMethod
& method
);
288 /// \ingroup StoreAPI
289 StoreEntry
*storeGetPublicByRequest(HttpRequest
* request
);
291 /// \ingroup StoreAPI
292 StoreEntry
*storeGetPublicByRequestMethod(HttpRequest
* request
, const HttpRequestMethod
& method
);
294 /// \ingroup StoreAPI
295 /// Like storeCreatePureEntry(), but also locks the entry and sets entry key.
296 StoreEntry
*storeCreateEntry(const char *, const char *, const RequestFlags
&, const HttpRequestMethod
&);
298 /// \ingroup StoreAPI
299 /// Creates a new StoreEntry with mem_obj and sets initial flags/states.
300 StoreEntry
*storeCreatePureEntry(const char *storeId
, const char *logUrl
, const RequestFlags
&, const HttpRequestMethod
&);
302 /// \ingroup StoreAPI
303 void storeInit(void);
305 /// \ingroup StoreAPI
306 void storeConfigure(void);
308 /// \ingroup StoreAPI
309 void storeFreeMemory(void);
311 /// \ingroup StoreAPI
312 int expiresMoreThan(time_t, time_t);
314 /// \ingroup StoreAPI
315 void storeAppendPrintf(StoreEntry
*, const char *,...) PRINTF_FORMAT_ARG2
;
317 /// \ingroup StoreAPI
318 void storeAppendVPrintf(StoreEntry
*, const char *, va_list ap
);
320 /// \ingroup StoreAPI
321 int storeTooManyDiskFilesOpen(void);
323 /// \ingroup StoreAPI
324 void storeHeapPositionUpdate(StoreEntry
*, SwapDir
*);
326 /// \ingroup StoreAPI
327 void storeSwapFileNumberSet(StoreEntry
* e
, sfileno filn
);
329 /// \ingroup StoreAPI
330 void storeFsInit(void);
332 /// \ingroup StoreAPI
333 void storeFsDone(void);
335 /// \ingroup StoreAPI
336 void storeReplAdd(const char *, REMOVALPOLICYCREATE
*);
338 /// \ingroup StoreAPI
339 extern FREE destroyStoreEntry
;
341 /// \ingroup StoreAPI
342 void storeGetMemSpace(int size
);
344 #endif /* SQUID_STORE_H */