summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Zolnierz <nicholas.zolnierz@mongodb.com>2020-01-13 18:38:37 +0000
committerevergreen <evergreen@mongodb.com>2020-01-13 18:38:37 +0000
commit0460c5964375a50df62811e36a40fc5abf8c7a5a (patch)
treed8ffac8e769b4f5dac4043d52c66aca6a447a431
parentcf013cac38ee4b655c990fd0db341298a8d6d563 (diff)
downloadmongo-0460c5964375a50df62811e36a40fc5abf8c7a5a.tar.gz
SERVER-44477 Use correct collection count in cluster MR when determining whether to drop and reshard target
-rw-r--r--buildscripts/resmokeconfig/suites/sharding_last_stable_mongos_and_mixed_shards.yml3
-rw-r--r--jstests/sharding/mapReduce_outSharded_checkUUID.js6
-rw-r--r--jstests/sharding/mr_merge_to_existing.js61
-rw-r--r--src/mongo/s/commands/cluster_map_reduce_cmd.cpp19
4 files changed, 71 insertions, 18 deletions
diff --git a/buildscripts/resmokeconfig/suites/sharding_last_stable_mongos_and_mixed_shards.yml b/buildscripts/resmokeconfig/suites/sharding_last_stable_mongos_and_mixed_shards.yml
index 57df1df78bc..2171d2d739e 100644
--- a/buildscripts/resmokeconfig/suites/sharding_last_stable_mongos_and_mixed_shards.yml
+++ b/buildscripts/resmokeconfig/suites/sharding_last_stable_mongos_and_mixed_shards.yml
@@ -116,7 +116,8 @@ selector:
- jstests/sharding/explain_cmd.js
# Enable when SERVER-44733 is backported
- jstests/sharding/change_streams_update_lookup_shard_metadata_missing.js
-
+ # Enable after SERVER-44477 is backported and available on older binaries.
+ - jstests/sharding/mr_merge_to_existing.js
executor:
config:
shell_options:
diff --git a/jstests/sharding/mapReduce_outSharded_checkUUID.js b/jstests/sharding/mapReduce_outSharded_checkUUID.js
index 0de45c127c7..4a0044c563c 100644
--- a/jstests/sharding/mapReduce_outSharded_checkUUID.js
+++ b/jstests/sharding/mapReduce_outSharded_checkUUID.js
@@ -35,6 +35,7 @@
bulk.insert({j: j, i: i});
}
}
+
assert.writeOK(bulk.execute());
function map() {
@@ -47,14 +48,14 @@
// sharded src sharded dst
var suffix = "InShardedOutSharded";
- // Check that merge to an existing empty sharded collection works and creates a new UUID after
+ // Check that merge to an existing empty sharded collection works and preserves the UUID after
// M/R
st.adminCommand({shardcollection: "mrShard.outSharded", key: {"_id": 1}});
var origUUID = getUUIDFromConfigCollections(st.s, "mrShard.outSharded");
var out = db.srcSharded.mapReduce(map, reduce, {out: {merge: "outSharded", sharded: true}});
verifyOutput(out, 512);
var newUUID = getUUIDFromConfigCollections(st.s, "mrShard.outSharded");
- assert.neq(origUUID, newUUID);
+ assert.eq(origUUID, newUUID);
// Shard1 is the primary shard and only one chunk should have been written, so the chunk with
// the new UUID should have been written to it.
@@ -166,5 +167,4 @@
assert.eq(newUUID, getUUIDFromListCollections(st.shard1.getDB("mrShard"), "replaceUnsharded"));
st.stop();
-
})();
diff --git a/jstests/sharding/mr_merge_to_existing.js b/jstests/sharding/mr_merge_to_existing.js
new file mode 100644
index 00000000000..53f2263c74b
--- /dev/null
+++ b/jstests/sharding/mr_merge_to_existing.js
@@ -0,0 +1,61 @@
+// Test that running mapReduce to a target collection which is empty on the primary shard does *not*
+// drop and reshard it.
+(function() {
+
+ load("jstests/libs/fixture_helpers.js");
+
+ var st = new ShardingTest({
+ shards: 2,
+ rs: {nodes: 2},
+ });
+
+ const dbName = "test";
+ const collName = jsTestName();
+
+ let mongosConn = st.s;
+ assert.commandWorked(mongosConn.getDB(dbName).runCommand({create: collName}));
+ st.ensurePrimaryShard(dbName, st.shard0.shardName);
+
+ // Shard the test collection and split it into two chunks.
+ st.shardColl(collName,
+ {_id: 1} /* Shard key */,
+ {_id: 2} /* Split at */,
+ {_id: 2} /* Move the chunk to its own shard */,
+ dbName,
+ true /* Wait until documents orphaned by the move get deleted */);
+
+ // Seed the source collection.
+ let sourceColl = mongosConn.getDB(dbName)[collName];
+ assert.commandWorked(sourceColl.insert({key: 1}));
+ assert.commandWorked(sourceColl.insert({key: 2}));
+ assert.commandWorked(sourceColl.insert({key: 3}));
+ assert.commandWorked(sourceColl.insert({key: 4}));
+
+ // Shard the target collection.
+ let mergeColl = mongosConn.getDB(dbName).mr_merge_out;
+ st.shardColl("mr_merge_out",
+ {_id: 1} /* Shard key */,
+ {_id: 2} /* Split at */,
+ {_id: 2} /* Move the chunk containing {_id: 2} to its own shard */,
+ dbName);
+
+ // Insert a single document to the target collection and ensure that it lives on the non-primary
+ // shard.
+ assert.commandWorked(mergeColl.insert({_id: 5, value: 1}));
+
+ function map() {
+ emit(this.key, 1);
+ }
+ function reduce(key, values) {
+ return Array.sum(values);
+ }
+
+ // Run the mapReduce to merge to the existing sharded collection.
+ assert.commandWorked(
+ sourceColl.mapReduce(map, reduce, {out: {merge: mergeColl.getName(), sharded: true}}));
+
+ // Verify that the previous document still exists in the target collection.
+ assert.eq(mergeColl.find({_id: 5}).itcount(), 1);
+
+ st.stop();
+})();
diff --git a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
index a829839a03b..850ad34d49d 100644
--- a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
+++ b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
@@ -479,18 +479,16 @@ public:
// We need to determine whether we need to drop and shard the output collection and
// send the UUID to the shards. We will always do this if we are using replace so we
// can skip this check in that case. If using merge or reduce, we only want to do this
- // if the output collection does not exist or if it exists and is an empty sharded
- // collection.
+ // if the output collection does not exist.
bool shouldDropAndShard = replaceOutput;
if (!replaceOutput && outputCollNss.isValid()) {
- const auto primaryShard =
- uassertStatusOK(shardRegistry->getShard(opCtx, outputDbInfo.primaryId()));
- ScopedDbConnection conn(primaryShard->getConnString());
-
if (!outputRoutingInfo.cm()) {
// The output collection either exists and is unsharded, or does not exist. If
// the output collection exists and is unsharded, fail because we should not go
// from unsharded to sharded.
+ const auto primaryShard =
+ uassertStatusOK(shardRegistry->getShard(opCtx, outputDbInfo.primaryId()));
+ ScopedDbConnection conn(primaryShard->getConnString());
BSONObj listCollsCmdResponse;
ok = conn->runCommand(
outDB,
@@ -507,15 +505,8 @@ public:
// If we reach here, the collection does not exist at all.
shouldDropAndShard = true;
- } else {
- // The output collection exists and is sharded. We need to determine whether the
- // collection is empty in order to decide whether we should drop and re-shard
- // it.
- // We don't want to do this if the collection is not empty.
- shouldDropAndShard = (conn->count(outputCollNss.ns()) == 0);
+ conn.done();
}
-
- conn.done();
}
// If we are using replace, the output collection exists and is sharded, or the output