summaryrefslogtreecommitdiff
path: root/jstests/core/txns/transactions_profiling_with_drops.js
blob: 6147dbada2bb28fc78f14348cb8199ce875886d7 (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
// Tests that locks acquisitions for profiling in a transaction have a 0-second timeout.
// @tags: [uses_transactions, uses_multiple_connections]
(function() {
"use strict";

load("jstests/libs/profiler.js");  // For getLatestProfilerEntry.

const dbName = "test";
const collName = "transactions_profiling_with_drops";
const adminDB = db.getSiblingDB("admin");
const testDB = db.getSiblingDB(dbName);
const session = db.getMongo().startSession({causalConsistency: false});
const sessionDb = session.getDatabase(dbName);
const sessionColl = sessionDb[collName];

sessionDb.runCommand({dropDatabase: 1, writeConcern: {w: "majority"}});
assert.commandWorked(sessionColl.insert({_id: "doc"}, {w: "majority"}));
assert.commandWorked(sessionDb.runCommand({profile: 1, slowms: 1}));

jsTest.log("Test read profiling with operation holding database X lock.");

jsTest.log("Start transaction.");
session.startTransaction();

jsTest.log("Run a slow read. Profiling in the transaction should succeed.");
assert.sameMembers(
    [{_id: "doc"}],
    sessionColl.find({$where: "sleep(1000); return true;"}).comment("read success").toArray());
profilerHasSingleMatchingEntryOrThrow(
    {profileDB: testDB, filter: {"command.comment": "read success"}});

// Lock 'test' database in X mode.
let lockShell = startParallelShell(function() {
    assert.commandFailed(db.adminCommand({
        sleep: 1,
        secs: 500,
        lock: "w",
        lockTarget: "test",
        $comment: "transaction_profiling_with_drops lock sleep"
    }));
});

const waitForCommand = function(opFilter) {
    let opId = -1;
    assert.soon(function() {
        const curopRes = testDB.currentOp();
        assert.commandWorked(curopRes);
        const foundOp = curopRes["inprog"].filter(opFilter);

        if (foundOp.length == 1) {
            opId = foundOp[0]["opid"];
        }
        return (foundOp.length == 1);
    });
    return opId;
};

// Wait for sleep to appear in currentOp
let opId = waitForCommand(
    op => (op["ns"] == "admin.$cmd" &&
           op["command"]["$comment"] == "transaction_profiling_with_drops lock sleep"));

jsTest.log("Run a slow read. Profiling in the transaction should fail.");
assert.sameMembers(
    [{_id: "doc"}],
    sessionColl.find({$where: "sleep(1000); return true;"}).comment("read failure").toArray());
assert.commandWorked(session.commitTransaction_forTesting());

assert.commandWorked(testDB.killOp(opId));
lockShell();

profilerHasZeroMatchingEntriesOrThrow(
    {profileDB: testDB, filter: {"command.comment": "read failure"}});

jsTest.log("Test write profiling with operation holding database X lock.");

jsTest.log("Start transaction.");
session.startTransaction();

jsTest.log("Run a slow write. Profiling in the transaction should succeed.");
assert.commandWorked(sessionColl.update(
    {$where: "sleep(1000); return true;"}, {$inc: {good: 1}}, {collation: {locale: "en"}}));
profilerHasSingleMatchingEntryOrThrow(
    {profileDB: testDB, filter: {"command.collation": {locale: "en"}}});

// Lock 'test' database in X mode.
lockShell = startParallelShell(function() {
    assert.commandFailed(db.getSiblingDB("test").adminCommand(
        {sleep: 1, secs: 500, lock: "w", lockTarget: "test", $comment: "lock sleep"}));
});

// Wait for sleep to appear in currentOp
opId =
    waitForCommand(op => (op["ns"] == "admin.$cmd" && op["command"]["$comment"] == "lock sleep"));

jsTest.log("Run a slow write. Profiling in the transaction should still succeed " +
           "since the transaction already has an IX DB lock.");
assert.commandWorked(sessionColl.update(
    {$where: "sleep(1000); return true;"}, {$inc: {good: 1}}, {collation: {locale: "fr"}}));
assert.commandWorked(session.commitTransaction_forTesting());

assert.commandWorked(testDB.killOp(opId));
lockShell();

profilerHasSingleMatchingEntryOrThrow(
    {profileDB: testDB, filter: {"command.collation": {locale: "fr"}}});

jsTest.log("Both writes should succeed");
assert.docEq({_id: "doc", good: 2}, sessionColl.findOne());

session.endSession();
}());