1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// Test to ensure that catchup takeover runs even if it isn't the highest
// priority node and that once the high priority node is caught up,
// it becomes primary again.
// 3-node replica set with one high priority node.
// Start replica set. Make node 0 primary and stop the replication
// for the high priority node as well as isolate it. Have the
// primary write something so node 2 is more than 2 seconds behind.
// Write something else to ensure the third node is also lagged.
// Reconnect the high priority node to the other nodes and make
// the lagged node (node 1) the next primary.
// Confirm that the most up-to-date node becomes primary.
// Let the highest priority node catchup and then confirm
// that it becomes primary.
(function() {
'use strict';
load('jstests/replsets/rslib.js');
var name = 'catchup_takeover_one_high_priority';
var replSet = new ReplSetTest({name: name, nodes: 3, useBridge: true});
var nodenames = replSet.nodeList();
var nodes = replSet.startSet();
replSet.initiateWithAnyNodeAsPrimary({
"_id": name,
"members": [
{"_id": 0, "host": nodenames[0]},
{"_id": 1, "host": nodenames[1]},
{"_id": 2, "host": nodenames[2], "priority": 2}
]
});
// Wait until node 2 becomes primary.
replSet.waitForState(2, ReplSetTest.State.PRIMARY, replSet.kDefaultTimeoutMS);
jsTestLog('node 2 is now primary');
// The default WC is majority and this test can't test catchup properly if it used majority writes.
assert.commandWorked(replSet.getPrimary().adminCommand(
{setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}}));
replSet.awaitReplication();
replSet.waitForConfigReplication(nodes[2]);
// Stop replication and disconnect node 2 so that it cannot do a priority takeover.
stopServerReplication(nodes[2]);
nodes[2].disconnect(nodes[1]);
nodes[2].disconnect(nodes[0]);
// Ensure that node 0 becomes primary.
assert.commandWorked(nodes[0].adminCommand({replSetStepUp: 1}));
replSet.awaitNodesAgreeOnPrimary(replSet.kDefaultTimeoutMS, nodes.slice(0, 2));
assert.eq(ReplSetTest.State.PRIMARY,
assert.commandWorked(nodes[0].adminCommand('replSetGetStatus')).myState,
nodes[0].host + " was not primary after step-up");
jsTestLog('node 0 is now primary');
// Sleep for a few seconds to ensure that node 2's optime is more than 2 seconds behind.
// This will ensure it can't do a priority takeover until it catches up.
sleep(3000);
var primary = replSet.getPrimary();
var writeConcern = {writeConcern: {w: 2, wtimeout: replSet.kDefaultTimeoutMS}};
assert.commandWorked(primary.getDB(name).bar.insert({y: 100}, writeConcern));
// Write something so that node 0 is ahead of node 1.
stopServerReplication(nodes[1]);
writeConcern = {
writeConcern: {w: 1, wtimeout: replSet.kDefaultTimeoutMS}
};
assert.commandWorked(primary.getDB(name).bar.insert({x: 100}, writeConcern));
nodes[2].reconnect(nodes[0]);
nodes[2].reconnect(nodes[1]);
// Wait until nodes have learned the latest config.
replSet.waitForConfigReplication(nodes[1], [nodes[1], nodes[2]]);
// Step up a lagged node.
assert.commandWorked(nodes[1].adminCommand({replSetStepUp: 1}));
replSet.awaitNodesAgreeOnPrimary(replSet.kDefaultTimeoutMS, nodes);
assert.eq(ReplSetTest.State.PRIMARY,
assert.commandWorked(nodes[1].adminCommand('replSetGetStatus')).myState,
nodes[1].host + " was not primary after step-up");
jsTestLog('node 1 is now primary, but cannot accept writes');
// Confirm that the most up-to-date node becomes primary
// after the default catchup delay.
replSet.waitForState(0, ReplSetTest.State.PRIMARY, replSet.kDefaultTimeoutMS);
jsTestLog('node 0 performed catchup takeover and is now primary');
// Wait until the old primary steps down.
replSet.awaitNodesAgreeOnPrimary();
// Let the nodes catchup.
restartServerReplication(nodes[1]);
restartServerReplication(nodes[2]);
replSet.awaitReplication();
// Confirm that the highest priority node becomes primary
// after catching up.
replSet.waitForState(2, ReplSetTest.State.PRIMARY, replSet.kDefaultTimeoutMS);
jsTestLog('node 2 performed priority takeover and is now primary');
// Wait until the old primary steps down so the connections won't be closed during stopSet().
replSet.waitForState(0, ReplSetTest.State.SECONDARY, replSet.kDefaultTimeoutMS);
replSet.stopSet();
})();
|