From 2e51e445a7ea5222a92012715a26689e41730ce0 Mon Sep 17 00:00:00 2001 From: Benety Goh Date: Sat, 26 Oct 2019 18:31:37 +0000 Subject: SERVER-44186 IndexBuildsCoordinator waits for commit/abort depending on the node's current replication state --- src/mongo/db/index_builds_coordinator.cpp | 39 +++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp index 0108d8a4b50..b306e3b34a0 100644 --- a/src/mongo/db/index_builds_coordinator.cpp +++ b/src/mongo/db/index_builds_coordinator.cpp @@ -93,6 +93,29 @@ void checkShardKeyRestrictions(OperationContext* opCtx, shardKeyPattern.isUniqueIndexCompatible(newIdxKey)); } +/** + * Returns true if we should wait for a commitIndexBuild or abortIndexBuild oplog entry during oplog + * application. + */ +bool shouldWaitForCommitOrAbort(OperationContext* opCtx, + const NamespaceString& nss, + const ReplIndexBuildState& replState) { + if (IndexBuildProtocol::kTwoPhase != replState.protocol) { + return false; + } + + auto replCoord = repl::ReplicationCoordinator::get(opCtx); + if (!replCoord->getSettings().usingReplSets()) { + return false; + } + + if (replCoord->canAcceptWritesFor(opCtx, nss)) { + return false; + } + + return true; +} + /** * Signal downstream secondary nodes to abort index build. */ @@ -916,8 +939,11 @@ void IndexBuildsCoordinator::_runIndexBuildInner(OperationContext* opCtx, // deadlock could result if the index build was attempting to acquire a Collection S or // X lock while a prepared transaction held a Collection IX lock, and a step down was // waiting to acquire the RSTL in mode X. - const bool unlocked = opCtx->lockState()->unlockRSTLforPrepare(); - invariant(unlocked); + // TODO(SERVER-44045): Revisit this logic for the non-two phase index build case. + if (!supportsTwoPhaseIndexBuild()) { + const bool unlocked = opCtx->lockState()->unlockRSTLforPrepare(); + invariant(unlocked); + } opCtx->runWithoutInterruptionExceptAtGlobalShutdown([&, this] { _buildIndex(opCtx, dbAndUUID, replState, indexBuildOptions, &collLock); }); @@ -1120,6 +1146,9 @@ void IndexBuildsCoordinator::_buildIndex( hangAfterIndexBuildFirstDrain.pauseWhileSet(); } + // Cache collection namespace for shouldWaitForCommitOrAbort(). + NamespaceString nss; + // Perform the second drain while stopping writes on the collection. { opCtx->recoveryUnit()->abandonSnapshot(); @@ -1130,6 +1159,8 @@ void IndexBuildsCoordinator::_buildIndex( replState->buildUUID, RecoveryUnit::ReadSource::kUnset, IndexBuildInterceptor::DrainYieldPolicy::kNoYield)); + + nss = *CollectionCatalog::get(opCtx).lookupNSSByUUID(replState->collectionUUID); } if (MONGO_unlikely(hangAfterIndexBuildSecondDrain.shouldFail())) { @@ -1138,9 +1169,7 @@ void IndexBuildsCoordinator::_buildIndex( } Timestamp commitIndexBuildTimestamp; - if (supportsTwoPhaseIndexBuild() && indexBuildOptions.replSetAndNotPrimaryAtStart && - IndexBuildProtocol::kTwoPhase == replState->protocol) { - + if (shouldWaitForCommitOrAbort(opCtx, nss, *replState)) { log() << "Index build waiting for commit or abort before completing final phase: " << replState->buildUUID; -- cgit v1.2.1