summaryrefslogtreecommitdiff
path: root/jstests/libs/sbe_util.js
blob: 2d85bbb4f79cf3fc0bac54e5d91307bab74ad581 (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
147
/*
 * Utilities for checking whether SBE is enabled.
 */

load("jstests/libs/discover_topology.js");  // For findNonConfigNodes.
load("jstests/libs/fixture_helpers.js");    // For 'isMongos'

/**
 * Returns whether or not SBE is enabled for the given connection. Assumes that for repl sets and
 * sharded clusters, SBE is either enabled on each node, or disabled on each node.
 * If 'featureFlags' is non-empty, checks if SBE and all the feature flags are enabled.
 */
function checkSBEEnabled(theDB, featureFlags = []) {
    let checkResult = false;

    assert.soon(() => {
        // Some test suites kill the primary, potentially resulting in networking errors. We use:
        //  1. try..catch below to retry the whole check if we failed to discover topology
        //  2. try..catch in the loop to try the next node if the current is killed
        let nodes;
        try {
            nodes = DiscoverTopology.findNonConfigNodes(theDB.getMongo());
        } catch (e) {
            return false;
        }

        // Find a non-mongos node and check whether its forceClassicEngine flag is on. We
        // assume either all nodes in the cluster have SBE disabled or none.
        for (const node of nodes) {
            try {
                const conn = new Mongo(node);
                if (FixtureHelpers.isMongos(conn.getDB("admin"))) {
                    continue;
                }

                const getParam = conn.adminCommand({
                    getParameter: 1,
                    internalQueryForceClassicEngine: 1,
                    internalQueryEnableSlotBasedExecutionEngine: 1
                });
                if (getParam.hasOwnProperty("internalQueryForceClassicEngine") &&
                    !getParam.internalQueryForceClassicEngine) {
                    checkResult = true;
                }
                // Some versions use a different parameter to enable SBE instead of disabling it.
                if (getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine") &&
                    getParam.internalQueryEnableSlotBasedExecutionEngine) {
                    checkResult = true;
                }

                featureFlags.forEach(function(featureFlag) {
                    const featureFlagParam = conn.adminCommand({getParameter: 1, [featureFlag]: 1});
                    checkResult = checkResult && featureFlagParam.hasOwnProperty(featureFlag) &&
                        featureFlagParam[featureFlag]["value"];
                });

                return true;
            } catch (e) {
                continue;
            }
        }

        return false;
    });

    return checkResult;
}

/**
 * If 'theDB' corresponds to a node in a cluster, then returns true if the cluster that it
 * belongs to has at least one node that has SBE enabled and at least one node that has it
 * disabled; false otherwise.
 */
function checkBothEnginesAreRunOnCluster(theDB) {
    let result = false;
    assert.soon(() => {
        if (!FixtureHelpers.isMongos(theDB) && !FixtureHelpers.isReplSet(theDB)) {
            return true;
        }

        // Retry the check if we fail to discover the topology (this can happen if the test
        // suite has killed the primary).
        let nodes;
        try {
            nodes = DiscoverTopology.findNonConfigNodes(theDB.getMongo());
        } catch (e) {
            return false;
        }

        let engineMap = {sbe: 0, classic: 0};

        for (const node of nodes) {
            // If we cannot contact a node because it was killed or is otherwise unreachable, we
            // skip it and check the other nodes in the cluster. For our purposes, this is ok
            // because test suites which step down/kill certain nodes are configured to use
            // exactly one engine, whereas the test suites which are configured use both engines
            // (namely, the multiversion suites), do not step down/kill nodes.
            try {
                const conn = new Mongo(node);
                if (FixtureHelpers.isMongos(conn.getDB("admin"))) {
                    continue;
                }

                const getParam = conn.adminCommand({
                    getParameter: 1,
                    internalQueryForceClassicEngine: 1,
                    internalQueryEnableSlotBasedExecutionEngine: 1
                });

                if (getParam.hasOwnProperty("internalQueryForceClassicEngine")) {
                    if (getParam.internalQueryForceClassicEngine) {
                        engineMap.classic++;
                    } else {
                        engineMap.sbe++;
                    }
                }

                // Some versions use a different parameter to enable SBE instead of disabling it.
                if (getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine")) {
                    if (!getParam.internalQueryEnableSlotBasedExecutionEngine) {
                        engineMap.classic++;
                    } else {
                        engineMap.sbe++;
                    }
                }

                result = (engineMap.sbe > 0 && engineMap.classic > 0);
                if (result) {
                    return true;
                }
            } catch (e) {
                continue;
            }
        }

        return true;
    });

    return result;
}

/**
 * Returns 'true' if SBE is enabled on at least on one node for the given connection 'db'.
 */
function checkSBEEnabledOnSomeNode(db) {
    return checkSBEEnabled(db) || checkBothEnginesAreRunOnCluster(db);
}