diff options
author | Judah Schvimer <judah@mongodb.com> | 2018-04-18 17:41:40 -0400 |
---|---|---|
committer | Judah Schvimer <judah@mongodb.com> | 2018-04-19 17:36:44 -0400 |
commit | f39a2374e525e250dc145dfc36091038bb4a4fc0 (patch) | |
tree | e441566f05c6de79f41d303141b17cbf0e5787dc | |
parent | ffc12520c4ffbe816f7068637869bfca8761691c (diff) | |
download | mongo-f39a2374e525e250dc145dfc36091038bb4a4fc0.tar.gz |
SERVER-34529 Rollback via recover to timestamp respects createRollbackDataFiles parameter
-rw-r--r-- | jstests/replsets/rollback_creates_rollback_directory.js | 216 | ||||
-rw-r--r-- | src/mongo/db/repl/rollback_impl.cpp | 14 |
2 files changed, 118 insertions, 112 deletions
diff --git a/jstests/replsets/rollback_creates_rollback_directory.js b/jstests/replsets/rollback_creates_rollback_directory.js index 0de5e21f73e..c0af3044bac 100644 --- a/jstests/replsets/rollback_creates_rollback_directory.js +++ b/jstests/replsets/rollback_creates_rollback_directory.js @@ -8,114 +8,116 @@ // inital sync from, so no primary will be elected. This test induces such a scenario, so cannot be // run on ephemeral storage engines. // @tags: [requires_persistence] -var testName = "rollback_creates_rollback_directory"; -var replTest = new ReplSetTest({name: testName, nodes: 3}); -var nodes = replTest.nodeList(); - -var conns = replTest.startSet(); -var r = replTest.initiate({ - "_id": testName, - "members": [ - {"_id": 0, "host": nodes[0], priority: 3}, - {"_id": 1, "host": nodes[1]}, - {"_id": 2, "host": nodes[2], arbiterOnly: true} - ] -}); - -// Make sure we have a master -replTest.waitForState(replTest.nodes[0], ReplSetTest.State.PRIMARY); -var master = replTest.getPrimary(); -var a_conn = conns[0]; -var b_conn = conns[1]; -a_conn.setSlaveOk(); -b_conn.setSlaveOk(); -var A = a_conn.getDB("test"); -var B = b_conn.getDB("test"); -var AID = replTest.getNodeId(a_conn); -var BID = replTest.getNodeId(b_conn); -var Apath = MongoRunner.dataDir + "/" + testName + "-0/"; -var Bpath = MongoRunner.dataDir + "/" + testName + "-1/"; -assert(master == conns[0], "conns[0] assumed to be master"); -assert(a_conn.host == master.host); - -// Make sure we have an arbiter -assert.soon(function() { - res = conns[2].getDB("admin").runCommand({replSetGetStatus: 1}); - return res.myState == 7; -}, "Arbiter failed to initialize."); - -var options = {writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMS}, upsert: true}; -assert.writeOK(A.foo.update({key: 'value1'}, {$set: {req: 'req'}}, options)); -replTest.stop(AID); - -master = replTest.getPrimary(); -assert(b_conn.host == master.host); -options = { - writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}, - upsert: true -}; -assert.writeOK(B.foo.update({key: 'value1'}, {$set: {res: 'res'}}, options)); -replTest.stop(BID); -replTest.restart(AID); -master = replTest.getPrimary(); -assert(a_conn.host == master.host); -options = { - writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}, - upsert: true -}; -assert.writeOK(A.foo.update({key: 'value2'}, {$set: {req: 'req'}}, options)); -replTest.restart(BID); // should rollback -reconnect(B); - -print("BEFORE------------------"); -printjson(A.foo.find().toArray()); - -replTest.awaitReplication(); -replTest.awaitSecondaryNodes(); - -print("AFTER------------------"); -printjson(A.foo.find().toArray()); - -assert.eq(2, A.foo.find().itcount()); -assert.eq('req', A.foo.findOne({key: 'value1'}).req); -assert.eq(null, A.foo.findOne({key: 'value1'}).res); -reconnect(B); -assert.eq(2, B.foo.find().itcount()); -assert.eq('req', B.foo.findOne({key: 'value1'}).req); -assert.eq(null, B.foo.findOne({key: 'value1'}).res); - -// check here for rollback files -var rollbackDir = Bpath + "rollback/"; -assert(pathExists(rollbackDir), "rollback directory was not created!"); - -// Verify data consistency between nodes. -replTest.checkReplicatedDataHashes(); -replTest.checkOplogs(); - -print(testName + ".js SUCCESS"); -replTest.stopSet(15); - -function wait(f) { - var n = 0; - while (!f()) { - if (n % 4 == 0) - print(testName + ".js waiting"); - if (++n == 4) { - print("" + f); + +function runRollbackDirectoryTest(shouldCreateRollbackFiles) { + jsTestLog("Testing createRollbackDataFiles = " + shouldCreateRollbackFiles); + var testName = "rollback_creates_rollback_directory"; + var replTest = new ReplSetTest({name: testName, nodes: 3}); + var nodes = replTest.nodeList(); + + var conns = + replTest.startSet({setParameter: {createRollbackDataFiles: shouldCreateRollbackFiles}}); + var r = replTest.initiate({ + "_id": testName, + "members": [ + {"_id": 0, "host": nodes[0], priority: 3}, + {"_id": 1, "host": nodes[1]}, + {"_id": 2, "host": nodes[2], arbiterOnly: true} + ], + }); + + // Make sure we have a master + replTest.waitForState(replTest.nodes[0], ReplSetTest.State.PRIMARY); + var master = replTest.getPrimary(); + var a_conn = conns[0]; + var b_conn = conns[1]; + a_conn.setSlaveOk(); + b_conn.setSlaveOk(); + var A = a_conn.getDB("test"); + var B = b_conn.getDB("test"); + var AID = replTest.getNodeId(a_conn); + var BID = replTest.getNodeId(b_conn); + var Apath = MongoRunner.dataDir + "/" + testName + "-0/"; + var Bpath = MongoRunner.dataDir + "/" + testName + "-1/"; + assert(master == conns[0], "conns[0] assumed to be master"); + assert(a_conn.host == master.host); + + // Make sure we have an arbiter + assert.soon(function() { + res = conns[2].getDB("admin").runCommand({replSetGetStatus: 1}); + return res.myState == 7; + }, "Arbiter failed to initialize."); + + var options = {writeConcern: {w: 2, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true}; + assert.writeOK(A.foo.update({key: 'value1'}, {$set: {req: 'req'}}, options)); + replTest.stop(AID); + + master = replTest.getPrimary(); + assert(b_conn.host == master.host); + options = {writeConcern: {w: 1, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true}; + assert.writeOK(B.foo.update({key: 'value1'}, {$set: {res: 'res'}}, options)); + replTest.stop(BID); + replTest.restart(AID); + master = replTest.getPrimary(); + assert(a_conn.host == master.host); + options = {writeConcern: {w: 1, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true}; + assert.writeOK(A.foo.update({key: 'value2'}, {$set: {req: 'req'}}, options)); + replTest.restart(BID); // should rollback + reconnect(B); + + print("BEFORE------------------"); + printjson(A.foo.find().toArray()); + + replTest.awaitReplication(); + replTest.awaitSecondaryNodes(); + + print("AFTER------------------"); + printjson(A.foo.find().toArray()); + + assert.eq(2, A.foo.find().itcount()); + assert.eq('req', A.foo.findOne({key: 'value1'}).req); + assert.eq(null, A.foo.findOne({key: 'value1'}).res); + reconnect(B); + assert.eq(2, B.foo.find().itcount()); + assert.eq('req', B.foo.findOne({key: 'value1'}).req); + assert.eq(null, B.foo.findOne({key: 'value1'}).res); + + // check here for rollback files + var rollbackDir = Bpath + "rollback/"; + assert.eq(pathExists(rollbackDir), shouldCreateRollbackFiles); + + // Verify data consistency between nodes. + replTest.checkReplicatedDataHashes(); + replTest.checkOplogs(); + + print(testName + ".js SUCCESS"); + replTest.stopSet(15); + + function wait(f) { + var n = 0; + while (!f()) { + if (n % 4 == 0) + print(testName + ".js waiting"); + if (++n == 4) { + print("" + f); + } + assert(n < 200, 'tried 200 times, giving up'); + sleep(1000); } - assert(n < 200, 'tried 200 times, giving up'); - sleep(1000); } -} -function reconnect(a) { - wait(function() { - try { - a.bar.stats(); - return true; - } catch (e) { - print(e); - return false; - } - }); + function reconnect(a) { + wait(function() { + try { + a.bar.stats(); + return true; + } catch (e) { + print(e); + return false; + } + }); + } } + +runRollbackDirectoryTest(false); +runRollbackDirectoryTest(true); diff --git a/src/mongo/db/repl/rollback_impl.cpp b/src/mongo/db/repl/rollback_impl.cpp index db5eb8f209e..530e740c38f 100644 --- a/src/mongo/db/repl/rollback_impl.cpp +++ b/src/mongo/db/repl/rollback_impl.cpp @@ -176,11 +176,15 @@ Status RollbackImpl::runRollback(OperationContext* opCtx) { } _rollbackStats.rollbackId = _replicationProcess->getRollbackID(); - // Write a rollback file for each namespace that has documents that would be deleted by - // rollback. - status = _writeRollbackFiles(opCtx); - if (!status.isOK()) { - return status; + if (shouldCreateDataFiles()) { + // Write a rollback file for each namespace that has documents that would be deleted by + // rollback. + status = _writeRollbackFiles(opCtx); + if (!status.isOK()) { + return status; + } + } else { + log() << "Not writing rollback files. 'createRollbackDataFiles' set to false."; } // Recover to the stable timestamp. |