/
findAndModify_mixed_queue_unindexed.js
96 lines (82 loc) · 3.58 KB
/
findAndModify_mixed_queue_unindexed.js
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
'use strict';
/**
* findAndModify_mixed_queue_unindexed.js
*
* This workload is a combination of findAndModify_remove_queue_unindexed.js and
* findAndModify_update_queue_unindexed.js.
*
* Each thread contends on the same document as one another by randomly performing either a
* findAndModify update operation or a findAndModify remove operation. The lack of an index that
* could satisfy the sort forces the findAndModify operations to scan all the matching documents in
* order to find the relevant document. This increases the amount of work each findAndModify
* operation has to do before getting to the matching document, and thus increases the chance of a
* write conflict because each is trying to update or remove the same document.
*
* This workload was designed to reproduce SERVER-21434.
*/
load('jstests/concurrency/fsm_libs/extend_workload.js'); // for extendWorkload
load('jstests/concurrency/fsm_workloads/findAndModify_remove_queue.js'); // for $config
load('jstests/concurrency/fsm_workload_helpers/server_types.js'); // for isMMAPv1
var $config = extendWorkload(
$config,
function($config, $super) {
// Use the workload name as the database name, since the workload name is assumed to be
// unique.
$config.data.uniqueDBName = 'findAndModify_mixed_queue_unindexed';
$config.data.newDocForInsert = function newDocForInsert(i) {
return {
_id: i,
rand: Random.rand(),
counter: 0
};
};
$config.data.getIndexSpecs = function getIndexSpecs() {
return [];
};
$config.data.opName = 'modified';
$config.data.validateResult = function validateResult(db, collName, res) {
assertAlways.commandWorked(res);
var doc = res.value;
if (isMongod(db) && !isMMAPv1(db)) {
// MMAPv1 does not automatically retry if there was a conflict, so it is expected
// that it may return null in the case of a conflict. All other storage engines
// should automatically retry the operation, and thus should never return null.
assertWhenOwnColl.neq(
doc, null, 'findAndModify should have found a matching document');
}
if (doc !== null) {
this.saveDocId(db, collName, doc._id);
}
};
$config.states = (function() {
// Avoid removing documents that were already updated.
function remove(db, collName) {
var res = db.runCommand({
findAndModify: db[collName].getName(),
query: {counter: 0},
sort: {rand: -1},
remove: true
});
this.validateResult(db, collName, res);
}
function update(db, collName) {
// Update the counter field to avoid matching the same document again.
var res = db.runCommand({
findAndModify: db[collName].getName(),
query: {counter: 0},
sort: {rand: -1},
update: {$inc: {counter: 1}}, new: false
});
this.validateResult(db, collName, res);
}
return {
remove: remove,
update: update,
};
})();
$config.transitions = {
remove: {remove: 0.5, update: 0.5},
update: {remove: 0.5, update: 0.5},
};
return $config;
});