diff options
3 files changed, 66 insertions, 1 deletions
diff --git a/jstests/replsets/standalone_replication_recovery_relaxes_index_constaints.js b/jstests/replsets/standalone_replication_recovery_relaxes_index_constaints.js new file mode 100644 index 00000000000..64f7216d815 --- /dev/null +++ b/jstests/replsets/standalone_replication_recovery_relaxes_index_constaints.js @@ -0,0 +1,61 @@ +/* + * Tests that 'recoverFromOplogAsStandalone' relaxes index constraints. This test is + * non-deterministic. If there were a bug, it would still succeed with low probability, but should + * never fail without a bug. + * + * This test only makes sense for storage engines that support recover to stable timestamp. + * @tags: [requires_wiredtiger, requires_persistence, requires_journaling, requires_replication, + * requires_majority_read_concern] + */ + +(function() { +"use strict"; +load("jstests/replsets/rslib.js"); +load("jstests/libs/write_concern_util.js"); + +const name = jsTestName(); +const dbName = name; +const collName = 'coll'; +const logLevel = tojson({storage: {recovery: 2}, replication: 3}); + +const rst = new ReplSetTest({ + nodes: 1, +}); + +function getColl(conn) { + return conn.getDB(dbName)[collName]; +} + +jsTestLog("Initiating as a replica set."); +rst.startSet(); +rst.initiate(); +let node = rst.getPrimary(); + +assert.commandWorked(getColl(node).insert({_id: 1}, {writeConcern: {w: 1, j: 1}})); +assert.commandWorked(getColl(node).createIndex({x: 1}, {unique: true})); + +jsTestLog("Running inserts and removes"); +const start = (new Date()).getTime(); +const waitTimeMillis = 5 * 1000; +const baseNum = 10; +let iter = 2; +Random.setRandomSeed(); +while (((new Date()).getTime() - start) < waitTimeMillis) { + iter++; + const uniqueKey = Math.floor(Random.rand() * baseNum); + assert.commandWorked(getColl(node).insert({_id: iter, x: uniqueKey})); + assert.commandWorked(getColl(node).remove({_id: iter})); +} + +jsTestLog("Kill the node"); +rst.stop(node, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}); + +jsTestLog("Restart the node with 'recoverFromOplogAsStandalone'"); +node = rst.restart(node, { + noReplSet: true, + setParameter: {recoverFromOplogAsStandalone: true, logComponentVerbosity: logLevel} +}); +reconnect(node); + +rst.stopSet(); +})(); diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp index 586364fed55..51aeb7d574e 100644 --- a/src/mongo/db/index_builds_coordinator.cpp +++ b/src/mongo/db/index_builds_coordinator.cpp @@ -2250,7 +2250,8 @@ IndexBuildsCoordinator::CommitResult IndexBuildsCoordinator::_insertKeysFromSide // new signal from a new primary because we cannot commit. Note that two-phase index builds can // retry because a new signal should be received. Single-phase builds will be unable to commit // and will self-abort. - bool isMaster = replCoord->canAcceptWritesFor(opCtx, dbAndUUID); + bool isMaster = replCoord->canAcceptWritesFor(opCtx, dbAndUUID) && + !replCoord->getSettings().shouldRecoverFromOplogAsStandalone(); if (!isMaster && IndexBuildAction::kCommitQuorumSatisfied == action) { return CommitResult::kNoLongerPrimary; } diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 6a634f09168..943768b94b1 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -2867,6 +2867,9 @@ bool ReplicationCoordinatorImpl::isInPrimaryOrSecondaryState_UNSAFE() const { bool ReplicationCoordinatorImpl::shouldRelaxIndexConstraints(OperationContext* opCtx, const NamespaceString& ns) { + if (ReplSettings::shouldRecoverFromOplogAsStandalone()) { + return true; + } return !canAcceptWritesFor(opCtx, ns); } |