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
|
/**
* This test exercises an unrecoverable rollback using rollback_test.js, expecting it to terminate
* cleanly early instead of failing.
* An unrecoverable rollback can happen with EMRC:false, as it is possible for rollback via refetch
* to set a minValid based on oplog entries that the sync source may have failed to recover after
* an unclean shutdown. The rollback node will need to sync and apply oplog entries up to minValid
* to be consistent, but if those oplog entries no longer exist, then it will be stuck in sync
* source selection and unable to complete recovery.
* This test reproduces this scenario in a simpler form by modifying the minValid on the rollback
* node very far forward, so that we do not have to simulate anything happening to the sync source.
*/
(function() {
"use strict";
load("jstests/replsets/libs/rollback_test.js");
function tsToDate(ts) {
return new Date(ts.getTime() * 1000);
}
const testName = jsTestName();
const rst = new ReplSetTest({
name: testName,
nodes: [{}, {}, {rsConfig: {arbiterOnly: true}}],
useBridge: true,
settings: {chainingAllowed: false},
nodeOptions: {enableMajorityReadConcern: "false"}
});
rst.startSet();
rst.initiate();
const rollbackTest = new RollbackTest(testName, rst);
const rollbackNode = rollbackTest.transitionToRollbackOperations();
assert.commandWorked(rollbackNode.adminCommand(
{configureFailPoint: "rollbackHangBeforeFinish", mode: "alwaysOn"}));
rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
rollbackTest.transitionToSyncSourceOperationsDuringRollback();
checkLog.contains(rollbackNode, "rollbackHangBeforeFinish fail point enabled.");
const farFutureTS = new Timestamp(
Math.floor(new Date().getTime() / 1000) + (60 * 60 * 24 * 5 /* in five days*/), 0);
jsTest.log("future TS: " + tojson(farFutureTS) + ", date:" + tsToDate(farFutureTS));
const mMinvalid = rollbackNode.getDB("local").getCollection("replset.minvalid");
const minValidUpdate = {$set: {ts: farFutureTS}};
jsTestLog("Current minValid is " + tojson(mMinvalid.findOne()));
jsTestLog("Updating minValid to: " + tojson(minValidUpdate));
printjson(assert.commandWorked(mMinvalid.update({}, minValidUpdate)));
assert.commandWorked(
rollbackNode.adminCommand({configureFailPoint: "rollbackHangBeforeFinish", mode: "off"}));
rollbackTest.setAwaitSecondaryNodesForRollbackTimeout(5 * 1000);
// We will detect an unrecoverable rollback here.
rollbackTest.transitionToSteadyStateOperations();
rollbackTest.stop();
})();
|