summaryrefslogtreecommitdiff
path: root/jstests/replsets
diff options
context:
space:
mode:
authorJustin Seyster <justin.seyster@mongodb.com>2018-06-07 15:23:06 -0400
committerJustin Seyster <justin.seyster@mongodb.com>2018-06-08 16:02:58 -0400
commit73798323b769485ae18a4515c5f5a2cf035d7605 (patch)
tree23f651ee2294377795152a441b9d692d5c8f4335 /jstests/replsets
parentdbb8a02faa82c2e31307582030f20899c200af29 (diff)
downloadmongo-73798323b769485ae18a4515c5f5a2cf035d7605.tar.gz
SERVER-35365 MapReduce should write "inc" collections to "local" db.
(cherry picked from commit 30ac39448a0c83bb12fd4d0fa537e8292be20d08)
Diffstat (limited to 'jstests/replsets')
-rw-r--r--jstests/replsets/mr_nonrepl_coll_in_local_db.js83
1 files changed, 83 insertions, 0 deletions
diff --git a/jstests/replsets/mr_nonrepl_coll_in_local_db.js b/jstests/replsets/mr_nonrepl_coll_in_local_db.js
new file mode 100644
index 00000000000..2b6cd66617e
--- /dev/null
+++ b/jstests/replsets/mr_nonrepl_coll_in_local_db.js
@@ -0,0 +1,83 @@
+// All collections created during a map-reduce should be replicated to secondaries unless they are
+// in the "local" or "admin" databases. Any collection outside of "local" that does not get
+// replicated is a potential problem for workloads with transactions (see SERVER-35365 and
+// SERVER-35282).
+//
+// We verify this requirement by running a map-reduce, examining the logs to find the names of
+// all collections created, and checking the oplog for entries logging the creation of each of those
+// collections.
+(function() {
+ "use strict";
+
+ load("jstests/libs/check_log.js");
+
+ const name = "mr_nonrepl_coll_in_local_db";
+ const replSet = new ReplSetTest({name: name, nodes: 2});
+ replSet.startSet();
+ replSet.initiate();
+
+ const dbName = name;
+ const collName = "test";
+
+ const primary = replSet.getPrimary();
+ const primaryDB = primary.getDB(dbName);
+ const coll = primaryDB[collName];
+
+ // Insert 1000 documents in the "test" collection.
+ const bulk = coll.initializeUnorderedBulkOp();
+ for (let i = 0; i < 1000; i++) {
+ const array = Array.from({lengthToInsert: 10000}, _ => Math.floor(Math.random() * 100));
+ bulk.insert({arr: array});
+ }
+ assert.writeOK(bulk.execute());
+
+ // Run a simple map-reduce.
+ const result = coll.mapReduce(
+ function map() {
+ return this.arr.forEach(element => emit(element, 1));
+ },
+ function reduce(key, values) {
+ return Array.sum(values);
+ },
+ {query: {arr: {$exists: true}}, out: "mr_result"});
+ assert.commandWorked(result);
+
+ // Examine the logs to find a list of created collections.
+ const logLines = checkLog.getGlobalLog(primaryDB);
+ let createdCollections = [];
+ logLines.forEach(function(line) {
+ let matchResult = line.match(/createCollection: (.+) with/);
+ if (matchResult) {
+ createdCollections.push(matchResult[1]);
+ }
+ });
+
+ createdCollections.forEach(function(createdCollectionName) {
+ if (createdCollectionName.startsWith("admin.")) {
+ // Although the "admin.system.version" collection is replicated, no "c" entry gets
+ // created for it in the oplog, so this test would see it as unreplicated. In general,
+ // this test is not concerned with the "admin" database, so we don't examine any "admin"
+ // collections.
+ return;
+ }
+
+ // Search for a log entry for the creation of this collection.
+ const oplogEntries = primaryDB.getSiblingDB("local")["oplog.rs"]
+ .find({op: "c", "o.idIndex.ns": createdCollectionName})
+ .toArray();
+ if (createdCollectionName.startsWith("local.")) {
+ // We do not want to see any replication of "local" collections.
+ assert.eq(oplogEntries.length,
+ 0,
+ "Found unexpected oplog entry for creation of " + createdCollectionName +
+ ": " + tojson(oplogEntries));
+ } else {
+ assert.eq(oplogEntries.length,
+ 1,
+ "Found no oplog entry or too many entries for creation of " +
+ createdCollectionName + ": " + tojson(oplogEntries));
+ }
+ });
+
+ replSet.stopSet();
+}());