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
|
/* 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 = "/data/db/" + testname+"dur";
// run mongod with a short --syncdelay to make LSN writing sooner
log("run mongod --dur and a short --syncdelay");
conn = startMongodEmpty("--syncdelay", 2, "--port", 30001, "--dbpath", path2, "--dur", "--smallfiles", "--durOptions", /*DurParanoid*/8, "--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");
stopMongod(30001, /*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 = startMongodNoReset("--port", 30002, "--dbpath", path2, "--dur", "--smallfiles", "--durOptions", 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 30002");
stopMongod(30002);
print(testname + " SUCCESS");
|