]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors | |
3 | * | |
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. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_MEMSTORE_H | |
10 | #define SQUID_MEMSTORE_H | |
11 | ||
12 | #include "ipc/mem/Page.h" | |
13 | #include "ipc/mem/PageStack.h" | |
14 | #include "ipc/StoreMap.h" | |
15 | #include "Store.h" | |
16 | #include "store/Controlled.h" | |
17 | ||
18 | // StoreEntry restoration info not already stored by Ipc::StoreMap | |
19 | struct MemStoreMapExtraItem { | |
20 | Ipc::Mem::PageId page; ///< shared memory page with entry slice content | |
21 | }; | |
22 | typedef Ipc::StoreMapItems<MemStoreMapExtraItem> MemStoreMapExtras; | |
23 | typedef Ipc::StoreMap MemStoreMap; | |
24 | ||
25 | class ShmWriter; | |
26 | ||
27 | /// Stores HTTP entities in RAM. Current implementation uses shared memory. | |
28 | /// Unlike a disk store (SwapDir), operations are synchronous (and fast). | |
29 | class MemStore: public Store::Controlled, public Ipc::StoreMapCleaner | |
30 | { | |
31 | public: | |
32 | MemStore(); | |
33 | virtual ~MemStore(); | |
34 | ||
35 | /// whether e should be kept in local RAM for possible future caching | |
36 | bool keepInLocalMemory(const StoreEntry &e) const; | |
37 | ||
38 | /// copy non-shared entry data of the being-cached entry to our cache | |
39 | void write(StoreEntry &e); | |
40 | ||
41 | /// all data has been received; there will be no more write() calls | |
42 | void completeWriting(StoreEntry &e); | |
43 | ||
44 | /// called when the entry is about to forget its association with mem cache | |
45 | void disconnect(StoreEntry &e); | |
46 | ||
47 | /* Storage API */ | |
48 | virtual void create() override {} | |
49 | virtual void init() override; | |
50 | virtual StoreEntry *get(const cache_key *) override; | |
51 | virtual uint64_t maxSize() const override; | |
52 | virtual uint64_t minSize() const override; | |
53 | virtual uint64_t currentSize() const override; | |
54 | virtual uint64_t currentCount() const override; | |
55 | virtual int64_t maxObjectSize() const override; | |
56 | virtual void getStats(StoreInfoStats &stats) const override; | |
57 | virtual void stat(StoreEntry &e) const override; | |
58 | virtual void reference(StoreEntry &e) override; | |
59 | virtual bool dereference(StoreEntry &e) override; | |
60 | virtual void updateHeaders(StoreEntry *e) override; | |
61 | virtual void maintain() override; | |
62 | virtual bool anchorToCache(StoreEntry &e, bool &inSync) override; | |
63 | virtual bool updateAnchored(StoreEntry &) override; | |
64 | virtual void evictCached(StoreEntry &) override; | |
65 | virtual void evictIfFound(const cache_key *) override; | |
66 | ||
67 | /// whether Squid is correctly configured to use a shared memory cache | |
68 | static bool Enabled() { return EntryLimit() > 0; } | |
69 | static int64_t EntryLimit(); | |
70 | /// whether Squid is configured to use a shared memory cache | |
71 | /// (it may still be disabled due to the implicit minimum entry size limit) | |
72 | static bool Requested(); | |
73 | ||
74 | protected: | |
75 | friend ShmWriter; | |
76 | ||
77 | bool shouldCache(StoreEntry &e) const; | |
78 | bool startCaching(StoreEntry &e); | |
79 | ||
80 | void copyToShm(StoreEntry &e); | |
81 | void copyToShmSlice(StoreEntry &e, Ipc::StoreMapAnchor &anchor, Ipc::StoreMap::Slice &slice); | |
82 | bool copyFromShm(StoreEntry &e, const sfileno index, const Ipc::StoreMapAnchor &anchor); | |
83 | bool copyFromShmSlice(StoreEntry &e, const StoreIOBuffer &buf, bool eof); | |
84 | ||
85 | void updateHeadersOrThrow(Ipc::StoreMapUpdate &update); | |
86 | ||
87 | void anchorEntry(StoreEntry &e, const sfileno index, const Ipc::StoreMapAnchor &anchor); | |
88 | bool updateAnchoredWith(StoreEntry &, const sfileno, const Ipc::StoreMapAnchor &); | |
89 | ||
90 | Ipc::Mem::PageId pageForSlice(Ipc::StoreMapSliceId sliceId); | |
91 | Ipc::StoreMap::Slice &nextAppendableSlice(const sfileno entryIndex, sfileno &sliceOffset); | |
92 | sfileno reserveSapForWriting(Ipc::Mem::PageId &page); | |
93 | ||
94 | // Ipc::StoreMapCleaner API | |
95 | virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId) override; | |
96 | ||
97 | private: | |
98 | // TODO: move freeSlots into map | |
99 | Ipc::Mem::Pointer<Ipc::Mem::PageStack> freeSlots; ///< unused map slot IDs | |
100 | MemStoreMap *map; ///< index of mem-cached entries | |
101 | ||
102 | typedef MemStoreMapExtras Extras; | |
103 | Ipc::Mem::Pointer<Extras> extras; ///< IDs of pages with slice data | |
104 | ||
105 | /// the last allocate slice for writing a store entry (during copyToShm) | |
106 | sfileno lastWritingSlice; | |
107 | ||
108 | /// temporary storage for slot and page ID pointers; for the waiting cache | |
109 | class SlotAndPage | |
110 | { | |
111 | public: | |
112 | SlotAndPage(): slot(NULL), page(NULL) {} | |
113 | bool operator !() const { return !slot && !page; } | |
114 | Ipc::Mem::PageId *slot; ///< local slot variable, waiting to be filled | |
115 | Ipc::Mem::PageId *page; ///< local page variable, waiting to be filled | |
116 | }; | |
117 | SlotAndPage waitingFor; ///< a cache for a single "hot" free slot and page | |
118 | }; | |
119 | ||
120 | // Why use Store as a base? MemStore and SwapDir are both "caches". | |
121 | ||
122 | // Why not just use a SwapDir API? That would not help much because Store has | |
123 | // to check/update memory cache separately from the disk cache. And same API | |
124 | // would hurt because we can support synchronous get/put, unlike the disks. | |
125 | ||
126 | #endif /* SQUID_MEMSTORE_H */ | |
127 |