summaryrefslogtreecommitdiff
path: root/jstests/replsets/stepdown_killop.js
blob: a280e13e6b9d06ffd7e4a5bd58e3b0753c157049 (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
// Ensure stepDown operations that are waiting for replication can be interrupted with killOp()
// 1. Start up a 3 node set (1 arbiter).
// 2. Stop replication on the SECONDARY using a fail point.
// 3. Do one write and then spin up a second shell which asks the PRIMARY to StepDown.
// 4. Once StepDown has begun, attempt to do writes and confirm that they fail with
// NotWritablePrimary.
// 5. Kill the stepDown operation.
// 6. Writes should become allowed again and the primary should stay primary.

(function() {
"use strict";

load("jstests/libs/write_concern_util.js");

var name = "interruptStepDown";
var replSet = new ReplSetTest({name: name, nodes: 3});
var nodes = replSet.nodeList();
replSet.startSet();
replSet.initiate({
    "_id": name,
    "members": [
        {"_id": 0, "host": nodes[0]},
        {"_id": 1, "host": nodes[1], "priority": 0},
        {"_id": 2, "host": nodes[2], "arbiterOnly": true}
    ]
});

replSet.waitForState(replSet.nodes[0], ReplSetTest.State.PRIMARY);

var secondary = replSet.getSecondary();
jsTestLog('Disable replication on the SECONDARY ' + secondary.host);
stopServerReplication(secondary);

var primary = replSet.getPrimary();
assert.eq(primary.host, nodes[0], "primary assumed to be node 0");

// do a write then ask the PRIMARY to stepdown
jsTestLog("Initiating stepdown");
assert.commandWorked(primary.getDB(name).foo.insert(
    {myDoc: true, x: 1}, {writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}}));
var stepDownCmd = function() {
    var res =
        db.getSiblingDB('admin').runCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 60});
    assert.commandFailedWithCode(res, 11601 /*interrupted*/);
};
var stepDowner = startParallelShell(stepDownCmd, primary.port);
var stepDownOpID = -1;

jsTestLog("Looking for stepdown in currentOp() output");
assert.soon(function() {
    var res = primary.getDB('admin').currentOp(true);
    for (var index in res.inprog) {
        var entry = res.inprog[index];
        if (entry["command"] && entry["command"]["replSetStepDown"] === 60) {
            stepDownOpID = entry.opid;
            return true;
        }
    }
    printjson(res);
    return false;
}, "No pending stepdown command found");

jsTestLog("Ensure that writes start failing with NotWritablePrimary errors");
assert.soonNoExcept(function() {
    assert.commandFailedWithCode(primary.getDB(name).foo.insert({x: 2}),
                                 ErrorCodes.NotWritablePrimary);
    return true;
});

jsTestLog("Ensure that even though writes are failing with NotWritablePrimary, we still report " +
          "ourselves as PRIMARY");
assert.eq(ReplSetTest.State.PRIMARY, primary.adminCommand('replSetGetStatus').myState);

// kill the stepDown and ensure that that unblocks writes to the db
jsTestLog("Killing stepdown");
primary.getDB('admin').killOp(stepDownOpID);

var exitCode = stepDowner();
assert.eq(0, exitCode);

assert.commandWorked(primary.getDB(name).foo.remove({}));
restartServerReplication(secondary);
replSet.stopSet();
})();