]>
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); | |
65 | ||
66 | const int limit; ///< maximum number of map slots | |
67 | const size_t extrasSize; ///< size of slot extra data | |
794d4c0c | 68 | Atomic::Word count; ///< current number of map slots |
68353d5a DK |
69 | Slot slots[]; ///< slots storage |
70 | }; | |
71 | ||
72 | public: | |
73 | typedef Mem::Owner<Shared> Owner; | |
74 | ||
75 | /// initialize shared memory | |
76 | static Owner *Init(const char *const path, const int limit); | |
77 | ||
78 | StoreMap(const char *const aPath); | |
44c95fcf AR |
79 | |
80 | /// finds, reservers space for writing a new entry or returns nil | |
81 | Slot *openForWriting(const cache_key *const key, sfileno &fileno); | |
82 | /// successfully finish writing the entry | |
83 | void closeForWriting(const sfileno fileno, bool lockForReading = false); | |
84 | ||
85 | /// only works on locked entries; returns nil unless the slot is readable | |
86 | const Slot *peekAtReader(const sfileno fileno) const; | |
87 | ||
88 | /// mark the slot as waiting to be freed and, if possible, free it | |
89 | void free(const sfileno fileno); | |
90 | ||
91 | /// open slot for reading, increments read level | |
92 | const Slot *openForReading(const cache_key *const key, sfileno &fileno); | |
93 | /// open slot for reading, increments read level | |
94 | const Slot *openForReadingAt(const sfileno fileno); | |
95 | /// close slot after reading, decrements read level | |
96 | void closeForReading(const sfileno fileno); | |
97 | ||
98 | /// called by lock holder to terminate either slot writing or reading | |
99 | void abortIo(const sfileno fileno); | |
100 | ||
101 | bool full() const; ///< there are no empty slots left | |
68353d5a | 102 | bool valid(const int n) const; ///< whether n is a valid slot coordinate |
44c95fcf AR |
103 | int entryCount() const; ///< number of used slots |
104 | int entryLimit() const; ///< maximum number of slots that can be used | |
105 | ||
106 | /// adds approximate current stats to the supplied ones | |
107 | void updateStats(ReadWriteLockStats &stats) const; | |
108 | ||
7f6748c8 AR |
109 | StoreMapCleaner *cleaner; ///< notified before a readable entry is freed |
110 | ||
44c95fcf | 111 | protected: |
68353d5a | 112 | static Owner *Init(const char *const path, const int limit, const size_t extrasSize); |
44c95fcf | 113 | |
44c95fcf | 114 | const String path; ///< cache_dir path, used for logging |
68353d5a | 115 | Mem::Pointer<Shared> shared; |
44c95fcf AR |
116 | |
117 | private: | |
118 | int slotIndexByKey(const cache_key *const key) const; | |
119 | Slot &slotByKey(const cache_key *const key); | |
120 | ||
9199139f | 121 | Slot *openForReading(Slot &s); |
44c95fcf AR |
122 | void abortWriting(const sfileno fileno); |
123 | void freeIfNeeded(Slot &s); | |
124 | void freeLocked(Slot &s, bool keepLocked); | |
68353d5a | 125 | }; |
44c95fcf | 126 | |
68353d5a DK |
127 | /// StoreMap with extra slot data |
128 | /// Note: ExtrasT must be POD, it is initialized with zeroes, no | |
129 | /// constructors or destructors are called | |
130 | template <class ExtrasT> | |
131 | class StoreMapWithExtras: public StoreMap | |
132 | { | |
133 | public: | |
134 | typedef ExtrasT Extras; | |
135 | ||
136 | /// initialize shared memory | |
137 | static Owner *Init(const char *const path, const int limit); | |
138 | ||
139 | StoreMapWithExtras(const char *const path); | |
140 | ||
141 | /// write access to the extras; call openForWriting() first! | |
142 | ExtrasT &extras(const sfileno fileno); | |
143 | /// read-only access to the extras; call openForReading() first! | |
144 | const ExtrasT &extras(const sfileno fileno) const; | |
145 | ||
146 | protected: | |
147 | ||
148 | ExtrasT *sharedExtras; ///< pointer to extras in shared memory | |
44c95fcf AR |
149 | }; |
150 | ||
7f6748c8 AR |
151 | /// API for adjusting external state when dirty map slot is being freed |
152 | class StoreMapCleaner | |
153 | { | |
154 | public: | |
155 | virtual ~StoreMapCleaner() {} | |
156 | ||
157 | /// adjust slot-linked state before a locked Readable slot is erased | |
158 | virtual void cleanReadable(const sfileno fileno) = 0; | |
159 | }; | |
160 | ||
68353d5a DK |
161 | // StoreMapWithExtras implementation |
162 | ||
163 | template <class ExtrasT> | |
164 | StoreMap::Owner * | |
165 | StoreMapWithExtras<ExtrasT>::Init(const char *const path, const int limit) | |
166 | { | |
167 | return StoreMap::Init(path, limit, sizeof(Extras)); | |
168 | } | |
169 | ||
170 | template <class ExtrasT> | |
171 | StoreMapWithExtras<ExtrasT>::StoreMapWithExtras(const char *const path): | |
9199139f | 172 | StoreMap(path) |
68353d5a DK |
173 | { |
174 | const size_t sharedSizeWithoutExtras = | |
175 | Shared::SharedMemorySize(entryLimit(), 0); | |
176 | sharedExtras = reinterpret_cast<Extras *>(reinterpret_cast<char *>(shared.getRaw()) + sharedSizeWithoutExtras); | |
177 | } | |
178 | ||
179 | template <class ExtrasT> | |
180 | ExtrasT & | |
181 | StoreMapWithExtras<ExtrasT>::extras(const sfileno fileno) | |
182 | { | |
183 | return const_cast<ExtrasT &>(const_cast<const StoreMapWithExtras *>(this)->extras(fileno)); | |
184 | } | |
185 | ||
186 | template <class ExtrasT> | |
187 | const ExtrasT & | |
188 | StoreMapWithExtras<ExtrasT>::extras(const sfileno fileno) const | |
189 | { | |
190 | assert(sharedExtras); | |
191 | assert(valid(fileno)); | |
192 | return sharedExtras[fileno]; | |
193 | } | |
194 | ||
7f6748c8 | 195 | |
44c95fcf AR |
196 | } // namespace Ipc |
197 | ||
198 | // We do not reuse struct _fileMap because we cannot control its size, | |
199 | // resulting in sfilenos that are pointing beyond the database. | |
200 | ||
201 | #endif /* SQUID_IPC_STORE_MAP_H */ |