summaryrefslogtreecommitdiff
path: root/jstests/concurrency/fsm_workloads/yield_with_drop.js
blob: f06f26beec84ac51576fe03358aa61fcb74e749f (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"use strict";

/**
 * Executes query operations that can yield while the source collection is dropped and recreated.
 */

var $config = (function() {
    const data = {
        kAllowedErrors: [
            ErrorCodes.ConflictingOperationInProgress,
            ErrorCodes.CursorNotFound,
            ErrorCodes.DuplicateKey,
            ErrorCodes.OperationFailed,
            ErrorCodes.QueryPlanKilled,
        ],
        nDocs: 200,
        genUpdateDoc: function genUpdateDoc() {
            const newVal = Random.randInt(this.nDocs);
            return {$set: {a: newVal}};
        },
        // TODO SERVER-44673: Replace this function with calls to
        // commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors).
        assertWriteWorkedOrFailedWithExpectedCode:
            function assertWriteWorkedOrFailedWithExpectedCode(cmdRes) {
                if (cmdRes.ok) {
                    if (cmdRes.hasOwnProperty("writeErrors") && cmdRes.writeErrors.length > 0) {
                        assertAlways(this.kAllowedErrors.includes(cmdRes.writeErrors[0].code),
                                     cmdRes);
                    }

                    return;
                }

                assertAlways.commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors);
            },
        create: function create(db, collName) {
            for (let i = 0; i < this.nDocs; i++) {
                const cmdRes = db.runCommand({
                    update: collName,
                    updates: [{
                        q: {_id: i},
                        u: {$set: {a: i, b: this.nDocs - i, c: i, d: this.nDocs - i, e: "foo"}},
                        upsert: true
                    }]
                });
                this.assertWriteWorkedOrFailedWithExpectedCode(cmdRes);
            }
            assertAlways.commandWorkedOrFailedWithCode(db[collName].createIndex({a: 1}),
                                                       this.kAllowedErrors);
        }
    };

    var states = {
        query: function query(db, collName) {
            let cmdRes = db.runCommand(
                {find: collName, filter: {c: {$lt: this.nDocs}}, batchSize: this.nDocs});
            assertAlways.commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors);

            if (cmdRes.hasOwnProperty("cursor") && cmdRes.cursor.id > 0) {
                cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName});
                assertAlways.commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors);
            }
        },

        update: function update(db, collName) {
            const cmdRes = db.runCommand({
                update: collName,
                updates: [{q: {_id: Random.randInt(this.nDocs)}, u: this.genUpdateDoc()}]
            });

            this.assertWriteWorkedOrFailedWithExpectedCode(cmdRes);
        },

        remove: function remove(db, collName) {
            const cmdRes = db.runCommand(
                {delete: collName, deletes: [{q: {_id: Random.randInt(this.nDocs)}, limit: 1}]});

            this.assertWriteWorkedOrFailedWithExpectedCode(cmdRes);
        },

        count: function count(db, collName) {
            const cmdRes = db.runCommand({count: collName, query: {a: {$lt: this.nDocs}}});
            assertAlways.commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors);
        },

        distinct: function distinct(db, collName) {
            const cmdRes =
                db.runCommand({distinct: collName, key: "a", query: {a: {$lt: this.nDocs}}});
            assertAlways.commandWorkedOrFailedWithCode(cmdRes, this.kAllowedErrors);
        },

        recreateColl: function recreateColl(db, collName) {
            const cmdRes = db[collName].drop();
            this.create(db, collName);
        },
    };

    const kAllStatesEqual =
        {update: 0.18, remove: 0.18, query: 0.18, count: 0.18, distinct: 0.18, recreateColl: 0.1};
    const transitions = {
        update: kAllStatesEqual,
        remove: kAllStatesEqual,
        query: kAllStatesEqual,
        count: kAllStatesEqual,
        distinct: kAllStatesEqual,
        recreateColl: kAllStatesEqual,
    };

    /**
     * Lowers yielding parameters to increase frequency and sets up collection.
     */
    function setup(db, collName, cluster) {
        // Lower the following parameters to force even more yields.
        cluster.executeOnMongodNodes(function lowerYieldParams(db) {
            assertAlways.commandWorked(
                db.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 5}));
            assertAlways.commandWorked(
                db.adminCommand({setParameter: 1, internalQueryExecYieldPeriodMS: 1}));
        });

        data.create(db, collName);
    }

    /**
     * Disables failpoints.
     */
    function teardown(db, collName, cluster) {
        cluster.executeOnMongodNodes(function resetYieldParams(db) {
            assertAlways.commandWorked(
                db.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 128}));
            assertAlways.commandWorked(
                db.adminCommand({setParameter: 1, internalQueryExecYieldPeriodMS: 10}));
        });
    }

    return {
        threadCount: 10,
        iterations: 100,
        startState: 'update',
        states: states,
        transitions: transitions,
        setup: setup,
        teardown: teardown,
        data: data
    };
})();