]> git.ipfire.org Git - thirdparty/squid.git/blame - src/Store.h
Support "appending" read/write lock state that can be shared by readers
[thirdparty/squid.git] / src / Store.h
CommitLineData
e6ccf245 1/*
e6ccf245 2 *
3 * SQUID Web Proxy Cache http://www.squid-cache.org/
4 * ----------------------------------------------------------
5 *
6 * Squid is the result of efforts by numerous individuals from
7 * the Internet community; see the CONTRIBUTORS file for full
8 * details. Many organizations have provided support for Squid's
9 * development; see the SPONSORS file for full details. Squid is
10 * Copyrighted (C) 2001 by the Regents of the University of
11 * California; see the COPYRIGHT file for full details. Squid
12 * incorporates software developed and/or copyrighted by other
13 * sources; see the CREDITS file for full details.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
26ac0430 19 *
e6ccf245 20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
26ac0430 24 *
e6ccf245 25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
28 *
29 */
e6ccf245 30#ifndef SQUID_STORE_H
31#define SQUID_STORE_H
32
63be0a78 33/**
34 \defgroup StoreAPI Store API
35 \ingroup FileSystems
36 */
37
8bf217bd 38#include "base/RefCount.h"
3e4bebf8 39#include "comm/forward.h"
582c2af2 40#include "CommRead.h"
c6983ec7 41#include "hash.h"
43ca19e0 42#include "HttpReply.h"
582c2af2 43#include "HttpRequestMethod.h"
582c2af2 44#include "Range.h"
aa839030 45#include "RemovalPolicy.h"
582c2af2 46#include "StoreIOBuffer.h"
93bc1434 47#include "StoreStats.h"
528b2c61 48
f41735ea 49#if USE_SQUID_ESI
f99c2cfe 50#include "esi/Element.h"
43ae1d95 51#endif
52
27e059d4
AJ
53#if HAVE_OSTREAM
54#include <ostream>
55#endif
56
65517dc8 57class AsyncCall;
582c2af2 58class HttpRequest;
528b2c61 59class MemObject;
71b673d4
FC
60class Packer;
61class RequestFlags;
582c2af2 62class StoreClient;
c8f4eac4 63class StoreSearch;
7d3c4ca1 64class SwapDir;
c8f4eac4 65
8822ebee
AR
66extern StoreIoStats store_io_stats;
67
051dedf9
AR
68/// maximum number of entries per cache_dir
69enum { SwapFilenMax = 0xFFFFFF }; // keep in sync with StoreEntry::swap_filen
70
63be0a78 71/**
72 \ingroup StoreAPI
73 */
62e76326 74class StoreEntry : public hash_link
75{
76
332dafa2 77public:
a46d2c0e 78 static DeferredRead::DeferrableRead DeferReader;
79 bool checkDeferRead(int fd) const;
62e76326 80
528b2c61 81 virtual const char *getMD5Text() const;
c8f4eac4 82 StoreEntry();
83 StoreEntry(const char *url, const char *log_url);
6d8d05b5 84 virtual ~StoreEntry();
43ae1d95 85
528b2c61 86 virtual HttpReply const *getReply() const;
87 virtual void write (StoreIOBuffer);
88 virtual _SQUID_INLINE_ bool isEmpty() const;
aa18a4ca 89 virtual bool isAccepting() const;
384a7590 90 virtual size_t bytesWanted(Range<size_t> const aRange, bool ignoreDelayPool = false) const;
528b2c61 91 virtual void complete();
92 virtual store_client_t storeClientType() const;
93 virtual char const *getSerialisedMetaData();
3756e5c0
AR
94 void replaceHttpReply(HttpReply *, bool andStartWriting = true);
95 void startWriting(); ///< pack and write reply headers and, maybe, body
5b55f1f1
CT
96 /// whether we may start writing to disk (now or in the future)
97 virtual bool mayStartSwapOut();
98 virtual void trimMemory(const bool preserveSwappable);
bfb55b6f 99 void abort();
c8f4eac4 100 void unlink();
5ed72359 101 void makePublic();
102 void makePrivate();
d88e3c49 103 void setPublicKey();
104 void setPrivateKey();
105 void expireNow();
106 void releaseRequest();
107 void negativeCache();
63be0a78 108 void cacheNegatively(); /** \todo argh, why both? */
d88e3c49 109 void invokeHandlers();
110 void purgeMem();
9487bae9 111 void cacheInMemory(); ///< start or continue storing in memory cache
c07cbbf4 112 void swapOut();
5b55f1f1
CT
113 /// whether we are in the process of writing this entry to disk
114 bool swappingOut() const { return swap_status == SWAPOUT_WRITING; }
aa1a691e 115 void swapOutFileClose(int how);
3900307b 116 const char *url() const;
117 int checkCachable();
118 int checkNegativeHit() const;
119 int locked() const;
120 int validToSend() const;
9487bae9 121 bool memoryCachable() const; ///< may be cached in memory
3900307b 122 void createMemObject(const char *, const char *);
9487bae9 123 void hideMemObject(); ///< no mem_obj for callers until createMemObject
3900307b 124 void dump(int debug_lvl) const;
125 void hashDelete();
126 void hashInsert(const cache_key *);
127 void registerAbort(STABH * cb, void *);
128 void reset();
129 void setMemStatus(mem_status_t);
130 void timestampsSet();
131 void unregisterAbort();
132 void destroyMemObject();
133 int checkTooSmall();
528b2c61 134
3e4bebf8 135 void delayAwareRead(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer callback);
43ae1d95 136
a46d2c0e 137 void setNoDelay (bool const);
190154cf 138 bool modifiedSince(HttpRequest * request) const;
79c8035e
AR
139 /// has ETag matching at least one of the If-Match etags
140 bool hasIfMatchEtag(const HttpRequest &request) const;
141 /// has ETag matching at least one of the If-None-Match etags
142 bool hasIfNoneMatchEtag(const HttpRequest &request) const;
63be0a78 143
144 /** What store does this entry belong too ? */
7d3c4ca1 145 virtual RefCount<SwapDir> store() const;
a46d2c0e 146
e6ccf245 147 MemObject *mem_obj;
9487bae9 148 MemObject *hidden_mem_obj; ///< mem_obj created before URLs were known
e6ccf245 149 RemovalPolicyNode repl;
150 /* START OF ON-DISK STORE_META_STD TLV field */
151 time_t timestamp;
152 time_t lastref;
153 time_t expires;
154 time_t lastmod;
47f6e231 155 uint64_t swap_file_sz;
f45dd259
AJ
156 uint16_t refcount;
157 uint16_t flags;
e6ccf245 158 /* END OF ON-DISK STORE_META_STD */
62e76326 159
051dedf9
AR
160 /// unique ID inside a cache_dir for swapped out entries; -1 for others
161 sfileno swap_filen:25; // keep in sync with SwapFilenMax
d1398b75
HN
162
163 sdirno swap_dirn:7;
62e76326 164
f45dd259 165 unsigned short lock_count; /* Assume < 65536! */
62e76326 166
d1398b75 167 mem_status_t mem_status:3;
62e76326 168
d1398b75 169 ping_status_t ping_status:3;
62e76326 170
d1398b75 171 store_status_t store_status:3;
62e76326 172
d1398b75 173 swap_status_t swap_status:3;
62e76326 174
e6ccf245 175public:
176 static size_t inUseCount();
60745f24 177 static void getPublicByRequestMethod(StoreClient * aClient, HttpRequest * request, const HttpRequestMethod& method);
190154cf 178 static void getPublicByRequest(StoreClient * aClient, HttpRequest * request);
60745f24 179 static void getPublic(StoreClient * aClient, const char *uri, const HttpRequestMethod& method);
528b2c61 180
26ac0430 181 virtual bool isNull() {
62e76326 182 return false;
63be0a78 183 };
62e76326 184
35db0b4e 185 void *operator new(size_t byteCount);
e6ccf245 186 void operator delete(void *address);
43ae1d95 187 void setReleaseFlag();
f41735ea 188#if USE_SQUID_ESI
43ae1d95 189
190 ESIElement::Pointer cachedESITree;
191#endif
63be0a78 192 /** append bytes to the buffer */
c21ad0f5 193 virtual void append(char const *, int len);
63be0a78 194 /** disable sending content to the clients */
c21ad0f5 195 virtual void buffer();
63be0a78 196 /** flush any buffered content */
c21ad0f5 197 virtual void flush();
47f6e231 198 virtual int64_t objectLen() const;
199 virtual int64_t contentLen() const;
c21ad0f5 200
18994992
AR
201 /** deprecated: lock() in anonymous context folowed by touch()
202 * RBC 20050104 this is wrong- memory ref counting
203 * is not at all equivalent to the store 'usage' concept
204 * which the replacement policies should be acting upon.
205 * specifically, object iteration within stores needs
206 * memory ref counting to prevent race conditions,
207 * but this should not influence store replacement.
208 */
209 void lock() { lock("somebody"); touch(); }
210
211 /// claim shared ownership of this entry (for use in a given context)
212 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 = "somebody");
216 /// update last reference timestamp and related Store metadata
217 void touch();
218
5f33b71d 219 virtual void release();
62e76326 220
0ad2b63b
CT
221#if USE_ADAPTATION
222 /// call back producer when more buffer space is available
223 void deferProducer(const AsyncCall::Pointer &producer);
224 /// calls back producer registered with deferProducer
225 void kickProducer();
226#endif
227
e6ccf245 228private:
04eb0689 229 static MemAllocator *pool;
528b2c61 230
0ad2b63b
CT
231#if USE_ADAPTATION
232 /// producer callback registered with deferProducer
233 AsyncCall::Pointer deferredProducer;
234#endif
235
528b2c61 236 bool validLength() const;
79c8035e 237 bool hasOneOfEtags(const String &reqETags, const bool allowWeakMatch) const;
e6ccf245 238};
239
2c4cd1ad
AR
240std::ostream &operator <<(std::ostream &os, const StoreEntry &e);
241
63be0a78 242/// \ingroup StoreAPI
3b13a8fd 243class NullStoreEntry:public StoreEntry
e6ccf245 244{
62e76326 245
e6ccf245 246public:
247 static NullStoreEntry *getInstance();
26ac0430 248 bool isNull() {
62e76326 249 return true;
e6ccf245 250 }
62e76326 251
332dafa2 252 const char *getMD5Text() const;
528b2c61 253 _SQUID_INLINE_ HttpReply const *getReply() const;
26ac0430 254 void write (StoreIOBuffer) {}
62e76326 255
528b2c61 256 bool isEmpty () const {return true;}
62e76326 257
384a7590 258 virtual size_t bytesWanted(Range<size_t> const aRange, bool ignoreDelayPool = false) const { return aRange.end; }
62e76326 259
e6ccf245 260 void operator delete(void *address);
26ac0430 261 void complete() {}
62e76326 262
263private:
26ac0430 264 store_client_t storeClientType() const {return STORE_MEM_CLIENT;}
62e76326 265
528b2c61 266 char const *getSerialisedMetaData();
5b55f1f1 267 bool mayStartSwapout() {return false;}
62e76326 268
74b9c248 269 void trimMemory(const bool preserveSwappable) {}
528b2c61 270
e6ccf245 271 static NullStoreEntry _instance;
272};
273
63be0a78 274/// \ingroup StoreAPI
c8f4eac4 275typedef void (*STOREGETCLIENT) (StoreEntry *, void *cbdata);
276
63be0a78 277/**
278 \ingroup StoreAPI
279 * Abstract base class that will replace the whole store and swapdir interface.
280 */
c8f4eac4 281class Store : public RefCountable
282{
283
284public:
63be0a78 285 /** The root store */
88e13392 286 static _SQUID_INLINE_ Store &Root();
c8f4eac4 287 static void Root(Store *);
288 static void Root(RefCount<Store>);
289 static void Stats(StoreEntry * output);
290 static void Maintain(void *unused);
291
292 virtual ~Store() {}
293
63be0a78 294 /** Handle pending callbacks - called by the event loop. */
c8f4eac4 295 virtual int callback() = 0;
63be0a78 296
297 /** create the resources needed for this store to operate */
c8f4eac4 298 virtual void create();
63be0a78 299
300 /**
301 * Notify this store that its disk is full.
302 \todo XXX move into a protected api call between store files and their stores, rather than a top level api call
c8f4eac4 303 */
304 virtual void diskFull();
c8f4eac4 305
63be0a78 306 /** Retrieve a store entry from the store */
b21767da 307 virtual StoreEntry * get(const cache_key *) = 0;
c8f4eac4 308
63be0a78 309 /** \todo imeplement the async version */
b21767da 310 virtual void get(String const key , STOREGETCLIENT callback, void *cbdata) = 0;
c8f4eac4 311
312 /* prepare the store for use. The store need not be usable immediately,
313 * it should respond to readable() and writable() with true as soon
314 * as it can provide those services
315 */
316 virtual void init() = 0;
317
63be0a78 318 /**
319 * The maximum size the store will support in normal use. Inaccuracy is permitted,
320 * but may throw estimates for memory etc out of whack.
321 */
12e11a5c 322 virtual uint64_t maxSize() const = 0;
c8f4eac4 323
63be0a78 324 /** The minimum size the store will shrink to via normal housekeeping */
12e11a5c 325 virtual uint64_t minSize() const = 0;
c8f4eac4 326
57f583f1
DK
327 /** current store size */
328 virtual uint64_t currentSize() const = 0;
39c1e1d9
DK
329
330 /** the total number of objects stored */
331 virtual uint64_t currentCount() const = 0;
332
af2fda07
DK
333 /** the maximum object size that can be stored, -1 if unlimited */
334 virtual int64_t maxObjectSize() const = 0;
335
93bc1434
AR
336 /// collect cache storage-related statistics
337 virtual void getStats(StoreInfoStats &stats) const = 0;
338
63be0a78 339 /**
340 * Output stats to the provided store entry.
341 \todo make these calls asynchronous
342 */
343 virtual void stat(StoreEntry &) const = 0;
c8f4eac4 344
63be0a78 345 /** Sync the store prior to shutdown */
346 virtual void sync();
c8f4eac4 347
63be0a78 348 /** remove a Store entry from the store */
c8f4eac4 349 virtual void unlink (StoreEntry &);
350
351 /* search in the store */
30abd221 352 virtual StoreSearch *search(String const url, HttpRequest *) = 0;
c8f4eac4 353
354 /* pulled up from SwapDir for migration.... probably do not belong here */
355 virtual void reference(StoreEntry &) = 0; /* Reference this object */
356
4c973beb 357 /// Undo reference(), returning false iff idle e should be destroyed
54347cbd 358 virtual bool dereference(StoreEntry &e, bool wantsLocalMemory) = 0;
c8f4eac4 359
360 virtual void maintain() = 0; /* perform regular maintenance should be private and self registered ... */
361
9487bae9
AR
362 // XXX: This method belongs to Store::Root/StoreController, but it is here
363 // because test cases use non-StoreController derivatives as Root
364 /// called when the entry is no longer needed by any transaction
365 virtual void handleIdleEntry(StoreEntry &e) {}
366
96a7de88
DK
367 // XXX: This method belongs to Store::Root/StoreController, but it is here
368 // because test cases use non-StoreController derivatives as Root
369 /// called to get rid of no longer needed entry data in RAM, if any
370 virtual void maybeTrimMemory(StoreEntry &e, const bool preserveSwappable) {}
371
9a9954ba
AR
372 // XXX: This method belongs to Store::Root/StoreController, but it is here
373 // to avoid casting Root() to StoreController until Root() API is fixed.
374 /// makes the entry available for collapsing future requests
375 virtual void allowCollapsing(StoreEntry *e, const RequestFlags &reqFlags, const HttpRequestMethod &reqMethod) {}
376
ce49546e
AR
377 // XXX: This method belongs to Store::Root/StoreController, but it is here
378 // to avoid casting Root() to StoreController until Root() API is fixed.
379 /// Update local intransit entry after changes made by appending worker.
380 virtual void syncCollapsed(const cache_key *key) {}
381
382 // XXX: This method belongs to Store::Root/StoreController, but it is here
383 // to avoid casting Root() to StoreController until Root() API is fixed.
384 /// removes the entry from the memory cache
385 virtual void memoryUnlink(StoreEntry &e) {}
386
387 /// if the entry is found, tie it to this cache and call updateCollapsed()
388 virtual bool anchorCollapsed(StoreEntry &collapsed) { return false; }
389
390 /// update a local collapsed entry with fresh info from this cache (if any)
391 virtual bool updateCollapsed(StoreEntry &collapsed) { return false; }
392
c8f4eac4 393private:
394 static RefCount<Store> CurrentRoot;
395};
396
63be0a78 397/// \ingroup StoreAPI
c8f4eac4 398typedef RefCount<Store> StorePointer;
399
63be0a78 400/// \ingroup StoreAPI
71b673d4 401size_t storeEntryInUse();
63be0a78 402
403/// \ingroup StoreAPI
71b673d4 404const char *storeEntryFlags(const StoreEntry *);
63be0a78 405
406/// \ingroup StoreAPI
71b673d4 407void storeEntryReplaceObject(StoreEntry *, HttpReply *);
e6ccf245 408
63be0a78 409/// \ingroup StoreAPI
71b673d4 410StoreEntry *storeGetPublic(const char *uri, const HttpRequestMethod& method);
63be0a78 411
412/// \ingroup StoreAPI
71b673d4 413StoreEntry *storeGetPublicByRequest(HttpRequest * request);
63be0a78 414
415/// \ingroup StoreAPI
71b673d4 416StoreEntry *storeGetPublicByRequestMethod(HttpRequest * request, const HttpRequestMethod& method);
63be0a78 417
418/// \ingroup StoreAPI
71b673d4 419StoreEntry *storeCreateEntry(const char *, const char *, const RequestFlags &, const HttpRequestMethod&);
63be0a78 420
421/// \ingroup StoreAPI
71b673d4 422void storeInit(void);
63be0a78 423
63be0a78 424/// \ingroup StoreAPI
71b673d4 425void storeConfigure(void);
63be0a78 426
427/// \ingroup StoreAPI
71b673d4 428void storeFreeMemory(void);
63be0a78 429
430/// \ingroup StoreAPI
71b673d4 431int expiresMoreThan(time_t, time_t);
63be0a78 432
63be0a78 433/// \ingroup StoreAPI
71b673d4 434void storeAppendPrintf(StoreEntry *, const char *,...) PRINTF_FORMAT_ARG2;
63be0a78 435
436/// \ingroup StoreAPI
71b673d4 437void storeAppendVPrintf(StoreEntry *, const char *, va_list ap);
63be0a78 438
439/// \ingroup StoreAPI
71b673d4 440int storeTooManyDiskFilesOpen(void);
63be0a78 441
e1f7507e 442class SwapDir;
63be0a78 443/// \ingroup StoreAPI
71b673d4 444void storeHeapPositionUpdate(StoreEntry *, SwapDir *);
63be0a78 445
446/// \ingroup StoreAPI
71b673d4 447void storeSwapFileNumberSet(StoreEntry * e, sfileno filn);
63be0a78 448
449/// \ingroup StoreAPI
71b673d4 450void storeFsInit(void);
63be0a78 451
452/// \ingroup StoreAPI
71b673d4 453void storeFsDone(void);
63be0a78 454
455/// \ingroup StoreAPI
71b673d4 456void storeReplAdd(const char *, REMOVALPOLICYCREATE *);
63be0a78 457
458/// \ingroup StoreAPI
c8f4eac4 459extern FREE destroyStoreEntry;
e6ccf245 460
63be0a78 461/**
462 \ingroup StoreAPI
463 \todo should be a subclass of Packer perhaps ?
464 */
71b673d4 465void packerToStoreInit(Packer * p, StoreEntry * e);
25b6a907 466
6d3c2758 467/// \ingroup StoreAPI
71b673d4 468void storeGetMemSpace(int size);
6d3c2758 469
32d002cb 470#if _USE_INLINE_
528b2c61 471#include "Store.cci"
472#endif
473
e6ccf245 474#endif /* SQUID_STORE_H */