diff --git a/jstests/noPassthrough/read_majority.js b/jstests/noPassthrough/read_majority.js index 9fb2616178a..9c35711f7c6 100644 --- a/jstests/noPassthrough/read_majority.js +++ b/jstests/noPassthrough/read_majority.js @@ -1,4 +1,20 @@ -load('jstests/libs/analyze_plan.js'); +/** + * Tests a variety of functionality related to committed reads: + * - A killOp command can successfully kill an operation that is waiting for snapshots to be + * created. + * - A user should not be able to do any committed reads before a snapshot has been blessed. + * - Inserts and catalog changes should not be visible in a snapshot before they occurred. + * - A getMore should see the new blessed snapshot. + * - Dropping an index, repairing, and reIndexing should bump the min snapshot version. + * - Dropping a collection is visible in committed snapshot, since metadata changes are special. + * - 'local'-only commands should error on 'majority' level, and accept 'local' level. + * - An aggregation with '$out' should fail with 'majority' level. + * + * All of this requires support for committed reads, so this test will be skipped if the storage + * engine does not support them. + */ + +load("jstests/libs/analyze_plan.js"); (function() { "use strict"; diff --git a/jstests/replsets/read_committed.js b/jstests/replsets/read_committed.js index d3f8fc22afc..06776edcce1 100644 --- a/jstests/replsets/read_committed.js +++ b/jstests/replsets/read_committed.js @@ -1,4 +1,13 @@ -// Test basic read committed functionality. +/** + * Test basic read committed functionality, including: + * - Writes with writeConcern 'majority' should be visible once the write completes. + * - With the only data-bearing secondary down, committed reads should not include newly inserted + * data. + * - When data-bearing node comes back up and catches up, writes should be readable. + */ + +load("jstests/replsets/rslib.js"); // For startSetIfSupportsReadMajority. + (function() { "use strict"; @@ -7,20 +16,13 @@ var name = "read_committed"; var replTest = new ReplSetTest({name: name, nodes: 3, nodeOptions: {enableMajorityReadConcern: ''}}); -var nodes = replTest.nodeList(); -try { - replTest.startSet(); -} catch (e) { - var conn = MongoRunner.runMongod(); - if (!conn.getDB('admin').serverStatus().storageEngine.supportsCommittedReads) { - jsTest.log("skipping test since storage engine doesn't support committed reads"); - MongoRunner.stopMongod(conn); - return; - } - throw e; +if (!startSetIfSupportsReadMajority(replTest)) { + jsTest.log("skipping test since storage engine doesn't support committed reads"); + return; } +var nodes = replTest.nodeList(); replTest.initiate({"_id": name, "members": [ { "_id": 0, "host": nodes[0] }, diff --git a/jstests/replsets/read_committed_no_snapshots.js b/jstests/replsets/read_committed_no_snapshots.js index 307a6535ee1..60b5d7d9ca0 100644 --- a/jstests/replsets/read_committed_no_snapshots.js +++ b/jstests/replsets/read_committed_no_snapshots.js @@ -1,6 +1,11 @@ -// Test basic read committed maxTimeMS timeout while waiting for a committedSnapshot +/** + * Test basic read committed maxTimeMS timeout while waiting for a committed snapshot: + * - Reads with an 'afterOpTime' snapshot >= current time should be able to see things that + * happened before or at that opTime. + * - Reads should time out if there are no snapshots available on secondary. + */ -load("jstests/replsets/rslib.js"); +load("jstests/replsets/rslib.js"); // For reconfig and startSetIfSupportsReadMajority. (function() { "use strict"; @@ -10,20 +15,13 @@ var name = "read_committed_no_snapshots"; var replTest = new ReplSetTest({name: name, nodes: 3, nodeOptions: {enableMajorityReadConcern: ''}}); -var nodes = replTest.nodeList(); -try { - replTest.startSet(); -} catch (e) { - var conn = MongoRunner.runMongod(); - if (!conn.getDB('admin').serverStatus().storageEngine.supportsCommittedReads) { - jsTest.log("skipping test since storage engine doesn't support committed reads"); - MongoRunner.stopMongod(conn); - return; - } - throw e; +if (!startSetIfSupportsReadMajority(replTest)) { + jsTest.log("skipping test since storage engine doesn't support committed reads"); + return; } +var nodes = replTest.nodeList(); replTest.initiate({"_id": name, "members": [ { "_id": 0, "host": nodes[0] }, diff --git a/jstests/replsets/read_committed_on_secondary.js b/jstests/replsets/read_committed_on_secondary.js index 92409532823..1adf9dffae6 100644 --- a/jstests/replsets/read_committed_on_secondary.js +++ b/jstests/replsets/read_committed_on_secondary.js @@ -1,4 +1,11 @@ -// Test basic read committed functionality on a secondary. +/** + * Test basic read committed functionality on a secondary: + * - Updates should not be visible until they are in the blessed snapshot. + * - Updates should be visible once they are in the blessed snapshot. + */ + +load("jstests/replsets/rslib.js"); // For startSetIfSupportsReadMajority. + (function() { "use strict"; @@ -7,20 +14,13 @@ var name = "read_committed_on_secondary"; var replTest = new ReplSetTest({name: name, nodes: 3, nodeOptions: {enableMajorityReadConcern: ''}}); -var nodes = replTest.nodeList(); -try { - replTest.startSet(); -} catch (e) { - var conn = MongoRunner.runMongod(); - if (!conn.getDB('admin').serverStatus().storageEngine.supportsCommittedReads) { - jsTest.log("skipping test since storage engine doesn't support committed reads"); - MongoRunner.stopMongod(conn); - return; - } - throw e; +if (!startSetIfSupportsReadMajority(replTest)) { + jsTest.log("skipping test since storage engine doesn't support committed reads"); + return; } +var nodes = replTest.nodeList(); replTest.initiate({"_id": name, "members": [ { "_id": 0, "host": nodes[0] }, diff --git a/jstests/replsets/read_majority_two_arbs.js b/jstests/replsets/read_majority_two_arbs.js index 3f515024abf..824b733eaba 100644 --- a/jstests/replsets/read_majority_two_arbs.js +++ b/jstests/replsets/read_majority_two_arbs.js @@ -1,5 +1,10 @@ -// Test read committed and writeConcern: "majority" work properly with all other nodes being -// arbiters. +/** + * Tests that writeConcern 'majority' writes succeed and are visible in a replica set that has one + * data-bearing node and two arbiters. + */ + +load("jstests/replsets/rslib.js"); // For startSetIfSupportsReadMajority. + (function() { "use strict"; @@ -8,20 +13,13 @@ var name = "read_majority_two_arbs"; var replTest = new ReplSetTest({name: name, nodes: 3, nodeOptions: {enableMajorityReadConcern: ''}}); -var nodes = replTest.nodeList(); -try { - replTest.startSet(); -} catch (e) { - var conn = MongoRunner.runMongod(); - if (!conn.getDB('admin').serverStatus().storageEngine.supportsCommittedReads) { - jsTest.log("skipping test since storage engine doesn't support committed reads"); - MongoRunner.stopMongod(conn); - return; - } - throw e; +if (!startSetIfSupportsReadMajority(replTest)) { + jsTest.log("skipping test since storage engine doesn't support committed reads"); + return; } +var nodes = replTest.nodeList(); replTest.initiate({"_id": name, "members": [ {"_id": 0, "host": nodes[0]}, diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js index 6635c4be14b..f3dcdd3d204 100644 --- a/jstests/replsets/rslib.js +++ b/jstests/replsets/rslib.js @@ -1,4 +1,11 @@ -var wait, occasionally, reconnect, getLatestOp, waitForAllMembers, reconfig, awaitOpTime; +var wait; +var occasionally; +var reconnect; +var getLatestOp; +var waitForAllMembers; +var reconfig; +var awaitOpTime; +var startSetIfSupportsReadMajority; var waitUntilAllNodesCaughtUp; (function () { @@ -181,4 +188,25 @@ waitUntilAllNodesCaughtUp = function(rs) { }); }; +/** + * Starts each node in the given replica set if the storage engine supports readConcern 'majority'. + * Returns true if the replica set was started successfully and false otherwise. + * + * @param replSetTest - The instance of {@link ReplSetTest} to start + * @param options - The options passed to {@link ReplSetTest.startSet} + */ +startSetIfSupportsReadMajority = function (replSetTest, options) { + try { + replSetTest.startSet(options); + } catch (e) { + var conn = MongoRunner.runMongod(); + if (!conn.getDB("admin").serverStatus().storageEngine.supportsCommittedReads) { + MongoRunner.stopMongod(conn); + return false; + } + throw e; + } + return true; +}; + }()); diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index e3faa335573..6d2d4baae60 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -377,6 +377,11 @@ var ReplSetTest = function(opts) { return this.name + "/" + hosts.join(","); }; + /** + * Starts each node in the replica set with the given options. + * + * @param options - The options passed to {@link MongoRunner.runMongod} + */ this.startSet = function(options) { print("ReplSetTest starting set");