From c15e8ae74071482d69179c7e5e5e6bdc882d2beb Mon Sep 17 00:00:00 2001 From: Lingzhi Deng Date: Tue, 3 Mar 2020 10:46:39 -0500 Subject: SERVER-45626: Introduce AutoGetOplog for consistent oplog locking rules --- src/mongo/db/catalog_raii.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/mongo/db/catalog_raii.cpp') diff --git a/src/mongo/db/catalog_raii.cpp b/src/mongo/db/catalog_raii.cpp index 156727191dd..aacce83a287 100644 --- a/src/mongo/db/catalog_raii.cpp +++ b/src/mongo/db/catalog_raii.cpp @@ -182,4 +182,37 @@ ReadSourceScope::~ReadSourceScope() { } } +AutoGetOplog::AutoGetOplog(OperationContext* opCtx, OplogAccessMode mode, Date_t deadline) + : _shouldNotConflictWithSecondaryBatchApplicationBlock(opCtx->lockState()) { + if (mode == OplogAccessMode::kLogOp) { + // Invariant that global lock is already held for kLogOp mode. + invariant(opCtx->lockState()->isWriteLocked()); + } else { + _globalLock.emplace(opCtx, + mode == OplogAccessMode::kRead ? MODE_IS : MODE_IX, + deadline, + Lock::InterruptBehavior::kThrow); + } + + // Obtain database and collection intent locks for non-document-locking storage engines. + if (!opCtx->getServiceContext()->getStorageEngine()->supportsDocLocking()) { + auto lockMode = (mode == OplogAccessMode::kRead) ? MODE_IS : MODE_IX; + + // If mode is kLogOp, only acquire the database lock if it is not already held. + if (mode != OplogAccessMode::kLogOp || + !opCtx->lockState()->isDbLockedForMode(NamespaceString::kLocalDb, lockMode)) { + _dbWriteLock.emplace(opCtx, NamespaceString::kLocalDb, lockMode, deadline); + } + + // If mode is kLogOp, only acquire the collection lock if it is not already held. + if (mode != OplogAccessMode::kLogOp || + !opCtx->lockState()->isCollectionLockedForMode(NamespaceString::kRsOplogNamespace, + lockMode)) { + _collWriteLock.emplace(opCtx, NamespaceString::kRsOplogNamespace, lockMode, deadline); + } + } + _oplogInfo = repl::LocalOplogInfo::get(opCtx); + _oplog = _oplogInfo->getCollection(); +} + } // namespace mongo -- cgit v1.2.1