2018-01-02 14:42:52 -05:00
|
|
|
/*
|
2019-07-26 18:20:35 -04:00
|
|
|
* Test that the server is able to roll back a 'dropDatabase' entry correctly. This test creates
|
|
|
|
|
* a collection, then executes a 'dropDatabase' command, partitioning the primary such that the
|
|
|
|
|
* final 'dropDatabase' oplog entry is not replicated. The test then forces rollback of that entry.
|
|
|
|
|
*
|
|
|
|
|
* The 'dropDatabase' command drops each collection, ensures that the last drop is committed,
|
|
|
|
|
* and only then logs a 'dropDatabase' oplog entry. This is therefore the only entry that could
|
|
|
|
|
* get rolled back.
|
|
|
|
|
*/
|
2018-01-02 14:42:52 -05:00
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
load("jstests/replsets/libs/rollback_test.js");
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
const testName = "rollback_drop_database";
|
|
|
|
|
const oldDbName = "oldDatabase";
|
|
|
|
|
const newDbName = "newDatabase";
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
let rollbackTest = new RollbackTest(testName);
|
|
|
|
|
let rollbackNode = rollbackTest.getPrimary();
|
|
|
|
|
let syncSourceNode = rollbackTest.getSecondary();
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Perform initial insert (common operation).
|
2019-08-14 13:52:59 +00:00
|
|
|
assert.commandWorked(rollbackNode.getDB(oldDbName)["beforeRollback"].insert({"num": 1}));
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Set a failpoint on the original primary, so that it blocks after it commits the last
|
|
|
|
|
// 'dropCollection' entry but before the 'dropDatabase' entry is logged.
|
2019-10-01 00:32:17 +00:00
|
|
|
assert.commandWorked(rollbackNode.adminCommand(
|
|
|
|
|
{configureFailPoint: "dropDatabaseHangBeforeInMemoryDrop", mode: "alwaysOn"}));
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Issue a 'dropDatabase' command.
|
|
|
|
|
let dropDatabaseFn = function() {
|
|
|
|
|
const rollbackDb = "oldDatabase";
|
|
|
|
|
var primary = db.getMongo();
|
|
|
|
|
jsTestLog("Dropping database " + rollbackDb + " on primary node " + primary.host);
|
|
|
|
|
var dbToDrop = db.getSiblingDB(rollbackDb);
|
|
|
|
|
assert.commandWorked(dbToDrop.dropDatabase({w: 1}));
|
|
|
|
|
};
|
|
|
|
|
let waitForDropDatabaseToFinish = startParallelShell(dropDatabaseFn, rollbackNode.port);
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Ensure that we've hit the failpoint before moving on.
|
2019-10-01 00:32:17 +00:00
|
|
|
checkLog.contains(rollbackNode,
|
2020-05-26 13:45:40 -04:00
|
|
|
"dropDatabase - fail point dropDatabaseHangBeforeInMemoryDrop enabled");
|
2019-02-01 13:58:27 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Wait for the secondary to finish dropping the collection (the last replicated entry).
|
|
|
|
|
// We use the default 10-minute timeout for this.
|
|
|
|
|
assert.soon(function() {
|
|
|
|
|
let res = syncSourceNode.getDB(oldDbName).getCollectionNames().includes("beforeRollback");
|
|
|
|
|
return !res;
|
|
|
|
|
}, "Sync source did not finish dropping collection beforeRollback", 10 * 60 * 1000);
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
rollbackTest.transitionToRollbackOperations();
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Allow the final 'dropDatabase' entry to be logged on the now isolated primary.
|
|
|
|
|
// This is the rollback node's divergent oplog entry.
|
2019-10-01 00:32:17 +00:00
|
|
|
assert.commandWorked(rollbackNode.adminCommand(
|
|
|
|
|
{configureFailPoint: "dropDatabaseHangBeforeInMemoryDrop", mode: "off"}));
|
2019-07-26 18:20:35 -04:00
|
|
|
waitForDropDatabaseToFinish();
|
|
|
|
|
assert.eq(false, rollbackNode.getDB(oldDbName).getCollectionNames().includes("beforeRollback"));
|
|
|
|
|
jsTestLog("Database " + oldDbName + " successfully dropped on primary node " + rollbackNode.host);
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
// Perform an insert on another database while interfacing with the new primary.
|
|
|
|
|
// This is the sync source's divergent oplog entry.
|
2019-08-14 13:52:59 +00:00
|
|
|
assert.commandWorked(syncSourceNode.getDB(newDbName)["afterRollback"].insert({"num": 2}));
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
rollbackTest.transitionToSyncSourceOperationsDuringRollback();
|
|
|
|
|
rollbackTest.transitionToSteadyStateOperations();
|
2018-01-02 14:42:52 -05:00
|
|
|
|
2019-07-26 18:20:35 -04:00
|
|
|
rollbackTest.stop();
|
2017-11-30 13:48:57 -05:00
|
|
|
})();
|