2222
2323#include < fstream>
2424#include < vector>
25+ #include < string>
2526
2627#pragma GCC diagnostic push
2728#pragma GCC diagnostic ignored "-Wconversion"
@@ -98,7 +99,7 @@ ShmManager::ShmManager(const std::string& dir, bool usePosix)
9899 // if file exists, init from it if needed.
99100 const bool reattach = dropSegments ? false : initFromFile ();
100101 if (!reattach) {
101- DCHECK (nameToKey_ .empty ());
102+ DCHECK (nameToOpts_ .empty ());
102103 }
103104 // Lock file for exclusive access
104105 lockMetadataFile (metaFile);
@@ -109,7 +110,7 @@ ShmManager::ShmManager(const std::string& dir, bool usePosix)
109110}
110111
111112bool 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.
113114 const std::string fileName = pathName (controlDir_, kMetaDataFile );
114115 std::ifstream f (fileName);
115116 SCOPE_EXIT { f.close (); };
@@ -139,9 +140,16 @@ bool ShmManager::initFromFile() {
139140 }
140141
141142 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+ }
143152 }
144-
145153 return true ;
146154}
147155
@@ -157,17 +165,28 @@ typename ShmManager::ShutDownRes ShmManager::writeActiveSegmentsToFile() {
157165 return ShutDownRes::kFileDeleted ;
158166 }
159167
160- // write the shmtype, nameToKey_ map to the file.
168+ // write the shmtype, nameToOpts_ map to the file.
161169 DCHECK (metadataStream_);
162170
163171 serialization::ShmManagerObject object;
164172
165173 object.shmVal_ref () = usePosix_ ? static_cast <int >(ShmVal::SHM_POSIX)
166174 : static_cast <int >(ShmVal::SHM_SYS_V);
167175
168- for (const auto & kv : nameToKey_ ) {
176+ for (const auto & kv : nameToOpts_ ) {
169177 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+ }
171190 const auto it = segments_.find (name);
172191 // segment exists and is active.
173192 if (it != segments_.end () && it->second ->isActive ()) {
@@ -199,14 +218,14 @@ typename ShmManager::ShutDownRes ShmManager::shutDown() {
199218
200219 // clear our data.
201220 segments_.clear ();
202- nameToKey_ .clear ();
221+ nameToOpts_ .clear ();
203222 return ret;
204223}
205224
206225namespace {
207226
208227bool 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)) {
210229 return FileShmSegment::removeByPath (v->path );
211230 }
212231
@@ -258,22 +277,20 @@ void ShmManager::cleanup(const std::string& dir, bool posix) {
258277}
259278
260279void 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 ));
264282 }
265- nameToKey_ .clear ();
283+ nameToOpts_ .clear ();
266284}
267285
268286void 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 ()) {
272289 const auto name = it->first ;
273290 // check if the segment is attached.
274291 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);
277294 } else {
278295 ++it;
279296 }
@@ -292,13 +309,13 @@ ShmAddr ShmManager::createShm(const std::string& shmName,
292309 removeShm (shmName, opts.typeOpts );
293310
294311 DCHECK (segments_.find (shmName) == segments_.end ());
295- DCHECK (nameToKey_ .find (shmName) == nameToKey_ .end ());
312+ DCHECK (nameToOpts_ .find (shmName) == nameToOpts_ .end ());
296313
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" ));
302319 }
303320
304321 std::unique_ptr<ShmSegment> newSeg;
@@ -326,24 +343,32 @@ ShmAddr ShmManager::createShm(const std::string& shmName,
326343 }
327344
328345 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+ }
330355 segments_.emplace (shmName, std::move (newSeg));
331356 return ret;
332357}
333358
334359void ShmManager::attachNewShm (const std::string& shmName, ShmSegmentOpts opts) {
335- const auto keyIt = nameToKey_ .find (shmName);
360+ const auto keyIt = nameToOpts_ .find (shmName);
336361 // 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 ()) {
338363 throw std::invalid_argument (
339364 folly::sformat (" Unable to find any segment with name {}" , shmName));
340365 }
341366
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" ));
347372 }
348373
349374 // 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) {
360385 shmName, e.what ()));
361386 }
362387 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+ }
364399}
365400
366401ShmAddr ShmManager::attachShm (const std::string& shmName,
@@ -403,13 +438,13 @@ bool ShmManager::removeShm(const std::string& shmName, ShmTypeOpts typeOpts) {
403438 removeSegByName (typeOpts, uniqueIdForName (shmName));
404439 if (!wasPresent) {
405440 DCHECK (segments_.end () == segments_.find (shmName));
406- DCHECK (nameToKey_ .end () == nameToKey_ .find (shmName));
441+ DCHECK (nameToOpts_ .end () == nameToOpts_ .find (shmName));
407442 return false ;
408443 }
409444 }
410445 // not mapped and already removed.
411446 segments_.erase (shmName);
412- nameToKey_ .erase (shmName);
447+ nameToOpts_ .erase (shmName);
413448 return true ;
414449}
415450
@@ -424,5 +459,15 @@ ShmSegment& ShmManager::getShmByName(const std::string& shmName) {
424459 }
425460}
426461
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+
427472} // namespace cachelib
428473} // namespace facebook
0 commit comments