'use strict'; /** * update_simple.js * * Creates several docs. On each iteration, each thread chooses: * - a random doc * - whether to $set or $unset its field * - what value to $set the field to */ // For isMongod. load('jstests/concurrency/fsm_workload_helpers/server_types.js'); var $config = (function() { var states = { set: function set(db, collName) { this.setOrUnset(db, collName, true, this.numDocs); }, unset: function unset(db, collName) { this.setOrUnset(db, collName, false, this.numDocs); } }; var transitions = {set: {set: 0.5, unset: 0.5}, unset: {set: 0.5, unset: 0.5}}; function setup(db, collName, cluster) { // index on 'value', the field being updated assertAlways.commandWorked(db[collName].createIndex({value: 1})); // numDocs should be much less than threadCount, to make more threads use the same docs. this.numDocs = Math.floor(this.threadCount / 5); assertAlways.gt(this.numDocs, 0, 'numDocs should be a positive number'); for (var i = 0; i < this.numDocs; ++i) { // make sure the inserted docs have a 'value' field, so they won't need // to grow when this workload runs against a capped collection var res = db[collName].insert({_id: i, value: 0}); assertWhenOwnColl.commandWorked(res); assertWhenOwnColl.eq(1, res.nInserted); } } return { threadCount: 20, iterations: 20, startState: 'set', states: states, transitions: transitions, data: { // explicitly pass db to avoid accidentally using the global `db` assertResult: function assertResult(db, res) { assertAlways.eq(0, res.nUpserted, tojson(res)); if (isMongod(db)) { // Storage engines will automatically retry any operations when there are // conflicts, so we should always see a matching document. assertWhenOwnColl.eq(res.nMatched, 1, tojson(res)); } else { // On storage engines that do not support document-level concurrency, it is // possible that the query will not find the document. This can happen if // another thread updated the target document during a yield, triggering an // invalidation. assertWhenOwnColl.contains(res.nMatched, [0, 1], tojson(res)); } // We can't be sure nModified will be non-zero because we may have just set a key to // its existing value assertWhenOwnColl.contains(res.nModified, [0, 1], tojson(res)); }, setOrUnset: function setOrUnset(db, collName, set, numDocs) { // choose a doc and value to use in the update var docIndex = Random.randInt(numDocs); var value = Random.randInt(5); var updater = {}; updater[set ? '$set' : '$unset'] = {value: value}; var query = {_id: docIndex}; var res = this.doUpdate(db, collName, query, updater); this.assertResult(db, res); }, doUpdate: function doUpdate(db, collName, query, updater) { return db[collName].update(query, updater); }, }, setup: setup }; })();