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
|
/**
* This test uses the test only `pinHistoryReplicated` command to exercise the DurableHistoryPins
* across restart.
*
* The `pinHistoryReplicated` command will pin the oldest timestamp at the requested time (with an
* optional rounding up to oldest). If the pin is successfully, the pinned time is written to a
* document inside `mdb_testing.pinned_timestamp`.
*
* When the `TestingDurableHistoryPin` is registered at startup, it will repin the oldest timestamp
* at the minimum of all documents written to `mdb_testing.pinned_timestamp`.
*
* This test does the following:
*
* 1) Pin the timestamp with an artificially small value to take advantage of rounding.
* 2) See that the timestamp is pinned via serverStatus.
* 3) Restart the node, see the pin persist.
* 4) Make a new pin at "original pin" + 1
* 5) Remove the pin at "original pin"
* 6) Restart the node, see the incremented pin value from serverStatus.
*
* @tags: [
* requires_majority_read_concern,
* requires_persistence,
* ]
*/
(function() {
"use strict";
function incTs(ts) {
return Timestamp(ts.t, ts.i + 1);
}
let replTest = new ReplSetTest({
name: "use_history_after_restart",
nodes: 1,
nodeOptions: {
setParameter: {
// Set the history window to zero to more aggressively advance the oldest timestamp.
minSnapshotHistoryWindowInSeconds: 0,
logComponentVerbosity: tojson({storage: {recovery: 2}}),
}
}
});
let nodes = replTest.startSet();
replTest.initiate();
let primary = replTest.getPrimary();
// Pin with an arbitrarily small timestamp. Let the rounding tell us where the pin ended up. The
// write to the `mdb_testing.pinned_timestamp` collection is not logged/replayed during replication
// recovery. Repinning across startup happens before replication recovery. Do a majority write for
// predictability of the test.
let result = assert.commandWorked(primary.adminCommand(
{"pinHistoryReplicated": Timestamp(100, 1), round: true, writeConcern: {w: "majority"}}));
let origPinTs = result["pinTs"];
jsTestLog({"First pin result": result});
// Do some additional writes that would traditionally advance the oldest timestamp.
for (var idx = 0; idx < 10; ++idx) {
assert.commandWorked(primary.getDB("test")["coll"].insert({}));
}
assert.commandWorked(primary.getDB("test")["coll"].insert({}, {writeConcern: {w: "majority"}}));
// Observe that the pinned timestamp matches the command response.
let serverStatus = assert.commandWorked(primary.adminCommand("serverStatus"));
let pinnedTs = serverStatus["wiredTiger"]["snapshot-window-settings"]["min pinned timestamp"];
assert.eq(origPinTs, pinnedTs);
// Restarting the primary should preserve the pin.
replTest.restart(primary);
primary = replTest.getPrimary();
serverStatus = assert.commandWorked(primary.adminCommand("serverStatus"));
pinnedTs = serverStatus["wiredTiger"]["snapshot-window-settings"]["min pinned timestamp"];
assert.eq(origPinTs, pinnedTs);
// Create a new pin at "ts + 1". This should succeed, but have no effect.
result = assert.commandWorked(
primary.adminCommand({"pinHistoryReplicated": incTs(result["pinTs"]), round: false}));
jsTestLog({"Second pin result": result});
let newPinTs = result["pinTs"];
assert.eq(newPinTs, incTs(origPinTs));
// Remove the old pin at "ts".
assert.commandWorked(primary.getDB("mdb_testing")["pinned_timestamp"].remove(
{"pinTs": origPinTs}, {writeConcern: {w: "majority"}}));
// Restarting the node should observe a pin at "ts + 1".
replTest.restart(primary);
primary = replTest.getPrimary();
serverStatus = assert.commandWorked(primary.adminCommand("serverStatus"));
pinnedTs = serverStatus["wiredTiger"]["snapshot-window-settings"]["min pinned timestamp"];
assert.eq(newPinTs, pinnedTs);
replTest.stopSet();
})();
|