summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-09-28 10:41:35 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-09-30 15:26:17 +0000
commit3b8dfefeb9809a826354460b653b9d964730a18a (patch)
tree83b8bd97c666f2797e5e46eeefa53af85198d5a3
parentcadb990e1ac4229bcf419f47c82656b6458faf8a (diff)
downloadmongo-3b8dfefeb9809a826354460b653b9d964730a18a.tar.gz
SERVER-51091 Rearrange AutoGetCollection templating and inheritance to have separate -LFR and non-LFR (lock-free read) lock helpers.
-rw-r--r--src/mongo/db/catalog_raii.cpp39
-rw-r--r--src/mongo/db/catalog_raii.h86
-rw-r--r--src/mongo/db/db_raii.cpp27
-rw-r--r--src/mongo/db/db_raii.h73
4 files changed, 99 insertions, 126 deletions
diff --git a/src/mongo/db/catalog_raii.cpp b/src/mongo/db/catalog_raii.cpp
index 41e5e2576b6..f19b9738453 100644
--- a/src/mongo/db/catalog_raii.cpp
+++ b/src/mongo/db/catalog_raii.cpp
@@ -69,14 +69,13 @@ Database* AutoGetDb::ensureDbExists() {
return _db;
}
-template <typename CatalogCollectionLookupT>
-AutoGetCollectionBase<CatalogCollectionLookupT>::AutoGetCollectionBase(
- OperationContext* opCtx,
- const NamespaceStringOrUUID& nsOrUUID,
- LockMode modeColl,
- AutoGetCollectionViewMode viewMode,
- Date_t deadline)
- : _autoDb(opCtx,
+AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
+ const NamespaceStringOrUUID& nsOrUUID,
+ LockMode modeColl,
+ AutoGetCollectionViewMode viewMode,
+ Date_t deadline)
+ : _opCtx(opCtx),
+ _autoDb(opCtx,
!nsOrUUID.dbname().empty() ? nsOrUUID.dbname() : nsOrUUID.nss()->db(),
isSharedLockMode(modeColl) ? MODE_IS : MODE_IX,
deadline) {
@@ -112,7 +111,7 @@ AutoGetCollectionBase<CatalogCollectionLookupT>::AutoGetCollectionBase(
if (!db)
return;
- _coll = _lookup.lookupCollection(opCtx, _resolvedNss);
+ _coll = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, _resolvedNss);
invariant(!nsOrUUID.uuid() || _coll,
str::stream() << "Collection for " << _resolvedNss.ns()
<< " disappeared after successufully resolving "
@@ -149,13 +148,6 @@ AutoGetCollectionBase<CatalogCollectionLookupT>::AutoGetCollectionBase(
!_view || viewMode == AutoGetCollectionViewMode::kViewsPermitted);
}
-AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
- const NamespaceStringOrUUID& nsOrUUID,
- LockMode modeColl,
- AutoGetCollectionViewMode viewMode,
- Date_t deadline)
- : AutoGetCollectionBase(opCtx, nsOrUUID, modeColl, viewMode, deadline), _opCtx(opCtx) {}
-
Collection* AutoGetCollection::getWritableCollection(CollectionCatalog::LifetimeMode mode) {
// Acquire writable instance if not already available
if (!_writableColl) {
@@ -320,18 +312,6 @@ void CollectionWriter::commitToCatalog() {
_writableCollection = nullptr;
}
-CatalogCollectionLookup::CollectionStorage CatalogCollectionLookup::lookupCollection(
- OperationContext* opCtx, const NamespaceString& nss) {
- return CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nss);
-}
-
-CatalogCollectionLookupForRead::CollectionStorage CatalogCollectionLookupForRead::lookupCollection(
- OperationContext* opCtx, const NamespaceString& nss) {
- auto ptr = CollectionCatalog::get(opCtx).lookupCollectionByNamespaceForRead(opCtx, nss);
- _collection = CollectionPtr(ptr);
- return ptr;
-}
-
LockMode fixLockModeForSystemDotViewsChanges(const NamespaceString& nss, LockMode mode) {
return nss.isSystemDotViews() ? MODE_X : mode;
}
@@ -390,7 +370,4 @@ AutoGetOplog::AutoGetOplog(OperationContext* opCtx, OplogAccessMode mode, Date_t
_oplog = &_oplogInfo->getCollection();
}
-template class AutoGetCollectionBase<CatalogCollectionLookup>;
-template class AutoGetCollectionBase<CatalogCollectionLookupForRead>;
-
} // namespace mongo
diff --git a/src/mongo/db/catalog_raii.h b/src/mongo/db/catalog_raii.h
index 76fe75ba9c8..eade7f99c4b 100644
--- a/src/mongo/db/catalog_raii.h
+++ b/src/mongo/db/catalog_raii.h
@@ -82,6 +82,8 @@ private:
Database* _db;
};
+enum class AutoGetCollectionViewMode { kViewsPermitted, kViewsForbidden };
+
/**
* RAII-style class, which acquires global, database, and collection locks according to the chart
* below.
@@ -98,18 +100,12 @@ private:
* Any acquired locks may be released when this object goes out of scope, therefore the database
* and the collection references returned by this class should not be retained.
*/
-
-enum class AutoGetCollectionViewMode { kViewsPermitted, kViewsForbidden };
-
-template <typename CatalogCollectionLookupT>
-class AutoGetCollectionBase {
- AutoGetCollectionBase(const AutoGetCollectionBase&) = delete;
- AutoGetCollectionBase& operator=(const AutoGetCollectionBase&) = delete;
-
- using CollectionStorage = typename CatalogCollectionLookupT::CollectionStorage;
+class AutoGetCollection {
+ AutoGetCollection(const AutoGetCollection&) = delete;
+ AutoGetCollection& operator=(const AutoGetCollection&) = delete;
public:
- AutoGetCollectionBase(
+ AutoGetCollection(
OperationContext* opCtx,
const NamespaceStringOrUUID& nsOrUUID,
LockMode modeColl,
@@ -152,7 +148,7 @@ public:
* Returns nullptr if the collection didn't exist.
*/
const CollectionPtr& getCollection() const {
- return _lookup.toCollectionPtr(_coll);
+ return _coll;
}
/**
@@ -169,54 +165,14 @@ public:
return _resolvedNss;
}
-protected:
- AutoGetDb _autoDb;
-
- // If the object was instantiated with a UUID, contains the resolved namespace, otherwise it is
- // the same as the input namespace string
- NamespaceString _resolvedNss;
-
- // This field is boost::optional, because in the case of lookup by UUID, the collection lock
- // might need to be relocked for the correct namespace
- boost::optional<Lock::CollectionLock> _collLock;
-
- CollectionStorage _coll = nullptr;
- CatalogCollectionLookupT _lookup;
- std::shared_ptr<ViewDefinition> _view;
-};
-
-struct CatalogCollectionLookup {
- using CollectionStorage = CollectionPtr;
-
- CollectionStorage lookupCollection(OperationContext* opCtx, const NamespaceString& nss);
- const CollectionPtr& toCollectionPtr(const CollectionStorage& collection) const {
- return collection;
- }
-};
-struct CatalogCollectionLookupForRead {
- using CollectionStorage = std::shared_ptr<const Collection>;
-
- CollectionStorage lookupCollection(OperationContext* opCtx, const NamespaceString& nss);
- const CollectionPtr& toCollectionPtr(const CollectionStorage&) const {
- return _collection;
- }
-
-private:
- CollectionPtr _collection;
-};
-
-class AutoGetCollection : public AutoGetCollectionBase<CatalogCollectionLookup> {
-public:
- AutoGetCollection(
- OperationContext* opCtx,
- const NamespaceStringOrUUID& nsOrUUID,
- LockMode modeColl,
- AutoGetCollectionViewMode viewMode = AutoGetCollectionViewMode::kViewsForbidden,
- Date_t deadline = Date_t::max());
-
/**
- * Returns writable Collection. Necessary Collection lock mode is required.
- * Any previous Collection that has been returned may be invalidated.
+ * Returns a writable Collection copy that will be returned by current and future calls to this
+ * function as well as getCollection(). Any previous Collection pointers that were returned may
+ * be invalidated.
+ *
+ * CollectionCatalog::LifetimeMode::kManagedInWriteUnitOfWork will register an onCommit()
+ * handler to reset the pointers and an onRollback() handler that will reset getCollection() to
+ * the original Collection pointer.
*/
Collection* getWritableCollection(
CollectionCatalog::LifetimeMode mode =
@@ -226,9 +182,19 @@ public:
return _opCtx;
}
-private:
- Collection* _writableColl = nullptr;
+protected:
OperationContext* _opCtx = nullptr;
+ AutoGetDb _autoDb;
+ boost::optional<Lock::CollectionLock> _collLock;
+ CollectionPtr _coll = nullptr;
+ std::shared_ptr<ViewDefinition> _view;
+
+ // If the object was instantiated with a UUID, contains the resolved namespace, otherwise it is
+ // the same as the input namespace string
+ NamespaceString _resolvedNss;
+
+ // Populated if getWritableCollection() is called.
+ Collection* _writableColl = nullptr;
};
/**
diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp
index 7e2397f2521..7ffe40349ab 100644
--- a/src/mongo/db/db_raii.cpp
+++ b/src/mongo/db/db_raii.cpp
@@ -84,10 +84,12 @@ AutoStatsTracker::~AutoStatsTracker() {
curOp->getReadWriteType());
}
-AutoGetCollectionForRead::AutoGetCollectionForRead(OperationContext* opCtx,
- const NamespaceStringOrUUID& nsOrUUID,
- AutoGetCollectionViewMode viewMode,
- Date_t deadline) {
+template <typename AutoGetCollectionType>
+AutoGetCollectionForReadBase<AutoGetCollectionType>::AutoGetCollectionForReadBase(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& nsOrUUID,
+ AutoGetCollectionViewMode viewMode,
+ Date_t deadline) {
// The caller was expecting to conflict with batch application before entering this function.
// i.e. the caller does not currently have a ShouldNotConflict... block in scope.
bool callerWasConflicting = opCtx->lockState()->shouldConflictWithSecondaryBatchApplication();
@@ -241,13 +243,13 @@ AutoGetCollectionForRead::AutoGetCollectionForRead(OperationContext* opCtx,
}
}
-
-AutoGetCollectionForReadCommand::AutoGetCollectionForReadCommand(
- OperationContext* opCtx,
- const NamespaceStringOrUUID& nsOrUUID,
- AutoGetCollectionViewMode viewMode,
- Date_t deadline,
- AutoStatsTracker::LogMode logMode)
+template <typename AutoGetCollectionForReadType>
+AutoGetCollectionForReadCommandBase<AutoGetCollectionForReadType>::
+ AutoGetCollectionForReadCommandBase(OperationContext* opCtx,
+ const NamespaceStringOrUUID& nsOrUUID,
+ AutoGetCollectionViewMode viewMode,
+ Date_t deadline,
+ AutoStatsTracker::LogMode logMode)
: _autoCollForRead(opCtx, nsOrUUID, viewMode, deadline),
_statsTracker(
opCtx,
@@ -338,4 +340,7 @@ BlockSecondaryReadsDuringBatchApplication_DONT_USE::
allowSecondaryReads->swap(_originalSettings);
}
+template class AutoGetCollectionForReadBase<AutoGetCollection>;
+template class AutoGetCollectionForReadCommandBase<AutoGetCollectionForRead>;
+
} // namespace mongo
diff --git a/src/mongo/db/db_raii.h b/src/mongo/db/db_raii.h
index 89406e31939..dbe6b1c1b70 100644
--- a/src/mongo/db/db_raii.h
+++ b/src/mongo/db/db_raii.h
@@ -84,24 +84,13 @@ private:
const LogMode _logMode;
};
-/**
- * Same as calling AutoGetCollection with MODE_IS, but in addition ensures that the read will be
- * performed against an appropriately committed snapshot if the operation is using a readConcern of
- * 'majority'.
- *
- * Use this when you want to read the contents of a collection, but you are not at the top-level of
- * some command. This will ensure your reads obey any requested readConcern, but will not update the
- * status of CurrentOp, or add a Top entry.
- *
- * NOTE: Must not be used with any locks held, because it needs to block waiting on the committed
- * snapshot to become available.
- */
-class AutoGetCollectionForRead {
- AutoGetCollectionForRead(const AutoGetCollectionForRead&) = delete;
- AutoGetCollectionForRead& operator=(const AutoGetCollectionForRead&) = delete;
+template <typename AutoGetCollectionType>
+class AutoGetCollectionForReadBase {
+ AutoGetCollectionForReadBase(const AutoGetCollectionForReadBase&) = delete;
+ AutoGetCollectionForReadBase& operator=(const AutoGetCollectionForReadBase&) = delete;
public:
- AutoGetCollectionForRead(
+ AutoGetCollectionForReadBase(
OperationContext* opCtx,
const NamespaceStringOrUUID& nsOrUUID,
AutoGetCollectionViewMode viewMode = AutoGetCollectionViewMode::kViewsForbidden,
@@ -140,19 +129,39 @@ private:
// This field is optional, because the code to wait for majority committed snapshot needs to
// release locks in order to block waiting
- boost::optional<AutoGetCollectionBase<CatalogCollectionLookupForRead>> _autoColl;
+ boost::optional<AutoGetCollectionType> _autoColl;
};
/**
- * Same as AutoGetCollectionForRead, but in addition will add a Top entry upon destruction and
- * ensure the CurrentOp object has the right namespace and has started its timer.
+ * Same as calling AutoGetCollection with MODE_IS, but in addition ensures that the read will be
+ * performed against an appropriately committed snapshot if the operation is using a readConcern of
+ * 'majority'.
+ *
+ * Use this when you want to read the contents of a collection, but you are not at the top-level of
+ * some command. This will ensure your reads obey any requested readConcern, but will not update the
+ * status of CurrentOp, or add a Top entry.
+ *
+ * NOTE: Must not be used with any locks held, because it needs to block waiting on the committed
+ * snapshot to become available.
*/
-class AutoGetCollectionForReadCommand {
- AutoGetCollectionForReadCommand(const AutoGetCollectionForReadCommand&) = delete;
- AutoGetCollectionForReadCommand& operator=(const AutoGetCollectionForReadCommand&) = delete;
+class AutoGetCollectionForRead : public AutoGetCollectionForReadBase<AutoGetCollection> {
+public:
+ AutoGetCollectionForRead(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& nsOrUUID,
+ AutoGetCollectionViewMode viewMode = AutoGetCollectionViewMode::kViewsForbidden,
+ Date_t deadline = Date_t::max())
+ : AutoGetCollectionForReadBase(opCtx, nsOrUUID, viewMode, deadline) {}
+};
+
+template <typename AutoGetCollectionForReadType>
+class AutoGetCollectionForReadCommandBase {
+ AutoGetCollectionForReadCommandBase(const AutoGetCollectionForReadCommandBase&) = delete;
+ AutoGetCollectionForReadCommandBase& operator=(const AutoGetCollectionForReadCommandBase&) =
+ delete;
public:
- AutoGetCollectionForReadCommand(
+ AutoGetCollectionForReadCommandBase(
OperationContext* opCtx,
const NamespaceStringOrUUID& nsOrUUID,
AutoGetCollectionViewMode viewMode = AutoGetCollectionViewMode::kViewsForbidden,
@@ -184,11 +193,27 @@ public:
}
private:
- AutoGetCollectionForRead _autoCollForRead;
+ AutoGetCollectionForReadType _autoCollForRead;
AutoStatsTracker _statsTracker;
};
/**
+ * Same as AutoGetCollectionForRead, but in addition will add a Top entry upon destruction and
+ * ensure the CurrentOp object has the right namespace and has started its timer.
+ */
+class AutoGetCollectionForReadCommand
+ : public AutoGetCollectionForReadCommandBase<AutoGetCollectionForRead> {
+public:
+ AutoGetCollectionForReadCommand(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& nsOrUUID,
+ AutoGetCollectionViewMode viewMode = AutoGetCollectionViewMode::kViewsForbidden,
+ Date_t deadline = Date_t::max(),
+ AutoStatsTracker::LogMode logMode = AutoStatsTracker::LogMode::kUpdateTopAndCurOp)
+ : AutoGetCollectionForReadCommandBase(opCtx, nsOrUUID, viewMode, deadline, logMode) {}
+};
+
+/**
* Opens the database that we want to use and sets the appropriate namespace on the
* current operation.
*/