diff --git a/jstests/replsets/libs/rollback_test.js b/jstests/replsets/libs/rollback_test.js index aec5d56a241..2d38dd64863 100644 --- a/jstests/replsets/libs/rollback_test.js +++ b/jstests/replsets/libs/rollback_test.js @@ -105,6 +105,7 @@ export function RollbackTest(name = "RollbackTest", replSet, nodeOptions) { let curState = State.kSteadyStateOps; let lastRBID; + let clusterTime; // Make sure we have a replica set up and running. replSet = (replSet === undefined) ? performStandardSetup(nodeOptions) : replSet; @@ -156,8 +157,10 @@ export function RollbackTest(name = "RollbackTest", replSet, nodeOptions) { // Make sure we have a primary. curPrimary = replSet.getPrimary(); // The default WC is majority and we must use w:1 to be able to properly test rollback. + /* assert.commandWorked(curPrimary.adminCommand( {setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}})); + */ replSet.awaitReplication(); // Extract the other two nodes and wait for them to be ready. @@ -247,6 +250,7 @@ export function RollbackTest(name = "RollbackTest", replSet, nodeOptions) { let replSet = new ReplSetTest({name, nodes: 3, useBridge: true, nodeOptions: nodeOptions}); replSet.startSet(); + replSet.nodes.forEach(setFastGetMoreEnabled); let config = replSet.getReplSetConfig(); @@ -261,6 +265,18 @@ export function RollbackTest(name = "RollbackTest", replSet, nodeOptions) { assert.eq(replSet.nodes.length, kNumDataBearingNodes, "Mismatch between number of data bearing nodes and test configuration."); + jsTestLog('About to insert docs'); + for (let i = 0; i < 25; ++i) { + assert.commandWorked( + replSet.getPrimary().getDB('foo').getCollection('test').insert({x: i})); + } + jsTestLog('About to create index'); + clusterTime = + assert + .commandWorked( + replSet.getPrimary().getDB('foo').getCollection('test').createIndex({x: 1})) + .operationTime; + jsTestLog('Got clusterTime ' + tojson(clusterTime)); return replSet; } @@ -708,4 +724,8 @@ export function RollbackTest(name = "RollbackTest", replSet, nodeOptions) { this.setAwaitSecondaryNodesForRollbackTimeout = function(timeoutMillis) { awaitSecondaryNodesForRollbackTimeout = timeoutMillis; }; + + this.getClusterTime = function() { + return clusterTime; + }; } diff --git a/jstests/sharding/test_snapshot_reads_in_rollbacks.js b/jstests/sharding/test_snapshot_reads_in_rollbacks.js new file mode 100644 index 00000000000..659f8dcd428 --- /dev/null +++ b/jstests/sharding/test_snapshot_reads_in_rollbacks.js @@ -0,0 +1,65 @@ +/** + * Reproducible of BF-34498: execute an aggregation on config.transactions with snapshot readConcern + * and nearest readPreference while the node is doing a rollback. + */ + +import {configureFailPoint} from "jstests/libs/fail_point_util.js"; +import {RollbackTest} from "jstests/replsets/libs/rollback_test.js"; +import {ShardingTest} from "jstests/libs/shardingtest.js"; +import {Thread} from "jstests/libs/parallelTester.js"; + +const st = new ShardingTest({config: 1, shards: 0}); +const kRollbackRSName = 'RollbackRS' + +let rollbackRS = new RollbackTest(kRollbackRSName, undefined, {shardsvr: ''}); +rollbackRS.transitionToRollbackOperations(); +rollbackRS.transitionToSyncSourceOperationsBeforeRollback(); +rollbackRS.transitionToSyncSourceOperationsDuringRollback(); +rollbackRS.transitionToSteadyStateOperations(); + +assert.commandWorked(st.s.adminCommand({addShard: rollbackRS.getTestFixture().getURL()})); + +let snapshoReadThread = new Thread( + (rsConnString, operationTimeT, operationTimeI) => { + let mongo = new Mongo(rsConnString); + for (let i = 0; i < 35500; ++i) { + assert.commandWorkedOrFailedWithCode(mongo.getDB('foo').runCommand({ + aggregate: 'test', + pipeline: [{$match: {}}], + cursor: {batchSize: 5}, + $readPreference: {mode: 'nearest'}, + readConcern: { + level: 'snapshot', + atClusterTime: Timestamp(operationTimeT, operationTimeI), + $_allowTransactionTableSnapshot: true + }, + shardVersion: { + e: ObjectId("000000000000000000000000"), + t: Timestamp(0, 0), + v: Timestamp(0, 0) + } + }), + [ + ErrorCodes.ShardingStateNotInitialized, + ErrorCodes.MigrationConflict, + ErrorCodes.SnapshotTooOld, + ErrorCodes.ObjectIsBusy, + ErrorCodes.StaleConfig, + ]); + } + }, + rollbackRS.getTestFixture().getURL(), + rollbackRS.getClusterTime().t, + rollbackRS.getClusterTime().i); +jsTestLog('starting thread'); +snapshoReadThread.start(); +for (let i = 0; i < 100; ++i) { + rollbackRS.transitionToRollbackOperations(); + rollbackRS.transitionToSyncSourceOperationsBeforeRollback(); + rollbackRS.transitionToSyncSourceOperationsDuringRollback(); + rollbackRS.transitionToSteadyStateOperations(); +} + +snapshoReadThread.join(); +st.stop(); +rollbackRS.stop();