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