summaryrefslogtreecommitdiff
path: root/jstests/core
diff options
context:
space:
mode:
authorGeert Bosch <geert@mongodb.com>2017-04-07 11:33:02 -0400
committerGeert Bosch <geert@mongodb.com>2017-04-11 17:42:02 -0400
commite0d69be0ed9628034b70aacdc24fb843e640a10d (patch)
tree6bebb6dfddfb87ab728ade1adff3852fb535a879 /jstests/core
parent2206856999b0f9eb5a6b83f2da740efceeca1387 (diff)
downloadmongo-e0d69be0ed9628034b70aacdc24fb843e640a10d.tar.gz
SERVER-28645 Fail operations requiring too many locks, don't crash
(cherry picked from commit 85f26f1d66bbd43dc47b8f1c8b8f25bddf00d733) Conflicts: src/mongo/base/error_codes.err
Diffstat (limited to 'jstests/core')
-rw-r--r--jstests/core/apply_ops_atomicity.js38
1 files changed, 38 insertions, 0 deletions
diff --git a/jstests/core/apply_ops_atomicity.js b/jstests/core/apply_ops_atomicity.js
index f55a44f4048..afc131959b9 100644
--- a/jstests/core/apply_ops_atomicity.js
+++ b/jstests/core/apply_ops_atomicity.js
@@ -34,4 +34,42 @@
assert.commandWorked(newDB.runCommand(
{applyOps: [{op: "u", ns: newDBName + ".foo", o: {_id: 5, x: 17}, o2: {_id: 5, x: 16}}]}));
+ var sawTooManyLocksError = false;
+
+ function applyWithManyLocks(n) {
+ let cappedOps = [];
+ let multiOps = [];
+
+ for (let i = 0; i < n; i++) {
+ // Write to a capped collection, as that may require a lock for serialization.
+ let cappedName = "capped" + n + "-" + i;
+ newDB.createCollection(cappedName, {capped: true, size: 100});
+ cappedOps.push({op: 'i', ns: newDBName + "." + cappedName, o: {_id: 0}});
+
+ // Make an index multi-key, as that may require a lock for updating the catalog.
+ let multiName = "multi" + +n + "-" + i;
+ newDB[multiName].createIndex({x: 1});
+ multiOps.push({op: 'i', ns: newDBName + "." + multiName, o: {_id: 0, x: [0, 1]}});
+ }
+
+ let res = [cappedOps, multiOps].map((applyOps) => newDB.runCommand({applyOps}));
+ sawTooManyLocksError |= res.some((res) => res.code === ErrorCodes.TooManyLocks);
+ // Transactions involving just two collections should succeed.
+ if (n <= 2)
+ res.every((res) => res.ok);
+ // All transactions should either completely succeed or completely fail.
+ assert(res.every((res) => res.results.every((result) => result == res.ok)));
+ assert(res.every((res) => !res.ok || res.applied == n));
+ }
+
+ // Try requiring different numbers of collection accesses in a single operation to cover
+ // all edge cases, so we run out of available locks in different code paths such as during
+ // oplog application.
+ applyWithManyLocks(1);
+ applyWithManyLocks(2);
+
+ for (let i = 9; i < 16; i++) {
+ applyWithManyLocks(i);
+ }
+ assert(sawTooManyLocksError, "test no longer exhausts the max number of locks held at once");
})();