summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/read_concern_snapshot_catalog_invalidation.js
blob: 1cc7f5078e48d9e30663a51c27c541947a1778a2 (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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Tests that snapshot reads return an error when accessing a collection whose metadata is invalid
// for the snapshot's point in time.
// @tags: [requires_replication]
(function() {
    "use strict";

    const kDbName = "test";
    const kCollName = "coll";

    const rst = new ReplSetTest({nodes: 1});
    rst.startSet();
    rst.initiate();

    const testDB = rst.getPrimary().getDB(kDbName);
    if (!testDB.serverStatus().storageEngine.supportsSnapshotReadConcern) {
        rst.stopSet();
        return;
    }
    const adminDB = testDB.getSiblingDB("admin");
    const coll = testDB.getCollection(kCollName);
    coll.drop();

    function waitForOp(curOpFilter) {
        assert.soon(
            function() {
                const res = adminDB.aggregate([{$currentOp: {}}, {$match: curOpFilter}]).toArray();
                if (res.length === 1) {
                    return true;
                }
                return false;
            },
            function() {
                return "Failed to find operation in $currentOp output: " +
                    tojson(adminDB.aggregate([{$currentOp: {}}]).toArray());
            });
    }

    assert.commandWorked(coll.insert({x: 1}, {writeConcern: {w: "majority"}}));

    // Start a snapshot find that hangs after establishing a storage engine transaction.
    assert.commandWorked(testDB.adminCommand(
        {configureFailPoint: "hangAfterPreallocateSnapshot", mode: "alwaysOn"}));

    TestData.sessionId = assert.commandWorked(testDB.adminCommand({startSession: 1})).id;
    const awaitCommand = startParallelShell(function() {
        const res = db.runCommand({
            find: "coll",
            readConcern: {level: "snapshot"},
            lsid: TestData.sessionId,
            txnNumber: NumberLong(0)
        });
        assert.commandFailedWithCode(res, ErrorCodes.SnapshotUnavailable);
    }, rst.ports[0]);

    waitForOp({"command.find": kCollName, "command.readConcern.level": "snapshot"});

    // Create an index on the collection the find was executed against. This will move the
    // collection's minimum visible timestamp to a point later than the point-in-time referenced
    // by the find snapshot.
    assert.commandWorked(testDB.runCommand({
        createIndexes: kCollName,
        indexes: [{key: {x: 1}, name: "x_1"}],
        writeConcern: {w: "majority"}
    }));

    // Disable the hang and check for parallel shell success. Success indicates that the find
    // command failed due to collection metadata invalidation.
    assert.commandWorked(
        testDB.adminCommand({configureFailPoint: "hangAfterPreallocateSnapshot", mode: "off"}));

    awaitCommand();

    assert.commandWorked(testDB.adminCommand({endSessions: [TestData.sessionId]}));
    rst.stopSet();
})();