Files
mongo/jstests/replsets/rollback.js
2012-05-17 00:34:03 -04:00

204 lines
5.3 KiB
JavaScript

// test rollback in replica sets
// try running as :
//
// mongo --nodb rollback.js | tee out | grep -v ^m31
//
var debugging = 0;
function ifReady(db, f) {
var stats = db.adminCommand({ replSetGetStatus: 1 });
// only eval if state isn't recovery
if (stats && stats.myState != 3) {
return f();
}
return false;
}
function pause(s) {
print(s);
while (debugging) {
sleep(3000);
print(s);
}
}
function deb(obj) {
if( debugging ) {
print("\n\n\n" + obj + "\n\n");
}
}
w = 0;
function wait(f) {
w++;
var n = 0;
while (!f()) {
if( n % 4 == 0 )
print("rollback.js waiting " + w);
if (++n == 4) {
print("" + f);
}
assert(n < 200, 'tried 200 times, giving up');
sleep(1000);
}
}
doTest = function (signal) {
var replTest = new ReplSetTest({ name: 'unicomplex', nodes: 3 });
var nodes = replTest.nodeList();
//print(tojson(nodes));
var conns = replTest.startSet();
var r = replTest.initiate({ "_id": "unicomplex",
"members": [
{ "_id": 0, "host": nodes[0] },
{ "_id": 1, "host": nodes[1] },
{ "_id": 2, "host": nodes[2], arbiterOnly: true}]
});
// Make sure we have a master
var master = replTest.getMaster();
a_conn = conns[0];
A = a_conn.getDB("admin");
b_conn = conns[1];
a_conn.setSlaveOk();
b_conn.setSlaveOk();
B = b_conn.getDB("admin");
assert(master == conns[0], "conns[0] assumed to be master");
assert(a_conn == master);
//deb(master);
// 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.");
// Wait for initial replication
var a = a_conn.getDB("foo");
var b = b_conn.getDB("foo");
/* force the oplog to roll */
if (new Date() % 2 == 0) {
print("ROLLING OPLOG AS PART OF TEST (we only do this sometimes)");
var pass = 1;
var first = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
a.roll.insert({ x: 1 });
while (1) {
for (var i = 0; i < 10000; i++)
a.roll.update({}, { $inc: { x: 1} });
var op = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
if (tojson(op.h) != tojson(first.h)) {
printjson(op);
printjson(first);
break;
}
pass++;
a.getLastError(2); // unlikely secondary isn't keeping up, but let's avoid possible intermittent issues with that.
}
print("PASSES FOR OPLOG ROLL: " + pass);
}
else {
print("NO ROLL");
}
a.bar.insert({ q: 1, a: "foo" });
a.bar.insert({ q: 2, a: "foo", x: 1 });
a.bar.insert({ q: 3, bb: 9, a: "foo" });
assert(a.bar.count() == 3, "t.count");
// wait for secondary to get this data
wait(function () { return ifReady(b, function() { return b.bar.count() == 3 }); });
A.runCommand({ replSetTest: 1, blind: true });
reconnect(a,b);
wait(function () { return B.isMaster().ismaster; });
b.bar.insert({ q: 4 });
b.bar.insert({ q: 5 });
b.bar.insert({ q: 6 });
assert(b.bar.count() == 6, "u.count");
// a should not have the new data as it was in blind state.
B.runCommand({ replSetTest: 1, blind: true });
print("*************** wait for server to reconnect ****************");
reconnect(a,b);
A.runCommand({ replSetTest: 1, blind: false });
reconnect(a,b);
print("*************** B ****************");
wait(function () { try { return !B.isMaster().ismaster; } catch(e) { return false; } });
print("*************** A ****************");
reconnect(a,b);
wait(function () {
try {
return A.isMaster().ismaster;
} catch(e) {
return false;
}
});
assert(a.bar.count() == 3, "t is 3");
a.bar.insert({ q: 7 });
a.bar.insert({ q: 8 });
{
assert(a.bar.count() == 5);
var x = a.bar.find().toArray();
assert(x[0].q == 1, '1');
assert(x[1].q == 2, '2');
assert(x[2].q == 3, '3');
assert(x[3].q == 7, '7');
assert(x[4].q == 8, '8');
}
// A is 1 2 3 7 8
// B is 1 2 3 4 5 6
// bring B back online
B.runCommand({ replSetTest: 1, blind: false });
reconnect(a,b);
assert.soon(function() {
return (A.isMaster().ismaster || A.isMaster().secondary) &&
(B.isMaster().ismaster || B.isMaster().secondary);
});
replTest.awaitReplication();
assert.soon(function() {
return (A.isMaster().ismaster || A.isMaster().secondary) &&
(B.isMaster().ismaster || B.isMaster().secondary);
});
friendlyEqual(a.bar.find().sort({ _id: 1 }).toArray(), b.bar.find().sort({ _id: 1 }).toArray(), "server data sets do not match");
pause("rollback.js SUCCESS");
replTest.stopSet(signal);
};
var reconnect = function(a,b) {
wait(function() {
try {
a.bar.stats();
b.bar.stats();
return true;
} catch(e) {
print(e);
return false;
}
});
};
print("rollback.js");
doTest( 15 );