diff options
-rw-r--r-- | src/mongo/db/index_builds_coordinator_mongod.cpp | 29 | ||||
-rw-r--r-- | src/mongo/db/repl_index_build_state.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/repl_index_build_state.h | 18 |
3 files changed, 46 insertions, 21 deletions
diff --git a/src/mongo/db/index_builds_coordinator_mongod.cpp b/src/mongo/db/index_builds_coordinator_mongod.cpp index 5d75034fe7f..eef382c66de 100644 --- a/src/mongo/db/index_builds_coordinator_mongod.cpp +++ b/src/mongo/db/index_builds_coordinator_mongod.cpp @@ -522,10 +522,7 @@ void IndexBuildsCoordinatorMongod::_signalPrimaryForCommitReadiness( replState->clearVoteRequestCbk(); }; - auto needToVote = [replState]() -> bool { - stdx::unique_lock<Latch> lk(replState->mutex); - return !replState->waitForNextAction->getFuture().isReady() ? true : false; - }; + auto needToVote = [replState]() -> bool { return !replState->getNextActionNoWait(); }; // Retry 'voteCommitIndexBuild' command on error until we have been signaled either with commit // or abort. This way, we can make sure majority of nodes will never stop voting and wait for @@ -590,11 +587,7 @@ void IndexBuildsCoordinatorMongod::_signalPrimaryForCommitReadiness( IndexBuildAction IndexBuildsCoordinatorMongod::_drainSideWritesUntilNextActionIsAvailable( OperationContext* opCtx, std::shared_ptr<ReplIndexBuildState> replState) { - auto future = [&] { - stdx::unique_lock<Latch> lk(replState->mutex); - invariant(replState->waitForNextAction); - return replState->waitForNextAction->getFuture(); - }(); + auto future = replState->getNextActionFuture(); // Waits until the promise is fulfilled or the deadline expires. IndexBuildAction nextAction; @@ -696,11 +689,7 @@ void IndexBuildsCoordinatorMongod::_waitForNextIndexBuildActionAndCommit( "No longer primary while attempting to commit. Waiting again for next action " "before completing final phase", "buildUUID"_attr = replState->buildUUID); - { - stdx::unique_lock<Latch> lk(replState->mutex); - replState->waitForNextAction = - std::make_unique<SharedPromise<IndexBuildAction>>(); - } + replState->resetNextActionPromise(); needsToRetryWait = true; break; case CommitResult::kLockTimeout: @@ -802,11 +791,11 @@ Status IndexBuildsCoordinatorMongod::setCommitQuorum(OperationContext* opCtx, // satisfied with the stale read commit quorum value. Lock::ExclusiveLock commitQuorumLk(opCtx->lockState(), replState->commitQuorumLock.get()); { - stdx::unique_lock<Latch> lk(replState->mutex); - if (replState->waitForNextAction->getFuture().isReady()) { + if (auto action = replState->getNextActionNoWait()) { return Status(ErrorCodes::CommandFailed, str::stream() << "Commit quorum can't be changed as index build is " - "ready to commit or abort"); + "ready to commit or abort: " + << indexBuildActionToString(*action)); } } @@ -817,10 +806,8 @@ Status IndexBuildsCoordinatorMongod::setCommitQuorum(OperationContext* opCtx, { // Check to see the index build hasn't received commit index build signal while updating // the commit quorum value on-disk. - stdx::unique_lock<Latch> lk(replState->mutex); - if (replState->waitForNextAction->getFuture().isReady()) { - auto action = replState->waitForNextAction->getFuture().get(); - invariant(action != IndexBuildAction::kCommitQuorumSatisfied); + if (auto action = replState->getNextActionNoWait()) { + invariant(*action != IndexBuildAction::kCommitQuorumSatisfied); } } return status; diff --git a/src/mongo/db/repl_index_build_state.cpp b/src/mongo/db/repl_index_build_state.cpp index a05adeb21e8..1bcf3786ec5 100644 --- a/src/mongo/db/repl_index_build_state.cpp +++ b/src/mongo/db/repl_index_build_state.cpp @@ -359,6 +359,26 @@ void ReplIndexBuildState::clearVoteRequestCbk() { voteCmdCbkHandle = executor::TaskExecutor::CallbackHandle(); } +void ReplIndexBuildState::resetNextActionPromise() { + stdx::unique_lock<Latch> lk(mutex); + waitForNextAction = std::make_unique<SharedPromise<IndexBuildAction>>(); +} + +SharedSemiFuture<IndexBuildAction> ReplIndexBuildState::getNextActionFuture() const { + stdx::unique_lock<Latch> lk(mutex); + invariant(waitForNextAction, str::stream() << buildUUID); + return waitForNextAction->getFuture(); +} + +boost::optional<IndexBuildAction> ReplIndexBuildState::getNextActionNoWait() const { + stdx::unique_lock<Latch> lk(mutex); + auto future = waitForNextAction->getFuture(); + if (!future.isReady()) { + return boost::none; + } + return future.get(); +} + bool ReplIndexBuildState::isResumable() const { stdx::unique_lock<Latch> lk(mutex); return !_lastOpTimeBeforeInterceptors.isNull(); diff --git a/src/mongo/db/repl_index_build_state.h b/src/mongo/db/repl_index_build_state.h index d2b4a7918bc..6777b1078fd 100644 --- a/src/mongo/db/repl_index_build_state.h +++ b/src/mongo/db/repl_index_build_state.h @@ -325,6 +325,24 @@ public: void clearVoteRequestCbk(); /** + * (Re-)initializes promise for next action. + */ + void resetNextActionPromise(); + + + /** + * Returns a future that can be used to wait on 'waitForNextAction' for the next action to be + * available. + */ + SharedSemiFuture<IndexBuildAction> getNextActionFuture() const; + + /** + * Gets next action from future if available. + * Returns boost::none if future is not ready. + */ + boost::optional<IndexBuildAction> getNextActionNoWait() const; + + /** * Accessor and mutator for last optime in the oplog before the interceptors were installed. * This supports resumable index builds. */ |