'use strict'; /** * findAndModify_upsert.js * * Each thread repeatedly performs the findAndModify command, specifying * upsert as either true or false. A single document is selected (or * created) based on the 'query' specification, and updated using the * $push operator. */ var $config = (function() { var data = { sort: false, shardKey: {tid: 1} }; var states = (function() { // Returns true if the specified array is sorted in ascending order, // and false otherwise. function isSorted(arr) { for (var i = 0; i < arr.length - 1; ++i) { if (arr[i] > arr[i + 1]) { return false; } } return true; } function init(db, collName) { this.iter = 0; // Need to guarantee that an upsert has occurred prior to an update, // which is not enforced by the transition table under composition upsert.call(this, db, collName); } function upsert(db, collName) { var updatedValue = this.iter++; // Use a query specification that does not match any existing documents var query = { _id: new ObjectId(), tid: this.tid }; var cmdObj = { findandmodify: db[collName].getName(), query: query, update: {$setOnInsert: {values: [updatedValue]}}, new: true, upsert: true }; if (this.sort) { cmdObj.sort = this.sort; } var res = db.runCommand(cmdObj); assertAlways.commandWorked(res); var doc = res.value; assertAlways(doc !== null, 'a document should have been inserted'); assertAlways((function() { assertAlways.eq(this.tid, doc.tid); assertAlways(Array.isArray(doc.values), 'expected values to be an array'); assertAlways.eq(1, doc.values.length); assertAlways.eq(updatedValue, doc.values[0]); }).bind(this)); } function update(db, collName) { var updatedValue = this.iter++; var cmdObj = { findandmodify: db[collName].getName(), query: {tid: this.tid}, update: {$push: {values: updatedValue}}, new: true, upsert: false }; if (this.sort) { cmdObj.sort = this.sort; } var res = db.runCommand(cmdObj); assertAlways.commandWorked(res); var doc = res.value; assertWhenOwnColl(doc !== null, 'query spec should have matched a document'); if (doc !== null) { assertAlways.eq(this.tid, doc.tid); assertWhenOwnColl(Array.isArray(doc.values), 'expected values to be an array'); assertWhenOwnColl(function() { assertWhenOwnColl.gte(doc.values.length, 2); assertWhenOwnColl.eq(updatedValue, doc.values[doc.values.length - 1]); assertWhenOwnColl(isSorted(doc.values), 'expected values to be sorted: ' + tojson(doc.values)); }); } } return { init: init, upsert: upsert, update: update }; })(); var transitions = { init: {upsert: 0.1, update: 0.9}, upsert: {upsert: 0.1, update: 0.9}, update: {upsert: 0.1, update: 0.9} }; return { threadCount: 20, iterations: 20, data: data, states: states, transitions: transitions }; })();