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
|
/*
* @tags: [
* # Uses failpoints that the mongos does not have.
* assumes_against_mongod_not_mongos,
* # Sets a failpoint on one mongod, so switching primaries would break the test.
* does_not_support_stepdowns,
* ]
*/
(function() {
"use strict";
load("jstests/libs/parallel_shell_helpers.js");
load('jstests/libs/test_background_ops.js');
const dbName = "test";
const collName = "create_index_conflicts";
const testDB = db.getSiblingDB(dbName);
testDB.dropDatabase();
const testColl = testDB.getCollection(collName);
// Test scenario where a WriteConflictException is caught during createIndexes.
assert.commandWorked(db.adminCommand(
{configureFailPoint: "createIndexesWriteConflict", mode: {activationProbability: 0.5}}));
// Make sure at least one execution occurs where the failpoint activates.
for (let i = 0; i < 20; i++) {
const res = assert.commandWorked(testColl.createIndex({a: 1}));
assert.eq(1, res.numIndexesBefore);
assert.eq(2, res.numIndexesAfter);
assert(res.createdCollectionAutomatically);
testColl.drop();
}
assert.commandWorked(
db.adminCommand({configureFailPoint: "createIndexesWriteConflict", mode: "off"}));
// Test scenario where a conflicting collection creation occurs, and createIndexes "loses" to the
// create collection.
assert.commandWorked(testDB.adminCommand({clearLog: 'global'}));
function runSuccessfulIndexBuild(dbName, collName) {
jsTest.log("Index build request starting...");
const res = db.getSiblingDB(dbName).runCommand(
{createIndexes: collName, indexes: [{key: {b: 1}, name: "the_b_1_index"}]});
jsTest.log("Index build request expected to succeed, result: " + tojson(res));
assert.commandWorked(res);
// Since the createCollection succeeded first, the index build should proceed as if the
// collection already existed.
assert(!res.createdCollectionAutomatically);
}
// Simulate a scenario where a createCollection succeeds before createIndexes can create the same
// collection.
function runConflictingCollectionCreate(testDB, dbName, collName) {
testColl.drop();
assert.commandWorked(testDB.adminCommand(
{configureFailPoint: 'hangBeforeCreateIndexesCollectionCreate', mode: 'alwaysOn'}));
let joinCollectionCreate;
let joinIndexBuild;
try {
jsTest.log("Starting a parallel shell to run index build request...");
joinIndexBuild = startParallelShell(funWithArgs(runSuccessfulIndexBuild, dbName, collName),
db.getMongo().port);
jsTest.log("Waiting for create collection hang during index build...");
checkLog.contains(
db.getMongo(),
"Hanging create collection due to failpoint 'hangBeforeCreateIndexesCollectionCreate'");
jsTest.log("Create collection request starting...");
const res = db.getSiblingDB(dbName).runCommand({create: collName});
jsTest.log("Create collection request expected to succeed, result: " + tojson(res));
assert.commandWorked(res);
} finally {
assert.commandWorked(testDB.adminCommand(
{configureFailPoint: 'hangBeforeCreateIndexesCollectionCreate', mode: 'off'}));
}
joinIndexBuild();
// Make sure the new index was successfully built, either by the parallel shell or via
// createConflictingIndex. We should have the _id index and the 'the_b_1_index' index just built
// in the parallel shell.
assert.eq(testColl.getIndexes().length, 2);
}
runConflictingCollectionCreate(testDB, dbName, collName);
})();
|