summaryrefslogtreecommitdiff
path: root/jstests/dur/lsn.js
blob: 475263ce72a600b987c2c4340bd521802b31e861 (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* test durability, specifically last sequence number function
   runs mongod, kill -9's, recovers
   then writes more data and verifies with DurParanoid that it matches
*/

var debugging = false;
var testname = "lsn";
var step = 1;
var conn = null;

var start = new Date();
function howLongSecs() {
    return (new Date() - start) / 1000;
}

function log(str) {
    if(str)
        print("\n" + testname+" step " + step++ + " " + str);
    else
        print(testname+" step " + step++);
}

function verify() {
    log("verify");
    var d = conn.getDB("test");
    var mycount = d.foo.count();
    print("count:" + mycount);
    assert(mycount>2, "count wrong");
}

// if you do inserts here, you will want to set _id.  otherwise they won't match on different 
// runs so we can't do a binary diff of the resulting files to check they are consistent.
function work() {
    log("work");
    x = 'x'; while(x.length < 1024) x+=x;
    var d = conn.getDB("test");
    d.foo.drop();
    d.foo.insert({});

    // go long enough we will have time to kill it later during recovery
    var j = 2;
    var MaxTime = 15;
    if (Math.random() < 0.05) {
        print("doing a longer pass");
        MaxTime = 90;
    }
    while (1) {
        d.foo.insert({ _id: j, z: x });
        d.foo.update({ _id: j }, { $inc: { a: 1} });
        if (j % 25 == 0)
            d.foo.remove({ _id: j });
        j++;
        if( j % 3 == 0 )
            d.foo.update({ _id: j }, { $inc: { a: 1} }, true);
        if (j % 10000 == 0)
            print(j);
        if (howLongSecs() > MaxTime)
            break;
    }

    verify();
    d.runCommand({ getLastError: 1, fsync: 1 });
}

if( debugging ) {
    // mongod already running in debugger
    print("DOING DEBUG MODE BEHAVIOR AS 'db' IS DEFINED -- RUN mongo --nodb FOR REGULAR TEST BEHAVIOR");
    conn = db.getMongo();
    work();
    sleep(30000);
    quit();
}

// directories
var path2 = MongoRunner.dataPath + testname+"dur";

// run mongod with a short --syncdelay to make LSN writing sooner
log("run mongod --journal and a short --syncdelay");
conn = MongoRunner.runMongod({dbpath: path2,
                              syncdelay: 2,
                              journal: "",
                              smallfiles: "",
                              journalOptions: 8 /*DurParanoid*/,
                              master: "",
                              oplogSize: 64});
work();

log("wait a while for a sync and an lsn write");
sleep(14); // wait for lsn write

log("kill mongod -9");
MongoRunner.stopMongod(conn, /*signal*/9);

// journal file should be present, and non-empty as we killed hard

// check that there is an lsn file
{
    var files = listFiles(path2 + "/journal/");
    assert(files.some(function (f) { return f.name.indexOf("lsn") >= 0; }),
           "lsn.js FAIL no lsn file found after kill, yet one is expected");
}
/*assert.soon(
    function () {
        var files = listFiles(path2 + "/journal/");
        return files.some(function (f) { return f.name.indexOf("lsn") >= 0; });
    },
    "lsn.js FAIL no lsn file found after kill, yet one is expected"
);*/

// restart and recover
log("restart mongod, recover, verify");
conn = MongoRunner.runMongod({restart:true,
                              cleanData: false,
                              dbpath: path2,
                              journal: "",
                              smallfiles: "",
                              journalOptions: 24,
                              master: "",
                              oplogSize: 64});
verify();

// idea here is to verify (in a simplistic way) that we are in a good state to do further ops after recovery
log("add data after recovery");
{
    var d = conn.getDB("test");
    d.xyz.insert({ x: 1 });
    d.xyz.insert({ x: 1 });
    d.xyz.insert({ x: 1 });
    d.xyz.update({}, { $set: { x: "aaaaaaaaaaaa"} });
    d.xyz.reIndex();
    d.xyz.drop();
    sleep(1);
    d.xyz.insert({ x: 1 });
}

log("stop mongod " + conn.port);
MongoRunner.stopMongod(conn);

print(testname + " SUCCESS");