summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Mulrow <jack.mulrow@mongodb.com>2017-01-09 13:19:53 -0500
committerJack Mulrow <jack.mulrow@mongodb.com>2017-01-23 13:25:30 -0500
commit84ca21e55efe1bdf97380caaa10079b613f00cac (patch)
treec91b618754407c6055a1a81ee1945a1e2ec653e7
parentae04822985f2478c7da1e6821f5fc91b484b9555 (diff)
downloadmongo-84ca21e55efe1bdf97380caaa10079b613f00cac.tar.gz
SERVER-20844 Start ReplSetTests faster wrt initial election
-rw-r--r--jstests/gle/create_index_gle.js2
-rw-r--r--jstests/multiVersion/minor_version_tags_new_old_new.js3
-rw-r--r--jstests/multiVersion/mixed_storage_version_replication.js2
-rw-r--r--jstests/noPassthroughWithMongod/ttl_repl.js2
-rw-r--r--jstests/replsets/double_rollback.js16
-rw-r--r--jstests/replsets/initial_sync1.js2
-rw-r--r--jstests/replsets/initial_sync4.js2
-rw-r--r--jstests/replsets/ismaster1.js23
-rw-r--r--jstests/replsets/last_vote.js20
-rw-r--r--jstests/replsets/read_committed_stale_history.js14
-rw-r--r--jstests/replsets/remove1.js18
-rw-r--r--jstests/replsets/tags2.js9
-rw-r--r--jstests/replsets/tags_with_reconfig.js3
-rw-r--r--jstests/replsets/write_concern_after_stepdown.js13
-rw-r--r--src/mongo/shell/replsettest.js45
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') {