0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 01:21:03 +01:00
mongodb/jstests/noPassthrough/minvalid2.js
2019-07-27 11:02:23 -04:00

101 lines
3.4 KiB
JavaScript

/**
* This checks rollback, which shouldn't happen unless we have reached minvalid.
* 1. make 3-member set w/arb (2)
* 2. shut down slave
* 3. do writes to master
* 4. modify master's minvalid
* 5. shut down master
* 6. start up slave
* 7. writes on former slave (now primary)
* 8. start up master
* 9. check master does not rollback
*
* 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
* initial 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, requires_replication]
*/
// Skip db hash check because replset cannot reach consistent state.
TestData.skipCheckDBHashes = true;
print("1. make 3-member set w/arb (2)");
var name = "minvalid";
var replTest = new ReplSetTest({name: name, nodes: 3, oplogSize: 1, waitForKeys: true});
var host = getHostName();
var nodes = replTest.startSet();
replTest.initiate({
_id: name,
members: [
{_id: 0, host: host + ":" + replTest.ports[0]},
{_id: 1, host: host + ":" + replTest.ports[1]},
{_id: 2, host: host + ":" + replTest.ports[2], arbiterOnly: true}
]
});
var slaves = replTest._slaves;
var master = replTest.getPrimary();
var masterId = replTest.getNodeId(master);
var slave = slaves[0];
var slaveId = replTest.getNodeId(slave);
// Wait for primary to detect that the arbiter is up so that it won't step down when we later take
// the secondary offline.
replTest.waitForState(replTest.nodes[2], ReplSetTest.State.ARBITER);
var mdb = master.getDB("foo");
mdb.foo.save({a: 1000});
replTest.awaitReplication();
print("2: shut down slave");
replTest.stop(slaveId);
print("3: write to master");
assert.writeOK(mdb.foo.insert({a: 1001}, {writeConcern: {w: 1}}));
print("4: modify master's minvalid");
var local = master.getDB("local");
var lastOp = local.oplog.rs.find().sort({$natural: -1}).limit(1).next();
printjson(lastOp);
// Overwrite minvalid document to simulate an inconsistent state (as might result from a server
// crash.
local.replset.minvalid.update({},
{
ts: new Timestamp(lastOp.ts.t, lastOp.ts.i + 1),
t: NumberLong(-1),
},
{upsert: true});
printjson(local.replset.minvalid.findOne());
print("5: shut down master");
replTest.stop(masterId);
print("6: start up slave");
replTest.restart(slaveId);
print("7: writes on former slave");
master = replTest.getPrimary();
mdb1 = master.getDB("foo");
mdb1.foo.save({a: 1002});
print("8: start up former master");
clearRawMongoProgramOutput();
replTest.restart(masterId);
print("9: check former master " + replTest.nodes[masterId].host + " does not select former slave " +
slave.host + " as sync source");
replTest.waitForState(replTest.nodes[masterId], ReplSetTest.State.RECOVERING, 90000);
// Sync source selection will log this message if it does not detect min valid in the sync
// source candidate's oplog.
assert.soon(function() {
return rawMongoProgramOutput().match(
'it does not contain the necessary operations for us to reach a consistent state');
});
replTest.stopSet();