summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/drop_create_rollback.js
blob: 8f8b786f90694e4be3697caf4c2aba8aeecbf282 (plain)
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
/**
 * Tests that the _mdb_catalog does not reuse RecordIds after a catalog restart.
 * @tags: [
 *   requires_persistence,
 *   requires_replication,
 *   requires_wiredtiger,
 * ]
 */
(function() {
'use strict';

TestData.rollbackShutdowns = true;
TestData.logComponentVerbosity = {
    storage: {recovery: 2}
};
load('jstests/replsets/libs/rollback_test.js');

const rollbackTest = new RollbackTest();
let primary = rollbackTest.getPrimary();
// Do a majority write to guarantee the stable timestamp contains this create. Otherwise startup
// replication recovery will recreate the collection, initializing the _mdb_catalog RecordId
// generator.
assert.commandWorked(
    primary.getDB("foo").runCommand({create: "timestamped", writeConcern: {w: "majority"}}));

// This restart forces the _mdb_catalog to refresh, uninitializing the auto-incrementing RecordId
// generator.
jsTestLog({msg: "Restarting primary.", primary: primary, nodeId: primary.nodeId});
const SIGTERM = 15;  // clean shutdown
rollbackTest.restartNode(primary.nodeId, SIGTERM);

let rollbackNode = rollbackTest.transitionToRollbackOperations();
jsTestLog({
    msg: "The restarted primary must be the node that goes into rollback.",
    primary: primary,
    rollback: rollbackNode
});
assert.eq(primary, rollbackNode);
// The `timestamped` collection is positioned as the last record in the _mdb_catalog. An unpatched
// MongoDB dropping this collection will result in its RecordId being reused.
assert.commandWorked(rollbackNode.getDB("foo").runCommand({drop: "timestamped"}));
// Reusing the RecordId with an untimestamped write (due to being in the `local` database) results
// in an illegal update chain. A successful rollback should see the timestamped collection. But an
// unpatched MongoDB would have the untimestamped update on the same update chain, "locking in" the
// drop.
assert.commandWorked(rollbackNode.getDB("local").createCollection("untimestamped"));

rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
rollbackTest.transitionToSyncSourceOperationsDuringRollback();
rollbackTest.transitionToSteadyStateOperations();

assert.contains("timestamped", rollbackNode.getDB("foo").getCollectionNames());
assert.contains("untimestamped", rollbackNode.getDB("local").getCollectionNames());
rollbackTest.stop();
})();