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
|
'use strict';
/**
* Performs concurrent majority writes alongside transactions to verify both will eventually
* complete as expected.
*
* The base workload assumes transactions run at snapshot read concern, so the tag is copied here.
* @tags: [uses_transactions, assumes_snapshot_transactions]
*/
load('jstests/concurrency/fsm_libs/extend_workload.js'); // for extendWorkload
load('jstests/concurrency/fsm_workloads/multi_statement_transaction_simple.js'); // for $config
load('jstests/concurrency/fsm_workload_helpers/server_types.js'); // for isMongos
var $config = extendWorkload($config, function($config, $super) {
$config.data.majorityWriteCollName = 'majority_writes';
$config.data.counter = 0;
/**
* Runs the base workload's init state function and inserts a document to be majority updated
* later by this thread.
*/
$config.states.init = function init(db, collName) {
$super.states.init.apply(this, arguments);
assertWhenOwnColl.writeOK(db[this.majorityWriteCollName].insert(
{_id: this.tid, counter: this.counter}, {writeConcern: {w: 'majority'}}));
};
/**
* Updates a document unrelated to the transaction run in the base workload using majority write
* concern and verifies the update is immediately visible in the majority snapshot once the
* write returns.
*/
$config.states.majorityWriteUnrelatedDoc = function majorityWriteUnrelatedDoc(db, collName) {
this.counter += 1;
assertWhenOwnColl.writeOK(db[this.majorityWriteCollName].update(
{_id: this.tid}, {$set: {counter: this.counter}}, {writeConcern: {w: 'majority'}}));
// As soon as the write returns, its effects should be visible in the majority snapshot.
const doc = db[this.majorityWriteCollName].findOne({_id: this.tid});
assertWhenOwnColl.eq(
this.counter, doc.counter, 'unexpected counter value, doc: ' + tojson(doc));
};
/**
* Updates a document that may be written to by the transaction run in the base workload using
* majority write concern and verifies the update is immediately visible in the majority
* snapshot once the write returns.
*/
$config.states.majorityWriteTxnDoc = function majorityWriteTxnDoc(db, collName) {
this.counter += 1;
// Choose a random document that may be written to by the base workload. The base collection
// contains documents with _id ranging from 0 to the number of accounts. Update a field
// based on the thread's id, since threads may concurrently write to the same document.
const transactionDocId = Random.randInt(this.numAccounts);
const threadUniqueField = 'thread' + this.tid;
assertWhenOwnColl.writeOK(db[collName].update({_id: transactionDocId},
{$set: {[threadUniqueField]: this.counter}},
{writeConcern: {w: 'majority'}}));
// As soon as the write returns, its effects should be visible in the majority snapshot.
const doc = db[collName].findOne({_id: transactionDocId});
assertWhenOwnColl.eq(
this.counter,
doc[threadUniqueField],
'unexpected thread unique field value, thread: ' + this.tid + ', doc: ' + tojson(doc));
};
/**
* Runs the base workload's setup and, if necessary, shards the collection that is majority
* written to by this workload.
*/
$config.setup = function setup(db, collName, cluster) {
$super.setup.apply(this, arguments);
if (isMongos(db)) {
// The database will already have had sharding enabled by the fsm infrastructure.
db.adminCommand({
shardCollection: db[this.majorityWriteCollName].getFullName(),
key: {_id: 'hashed'}
});
}
};
$config.transitions = {
init: {transferMoney: 1},
transferMoney: {
transferMoney: 0.5,
checkMoneyBalance: 0.1,
majorityWriteUnrelatedDoc: 0.2,
majorityWriteTxnDoc: 0.2
},
checkMoneyBalance:
{transferMoney: 0.5, majorityWriteUnrelatedDoc: 0.25, majorityWriteTxnDoc: 0.25},
majorityWriteUnrelatedDoc:
{transferMoney: 0.5, majorityWriteUnrelatedDoc: 0.25, majorityWriteTxnDoc: 0.25},
majorityWriteTxnDoc:
{transferMoney: 0.5, majorityWriteUnrelatedDoc: 0.25, majorityWriteTxnDoc: 0.25},
};
return $config;
});
|