summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2019-02-11 18:52:28 -0500
committerMax Hirschhorn <max.hirschhorn@mongodb.com>2019-02-11 18:52:28 -0500
commite4f593b3dee7808d27c9db54c517ab198f5d9f89 (patch)
tree2f2a20a2008bed44a29aa3bb227def0d25ade0b9
parent8a02cc431f30168a80b22f109f6430761858734d (diff)
downloadmongo-e4f593b3dee7808d27c9db54c517ab198f5d9f89.tar.gz
SERVER-35551 Avoid restarting mongobridge processes.
Changes ReplSetTest, RollbackTest, and RollbackTestDeluxe to avoid restarting the mongobridge process associated with the mongod process being restarted. This ensures that any partitioning which has been configured remains intact after the server is restarted.
-rw-r--r--jstests/noPassthrough/restart_node_with_bridge.js57
-rw-r--r--jstests/replsets/libs/rollback_test.js2
-rw-r--r--jstests/replsets/libs/rollback_test_deluxe.js2
-rw-r--r--src/mongo/shell/bridge.js2
-rw-r--r--src/mongo/shell/replsettest.js24
5 files changed, 71 insertions, 16 deletions
diff --git a/jstests/noPassthrough/restart_node_with_bridge.js b/jstests/noPassthrough/restart_node_with_bridge.js
index 1774ce50167..004b595a208 100644
--- a/jstests/noPassthrough/restart_node_with_bridge.js
+++ b/jstests/noPassthrough/restart_node_with_bridge.js
@@ -1,23 +1,64 @@
/**
- * Tests that a node can be successfully restarted when the bridge is enabled.
+ * Tests that a node can be successfully restarted when the bridge is enabled. Also verifies the
+ * bridge configuration is left intact even after the node is restarted.
+ *
* @tags: [requires_persistence, requires_replication]
*/
(function() {
"use strict";
- const name = "restart_node_with_bridge";
- const rst = new ReplSetTest({name: name, nodes: 1, useBridge: true});
+ load("jstests/replsets/rslib.js"); // for reconnect
+
+ const rst = new ReplSetTest({
+ nodes: [{}, {rsConfig: {priority: 0, votes: 0}}],
+ useBridge: true,
+ });
+
rst.startSet();
rst.initiate();
rst.awaitNodesAgreeOnPrimary();
- let primary = rst.getPrimary();
- assert.commandWorked(primary.getDB("test").getCollection(name).insert({_id: 1}));
+ const primary = rst.getPrimary();
+ const secondary = rst.getSecondary();
+
+ const primaryDB = primary.getDB("test");
+ const primaryColl = primaryDB.getCollection("restart_node_with_bridge");
+
+ function assertWriteReplicates() {
+ assert.commandWorked(primaryColl.update(
+ {_id: 0}, {$inc: {counter: 1}}, {upsert: true, writeConcern: {w: 2}}));
+ }
+
+ function assertWriteFailsToReplicate() {
+ assert.commandFailedWithCode(
+ primaryColl.update(
+ {_id: 0}, {$inc: {counter: 1}}, {writeConcern: {w: 2, wtimeout: 1000}}),
+ ErrorCodes.WriteConcernFailed);
+ }
+ // By default, the primary should be connected to the secondary. Replicating a write should
+ // therefore succeed.
+ assertWriteReplicates();
+
+ // We disconnect the primary from the secondary and verify that replicating a write fails.
+ primary.disconnect(secondary);
+ assertWriteFailsToReplicate();
+
+ // We restart the secondary and verify that replicating a write still fails.
+ rst.restart(secondary);
+ assertWriteFailsToReplicate();
+
+ // We restart the primary and verify that replicating a write still fails.
rst.restart(primary);
- rst.awaitNodesAgreeOnPrimary();
- primary = rst.getPrimary();
- assert.eq(primary.getDB("test").getCollection(name).count({_id: 1}), 1);
+ rst.getPrimary();
+ // Note that we specify 'primaryDB' to avoid having reconnect() send a message directly to the
+ // mongod process rather than going through the mongobridge process as well.
+ reconnect(primaryDB);
+ assertWriteFailsToReplicate();
+
+ // We reconnect the primary to the secondary and verify that replicating a write succeeds.
+ primary.reconnect(secondary);
+ assertWriteReplicates();
rst.stopSet();
}());
diff --git a/jstests/replsets/libs/rollback_test.js b/jstests/replsets/libs/rollback_test.js
index 41717a664cd..a7db988e0e7 100644
--- a/jstests/replsets/libs/rollback_test.js
+++ b/jstests/replsets/libs/rollback_test.js
@@ -396,7 +396,7 @@ function RollbackTest(name = "RollbackTest", replSet) {
}
log(`Stopping node ${hostName} with signal ${signal}`);
- rst.stop(nodeId, signal, opts);
+ rst.stop(nodeId, signal, opts, {forRestart: true});
log(`Restarting node ${hostName}`);
rst.start(nodeId, {}, true /* restart */);
diff --git a/jstests/replsets/libs/rollback_test_deluxe.js b/jstests/replsets/libs/rollback_test_deluxe.js
index 0c4cb988dfc..b3b85de152d 100644
--- a/jstests/replsets/libs/rollback_test_deluxe.js
+++ b/jstests/replsets/libs/rollback_test_deluxe.js
@@ -572,7 +572,7 @@ function RollbackTestDeluxe(name = "FiveNodeDoubleRollbackTest", replSet) {
}
log(`Stopping node ${hostName} with signal ${signal}`);
- rst.stop(nodeId, signal, opts);
+ rst.stop(nodeId, signal, opts, {forRestart: true});
log(`Restarting node ${hostName}`);
const restart = true;
diff --git a/src/mongo/shell/bridge.js b/src/mongo/shell/bridge.js
index 28831ba7a76..e50f9f12c86 100644
--- a/src/mongo/shell/bridge.js
+++ b/src/mongo/shell/bridge.js
@@ -113,7 +113,7 @@ function MongoBridge(options) {
* Terminates the mongobridge process.
*/
this.stop = function stop() {
- _stopMongoProgram(this.port);
+ return _stopMongoProgram(this.port);
};
// Throws an error if 'obj' is not a MongoBridge instance.
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index 9efa8ac7f2e..06d72bc54f7 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -2311,7 +2311,9 @@ var ReplSetTest = function(opts) {
print("ReplSetTest " + (restart ? "(Re)" : "") + "Starting....");
- if (_useBridge) {
+ if (_useBridge && (restart === undefined || !restart)) {
+ // We leave the mongobridge process running when the mongod process is restarted so we
+ // don't need to start a new one.
var bridgeOptions = Object.merge(_bridgeOptions, options.bridgeOptions || {});
bridgeOptions = Object.merge(bridgeOptions, {
hostName: this.host,
@@ -2395,7 +2397,7 @@ var ReplSetTest = function(opts) {
signal = undefined;
}
- this.stop(n, signal, options);
+ this.stop(n, signal, options, {forRestart: true});
var started = this.start(n, options, true, wait);
@@ -2421,11 +2423,18 @@ var ReplSetTest = function(opts) {
/**
* Stops a particular node or nodes, specified by conn or id
*
+ * If _useBridge=true, then the mongobridge process(es) corresponding to the node(s) are also
+ * terminated unless forRestart=true. The mongobridge process(es) are left running across
+ * restarts to ensure their configuration remains intact.
+ *
* @param {number|Mongo} n the index or connection object of the replica set member to stop.
* @param {number} signal the signal number to use for killing
* @param {Object} opts @see MongoRunner.stopMongod
+ * @param {Object} [extraOptions={}]
+ * @param {boolean} [extraOptions.forRestart=false] indicates whether stop() is being called
+ * with the intent to call start() with restart=true for the same node(s) n.
*/
- this.stop = function(n, signal, opts) {
+ this.stop = function(n, signal, opts, {forRestart: forRestart = false} = {}) {
// Flatten array of nodes to stop
if (n.length) {
var nodes = n;
@@ -2453,8 +2462,13 @@ var ReplSetTest = function(opts) {
print('ReplSetTest stop *** Mongod in port ' + conn.port + ' shutdown with code (' + ret +
') ***');
- if (_useBridge) {
- this.nodes[n].stop();
+ if (_useBridge && !forRestart) {
+ // We leave the mongobridge process running when the mongod process is being restarted.
+ const bridge = this.nodes[n];
+ print('ReplSetTest stop *** Shutting down mongobridge on port ' + bridge.port + ' ***');
+ const exitCode = bridge.stop(); // calls MongoBridge#stop()
+ print('ReplSetTest stop *** mongobridge on port ' + bridge.port +
+ ' exited with code (' + exitCode + ') ***');
}
return ret;