diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2020-09-28 10:41:35 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-30 15:26:17 +0000 |
commit | 3b8dfefeb9809a826354460b653b9d964730a18a (patch) | |
tree | 83b8bd97c666f2797e5e46eeefa53af85198d5a3 /src/mongo/db | |
parent | cadb990e1ac4229bcf419f47c82656b6458faf8a (diff) | |
download | mongo-3b8dfefeb9809a826354460b653b9d964730a18a.tar.gz |
SERVER-51091 Rearrange AutoGetCollection templating and inheritance to have separate -LFR and non-LFR (lock-free read) lock helpers.
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/catalog_raii.cpp | 39 | ||||
-rw-r--r-- | src/mongo/db/catalog_raii.h | 86 | ||||
-rw-r--r-- | src/mongo/db/db_raii.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/db_raii.h | 73 |
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. */ |