22
22
23
23
#include < fstream>
24
24
#include < vector>
25
+ #include < string>
25
26
26
27
#pragma GCC diagnostic push
27
28
#pragma GCC diagnostic ignored "-Wconversion"
@@ -98,7 +99,7 @@ ShmManager::ShmManager(const std::string& dir, bool usePosix)
98
99
// if file exists, init from it if needed.
99
100
const bool reattach = dropSegments ? false : initFromFile ();
100
101
if (!reattach) {
101
- DCHECK (nameToKey_ .empty ());
102
+ DCHECK (nameToOpts_ .empty ());
102
103
}
103
104
// Lock file for exclusive access
104
105
lockMetadataFile (metaFile);
@@ -109,7 +110,7 @@ ShmManager::ShmManager(const std::string& dir, bool usePosix)
109
110
}
110
111
111
112
bool ShmManager::initFromFile () {
112
- // restore the nameToKey_ map and destroy the contents of the file.
113
+ // restore the nameToOpts_ map and destroy the contents of the file.
113
114
const std::string fileName = pathName (controlDir_, kMetaDataFile );
114
115
std::ifstream f (fileName);
115
116
SCOPE_EXIT { f.close (); };
@@ -139,9 +140,16 @@ bool ShmManager::initFromFile() {
139
140
}
140
141
141
142
for (const auto & kv : *object.nameToKeyMap_ref ()) {
142
- nameToKey_.insert ({kv.first , kv.second });
143
+ if (kv.second .path == " " ) {
144
+ PosixSysVSegmentOpts type;
145
+ type.usePosix = kv.second .usePosix ;
146
+ nameToOpts_.insert ({kv.first , type});
147
+ } else {
148
+ FileShmSegmentOpts type;
149
+ type.path = kv.second .path ;
150
+ nameToOpts_.insert ({kv.first , type});
151
+ }
143
152
}
144
-
145
153
return true ;
146
154
}
147
155
@@ -157,17 +165,28 @@ typename ShmManager::ShutDownRes ShmManager::writeActiveSegmentsToFile() {
157
165
return ShutDownRes::kFileDeleted ;
158
166
}
159
167
160
- // write the shmtype, nameToKey_ map to the file.
168
+ // write the shmtype, nameToOpts_ map to the file.
161
169
DCHECK (metadataStream_);
162
170
163
171
serialization::ShmManagerObject object;
164
172
165
173
object.shmVal_ref () = usePosix_ ? static_cast <int8_t >(ShmVal::SHM_POSIX)
166
174
: static_cast <int8_t >(ShmVal::SHM_SYS_V);
167
175
168
- for (const auto & kv : nameToKey_ ) {
176
+ for (const auto & kv : nameToOpts_ ) {
169
177
const auto & name = kv.first ;
170
- const auto & key = kv.second ;
178
+ serialization::ShmTypeObject key;
179
+ if (const auto * opts = std::get_if<FileShmSegmentOpts>(&kv.second )) {
180
+ key.path = opts->path ;
181
+ } else {
182
+ try {
183
+ const auto & v = std::get<PosixSysVSegmentOpts>(kv.second );
184
+ key.usePosix = v.usePosix ;
185
+ key.path = " " ;
186
+ } catch (std::bad_variant_access&) {
187
+ throw std::invalid_argument (folly::sformat (" Not a valid segment" ));
188
+ }
189
+ }
171
190
const auto it = segments_.find (name);
172
191
// segment exists and is active.
173
192
if (it != segments_.end () && it->second ->isActive ()) {
@@ -199,14 +218,14 @@ typename ShmManager::ShutDownRes ShmManager::shutDown() {
199
218
200
219
// clear our data.
201
220
segments_.clear ();
202
- nameToKey_ .clear ();
221
+ nameToOpts_ .clear ();
203
222
return ret;
204
223
}
205
224
206
225
namespace {
207
226
208
227
bool removeSegByName (ShmTypeOpts typeOpts, const std::string& uniqueName) {
209
- if (auto * v = std::get_if<FileShmSegmentOpts>(&typeOpts)) {
228
+ if (const auto * v = std::get_if<FileShmSegmentOpts>(&typeOpts)) {
210
229
return FileShmSegment::removeByPath (v->path );
211
230
}
212
231
@@ -258,22 +277,20 @@ void ShmManager::cleanup(const std::string& dir, bool posix) {
258
277
}
259
278
260
279
void ShmManager::removeAllSegments () {
261
- // TODO(SHM_FILE): extend this once we have opts stored in nameToKey_
262
- for (const auto & kv : nameToKey_) {
263
- removeSegByName (usePosix_, uniqueIdForName (kv.first ));
280
+ for (const auto & kv : nameToOpts_) {
281
+ removeSegByName (kv.second , uniqueIdForName (kv.first ));
264
282
}
265
- nameToKey_ .clear ();
283
+ nameToOpts_ .clear ();
266
284
}
267
285
268
286
void ShmManager::removeUnAttachedSegments () {
269
- // TODO(SHM_FILE): extend this once we have opts stored in nameToKey_
270
- auto it = nameToKey_.begin ();
271
- while (it != nameToKey_.end ()) {
287
+ auto it = nameToOpts_.begin ();
288
+ while (it != nameToOpts_.end ()) {
272
289
const auto name = it->first ;
273
290
// check if the segment is attached.
274
291
if (segments_.find (name) == segments_.end ()) { // not attached
275
- removeSegByName (usePosix_ , uniqueIdForName (name));
276
- it = nameToKey_ .erase (it);
292
+ removeSegByName (it-> second , uniqueIdForName (name));
293
+ it = nameToOpts_ .erase (it);
277
294
} else {
278
295
++it;
279
296
}
@@ -292,13 +309,13 @@ ShmAddr ShmManager::createShm(const std::string& shmName,
292
309
removeShm (shmName, opts.typeOpts );
293
310
294
311
DCHECK (segments_.find (shmName) == segments_.end ());
295
- DCHECK (nameToKey_ .find (shmName) == nameToKey_ .end ());
312
+ DCHECK (nameToOpts_ .find (shmName) == nameToOpts_ .end ());
296
313
297
- if ( auto * v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts )) {
298
- if (usePosix_ != v->usePosix )
299
- throw std::invalid_argument (
300
- folly::sformat (" Expected {} but got {} segment" ,
301
- usePosix_ ? " posix" : " SysV" , usePosix_ ? " SysV" : " posix" ));
314
+ const auto * v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts );
315
+ if (v && usePosix_ != v->usePosix ) {
316
+ throw std::invalid_argument (
317
+ folly::sformat (" Expected {} but got {} segment" ,
318
+ usePosix_ ? " posix" : " SysV" , usePosix_ ? " SysV" : " posix" ));
302
319
}
303
320
304
321
std::unique_ptr<ShmSegment> newSeg;
@@ -326,24 +343,32 @@ ShmAddr ShmManager::createShm(const std::string& shmName,
326
343
}
327
344
328
345
auto ret = newSeg->getCurrentMapping ();
329
- nameToKey_.emplace (shmName, newSeg->getKeyStr ());
346
+ if (v) {
347
+ PosixSysVSegmentOpts opts;
348
+ opts.usePosix = v->usePosix ;
349
+ nameToOpts_.emplace (shmName, opts);
350
+ } else {
351
+ FileShmSegmentOpts opts;
352
+ opts.path = newSeg->getKeyStr ();
353
+ nameToOpts_.emplace (shmName, opts);
354
+ }
330
355
segments_.emplace (shmName, std::move (newSeg));
331
356
return ret;
332
357
}
333
358
334
359
void ShmManager::attachNewShm (const std::string& shmName, ShmSegmentOpts opts) {
335
- const auto keyIt = nameToKey_ .find (shmName);
360
+ const auto keyIt = nameToOpts_ .find (shmName);
336
361
// if key is not known already, there is not much we can do to attach.
337
- if (keyIt == nameToKey_ .end ()) {
362
+ if (keyIt == nameToOpts_ .end ()) {
338
363
throw std::invalid_argument (
339
364
folly::sformat (" Unable to find any segment with name {}" , shmName));
340
365
}
341
366
342
- if ( auto * v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts )) {
343
- if (usePosix_ != v->usePosix )
344
- throw std::invalid_argument (
345
- folly::sformat (" Expected {} but got {} segment" ,
346
- usePosix_ ? " posix" : " SysV" , usePosix_ ? " SysV" : " posix" ));
367
+ const auto * v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts );
368
+ if (v && usePosix_ != v->usePosix ) {
369
+ throw std::invalid_argument (
370
+ folly::sformat (" Expected {} but got {} segment" ,
371
+ usePosix_ ? " posix" : " SysV" , usePosix_ ? " SysV" : " posix" ));
347
372
}
348
373
349
374
// This means the segment exists and we can try to attach it.
@@ -360,7 +385,17 @@ void ShmManager::attachNewShm(const std::string& shmName, ShmSegmentOpts opts) {
360
385
shmName, e.what ()));
361
386
}
362
387
DCHECK (segments_.find (shmName) != segments_.end ());
363
- DCHECK_EQ (segments_[shmName]->getKeyStr (), keyIt->second );
388
+ if (v) { // If it is a posix shm segment
389
+ // Comparison unnecessary since getKeyStr() retuns name_from ShmBase
390
+ // createKeyForShm also returns the same variable.
391
+ } else { // Else it is a file segment
392
+ try {
393
+ auto opts = std::get<FileShmSegmentOpts>(keyIt->second );
394
+ DCHECK_EQ (segments_[shmName]->getKeyStr (), opts.path );
395
+ } catch (std::bad_variant_access&) {
396
+ throw std::invalid_argument (folly::sformat (" Not a valid segment" ));
397
+ }
398
+ }
364
399
}
365
400
366
401
ShmAddr ShmManager::attachShm (const std::string& shmName,
@@ -403,13 +438,13 @@ bool ShmManager::removeShm(const std::string& shmName, ShmTypeOpts typeOpts) {
403
438
removeSegByName (typeOpts, uniqueIdForName (shmName));
404
439
if (!wasPresent) {
405
440
DCHECK (segments_.end () == segments_.find (shmName));
406
- DCHECK (nameToKey_ .end () == nameToKey_ .find (shmName));
441
+ DCHECK (nameToOpts_ .end () == nameToOpts_ .find (shmName));
407
442
return false ;
408
443
}
409
444
}
410
445
// not mapped and already removed.
411
446
segments_.erase (shmName);
412
- nameToKey_ .erase (shmName);
447
+ nameToOpts_ .erase (shmName);
413
448
return true ;
414
449
}
415
450
@@ -424,5 +459,15 @@ ShmSegment& ShmManager::getShmByName(const std::string& shmName) {
424
459
}
425
460
}
426
461
462
+ ShmTypeOpts& ShmManager::getShmTypeByName (const std::string& shmName) {
463
+ const auto it = nameToOpts_.find (shmName);
464
+ if (it != nameToOpts_.end ()) {
465
+ return it->second ;
466
+ } else {
467
+ throw std::invalid_argument (folly::sformat (
468
+ " shared memory segment does not exist: name: {}" , shmName));
469
+ }
470
+ }
471
+
427
472
} // namespace cachelib
428
473
} // namespace facebook
0 commit comments