]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/StoreMap.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / ipc / StoreMap.h
1 #ifndef SQUID_IPC_STORE_MAP_H
2 #define SQUID_IPC_STORE_MAP_H
3
4 #include "ipc/ReadWriteLock.h"
5 #include "ipc/mem/Pointer.h"
6 #include "typedefs.h"
7
8 namespace Ipc
9 {
10
11 /// a StoreMap element, holding basic shareable StoreEntry info
12 class StoreMapSlot
13 {
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
25 Atomic::WordT<uint8_t> waitingToBeFreed; ///< may be accessed w/o a lock
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;
36 uint16_t refcount;
37 uint16_t flags;
38 } basics;
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
45 } State;
46 State state; ///< current state
47 };
48
49 class StoreMapCleaner;
50
51 /// map of StoreMapSlots indexed by their keys, with read/write slot locking
52 /// kids extend to store custom data
53 class StoreMap
54 {
55 public:
56 typedef StoreMapSlot Slot;
57
58 /// data shared across maps in different processes
59 class Shared
60 {
61 public:
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 ~Shared();
66
67 const int limit; ///< maximum number of map slots
68 const size_t extrasSize; ///< size of slot extra data
69 Atomic::Word count; ///< current number of map slots
70 Slot *slots; ///< slots storage
71 private:
72 Shared(); //disabled
73 Shared &operator=(const Shared&); //disabled
74 Shared(const Shared&); //disabled
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);
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
107 bool valid(const int n) const; ///< whether n is a valid slot coordinate
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
114 StoreMapCleaner *cleaner; ///< notified before a readable entry is freed
115
116 protected:
117 static Owner *Init(const char *const path, const int limit, const size_t extrasSize);
118
119 const String path; ///< cache_dir path, used for logging
120 Mem::Pointer<Shared> shared;
121
122 private:
123 int slotIndexByKey(const cache_key *const key) const;
124 Slot &slotByKey(const cache_key *const key);
125
126 Slot *openForReading(Slot &s);
127 void abortWriting(const sfileno fileno);
128 void freeIfNeeded(Slot &s);
129 void freeLocked(Slot &s, bool keepLocked);
130 };
131
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
154 };
155
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
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):
177 StoreMap(path)
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
200 } // namespace Ipc
201
202 // We do not reuse FileMap because we cannot control its size,
203 // resulting in sfilenos that are pointing beyond the database.
204
205 #endif /* SQUID_IPC_STORE_MAP_H */