summaryrefslogtreecommitdiff
path: root/jstests/replsets/election_id.js
blob: 917be72d561b77a5172c18beb20513d51f8ca48c (plain)
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
load("jstests/replsets/rslib.js");

// Test SERVER-21744 Clients may fail to discover new primaries when clock skew
// between nodes is greater than electionTimeout.
//
// In PV0, the election ID is generated based on Timestamp. On protocol version upgrade,
// the current primary updates its election ID to <max Timestamp, term> which is greater than
// any PV0 election id. On downgrade, the election id will be updated to old PV0 format.
(function() {

"use strict";

function checkPV1ElectionId(electionId) {
  var electionIdStr = electionId.valueOf();
  assert.eq(electionIdStr.slice(0, 8), "7fffffff");
  var res = assert.commandWorked(rst.getPrimary().adminCommand({replSetGetStatus: 1}));
  var termStr = "" + res.term;
  assert.eq(electionIdStr.slice(-termStr.length), termStr);
}

var name = "election_id";
var rst = new ReplSetTest({name: name, nodes: 3});

rst.startSet();
// Initiate the replset in protocol version 0.
var conf = rst.getReplSetConfig();
conf.protocolVersion = 0;
rst.initiate(conf);
rst.awaitSecondaryNodes();

var primary = rst.getPrimary();
var primaryColl = primary.getDB("test").coll;

// Do a write, this will set up sync sources on secondaries.
assert.writeOK(primaryColl.insert({x: 1}, {writeConcern: {w: 3}}));

var res = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
var oldElectionId = res.repl.electionId;

// Upgrade protocol version
//
conf = rst.getReplSetConfigFromNode();
conf.protocolVersion = 1;
conf.version++;
reconfig(rst, conf);
// This write will block until all nodes finish upgrade.
assert.writeOK(primaryColl.insert({x: 2}, {writeConcern: {w: 3}}));

// Check election id after upgrade
res = assert.commandWorked(rst.getPrimary().adminCommand({serverStatus: 1}));
var newElectionId = res.repl.electionId;
assert.lt(oldElectionId.valueOf(), newElectionId.valueOf());
checkPV1ElectionId(newElectionId);
oldElectionId = newElectionId;

// Step down
assert.throws(function() {
    var res = primary.adminCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 30});
    // Error out if stepdown command failed to run and throw.
    printjson(res);
});
rst.awaitSecondaryNodes();
res = assert.commandWorked(rst.getPrimary().adminCommand({serverStatus: 1}));
var newElectionId = res.repl.electionId;

// Compare the string of ObjectId
assert.lt(oldElectionId.valueOf(), newElectionId.valueOf());
checkPV1ElectionId(newElectionId);
oldElectionId = newElectionId;


// Downgrade protocol version
//
conf = rst.getReplSetConfigFromNode();
conf.protocolVersion = 0;
conf.version++;
reconfig(rst, conf);
// This write will block until all nodes finish upgrade.
assert.writeOK(rst.getPrimary().getDB("test").coll.insert({x: 2}, {writeConcern: {w: 3}}));

// Check election id after downgrade
res = assert.commandWorked(rst.getPrimary().adminCommand({serverStatus: 1}));
var newElectionId = res.repl.electionId;
// new election id in PV0 is less than the old one in PV1.
assert.gt(oldElectionId.valueOf(), newElectionId.valueOf());
oldElectionId = newElectionId;


// Step down
assert.throws(function() {
    var res = rst.getPrimary().adminCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 30});
    // Error out if stepdown command failed to run and throw.
    printjson(res);
});
rst.awaitSecondaryNodes();
res = assert.commandWorked(rst.getPrimary().adminCommand({serverStatus: 1}));
var newElectionId = res.repl.electionId;
assert.lt(oldElectionId.valueOf(), newElectionId.valueOf());
oldElectionId = newElectionId;

})();