summaryrefslogtreecommitdiff
path: root/jstests/replsets/rollback_creates_rollback_directory.js
blob: 3cb47eb65a255d8d7580b3ebf00032e36532476f (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// test that a rollback directory is created during a replica set rollback
// this also tests that updates are recorded in the rollback file
//  (this test does no delete rollbacks)
//
// If all data-bearing nodes in a replica set are using an ephemeral storage engine, the set will
// not be able to survive a scenario where all data-bearing nodes are down simultaneously. In such a
// scenario, none of the members will have any data, and upon restart will each look for a member to
// inital sync from, so no primary will be elected. This test induces such a scenario, so cannot be
// run on ephemeral storage engines.
// @tags: [requires_persistence]

function runRollbackDirectoryTest(shouldCreateRollbackFiles) {
    jsTestLog("Testing createRollbackDataFiles = " + shouldCreateRollbackFiles);
    var testName = "rollback_creates_rollback_directory";
    var replTest = new ReplSetTest({name: testName, nodes: 3});
    var nodes = replTest.nodeList();

    var conns =
        replTest.startSet({setParameter: {createRollbackDataFiles: shouldCreateRollbackFiles}});
    var r = replTest.initiate({
        "_id": testName,
        "members": [
            {"_id": 0, "host": nodes[0], priority: 3},
            {"_id": 1, "host": nodes[1]},
            {"_id": 2, "host": nodes[2], arbiterOnly: true}
        ],
    });

    // Make sure we have a master
    replTest.waitForState(replTest.nodes[0], ReplSetTest.State.PRIMARY);
    var master = replTest.getPrimary();
    var a_conn = conns[0];
    var b_conn = conns[1];
    a_conn.setSlaveOk();
    b_conn.setSlaveOk();
    var A = a_conn.getDB("test");
    var B = b_conn.getDB("test");
    var Apath = replTest.getDbPath(a_conn) + '/';
    var Bpath = replTest.getDbPath(b_conn) + '/';
    assert(master == conns[0], "conns[0] assumed to be master");
    assert(a_conn.host == master.host);

    // Make sure we have an arbiter
    assert.soon(function() {
        res = conns[2].getDB("admin").runCommand({replSetGetStatus: 1});
        return res.myState == 7;
    }, "Arbiter failed to initialize.");

    var options = {writeConcern: {w: 2, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true};
    assert.commandWorked(A.foo.update({key: 'value1'}, {$set: {req: 'req'}}, options));
    var AID = replTest.getNodeId(a_conn);
    replTest.stop(AID);

    master = replTest.getPrimary();
    assert(b_conn.host == master.host);
    options = {writeConcern: {w: 1, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true};
    assert.commandWorked(B.foo.update({key: 'value1'}, {$set: {res: 'res'}}, options));
    var BID = replTest.getNodeId(b_conn);
    replTest.stop(BID);
    replTest.restart(AID);
    master = replTest.getPrimary();
    assert(a_conn.host == master.host);
    options = {writeConcern: {w: 1, wtimeout: replTest.kDefaultTimeoutMS}, upsert: true};
    assert.commandWorked(A.foo.update({key: 'value2'}, {$set: {req: 'req'}}, options));
    replTest.restart(BID);  // should rollback
    reconnect(B);

    print("BEFORE------------------");
    printjson(A.foo.find().toArray());

    replTest.awaitReplication();
    replTest.awaitSecondaryNodes();

    print("AFTER------------------");
    printjson(A.foo.find().toArray());

    assert.eq(2, A.foo.find().itcount());
    assert.eq('req', A.foo.findOne({key: 'value1'}).req);
    assert.eq(null, A.foo.findOne({key: 'value1'}).res);
    reconnect(B);
    assert.eq(2, B.foo.find().itcount());
    assert.eq('req', B.foo.findOne({key: 'value1'}).req);
    assert.eq(null, B.foo.findOne({key: 'value1'}).res);

    // check here for rollback files
    var rollbackDir = Bpath + "rollback/";
    assert.eq(pathExists(rollbackDir), shouldCreateRollbackFiles, rollbackDir);

    // Verify data consistency between nodes.
    replTest.checkReplicatedDataHashes();
    replTest.checkOplogs();

    print(testName + ".js SUCCESS");
    replTest.stopSet(15);

    function wait(f) {
        var n = 0;
        while (!f()) {
            if (n % 4 == 0)
                print(testName + ".js waiting");
            if (++n == 4) {
                print("" + f);
            }
            assert(n < 200, 'tried 200 times, giving up');
            sleep(1000);
        }
    }

    function reconnect(a) {
        wait(function() {
            try {
                a.bar.stats();
                return true;
            } catch (e) {
                print(e);
                return false;
            }
        });
    }
}

runRollbackDirectoryTest(false);
runRollbackDirectoryTest(true);