diff --git a/jstests/replsets/libs/rollback_test.js b/jstests/replsets/libs/rollback_test.js index 023380a69af..12edd71dc92 100644 --- a/jstests/replsets/libs/rollback_test.js +++ b/jstests/replsets/libs/rollback_test.js @@ -159,6 +159,13 @@ function RollbackTest(name = "RollbackTest") { // should never be possible with 2 electable nodes and the sequence of operations thus far. assert.eq(newPrimary, curSecondary, "Did not elect a new node as primary"); + // Add a sleep and a dummy write to ensure the new primary has an optime greater than + // the last optime on the node that will undergo rollback. This greater optime ensures that + // the new primary is eligible to become a sync source in pv0. + sleep(1000); + var dbName = "ensureEligiblePV0"; + assert.writeOK(newPrimary.getDB(dbName).testColl.insert({id: 0})); + // The old primary is the new secondary; the old secondary just got elected as the new // primary, so we update the topology to reflect this change. curSecondary = curPrimary; diff --git a/jstests/replsets/rollback_drop_index_after_rename.js b/jstests/replsets/rollback_drop_index_after_rename.js new file mode 100644 index 00000000000..e3b965c1c9b --- /dev/null +++ b/jstests/replsets/rollback_drop_index_after_rename.js @@ -0,0 +1,59 @@ +/** + * Test that a dropIndex on a collection that was renamed is rolled back successfully. + * + * This test works by creating a collection and an index in that collection, + * then renaming that collection and rolling back a drop on that index. + */ + +(function() { + "use strict"; + + load("jstests/replsets/libs/rollback_test.js"); + + const testName = "rollback_drop_index_after_rename"; + const dbName = testName; + + var fromColl = "fromColl"; + var toColl = "toColl"; + var idxName = "a_1"; + + // Operations that will be present on both nodes, before the common point. + let CommonOps = (node) => { + let testDb = node.getDB(dbName); + // This creates the collection implicitly and then creates the index. + assert.commandWorked(testDb.runCommand({ + createIndexes: fromColl, + indexes: [{ + key: { + "a": 1, + }, + name: idxName + }] + })); + }; + + // Operations that will be performed on the rollback node past the common point. + let RollbackOps = (node) => { + let testDb = node.getDB(dbName); + assert.commandWorked(testDb.adminCommand({ + renameCollection: dbName + "." + fromColl, + to: dbName + "." + toColl, + })); + assert.commandWorked(testDb.runCommand({dropIndexes: toColl, index: idxName})); + }; + + // Set up Rollback Test. + let rollbackTest = new RollbackTest(testName); + CommonOps(rollbackTest.getPrimary()); + + let rollbackNode = rollbackTest.transitionToRollbackOperations(); + RollbackOps(rollbackNode); + + // No sync source ops. + rollbackTest.transitionToSyncSourceOperations(); + + // Wait for rollback to finish. + rollbackTest.transitionToSteadyStateOperations({waitForRollback: true}); + + rollbackTest.stop(); +})(); diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp index 4bf07449dae..902eddffdde 100644 --- a/src/mongo/db/repl/rs_rollback.cpp +++ b/src/mongo/db/repl/rs_rollback.cpp @@ -669,7 +669,7 @@ void rollbackDropIndexes(OperationContext* opCtx, updatedNss.append("ns", nss.ns()); BSONObj updatedNssObj = updatedNss.obj(); - indexSpec.addField(updatedNssObj.firstElement()); + indexSpec = indexSpec.addField(updatedNssObj.firstElement()); createIndexForApplyOps(opCtx, indexSpec, nss, {});