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