diff options
author | Geert Bosch <geert@mongodb.com> | 2017-04-07 11:33:02 -0400 |
---|---|---|
committer | Geert Bosch <geert@mongodb.com> | 2017-04-11 17:42:02 -0400 |
commit | e0d69be0ed9628034b70aacdc24fb843e640a10d (patch) | |
tree | 6bebb6dfddfb87ab728ade1adff3852fb535a879 /jstests/core | |
parent | 2206856999b0f9eb5a6b83f2da740efceeca1387 (diff) | |
download | mongo-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.js | 38 |
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"); })(); |