diff options
author | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2021-09-22 13:33:07 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-10-12 14:04:56 +0000 |
commit | 6427bb01da49015bbac8e6774aea4e90993053ae (patch) | |
tree | 8e144cbd81a5d122a2ac4f800cac1f153f7c4728 | |
parent | 4da49024045ef47a6958157b64e73511c4865b49 (diff) | |
download | mongo-6427bb01da49015bbac8e6774aea4e90993053ae.tar.gz |
SERVER-58780: Ensure that _shouldSetStableTimestamp restores to true if replSetInitiate fails
(cherry picked from commit 75e59101ebc9d8a4633b270a3fd44d6e2058a1b9)
-rw-r--r-- | jstests/replsets/initiate_emrc_false.js | 65 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 8 |
2 files changed, 73 insertions, 0 deletions
diff --git a/jstests/replsets/initiate_emrc_false.js b/jstests/replsets/initiate_emrc_false.js new file mode 100644 index 00000000000..6843c805405 --- /dev/null +++ b/jstests/replsets/initiate_emrc_false.js @@ -0,0 +1,65 @@ +/* + * Test that there is no side effects of failing replSetInitiate with eMRC=false, SERVER-58780. + * @tags: [requires_persistence, multiversion_incompatible] + */ + +(function() { +"use strict"; + +function runTest({cleanShutdown}) { + const rst = new ReplSetTest({ + name: jsTestName(), + nodes: 2, + nodeOptions: { + enableMajorityReadConcern: "false", + } + }); + const nodes = rst.startSet(); + + // Run replSetInitiate with an invalid config and expect it to fail. + jsTestLog("Running invalid replSetInitiate"); + assert.commandFailedWithCode(nodes[0].adminCommand({replSetInitiate: {foo: "bar"}}), + ErrorCodes.InvalidReplicaSetConfig); + assert.commandFailedWithCode(nodes[1].adminCommand({replSetInitiate: {foo: "bar"}}), + ErrorCodes.InvalidReplicaSetConfig); + + rst.initiateWithHighElectionTimeout(); + + // Do some dummy writes. + const primary = rst.getPrimary(); + const testDB = primary.getDB("test"); + assert.commandWorked(testDB.runCommand({ + insert: "coll", + documents: [...Array(100).keys()].map(x => ({_id: x})), + writeConcern: {w: "majority"} + })); + rst.awaitSecondaryNodes(); + + let secondary = rst.getSecondary(); + if (cleanShutdown) { + jsTestLog("Restarting secondary node from clean shutdown"); + rst.stop(secondary, 0, undefined, {forRestart: true}); + } else { + jsTestLog("Restarting secondary node from unclean shutdown"); + rst.stop(secondary, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}, {forRestart: true}); + } + + // Restarting from shutdown shouldn't need to go through initial sync again. Set a failpoint to + // hang initial sync so that if the node decides to do initial sync again, the test will fail. + secondary = rst.start(secondary, + { + setParameter: { + 'failpoint.initialSyncHangAfterGettingBeginFetchingTimestamp': + tojson({mode: 'alwaysOn'}), + } + }, + true /* restart */); + + rst.awaitSecondaryNodes(); + + rst.stopSet(); +} + +runTest({cleanShutdown: true}); +runTest({cleanShutdown: false}); +})(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 9c61b67b0dc..1cad14b0682 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -2864,6 +2864,13 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt if (!serverGlobalParams.enableMajorityReadConcern) { _shouldSetStableTimestamp = false; } + auto setStableTimestampGuard = makeGuard([&] { + lockAndCall(&lk, [=] { + if (!serverGlobalParams.enableMajorityReadConcern) { + _shouldSetStableTimestamp = true; + } + }); + }); lk.unlock(); @@ -2924,6 +2931,7 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt // Set our stable timestamp for storage and re-enable stable timestamp advancement after we have // set our initial data timestamp. + setStableTimestampGuard.dismiss(); if (!serverGlobalParams.enableMajorityReadConcern) { stdx::unique_lock<Latch> lk(_mutex); _shouldSetStableTimestamp = true; |