diff options
-rw-r--r-- | jstests/noPassthrough/restart_node_with_bridge.js | 57 | ||||
-rw-r--r-- | jstests/replsets/libs/rollback_test.js | 2 | ||||
-rw-r--r-- | jstests/replsets/libs/rollback_test_deluxe.js | 2 | ||||
-rw-r--r-- | src/mongo/shell/bridge.js | 2 | ||||
-rw-r--r-- | src/mongo/shell/replsettest.js | 24 |
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; |