summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Judd <ben.judd@10gen.com>2018-06-20 15:19:09 -0400
committerBen Judd <ben.judd@10gen.com>2018-07-03 09:20:32 -0400
commit07517066b7d944374d49e0b668d60e490c7871a7 (patch)
tree764dffe992d5651a1bd615c73da41274807aed63 /src
parent197a39dd137ad5d8bb1315fd3102a7a5791ae631 (diff)
downloadmongo-07517066b7d944374d49e0b668d60e490c7871a7.tar.gz
SERVER-35563 Refactor register/remove UUID to _inlock functions to avoid race conditions
(cherry picked from commit 26b3b97ad24d8592e2f93e79f2dc18a8b76d3b3d)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/uuid_catalog.cpp71
-rw-r--r--src/mongo/db/catalog/uuid_catalog.h2
2 files changed, 34 insertions, 39 deletions
diff --git a/src/mongo/db/catalog/uuid_catalog.cpp b/src/mongo/db/catalog/uuid_catalog.cpp
index 91595b5c69b..5ea95f14d2a 100644
--- a/src/mongo/db/catalog/uuid_catalog.cpp
+++ b/src/mongo/db/catalog/uuid_catalog.cpp
@@ -128,8 +128,10 @@ UUIDCatalog& UUIDCatalog::get(OperationContext* opCtx) {
void UUIDCatalog::onCreateCollection(OperationContext* opCtx,
Collection* coll,
CollectionUUID uuid) {
- removeUUIDCatalogEntry(uuid);
- registerUUIDCatalogEntry(uuid, coll);
+
+ stdx::lock_guard<stdx::mutex> lock(_catalogLock);
+ _removeUUIDCatalogEntry_inlock(uuid); // Remove UUID if it exists
+ _registerUUIDCatalogEntry_inlock(uuid, coll);
opCtx->recoveryUnit()->onRollback([this, uuid] { removeUUIDCatalogEntry(uuid); });
}
@@ -198,51 +200,19 @@ NamespaceString UUIDCatalog::lookupNSSByUUID(CollectionUUID uuid) const {
Collection* UUIDCatalog::replaceUUIDCatalogEntry(CollectionUUID uuid, Collection* coll) {
stdx::lock_guard<stdx::mutex> lock(_catalogLock);
invariant(coll);
-
- auto foundIt = _catalog.find(uuid);
- invariant(foundIt != _catalog.end());
- // Invalidate the source database's ordering, since we're deleting a UUID.
- _orderedCollections.erase(foundIt->second->ns().db());
-
- Collection* oldColl = foundIt->second;
- LOG(2) << "unregistering collection " << oldColl->ns() << " with UUID " << uuid.toString();
- _catalog.erase(foundIt);
-
- // Invalidate the destination database's ordering, since we're adding a new UUID.
- _orderedCollections.erase(coll->ns().db());
-
- std::pair<CollectionUUID, Collection*> entry = std::make_pair(uuid, coll);
- LOG(2) << "registering collection " << coll->ns() << " with UUID " << uuid.toString();
- invariant(_catalog.insert(entry).second == true);
+ Collection* oldColl = _removeUUIDCatalogEntry_inlock(uuid);
+ invariant(oldColl != nullptr); // Need to replace an existing coll
+ _registerUUIDCatalogEntry_inlock(uuid, coll);
return oldColl;
}
void UUIDCatalog::registerUUIDCatalogEntry(CollectionUUID uuid, Collection* coll) {
stdx::lock_guard<stdx::mutex> lock(_catalogLock);
-
- if (coll && !_catalog.count(uuid)) {
- // Invalidate this database's ordering, since we're adding a new UUID.
- _orderedCollections.erase(coll->ns().db());
-
- std::pair<CollectionUUID, Collection*> entry = std::make_pair(uuid, coll);
- LOG(2) << "registering collection " << coll->ns() << " with UUID " << uuid.toString();
- invariant(_catalog.insert(entry).second == true);
- }
+ _registerUUIDCatalogEntry_inlock(uuid, coll);
}
Collection* UUIDCatalog::removeUUIDCatalogEntry(CollectionUUID uuid) {
stdx::lock_guard<stdx::mutex> lock(_catalogLock);
-
- auto foundIt = _catalog.find(uuid);
- if (foundIt == _catalog.end())
- return nullptr;
-
- // Invalidate this database's ordering, since we're deleting a UUID.
- _orderedCollections.erase(foundIt->second->ns().db());
-
- auto foundCol = foundIt->second;
- LOG(2) << "unregistering collection " << foundCol->ns() << " with UUID " << uuid.toString();
- _catalog.erase(foundIt);
- return foundCol;
+ return _removeUUIDCatalogEntry_inlock(uuid);
}
boost::optional<CollectionUUID> UUIDCatalog::prev(const StringData& db, CollectionUUID uuid) {
@@ -292,4 +262,27 @@ const std::vector<CollectionUUID>& UUIDCatalog::_getOrdering_inlock(
return newOrdering;
}
+void UUIDCatalog::_registerUUIDCatalogEntry_inlock(CollectionUUID uuid, Collection* coll) {
+ if (coll && !_catalog.count(uuid)) {
+ // Invalidate this database's ordering, since we're adding a new UUID.
+ _orderedCollections.erase(coll->ns().db());
+
+ std::pair<CollectionUUID, Collection*> entry = std::make_pair(uuid, coll);
+ LOG(2) << "registering collection " << coll->ns() << " with UUID " << uuid.toString();
+ invariant(_catalog.insert(entry).second == true);
+ }
+}
+Collection* UUIDCatalog::_removeUUIDCatalogEntry_inlock(CollectionUUID uuid) {
+ auto foundIt = _catalog.find(uuid);
+ if (foundIt == _catalog.end())
+ return nullptr;
+
+ // Invalidate this database's ordering, since we're deleting a UUID.
+ _orderedCollections.erase(foundIt->second->ns().db());
+
+ auto foundCol = foundIt->second;
+ LOG(2) << "unregistering collection " << foundCol->ns() << " with UUID " << uuid.toString();
+ _catalog.erase(foundIt);
+ return foundCol;
+}
} // namespace mongo
diff --git a/src/mongo/db/catalog/uuid_catalog.h b/src/mongo/db/catalog/uuid_catalog.h
index a96210856fc..cc093b31c06 100644
--- a/src/mongo/db/catalog/uuid_catalog.h
+++ b/src/mongo/db/catalog/uuid_catalog.h
@@ -207,6 +207,8 @@ public:
private:
const std::vector<CollectionUUID>& _getOrdering_inlock(const StringData& db,
const stdx::lock_guard<stdx::mutex>&);
+ void _registerUUIDCatalogEntry_inlock(CollectionUUID uuid, Collection* coll);
+ Collection* _removeUUIDCatalogEntry_inlock(CollectionUUID uuid);
mutable mongo::stdx::mutex _catalogLock;
/**