]>
Commit | Line | Data |
---|---|---|
44c95fcf | 1 | /* |
44c95fcf AR |
2 | * DEBUG: section 54 Interprocess Communication |
3 | */ | |
4 | ||
582c2af2 | 5 | #include "squid.h" |
5bed43d6 | 6 | #include "ipc/StoreMap.h" |
1860fbac | 7 | #include "SBuf.h" |
5bed43d6 | 8 | #include "Store.h" |
602d9612 | 9 | #include "store_key_md5.h" |
5bed43d6 | 10 | #include "tools.h" |
44c95fcf | 11 | |
1860fbac AR |
12 | static SBuf |
13 | StoreMapSlicesId(const SBuf &path) | |
44c95fcf | 14 | { |
1860fbac | 15 | return Ipc::Mem::Segment::Name(path, "slices"); |
44c95fcf AR |
16 | } |
17 | ||
1860fbac AR |
18 | static SBuf |
19 | StoreMapAnchorsId(const SBuf &path) | |
44c95fcf | 20 | { |
1860fbac | 21 | return Ipc::Mem::Segment::Name(path, "anchors"); |
44c95fcf AR |
22 | } |
23 | ||
1860fbac AR |
24 | Ipc::StoreMap::Owner * |
25 | Ipc::StoreMap::Init(const SBuf &path, const int sliceLimit) | |
26 | { | |
27 | assert(sliceLimit > 0); // we should not be created otherwise | |
28 | const int anchorLimit = min(sliceLimit, static_cast<int>(SwapFilenMax)); | |
29 | Owner *owner = new Owner; | |
30 | owner->anchors = shm_new(Anchors)(StoreMapAnchorsId(path).c_str(), anchorLimit); | |
31 | owner->slices = shm_new(Slices)(StoreMapSlicesId(path).c_str(), sliceLimit); | |
32 | debugs(54, 5, "created " << path << " with " << anchorLimit << '+' << sliceLimit); | |
33 | return owner; | |
34 | } | |
35 | ||
36 | Ipc::StoreMap::StoreMap(const SBuf &aPath): cleaner(NULL), path(aPath), | |
37 | anchors(shm_old(Anchors)(StoreMapAnchorsId(path).c_str())), | |
38 | slices(shm_old(Slices)(StoreMapSlicesId(path).c_str())) | |
c011f9bc | 39 | { |
1860fbac AR |
40 | debugs(54, 5, "attached " << path << " with " << |
41 | anchors->capacity << '+' << slices->capacity); | |
42 | assert(entryLimit() > 0); // key-to-position mapping requires this | |
43 | assert(entryLimit() <= sliceLimit()); // at least one slice per entry | |
c011f9bc DK |
44 | } |
45 | ||
50dc81ec AR |
46 | int |
47 | Ipc::StoreMap::compareVersions(const sfileno fileno, time_t newVersion) const | |
48 | { | |
1860fbac | 49 | const Anchor &inode = anchorAt(fileno); |
50dc81ec AR |
50 | |
51 | // note: we do not lock, so comparison may be inacurate | |
52 | ||
ce49546e | 53 | if (inode.empty()) |
50dc81ec AR |
54 | return +2; |
55 | ||
56 | if (const time_t diff = newVersion - inode.basics.timestamp) | |
57 | return diff < 0 ? -1 : +1; | |
9d4e9cfb | 58 | |
50dc81ec AR |
59 | return 0; |
60 | } | |
61 | ||
62 | void | |
63 | Ipc::StoreMap::forgetWritingEntry(sfileno fileno) | |
64 | { | |
1860fbac | 65 | Anchor &inode = anchorAt(fileno); |
50dc81ec | 66 | |
ce49546e | 67 | assert(inode.writing()); |
50dc81ec AR |
68 | |
69 | // we do not iterate slices because we were told to forget about | |
70 | // them; the caller is responsible for freeing them (most likely | |
71 | // our slice list is incomplete or has holes) | |
72 | ||
73 | inode.waitingToBeFreed = false; | |
ce49546e | 74 | inode.rewind(); |
50dc81ec AR |
75 | |
76 | inode.lock.unlockExclusive(); | |
51dcaa03 | 77 | --anchors->count; |
50dc81ec AR |
78 | |
79 | debugs(54, 8, "closed entry " << fileno << " for writing " << path); | |
80 | } | |
81 | ||
82 | Ipc::StoreMap::Anchor * | |
44c95fcf AR |
83 | Ipc::StoreMap::openForWriting(const cache_key *const key, sfileno &fileno) |
84 | { | |
50dc81ec | 85 | debugs(54, 5, "opening entry with key " << storeKeyText(key) |
6d68a230 | 86 | << " for writing " << path); |
50dc81ec | 87 | const int idx = anchorIndexByKey(key); |
44c95fcf | 88 | |
50dc81ec AR |
89 | if (Anchor *anchor = openForWritingAt(idx)) { |
90 | fileno = idx; | |
91 | return anchor; | |
92 | } | |
93 | ||
94 | return NULL; | |
95 | } | |
96 | ||
97 | Ipc::StoreMap::Anchor * | |
98 | Ipc::StoreMap::openForWritingAt(const sfileno fileno, bool overwriteExisting) | |
99 | { | |
1860fbac | 100 | Anchor &s = anchorAt(fileno); |
44c95fcf AR |
101 | ReadWriteLock &lock = s.lock; |
102 | ||
103 | if (lock.lockExclusive()) { | |
ce49546e | 104 | assert(s.writing() && !s.reading()); |
50dc81ec AR |
105 | |
106 | // bail if we cannot empty this position | |
ce49546e | 107 | if (!s.waitingToBeFreed && !s.empty() && !overwriteExisting) { |
50dc81ec | 108 | lock.unlockExclusive(); |
6d68a230 AR |
109 | debugs(54, 5, "cannot open existing entry " << fileno << |
110 | " for writing " << path); | |
50dc81ec AR |
111 | return NULL; |
112 | } | |
44c95fcf | 113 | |
7f6748c8 | 114 | // free if the entry was used, keeping the entry locked |
ce49546e | 115 | if (s.waitingToBeFreed || !s.empty()) |
50dc81ec | 116 | freeChain(fileno, s, true); |
44c95fcf | 117 | |
ce49546e | 118 | assert(s.empty()); |
a3023c03 | 119 | s.start = -1; // we have not allocated any slices yet |
1860fbac | 120 | ++anchors->count; |
50dc81ec | 121 | |
44c95fcf | 122 | //s.setKey(key); // XXX: the caller should do that |
50dc81ec | 123 | debugs(54, 5, "opened entry " << fileno << " for writing " << path); |
44c95fcf | 124 | return &s; // and keep the entry locked |
6d68a230 | 125 | } |
44c95fcf | 126 | |
6d68a230 AR |
127 | debugs(54, 5, "cannot open busy entry " << fileno << |
128 | " for writing " << path); | |
44c95fcf AR |
129 | return NULL; |
130 | } | |
131 | ||
ce49546e AR |
132 | void |
133 | Ipc::StoreMap::startAppending(const sfileno fileno) | |
134 | { | |
1860fbac | 135 | Anchor &s = anchorAt(fileno); |
ce49546e AR |
136 | assert(s.writing()); |
137 | s.lock.startAppending(); | |
138 | debugs(54, 5, "restricted entry " << fileno << " to appending " << path); | |
139 | } | |
140 | ||
44c95fcf AR |
141 | void |
142 | Ipc::StoreMap::closeForWriting(const sfileno fileno, bool lockForReading) | |
143 | { | |
1860fbac | 144 | Anchor &s = anchorAt(fileno); |
ce49546e | 145 | assert(s.writing()); |
50dc81ec | 146 | if (lockForReading) { |
44c95fcf | 147 | s.lock.switchExclusiveToShared(); |
6d68a230 AR |
148 | debugs(54, 5, "switched entry " << fileno << |
149 | " from writing to reading " << path); | |
ce49546e | 150 | assert(s.complete()); |
50dc81ec | 151 | } else { |
44c95fcf | 152 | s.lock.unlockExclusive(); |
50dc81ec | 153 | debugs(54, 5, "closed entry " << fileno << " for writing " << path); |
ce49546e | 154 | // cannot assert completeness here because we have no lock |
50dc81ec AR |
155 | } |
156 | } | |
157 | ||
158 | Ipc::StoreMap::Slice & | |
159 | Ipc::StoreMap::writeableSlice(const AnchorId anchorId, const SliceId sliceId) | |
160 | { | |
1860fbac | 161 | assert(anchorAt(anchorId).writing()); |
36c84e19 | 162 | assert(validSlice(sliceId)); |
1860fbac | 163 | return sliceAt(sliceId); |
50dc81ec AR |
164 | } |
165 | ||
166 | const Ipc::StoreMap::Slice & | |
167 | Ipc::StoreMap::readableSlice(const AnchorId anchorId, const SliceId sliceId) const | |
168 | { | |
1860fbac | 169 | assert(anchorAt(anchorId).reading()); |
36c84e19 | 170 | assert(validSlice(sliceId)); |
1860fbac | 171 | return sliceAt(sliceId); |
50dc81ec AR |
172 | } |
173 | ||
174 | Ipc::StoreMap::Anchor & | |
175 | Ipc::StoreMap::writeableEntry(const AnchorId anchorId) | |
176 | { | |
1860fbac AR |
177 | assert(anchorAt(anchorId).writing()); |
178 | return anchorAt(anchorId); | |
ce49546e AR |
179 | } |
180 | ||
181 | const Ipc::StoreMap::Anchor & | |
182 | Ipc::StoreMap::readableEntry(const AnchorId anchorId) const | |
183 | { | |
1860fbac AR |
184 | assert(anchorAt(anchorId).reading()); |
185 | return anchorAt(anchorId); | |
44c95fcf AR |
186 | } |
187 | ||
44c95fcf AR |
188 | void |
189 | Ipc::StoreMap::abortWriting(const sfileno fileno) | |
190 | { | |
6d68a230 | 191 | debugs(54, 5, "aborting entry " << fileno << " for writing " << path); |
1860fbac | 192 | Anchor &s = anchorAt(fileno); |
ce49546e AR |
193 | assert(s.writing()); |
194 | s.lock.appending = false; // locks out any new readers | |
195 | if (!s.lock.readers) { | |
196 | freeChain(fileno, s, false); | |
197 | debugs(54, 5, "closed clean entry " << fileno << " for writing " << path); | |
198 | } else { | |
199 | s.waitingToBeFreed = true; | |
ce49546e AR |
200 | s.lock.unlockExclusive(); |
201 | debugs(54, 5, "closed dirty entry " << fileno << " for writing " << path); | |
9d4e9cfb | 202 | } |
44c95fcf AR |
203 | } |
204 | ||
50dc81ec | 205 | const Ipc::StoreMap::Anchor * |
44c95fcf AR |
206 | Ipc::StoreMap::peekAtReader(const sfileno fileno) const |
207 | { | |
1860fbac | 208 | const Anchor &s = anchorAt(fileno); |
ce49546e | 209 | if (s.reading()) |
44c95fcf | 210 | return &s; // immediate access by lock holder so no locking |
ce49546e AR |
211 | if (s.writing()) |
212 | return NULL; // the caller is not a read lock holder | |
213 | assert(false); // must be locked for reading or writing | |
44c95fcf AR |
214 | return NULL; |
215 | } | |
216 | ||
d366a7fa AR |
217 | const Ipc::StoreMap::Anchor & |
218 | Ipc::StoreMap::peekAtEntry(const sfileno fileno) const | |
219 | { | |
1860fbac | 220 | return anchorAt(fileno); |
d366a7fa AR |
221 | } |
222 | ||
44c95fcf | 223 | void |
50dc81ec | 224 | Ipc::StoreMap::freeEntry(const sfileno fileno) |
44c95fcf | 225 | { |
6d68a230 | 226 | debugs(54, 5, "marking entry " << fileno << " to be freed in " << path); |
44c95fcf | 227 | |
1860fbac | 228 | Anchor &s = anchorAt(fileno); |
44c95fcf AR |
229 | |
230 | if (s.lock.lockExclusive()) | |
50dc81ec | 231 | freeChain(fileno, s, false); |
44c95fcf AR |
232 | else |
233 | s.waitingToBeFreed = true; // mark to free it later | |
234 | } | |
235 | ||
ce49546e AR |
236 | void |
237 | Ipc::StoreMap::freeEntryByKey(const cache_key *const key) | |
238 | { | |
239 | debugs(54, 5, "marking entry with key " << storeKeyText(key) | |
240 | << " to be freed in " << path); | |
241 | ||
242 | const int idx = anchorIndexByKey(key); | |
1860fbac | 243 | Anchor &s = anchorAt(idx); |
ce49546e AR |
244 | if (s.lock.lockExclusive()) { |
245 | if (s.sameKey(key)) | |
246 | freeChain(idx, s, true); | |
247 | s.lock.unlockExclusive(); | |
9d4e9cfb | 248 | } else if (s.lock.lockShared()) { |
ce49546e AR |
249 | if (s.sameKey(key)) |
250 | s.waitingToBeFreed = true; // mark to free it later | |
251 | s.lock.unlockShared(); | |
252 | } else { | |
9d4e9cfb AR |
253 | // we cannot be sure that the entry we found is ours because we do not |
254 | // have a lock on it, but we still check to minimize false deletions | |
255 | if (s.sameKey(key)) | |
256 | s.waitingToBeFreed = true; // mark to free it later | |
ce49546e AR |
257 | } |
258 | } | |
259 | ||
50dc81ec AR |
260 | /// unconditionally frees an already locked chain of slots, unlocking if needed |
261 | void | |
262 | Ipc::StoreMap::freeChain(const sfileno fileno, Anchor &inode, const bool keepLocked) | |
263 | { | |
ce49546e | 264 | debugs(54, 7, "freeing entry " << fileno << |
6d68a230 | 265 | " in " << path); |
ce49546e | 266 | if (!inode.empty()) { |
50dc81ec | 267 | sfileno sliceId = inode.start; |
6d68a230 | 268 | debugs(54, 8, "first slice " << sliceId); |
50dc81ec | 269 | while (sliceId >= 0) { |
1860fbac | 270 | Slice &slice = sliceAt(sliceId); |
485466dc | 271 | const sfileno nextId = slice.next; |
a3023c03 | 272 | slice.size = 0; |
485466dc AR |
273 | slice.next = -1; |
274 | if (cleaner) | |
275 | cleaner->noteFreeMapSlice(sliceId); // might change slice state | |
50dc81ec AR |
276 | sliceId = nextId; |
277 | } | |
278 | } | |
279 | ||
280 | inode.waitingToBeFreed = false; | |
ce49546e | 281 | inode.rewind(); |
50dc81ec AR |
282 | |
283 | if (!keepLocked) | |
284 | inode.lock.unlockExclusive(); | |
1860fbac | 285 | --anchors->count; |
6d68a230 | 286 | debugs(54, 5, "freed entry " << fileno << " in " << path); |
50dc81ec AR |
287 | } |
288 | ||
289 | const Ipc::StoreMap::Anchor * | |
44c95fcf AR |
290 | Ipc::StoreMap::openForReading(const cache_key *const key, sfileno &fileno) |
291 | { | |
50dc81ec | 292 | debugs(54, 5, "opening entry with key " << storeKeyText(key) |
6d68a230 | 293 | << " for reading " << path); |
50dc81ec AR |
294 | const int idx = anchorIndexByKey(key); |
295 | if (const Anchor *slot = openForReadingAt(idx)) { | |
44c95fcf AR |
296 | if (slot->sameKey(key)) { |
297 | fileno = idx; | |
44c95fcf AR |
298 | return slot; // locked for reading |
299 | } | |
300 | slot->lock.unlockShared(); | |
50dc81ec | 301 | debugs(54, 7, "closed entry " << idx << " for reading " << path); |
44c95fcf | 302 | } |
44c95fcf AR |
303 | return NULL; |
304 | } | |
305 | ||
50dc81ec | 306 | const Ipc::StoreMap::Anchor * |
44c95fcf AR |
307 | Ipc::StoreMap::openForReadingAt(const sfileno fileno) |
308 | { | |
6d68a230 | 309 | debugs(54, 5, "opening entry " << fileno << " for reading " << path); |
1860fbac | 310 | Anchor &s = anchorAt(fileno); |
44c95fcf AR |
311 | |
312 | if (!s.lock.lockShared()) { | |
6d68a230 AR |
313 | debugs(54, 5, "cannot open busy entry " << fileno << |
314 | " for reading " << path); | |
44c95fcf AR |
315 | return NULL; |
316 | } | |
317 | ||
ce49546e | 318 | if (s.empty()) { |
44c95fcf | 319 | s.lock.unlockShared(); |
6d68a230 AR |
320 | debugs(54, 7, "cannot open empty entry " << fileno << |
321 | " for reading " << path); | |
44c95fcf AR |
322 | return NULL; |
323 | } | |
324 | ||
325 | if (s.waitingToBeFreed) { | |
326 | s.lock.unlockShared(); | |
539283df | 327 | debugs(54, 7, "cannot open marked entry " << fileno << |
6d68a230 | 328 | " for reading " << path); |
44c95fcf AR |
329 | return NULL; |
330 | } | |
331 | ||
50dc81ec | 332 | debugs(54, 5, "opened entry " << fileno << " for reading " << path); |
44c95fcf AR |
333 | return &s; |
334 | } | |
335 | ||
336 | void | |
337 | Ipc::StoreMap::closeForReading(const sfileno fileno) | |
338 | { | |
1860fbac | 339 | Anchor &s = anchorAt(fileno); |
ce49546e | 340 | assert(s.reading()); |
44c95fcf | 341 | s.lock.unlockShared(); |
50dc81ec AR |
342 | debugs(54, 5, "closed entry " << fileno << " for reading " << path); |
343 | } | |
344 | ||
345 | bool | |
346 | Ipc::StoreMap::purgeOne() | |
347 | { | |
348 | // Hopefully, we find a removable entry much sooner (TODO: use time?). | |
349 | // The min() will protect us from division by zero inside the loop. | |
350 | const int searchLimit = min(10000, entryLimit()); | |
351 | int tries = 0; | |
352 | for (; tries < searchLimit; ++tries) { | |
1860fbac AR |
353 | const sfileno fileno = static_cast<sfileno>(++anchors->victim % entryLimit()); |
354 | Anchor &s = anchorAt(fileno); | |
50dc81ec | 355 | if (s.lock.lockExclusive()) { |
5bba33c9 AR |
356 | // the caller wants a free slice; empty anchor is not enough |
357 | if (!s.empty() && s.start >= 0) { | |
50dc81ec AR |
358 | // this entry may be marked for deletion, and that is OK |
359 | freeChain(fileno, s, false); | |
6d68a230 | 360 | debugs(54, 5, "purged entry " << fileno << " from " << path); |
50dc81ec | 361 | return true; |
6d68a230 | 362 | } |
50dc81ec AR |
363 | s.lock.unlockExclusive(); |
364 | } | |
6d68a230 AR |
365 | } |
366 | debugs(54, 5, "no entries to purge from " << path << "; tried: " << tries); | |
50dc81ec AR |
367 | return false; |
368 | } | |
369 | ||
370 | void | |
371 | Ipc::StoreMap::importSlice(const SliceId sliceId, const Slice &slice) | |
372 | { | |
373 | // Slices are imported into positions that should not be available via | |
374 | // "get free slice" API. This is not something we can double check | |
375 | // reliably because the anchor for the imported slice may not have been | |
376 | // imported yet. | |
36c84e19 | 377 | assert(validSlice(sliceId)); |
1860fbac | 378 | sliceAt(sliceId) = slice; |
44c95fcf AR |
379 | } |
380 | ||
381 | int | |
382 | Ipc::StoreMap::entryLimit() const | |
383 | { | |
36c84e19 | 384 | return min(sliceLimit(), static_cast<int>(SwapFilenMax+1)); |
44c95fcf AR |
385 | } |
386 | ||
387 | int | |
388 | Ipc::StoreMap::entryCount() const | |
389 | { | |
1860fbac | 390 | return anchors->count; |
36c84e19 AR |
391 | } |
392 | ||
393 | int | |
394 | Ipc::StoreMap::sliceLimit() const | |
395 | { | |
1860fbac | 396 | return slices->capacity; |
44c95fcf AR |
397 | } |
398 | ||
44c95fcf AR |
399 | void |
400 | Ipc::StoreMap::updateStats(ReadWriteLockStats &stats) const | |
401 | { | |
1860fbac AR |
402 | for (int i = 0; i < anchors->capacity; ++i) |
403 | anchorAt(i).lock.updateStats(stats); | |
44c95fcf AR |
404 | } |
405 | ||
406 | bool | |
36c84e19 | 407 | Ipc::StoreMap::validEntry(const int pos) const |
44c95fcf AR |
408 | { |
409 | return 0 <= pos && pos < entryLimit(); | |
410 | } | |
411 | ||
36c84e19 AR |
412 | bool |
413 | Ipc::StoreMap::validSlice(const int pos) const | |
414 | { | |
415 | return 0 <= pos && pos < sliceLimit(); | |
416 | } | |
417 | ||
1860fbac | 418 | Ipc::StoreMap::Anchor& |
2da4bfe6 A |
419 | Ipc::StoreMap::anchorAt(const sfileno fileno) |
420 | { | |
1860fbac AR |
421 | assert(validEntry(fileno)); |
422 | return anchors->items[fileno]; | |
423 | } | |
424 | ||
425 | const Ipc::StoreMap::Anchor& | |
2da4bfe6 A |
426 | Ipc::StoreMap::anchorAt(const sfileno fileno) const |
427 | { | |
1860fbac AR |
428 | return const_cast<StoreMap&>(*this).anchorAt(fileno); |
429 | } | |
430 | ||
50dc81ec AR |
431 | sfileno |
432 | Ipc::StoreMap::anchorIndexByKey(const cache_key *const key) const | |
44c95fcf AR |
433 | { |
434 | const uint64_t *const k = reinterpret_cast<const uint64_t *>(key); | |
435 | // TODO: use a better hash function | |
36c84e19 | 436 | return (k[0] + k[1]) % entryLimit(); |
44c95fcf AR |
437 | } |
438 | ||
50dc81ec AR |
439 | Ipc::StoreMap::Anchor & |
440 | Ipc::StoreMap::anchorByKey(const cache_key *const key) | |
44c95fcf | 441 | { |
1860fbac AR |
442 | return anchorAt(anchorIndexByKey(key)); |
443 | } | |
444 | ||
445 | Ipc::StoreMap::Slice& | |
2da4bfe6 A |
446 | Ipc::StoreMap::sliceAt(const SliceId sliceId) |
447 | { | |
1860fbac AR |
448 | assert(validSlice(sliceId)); |
449 | return slices->items[sliceId]; | |
450 | } | |
451 | ||
452 | const Ipc::StoreMap::Slice& | |
2da4bfe6 A |
453 | Ipc::StoreMap::sliceAt(const SliceId sliceId) const |
454 | { | |
1860fbac | 455 | return const_cast<StoreMap&>(*this).sliceAt(sliceId); |
44c95fcf AR |
456 | } |
457 | ||
50dc81ec | 458 | /* Ipc::StoreMapAnchor */ |
44c95fcf | 459 | |
ce49546e | 460 | Ipc::StoreMapAnchor::StoreMapAnchor(): start(0) |
44c95fcf | 461 | { |
e297be13 AJ |
462 | memset(&key, 0, sizeof(key)); |
463 | memset(&basics, 0, sizeof(basics)); | |
50dc81ec | 464 | // keep in sync with rewind() |
44c95fcf AR |
465 | } |
466 | ||
467 | void | |
50dc81ec | 468 | Ipc::StoreMapAnchor::setKey(const cache_key *const aKey) |
44c95fcf AR |
469 | { |
470 | memcpy(key, aKey, sizeof(key)); | |
471 | } | |
472 | ||
473 | bool | |
50dc81ec | 474 | Ipc::StoreMapAnchor::sameKey(const cache_key *const aKey) const |
44c95fcf AR |
475 | { |
476 | const uint64_t *const k = reinterpret_cast<const uint64_t *>(aKey); | |
477 | return k[0] == key[0] && k[1] == key[1]; | |
478 | } | |
479 | ||
480 | void | |
50dc81ec | 481 | Ipc::StoreMapAnchor::set(const StoreEntry &from) |
44c95fcf | 482 | { |
ce49546e | 483 | assert(writing() && !reading()); |
44c95fcf | 484 | memcpy(key, from.key, sizeof(key)); |
44c95fcf AR |
485 | basics.timestamp = from.timestamp; |
486 | basics.lastref = from.lastref; | |
487 | basics.expires = from.expires; | |
488 | basics.lastmod = from.lastmod; | |
489 | basics.swap_file_sz = from.swap_file_sz; | |
490 | basics.refcount = from.refcount; | |
491 | basics.flags = from.flags; | |
492 | } | |
493 | ||
50dc81ec AR |
494 | void |
495 | Ipc::StoreMapAnchor::rewind() | |
496 | { | |
ce49546e | 497 | assert(writing()); |
50dc81ec AR |
498 | start = 0; |
499 | memset(&key, 0, sizeof(key)); | |
500 | memset(&basics, 0, sizeof(basics)); | |
501 | // but keep the lock | |
502 | } | |
503 | ||
1860fbac AR |
504 | Ipc::StoreMap::Owner::Owner(): anchors(NULL), slices(NULL) |
505 | { | |
506 | } | |
507 | ||
508 | Ipc::StoreMap::Owner::~Owner() | |
509 | { | |
510 | delete anchors; | |
511 | delete slices; | |
512 | } | |
513 | ||
514 | /* Ipc::StoreMapAnchors */ | |
44c95fcf | 515 | |
1860fbac AR |
516 | Ipc::StoreMapAnchors::StoreMapAnchors(const int aCapacity): |
517 | count(0), | |
36c84e19 | 518 | victim(0), |
1860fbac AR |
519 | capacity(aCapacity), |
520 | items(aCapacity) | |
68353d5a DK |
521 | { |
522 | } | |
523 | ||
524 | size_t | |
1860fbac | 525 | Ipc::StoreMapAnchors::sharedMemorySize() const |
44c95fcf | 526 | { |
1860fbac | 527 | return SharedMemorySize(capacity); |
44c95fcf AR |
528 | } |
529 | ||
530 | size_t | |
1860fbac | 531 | Ipc::StoreMapAnchors::SharedMemorySize(const int capacity) |
44c95fcf | 532 | { |
1860fbac | 533 | return sizeof(StoreMapAnchors) + capacity * sizeof(StoreMapAnchor); |
44c95fcf AR |
534 | } |
535 |