Index: jstests/concurrency/fsm_workloads/yield_and_hashed.js diff --git a/jstests/concurrency/fsm_workloads/yield_and_hashed.js b/jstests/concurrency/fsm_workloads/yield_and_hashed.js new file mode 100644 index 0000000000000000000000000000000000000000..91e22e9a7daa0a3ca641aeffeb0fde691fdbce27 --- /dev/null +++ b/jstests/concurrency/fsm_workloads/yield_and_hashed.js @@ -0,0 +1,65 @@ +'use strict'; + +load('jstests/concurrency/fsm_libs/extend_workload.js'); // for extendWorkload +load('jstests/concurrency/fsm_workloads/yield.js'); // for $config + +/* + * yield_and_hashed.js (extends yield.js) + * + * Intersperse queries which use the AND_HASH stage with updates and deletes of documents they may + * match. + */ +var $config = extendWorkload($config, function($config, $super) { + + /* + * Issue a query that will use the AND_HASH stage. This is a little tricky, so use + * stagedebug to force it to happen. Unfortunately this means it can't be batched. + */ + $config.states.query = function andHash(db, collName) { + var nMatches = 100; + assertAlways.lte(nMatches, this.nDocs); + // Construct the query plan: two ixscans under an andHashed. + // Scan c <= nMatches + var ixscan1 = { ixscan: { args: { name: 'stages_and_hashed', keyPattern:{ c: 1 }, + startKey: { '': nMatches }, endKey: {}, + endKeyInclusive: true, direction: -1 } } }; + + // Scan d >= this.nDocs - nMatches + var ixscan2 = { ixscan: { args: { name: 'stages_and_hashed', keyPattern:{ d: 1 }, + startKey: { '': this.nDocs - nMatches }, endKey: {}, + endKeyInclusive: true, direction: 1 } } }; + + var andix1ix2 = { andHash: { args: { nodes: [ixscan1, ixscan2] } } }; + var res = db.runCommand({ stageDebug: { plan: andix1ix2, collection: collName } }); + assertAlways.commandWorked(res); + for (var i = 0; i < res.results.length; i++) { + var result = res.results[i]; + assertAlways.lte(result.c, nMatches); + assertAlways.gte(result.d, this.nDocs - nMatches); + } + }; + + /* + * A function which produces a random update doc (e.g. { $set: { c: 2, d: 10 } }), that can + * be used to update a random doc which may match the query. + */ + function getUpdateDoc() { + var newC = Random.randInt($config.data.nDocs); + var newD = Random.randInt($config.data.nDocs); + return { $set: { c: newC, b: newD } }; + } + + $config.states.update = $config.data.genUpdateFunction(getUpdateDoc); + + $config.setup = function(db, collName) { + $super.setup.apply(this, arguments); + + assertAlways.commandWorked(db[collName].ensureIndex({ c: 1 })); + assertAlways.commandWorked(db[collName].ensureIndex({ d: 1 })); + }; + + return $config; +}); + + +