diff options
author | Justin Seyster <justin.seyster@mongodb.com> | 2018-06-07 15:23:06 -0400 |
---|---|---|
committer | Justin Seyster <justin.seyster@mongodb.com> | 2018-06-08 16:02:58 -0400 |
commit | 73798323b769485ae18a4515c5f5a2cf035d7605 (patch) | |
tree | 23f651ee2294377795152a441b9d692d5c8f4335 /jstests/replsets | |
parent | dbb8a02faa82c2e31307582030f20899c200af29 (diff) | |
download | mongo-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.js | 83 |
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(); +}()); |