]>
Commit | Line | Data |
---|---|---|
44c95fcf AR |
1 | #ifndef SQUID_IPC_STORE_MAP_H |
2 | #define SQUID_IPC_STORE_MAP_H | |
3 | ||
4 | #include "ipc/ReadWriteLock.h" | |
68353d5a | 5 | #include "ipc/mem/Pointer.h" |
7f6748c8 | 6 | #include "typedefs.h" |
44c95fcf | 7 | |
9199139f AR |
8 | namespace Ipc |
9 | { | |
44c95fcf AR |
10 | |
11 | /// a StoreMap element, holding basic shareable StoreEntry info | |
9199139f AR |
12 | class StoreMapSlot |
13 | { | |
44c95fcf AR |
14 | public: |
15 | StoreMapSlot(); | |
16 | ||
17 | /// store StoreEntry key and basics | |
18 | void set(const StoreEntry &anEntry); | |
19 | ||
20 | void setKey(const cache_key *const aKey); | |
21 | bool sameKey(const cache_key *const aKey) const; | |
22 | ||
23 | public: | |
24 | mutable ReadWriteLock lock; ///< protects slot data below | |
794d4c0c | 25 | Atomic::WordT<uint8_t> waitingToBeFreed; ///< may be accessed w/o a lock |
44c95fcf AR |
26 | |
27 | uint64_t key[2]; ///< StoreEntry key | |
28 | ||
29 | // STORE_META_STD TLV field from StoreEntry | |
30 | struct Basics { | |
31 | time_t timestamp; | |
32 | time_t lastref; | |
33 | time_t expires; | |
34 | time_t lastmod; | |
35 | uint64_t swap_file_sz; | |
89924985 AR |
36 | uint16_t refcount; |
37 | uint16_t flags; | |
9199139f | 38 | } basics; |
44c95fcf AR |
39 | |
40 | /// possible persistent states | |
41 | typedef enum { | |
42 | Empty, ///< ready for writing, with nothing of value | |
43 | Writeable, ///< transitions from Empty to Readable | |
44 | Readable, ///< ready for reading | |
9199139f | 45 | } State; |
44c95fcf AR |
46 | State state; ///< current state |
47 | }; | |
48 | ||
7f6748c8 AR |
49 | class StoreMapCleaner; |
50 | ||
9199139f | 51 | /// map of StoreMapSlots indexed by their keys, with read/write slot locking |
44c95fcf AR |
52 | /// kids extend to store custom data |
53 | class StoreMap | |
54 | { | |
55 | public: | |
56 | typedef StoreMapSlot Slot; | |
57 | ||
f8f98441 | 58 | /// data shared across maps in different processes |
fc3921ec A |
59 | class Shared |
60 | { | |
f8f98441 | 61 | public: |
68353d5a DK |
62 | Shared(const int aLimit, const size_t anExtrasSize); |
63 | size_t sharedMemorySize() const; | |
64 | static size_t SharedMemorySize(const int limit, const size_t anExtrasSize); | |
2cde0303 | 65 | ~Shared(); |
68353d5a DK |
66 | |
67 | const int limit; ///< maximum number of map slots | |
68 | const size_t extrasSize; ///< size of slot extra data | |
794d4c0c | 69 | Atomic::Word count; ///< current number of map slots |
2cde0303 FC |
70 | Slot *slots; ///< slots storage |
71 | private: | |
72 | Shared(); //disabled | |
73 | Shared &operator=(const Shared&); //disabled | |
74 | Shared(const Shared&); //disabled | |
68353d5a DK |
75 | }; |
76 | ||
77 | public: | |
78 | typedef Mem::Owner<Shared> Owner; | |
79 | ||
80 | /// initialize shared memory | |
81 | static Owner *Init(const char *const path, const int limit); | |
82 | ||
83 | StoreMap(const char *const aPath); | |
44c95fcf AR |
84 | |
85 | /// finds, reservers space for writing a new entry or returns nil | |
86 | Slot *openForWriting(const cache_key *const key, sfileno &fileno); | |
87 | /// successfully finish writing the entry | |
88 | void closeForWriting(const sfileno fileno, bool lockForReading = false); | |
89 | ||
90 | /// only works on locked entries; returns nil unless the slot is readable | |
91 | const Slot *peekAtReader(const sfileno fileno) const; | |
92 | ||
93 | /// mark the slot as waiting to be freed and, if possible, free it | |
94 | void free(const sfileno fileno); | |
95 | ||
96 | /// open slot for reading, increments read level | |
97 | const Slot *openForReading(const cache_key *const key, sfileno &fileno); | |
98 | /// open slot for reading, increments read level | |
99 | const Slot *openForReadingAt(const sfileno fileno); | |
100 | /// close slot after reading, decrements read level | |
101 | void closeForReading(const sfileno fileno); | |
102 | ||
103 | /// called by lock holder to terminate either slot writing or reading | |
104 | void abortIo(const sfileno fileno); | |
105 | ||
106 | bool full() const; ///< there are no empty slots left | |
68353d5a | 107 | bool valid(const int n) const; ///< whether n is a valid slot coordinate |
44c95fcf AR |
108 | int entryCount() const; ///< number of used slots |
109 | int entryLimit() const; ///< maximum number of slots that can be used | |
110 | ||
111 | /// adds approximate current stats to the supplied ones | |
112 | void updateStats(ReadWriteLockStats &stats) const; | |
113 | ||
7f6748c8 AR |
114 | StoreMapCleaner *cleaner; ///< notified before a readable entry is freed |
115 | ||
44c95fcf | 116 | protected: |
68353d5a | 117 | static Owner *Init(const char *const path, const int limit, const size_t extrasSize); |
44c95fcf | 118 | |
44c95fcf | 119 | const String path; ///< cache_dir path, used for logging |
68353d5a | 120 | Mem::Pointer<Shared> shared; |
44c95fcf AR |
121 | |
122 | private: | |
123 | int slotIndexByKey(const cache_key *const key) const; | |
124 | Slot &slotByKey(const cache_key *const key); | |
125 | ||
9199139f | 126 | Slot *openForReading(Slot &s); |
44c95fcf AR |
127 | void abortWriting(const sfileno fileno); |
128 | void freeIfNeeded(Slot &s); | |
129 | void freeLocked(Slot &s, bool keepLocked); | |
68353d5a | 130 | }; |
44c95fcf | 131 | |
68353d5a DK |
132 | /// StoreMap with extra slot data |
133 | /// Note: ExtrasT must be POD, it is initialized with zeroes, no | |
134 | /// constructors or destructors are called | |
135 | template <class ExtrasT> | |
136 | class StoreMapWithExtras: public StoreMap | |
137 | { | |
138 | public: | |
139 | typedef ExtrasT Extras; | |
140 | ||
141 | /// initialize shared memory | |
142 | static Owner *Init(const char *const path, const int limit); | |
143 | ||
144 | StoreMapWithExtras(const char *const path); | |
145 | ||
146 | /// write access to the extras; call openForWriting() first! | |
147 | ExtrasT &extras(const sfileno fileno); | |
148 | /// read-only access to the extras; call openForReading() first! | |
149 | const ExtrasT &extras(const sfileno fileno) const; | |
150 | ||
151 | protected: | |
152 | ||
153 | ExtrasT *sharedExtras; ///< pointer to extras in shared memory | |
44c95fcf AR |
154 | }; |
155 | ||
7f6748c8 AR |
156 | /// API for adjusting external state when dirty map slot is being freed |
157 | class StoreMapCleaner | |
158 | { | |
159 | public: | |
160 | virtual ~StoreMapCleaner() {} | |
161 | ||
162 | /// adjust slot-linked state before a locked Readable slot is erased | |
163 | virtual void cleanReadable(const sfileno fileno) = 0; | |
164 | }; | |
165 | ||
68353d5a DK |
166 | // StoreMapWithExtras implementation |
167 | ||
168 | template <class ExtrasT> | |
169 | StoreMap::Owner * | |
170 | StoreMapWithExtras<ExtrasT>::Init(const char *const path, const int limit) | |
171 | { | |
172 | return StoreMap::Init(path, limit, sizeof(Extras)); | |
173 | } | |
174 | ||
175 | template <class ExtrasT> | |
176 | StoreMapWithExtras<ExtrasT>::StoreMapWithExtras(const char *const path): | |
9199139f | 177 | StoreMap(path) |
68353d5a DK |
178 | { |
179 | const size_t sharedSizeWithoutExtras = | |
180 | Shared::SharedMemorySize(entryLimit(), 0); | |
181 | sharedExtras = reinterpret_cast<Extras *>(reinterpret_cast<char *>(shared.getRaw()) + sharedSizeWithoutExtras); | |
182 | } | |
183 | ||
184 | template <class ExtrasT> | |
185 | ExtrasT & | |
186 | StoreMapWithExtras<ExtrasT>::extras(const sfileno fileno) | |
187 | { | |
188 | return const_cast<ExtrasT &>(const_cast<const StoreMapWithExtras *>(this)->extras(fileno)); | |
189 | } | |
190 | ||
191 | template <class ExtrasT> | |
192 | const ExtrasT & | |
193 | StoreMapWithExtras<ExtrasT>::extras(const sfileno fileno) const | |
194 | { | |
195 | assert(sharedExtras); | |
196 | assert(valid(fileno)); | |
197 | return sharedExtras[fileno]; | |
198 | } | |
199 | ||
44c95fcf AR |
200 | } // namespace Ipc |
201 | ||
75f8f9a2 | 202 | // We do not reuse FileMap because we cannot control its size, |
44c95fcf AR |
203 | // resulting in sfilenos that are pointing beyond the database. |
204 | ||
205 | #endif /* SQUID_IPC_STORE_MAP_H */ |