diff options
author | Jack Mulrow <jack.mulrow@mongodb.com> | 2017-01-09 13:19:53 -0500 |
---|---|---|
committer | Jack Mulrow <jack.mulrow@mongodb.com> | 2017-01-23 13:25:30 -0500 |
commit | 84ca21e55efe1bdf97380caaa10079b613f00cac (patch) | |
tree | c91b618754407c6055a1a81ee1945a1e2ec653e7 | |
parent | ae04822985f2478c7da1e6821f5fc91b484b9555 (diff) | |
download | mongo-84ca21e55efe1bdf97380caaa10079b613f00cac.tar.gz |
SERVER-20844 Start ReplSetTests faster wrt initial election
-rw-r--r-- | jstests/gle/create_index_gle.js | 2 | ||||
-rw-r--r-- | jstests/multiVersion/minor_version_tags_new_old_new.js | 3 | ||||
-rw-r--r-- | jstests/multiVersion/mixed_storage_version_replication.js | 2 | ||||
-rw-r--r-- | jstests/noPassthroughWithMongod/ttl_repl.js | 2 | ||||
-rw-r--r-- | jstests/replsets/double_rollback.js | 16 | ||||
-rw-r--r-- | jstests/replsets/initial_sync1.js | 2 | ||||
-rw-r--r-- | jstests/replsets/initial_sync4.js | 2 | ||||
-rw-r--r-- | jstests/replsets/ismaster1.js | 23 | ||||
-rw-r--r-- | jstests/replsets/last_vote.js | 20 | ||||
-rw-r--r-- | jstests/replsets/read_committed_stale_history.js | 14 | ||||
-rw-r--r-- | jstests/replsets/remove1.js | 18 | ||||
-rw-r--r-- | jstests/replsets/tags2.js | 9 | ||||
-rw-r--r-- | jstests/replsets/tags_with_reconfig.js | 3 | ||||
-rw-r--r-- | jstests/replsets/write_concern_after_stepdown.js | 13 | ||||
-rw-r--r-- | src/mongo/shell/replsettest.js | 45 |
15 files changed, 99 insertions, 75 deletions
diff --git a/jstests/gle/create_index_gle.js b/jstests/gle/create_index_gle.js index 2a93521ba57..e9db4846fdd 100644 --- a/jstests/gle/create_index_gle.js +++ b/jstests/gle/create_index_gle.js @@ -16,7 +16,7 @@ load('jstests/replsets/rslib.js'); var config = replTest.getReplSetConfig(); // Add a delay long enough so getLastError would actually 'wait' for write concern. config.members[1].slaveDelay = 3; - config.version = 2; + config.version = replTest.getReplSetConfigFromNode().version + 1; reconfig(replTest, config, true); diff --git a/jstests/multiVersion/minor_version_tags_new_old_new.js b/jstests/multiVersion/minor_version_tags_new_old_new.js index 9420211b4da..0779c4911aa 100644 --- a/jstests/multiVersion/minor_version_tags_new_old_new.js +++ b/jstests/multiVersion/minor_version_tags_new_old_new.js @@ -27,6 +27,7 @@ const conns = replTest.nodes; nodes = replTest.nodeList(); var port = replTest.ports; + var nextVersion = replTest.getReplSetConfigFromNode().version + 1; const replSetConfig = { _id: name, members: [ @@ -104,7 +105,7 @@ }, }, }, - version: 2, + version: nextVersion, }; reconfig(replTest, replSetConfig); diff --git a/jstests/multiVersion/mixed_storage_version_replication.js b/jstests/multiVersion/mixed_storage_version_replication.js index 94ccf174bb5..332d23442d3 100644 --- a/jstests/multiVersion/mixed_storage_version_replication.js +++ b/jstests/multiVersion/mixed_storage_version_replication.js @@ -682,7 +682,7 @@ function doMultiThreadedWork(primary, numThreads) { // primary/secondary syncing. config.settings = {chainingAllowed: false}; config.protocolVersion = 0; - config.version = 2; + config.version = replTest.getReplSetConfigFromNode().version + 1; reconfig(replTest, config); // Ensure all are synced. diff --git a/jstests/noPassthroughWithMongod/ttl_repl.js b/jstests/noPassthroughWithMongod/ttl_repl.js index 794f0c3ad90..79892cb93b1 100644 --- a/jstests/noPassthroughWithMongod/ttl_repl.js +++ b/jstests/noPassthroughWithMongod/ttl_repl.js @@ -66,7 +66,7 @@ assert.eq(6, slave1col.count(), "docs not deleted on secondary"); // add a new secondary, wait for it to fully join var slave = rt.add(); var config = rt.getReplSetConfig(); -config.version = 2; +config.version = rt.getReplSetConfigFromNode().version + 1; reconfig(rt, config); var slave2col = slave.getDB('d')['c']; diff --git a/jstests/replsets/double_rollback.js b/jstests/replsets/double_rollback.js index 342775c2545..03e787343e5 100644 --- a/jstests/replsets/double_rollback.js +++ b/jstests/replsets/double_rollback.js @@ -34,21 +34,9 @@ var nodes = rst.startSet(); rst.initiate(); - function stepUp(rst, node) { - var primary = rst.getPrimary(); - if (primary != node) { - try { - assert.commandWorked(primary.adminCommand({replSetStepDown: 1, force: true})); - } catch (ex) { - print("Caught exception while stepping down from node '" + tojson(node.host) + - "': " + tojson(ex)); - } - } - waitForState(node, ReplSetTest.State.PRIMARY); - } - + // SERVER-20844 ReplSetTest starts up a single node replica set then reconfigures to the correct + // size for faster startup, so nodes[0] is always the first primary. jsTestLog("Make sure node 0 is primary."); - stepUp(rst, nodes[0]); assert.eq(nodes[0], rst.getPrimary()); // Wait for all data bearing nodes to get up to date. assert.writeOK(nodes[0].getDB(dbName).getCollection(collName).insert( diff --git a/jstests/replsets/initial_sync1.js b/jstests/replsets/initial_sync1.js index 3087793dcd1..cf876a7f1b2 100644 --- a/jstests/replsets/initial_sync1.js +++ b/jstests/replsets/initial_sync1.js @@ -57,7 +57,7 @@ var local_s2 = slave2.getDB("local"); var admin_s2 = slave2.getDB("admin"); var config = replTest.getReplSetConfig(); -config.version = 2; +config.version = replTest.getReplSetConfigFromNode().version + 1; config.members.push({_id: 2, host: slave2.host}); try { admin.runCommand({replSetReconfig: config}); diff --git a/jstests/replsets/initial_sync4.js b/jstests/replsets/initial_sync4.js index 71550251b96..d7f2ec01697 100644 --- a/jstests/replsets/initial_sync4.js +++ b/jstests/replsets/initial_sync4.js @@ -30,7 +30,7 @@ hostname = getHostName(); s = MongoRunner.runMongod({replSet: basename, oplogSize: 2}); var config = replTest.getReplSetConfig(); -config.version = 2; +config.version = replTest.getReplSetConfigFromNode().version + 1; config.members.push({_id: 2, host: hostname + ":" + s.port}); try { m.getDB("admin").runCommand({replSetReconfig: config}); diff --git a/jstests/replsets/ismaster1.js b/jstests/replsets/ismaster1.js index 2d469f385a2..96de229832a 100644 --- a/jstests/replsets/ismaster1.js +++ b/jstests/replsets/ismaster1.js @@ -119,8 +119,9 @@ var agreeOnPrimaryAndSetVersion = function(setVersion) { }; var master = replTest.getPrimary(); +var expectedVersion = replTest.getReplSetConfigFromNode().version; assert.soon(function() { - return agreeOnPrimaryAndSetVersion(1); + return agreeOnPrimaryAndSetVersion(expectedVersion); }, "Nodes did not initiate in less than a minute", 60000); // check to see if the information from isMaster() is correct at each node @@ -128,7 +129,8 @@ assert.soon(function() { checkMember({ conn: master, name: "master", - goodValues: {setName: "ismaster", setVersion: 1, ismaster: true, secondary: false, ok: 1}, + goodValues: + {setName: "ismaster", setVersion: expectedVersion, ismaster: true, secondary: false, ok: 1}, wantedFields: ["hosts", "passives", "arbiters", "primary", "me", "maxBsonObjectSize", "localTime"], unwantedFields: ["arbiterOnly", "passive", "slaveDelay", "hidden", "tags", "buildIndexes"] @@ -139,7 +141,7 @@ checkMember({ name: "slave", goodValues: { setName: "ismaster", - setVersion: 1, + setVersion: expectedVersion, ismaster: false, secondary: true, passive: true, @@ -155,7 +157,7 @@ checkMember({ name: "delayed_slave", goodValues: { setName: "ismaster", - setVersion: 1, + setVersion: expectedVersion, ismaster: false, secondary: true, passive: true, @@ -173,7 +175,7 @@ checkMember({ name: "arbiter", goodValues: { setName: "ismaster", - setVersion: 1, + setVersion: expectedVersion, ismaster: false, secondary: false, arbiterOnly: true, @@ -205,8 +207,9 @@ try { } master = replTest.getPrimary(); +expectedVersion = config.version; assert.soon(function() { - return agreeOnPrimaryAndSetVersion(2); + return agreeOnPrimaryAndSetVersion(expectedVersion); }, "Nodes did not sync in less than a minute", 60000); // check nodes for their new settings @@ -215,7 +218,7 @@ checkMember({ name: "master2", goodValues: { setName: "ismaster", - setVersion: 2, + setVersion: expectedVersion, ismaster: true, secondary: false, tags: {"disk": "ssd"}, @@ -231,7 +234,7 @@ checkMember({ name: "first_slave", goodValues: { setName: "ismaster", - setVersion: 2, + setVersion: expectedVersion, ismaster: false, secondary: true, tags: {"disk": "ssd"}, @@ -248,7 +251,7 @@ checkMember({ name: "very_delayed_slave", goodValues: { setName: "ismaster", - setVersion: 2, + setVersion: expectedVersion, ismaster: false, secondary: true, tags: {"disk": "hdd"}, @@ -267,7 +270,7 @@ checkMember({ name: "arbiter", goodValues: { setName: "ismaster", - setVersion: 2, + setVersion: expectedVersion, ismaster: false, secondary: false, arbiterOnly: true, diff --git a/jstests/replsets/last_vote.js b/jstests/replsets/last_vote.js index 6e8de65f4fc..f087330846e 100644 --- a/jstests/replsets/last_vote.js +++ b/jstests/replsets/last_vote.js @@ -61,9 +61,13 @@ var term = getLatestOp(primary).t; jsTestLog("Last vote should have term: " + term + " and candidate: " + primary.host + ", index: " + rst.getNodeId(primary)); - rst.nodes.forEach(function(node) { - assertNodeHasLastVote(node, term, primary); - }); + // SERVER-20844 ReplSetTest starts up a single node replica set then reconfigures to the + // correct size, so secondaries didn't vote in the first election. + if (i > 0) { + rst.nodes.forEach(function(node) { + assertNodeHasLastVote(node, term, primary); + }); + } assert.throws(function() { primary.adminCommand({replSetStepDown: 5, force: true}); }); @@ -109,7 +113,7 @@ dryRun: true, term: term - 1, candidateIndex: 1, - configVersion: 2, + configVersion: conf.version, lastCommittedOp: getLatestOp(node0) })); assert.eq(response.term, @@ -131,7 +135,7 @@ dryRun: true, term: term, candidateIndex: 1, - configVersion: 2, + configVersion: conf.version, lastCommittedOp: getLatestOp(node0) })); assert.eq(response.term, @@ -153,7 +157,7 @@ dryRun: false, term: term, candidateIndex: 1, - configVersion: 2, + configVersion: conf.version, lastCommittedOp: getLatestOp(node0) })); assert.eq(response.term, @@ -175,7 +179,7 @@ dryRun: false, term: term + 1, candidateIndex: 1, - configVersion: 2, + configVersion: conf.version, lastCommittedOp: getLatestOp(node0) })); assert.eq(response.term, @@ -197,7 +201,7 @@ dryRun: true, term: term + 2, candidateIndex: 1, - configVersion: 2, + configVersion: conf.version, lastCommittedOp: getLatestOp(node0) })); assert.eq(response.term, diff --git a/jstests/replsets/read_committed_stale_history.js b/jstests/replsets/read_committed_stale_history.js index 5751ba9cf28..a7dac2006dc 100644 --- a/jstests/replsets/read_committed_stale_history.js +++ b/jstests/replsets/read_committed_stale_history.js @@ -42,16 +42,6 @@ }); } - function stepUp(node) { - var primary = rst.getPrimary(); - if (primary != node) { - assert.throws(function() { - primary.adminCommand({replSetStepDown: 60 * 5}); - }); - } - waitForPrimary(node); - } - // Asserts that the given document is not visible in the committed snapshot on the given node. function checkDocNotCommitted(node, doc) { var docs = @@ -59,9 +49,9 @@ assert.eq(0, docs.length, tojson(docs)); } + // SERVER-20844 ReplSetTest starts up a single node replica set then reconfigures to the correct + // size for faster startup, so nodes[0] is always the first primary. jsTestLog("Make sure node 0 is primary."); - rst.getPrimary(); - stepUp(nodes[0]); var primary = rst.getPrimary(); var secondaries = rst.getSecondaries(); assert.eq(nodes[0], primary); diff --git a/jstests/replsets/remove1.js b/jstests/replsets/remove1.js index f587275570a..62977c517d6 100644 --- a/jstests/replsets/remove1.js +++ b/jstests/replsets/remove1.js @@ -32,7 +32,8 @@ for (var i = 0; i < config.members.length; i++) { break; } } -config.version = 2; +var nextVersion = replTest.getReplSetConfigFromNode().version + 1; +config.version = nextVersion; assert.eq(secondary.getDB("admin").runCommand({ping: 1}).ok, 1, @@ -62,12 +63,13 @@ reconnect(master); assert.soon(function() { var c = master.getDB("local").system.replset.findOne(); - return c.version == 2; + return c.version == nextVersion; }); print("Add it back as a secondary"); config.members.push({_id: 2, host: secondary.host}); -config.version = 3; +nextVersion++; +config.version = nextVersion; // Need to keep retrying reconfig here, as it will not work at first due to the primary's // perception that the secondary is still "down". assert.soon(function() { @@ -79,10 +81,11 @@ assert.soon(function() { } }); master = replTest.getPrimary(); +secondary = replTest.getSecondary(); printjson(master.getDB("admin").runCommand({replSetGetStatus: 1})); var newConfig = master.getDB("local").system.replset.findOne(); print("newConfig: " + tojson(newConfig)); -assert.eq(newConfig.version, 3); +assert.eq(newConfig.version, nextVersion); print("reconfig with minority"); replTest.stop(secondary); @@ -95,8 +98,9 @@ assert.soon(function() { } }, "waiting for primary to step down", (60 * 1000), 1000); -config.version = 4; -config.members.pop(); +nextVersion++; +config.version = nextVersion; +config.members = config.members.filter(node => node.host == master.host); try { master.getDB("admin").runCommand({replSetReconfig: config, force: true}); } catch (e) { @@ -110,6 +114,6 @@ assert.soon(function() { config = master.getDB("local").system.replset.findOne(); printjson(config); -assert.gt(config.version, 4); +assert.gt(config.version, nextVersion); replTest.stopSet(); diff --git a/jstests/replsets/tags2.js b/jstests/replsets/tags2.js index ec07a8b4c37..15996fc6468 100644 --- a/jstests/replsets/tags2.js +++ b/jstests/replsets/tags2.js @@ -9,7 +9,6 @@ var ports = replTest.ports; var conf = { _id: replTest.name, - version: 1, members: [ {_id: 0, host: host + ":" + ports[0], tags: {"backup": "A"}}, {_id: 1, host: host + ":" + ports[1], tags: {"backup": "B"}}, @@ -37,7 +36,8 @@ assert.writeOK(db.foo.insert({x: 1}, {writeConcern: {w: 'backedUp', wtimeout: wtimeout}})); - conf.version = 2; + var nextVersion = replTest.getReplSetConfigFromNode().version + 1; + conf.version = nextVersion; conf.settings.getLastErrorModes.backedUp.backup = 3; master.getDB("admin").runCommand({replSetReconfig: conf}); replTest.awaitReplication(); @@ -46,7 +46,8 @@ var db = master.getDB("test"); assert.writeOK(db.foo.insert({x: 2}, {writeConcern: {w: 'backedUp', wtimeout: wtimeout}})); - conf.version = 3; + nextVersion++; + conf.version = nextVersion; conf.members[0].priorty = 3; conf.members[2].priorty = 0; master.getDB("admin").runCommand({replSetReconfig: conf}); @@ -56,4 +57,4 @@ assert.writeOK(db.foo.insert({x: 3}, {writeConcern: {w: 'backedUp', wtimeout: wtimeout}})); replTest.stopSet(); -}());
\ No newline at end of file +}()); diff --git a/jstests/replsets/tags_with_reconfig.js b/jstests/replsets/tags_with_reconfig.js index 73e87755ec5..60b04f3cf08 100644 --- a/jstests/replsets/tags_with_reconfig.js +++ b/jstests/replsets/tags_with_reconfig.js @@ -15,7 +15,6 @@ // Set tags and getLastErrorModes var conf = { _id: replTest.name, - version: 1, members: [ {_id: 0, host: host + ":" + ports[0], tags: {"dc": "bbb"}}, {_id: 1, host: host + ":" + ports[1], tags: {"dc": "bbb"}}, @@ -71,4 +70,4 @@ assert.writeOK(db.foo.insert({x: 4}, {writeConcern: {w: 'alldc', wtimeout: wtimeout}})); replTest.stopSet(); -}());
\ No newline at end of file +}()); diff --git a/jstests/replsets/write_concern_after_stepdown.js b/jstests/replsets/write_concern_after_stepdown.js index 95a08a005e0..de843994f1c 100644 --- a/jstests/replsets/write_concern_after_stepdown.js +++ b/jstests/replsets/write_concern_after_stepdown.js @@ -30,18 +30,9 @@ }); } - function stepUp(node) { - var primary = rst.getPrimary(); - if (primary != node) { - assert.throws(function() { - primary.adminCommand({replSetStepDown: 60 * 5}); - }); - } - waitForPrimary(node); - } - + // SERVER-20844 ReplSetTest starts up a single node replica set then reconfigures to the correct + // size for faster startup, so nodes[0] is always the first primary. jsTestLog("Make sure node 0 is primary."); - stepUp(nodes[0]); var primary = rst.getPrimary(); var secondaries = rst.getSecondaries(); assert.eq(nodes[0], primary); diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index 871f3b5b00f..9a2c16d5c4a 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -360,6 +360,13 @@ var ReplSetTest = function(opts) { return ts1.getTime() < ts2.getTime(); } + /* + * Returns true if the node can be elected primary of a replica set. + */ + function _isElectable(node) { + return !node.arbiterOnly && (node.priority === undefined || node.priority != 0); + } + /** * Returns list of nodes as host:port strings. */ @@ -697,13 +704,49 @@ var ReplSetTest = function(opts) { var cmdKey = initCmd || 'replSetInitiate'; timeout = timeout || self.kDefaultTimeoutMS; + // Throw an exception if nodes[0] is unelectable in the given config. + if (!_isElectable(config.members[0])) { + throw Error("The node at index 0 must be electable"); + } + + // Start up a single node replica set then reconfigure to the correct size (if the config + // contains more than 1 node), so the primary is elected more quickly. + var originalMembers, originalSettings; + if (config.members && config.members.length > 1) { + originalMembers = config.members.slice(); + config.members = config.members.slice(0, 1); + originalSettings = config.settings; + delete config.settings; // Clear settings to avoid tags referencing sliced nodes. + } this._setDefaultConfigOptions(config); cmd[cmdKey] = config; printjson(cmd); assert.commandWorked(master.runCommand(cmd), tojson(cmd)); - this.awaitSecondaryNodes(timeout); + this.getPrimary(); // Blocks until there is a primary. + + // Reconfigure the set to contain the correct number of nodes (if necessary). + if (originalMembers) { + config.members = originalMembers; + if (originalSettings) { + config.settings = originalSettings; + } + config.version = 2; + + // Nodes started with the --configsvr flag must have configsvr = true in their config. + if (this.nodes[0].hasOwnProperty("fullOptions") && + this.nodes[0].fullOptions.hasOwnProperty("configsvr")) { + config.configsvr = true; + } + + cmd = {replSetReconfig: config}; + print("Reconfiguring replica set to add in other nodes"); + printjson(cmd); + + assert.commandWorked(master.runCommand(cmd), tojson(cmd)); + this.awaitSecondaryNodes(timeout); + } // Setup authentication if running test with authentication if ((jsTestOptions().keyFile) && cmdKey == 'replSetInitiate') { |