Status RollbackImpl::_awaitBgIndexCompletion(OperationContext* opCtx) { invariant(opCtx); if (_isInShutdown()) { return Status(ErrorCodes::ShutdownInProgress, "rollback shutting down"); } // Get a list of all databases. StorageEngine* storageEngine = opCtx->getServiceContext()->getGlobalStorageEngine(); std::vector<std::string> dbs; { Lock::GlobalLock lk(opCtx, MODE_IS, Date_t::max()); storageEngine->listDatabases(&dbs); } // Wait for all background operations to complete by waiting on each database. std::vector<StringData> dbNames(dbs.begin(), dbs.end()); log() << "Waiting for all background operations to complete before starting rollback"; for (auto db : dbNames) { LOG(1) << "Waiting for " << BackgroundOperation::numInProgForDb(db) << " background operations to complete on database '" << db << "'"; BackgroundOperation::awaitNoBgOpInProgForDb(db); // Check for shutdown again. if (_isInShutdown()) { return Status(ErrorCodes::ShutdownInProgress, "rollback shutting down"); } } log() << "Finished waiting for background operations to complete before rollback"; return Status::OK(); }
void RSDataSync::_run() { Client::initThread("rsSync"); AuthorizationSession::get(cc())->grantInternalAuthorization(); // Overwrite prefetch index mode in BackgroundSync if ReplSettings has a mode set. auto&& replSettings = _replCoord->getSettings(); if (replSettings.isPrefetchIndexModeSet()) _replCoord->setIndexPrefetchConfig(replSettings.getPrefetchIndexMode()); while (!_isInShutdown()) { // After a reconfig, we may not be in the replica set anymore, so // check that we are in the set (and not an arbiter) before // trying to sync with other replicas. // TODO(spencer): Use a condition variable to await loading a config if (_replCoord->getMemberState().startup()) { warning() << "did not receive a valid config yet"; sleepsecs(1); continue; } const MemberState memberState = _replCoord->getMemberState(); // An arbiter can never transition to any other state, and doesn't replicate, ever if (memberState.arbiter()) { break; } // If we are removed then we don't belong to the set anymore if (memberState.removed()) { sleepsecs(5); continue; } try { if (memberState.primary() && !_replCoord->isWaitingForApplierToDrain()) { sleepsecs(1); continue; } if (!_replCoord->setFollowerMode(MemberState::RS_RECOVERING)) { continue; } SyncTail tail(_bgsync, multiSyncApply); tail.oplogApplication(_replCoord, [this]() { return _isInShutdown(); }); } catch (...) { std::terminate(); } } LockGuard lk(_mutex); _inShutdown = false; _stopped = true; }
Status RollbackImpl::_transitionToRollback(OperationContext* opCtx) { invariant(opCtx); if (_isInShutdown()) { return Status(ErrorCodes::ShutdownInProgress, "rollback shutting down"); } log() << "transition to ROLLBACK"; { Lock::GlobalWrite globalWrite(opCtx); auto status = _replicationCoordinator->setFollowerMode(MemberState::RS_ROLLBACK); if (!status.isOK()) { status.addContext(str::stream() << "Cannot transition from " << _replicationCoordinator->getMemberState().toString() << " to " << MemberState(MemberState::RS_ROLLBACK).toString()); log() << status; return status; } } return Status::OK(); }