summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheahuychou Mao <cheahuychou.mao@mongodb.com>2019-10-10 13:39:03 +0000
committerevergreen <evergreen@mongodb.com>2019-10-10 13:39:03 +0000
commit0efcbe92a9888c684472439844822e7e98885802 (patch)
tree15ed1bd224d4351fafa5b1908892c194b0d14796
parent69ef3ed5cf4ac634fd7a749f9428871ec6f40fd2 (diff)
downloadmongo-0efcbe92a9888c684472439844822e7e98885802.tar.gz
SERVER-10720 Add a way for getShardVersion on mongos to return the full cached chunk distribution for a collection
-rw-r--r--jstests/sharding/mongos_get_shard_version.js101
-rw-r--r--src/mongo/s/commands/cluster_get_shard_version_cmd.cpp25
2 files changed, 122 insertions, 4 deletions
diff --git a/jstests/sharding/mongos_get_shard_version.js b/jstests/sharding/mongos_get_shard_version.js
new file mode 100644
index 00000000000..ecd383772e4
--- /dev/null
+++ b/jstests/sharding/mongos_get_shard_version.js
@@ -0,0 +1,101 @@
+/**
+ * Test that mongos getShardVersion returns the correct version and chunks.
+ */
+(function() {
+'use strict';
+
+const st = new ShardingTest({shards: 2, mongos: 1});
+const dbName = "test";
+const collName = "foo";
+const ns = dbName + "." + collName;
+const primaryShard = st.shard0;
+const otherShard = st.shard1;
+const min = {
+ x: MinKey,
+ y: MinKey
+};
+const max = {
+ x: MaxKey,
+ y: MaxKey
+};
+
+assert.commandWorked(st.s.adminCommand({enablesharding: dbName}));
+st.ensurePrimaryShard(dbName, primaryShard.shardName);
+assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1, y: 1}}));
+
+// Check shard version.
+let res = st.s.adminCommand({getShardVersion: ns});
+assert.commandWorked(res);
+assert.eq(res.version.t, 1);
+assert.eq(res.version.i, 0);
+assert.eq(undefined, res.chunks);
+
+// When fullMetadata set to true, chunks should be included in the response
+// if the mongos version is v4.4.
+res = st.s.adminCommand({getShardVersion: ns, fullMetadata: true});
+assert.commandWorked(res);
+assert.eq(res.version.t, 1);
+assert.eq(res.version.i, 0);
+if (jsTestOptions().mongosBinVersion == "last-stable") {
+ assert.eq(undefined, res.chunks);
+} else {
+ assert.eq(1, res.chunks.length);
+ assert.eq(min, res.chunks[0][0]);
+ assert.eq(max, res.chunks[0][1]);
+}
+
+// Split the existing chunks to create a large number of chunks (> 16MB).
+// This needs to be done twice since the BSONObj size limit also applies
+// to command objects for commands like splitChunk.
+
+// The chunk min and max need to be large, otherwise we need a lot more
+// chunks to reach the size limit.
+const splitPoint = {
+ x: 0,
+ y: "A".repeat(512)
+};
+
+let splitPoints = [];
+for (let i = 0; i < 10000; i++) {
+ splitPoints.push({x: i, y: splitPoint.y});
+}
+assert.commandWorked(st.rs0.getPrimary().getDB('admin').runCommand({
+ splitChunk: ns,
+ from: st.shard0.shardName,
+ min: min,
+ max: max,
+ keyPattern: {x: 1},
+ splitKeys: splitPoints,
+ epoch: res.versionEpoch,
+}));
+
+let prevMin = splitPoints[splitPoints.length - 1];
+splitPoints = [];
+for (let i = 10000; i < 20000; i++) {
+ splitPoints.push({x: i, y: splitPoint.y});
+}
+assert.commandWorked(st.rs0.getPrimary().getDB('admin').runCommand({
+ splitChunk: ns,
+ from: st.shard0.shardName,
+ min: prevMin,
+ max: max,
+ keyPattern: {x: 1},
+ splitKeys: splitPoints,
+ epoch: res.versionEpoch,
+}));
+
+// Move a chunk so that mongos's routing entry gets marked as stale, making
+// the next getShardVersion trigger a refresh.
+assert.commandWorked(
+ st.s.adminCommand({moveChunk: ns, find: splitPoint, to: otherShard.shardName}));
+
+// Chunks should not be included in the response regardless of the mongos version
+// because the chunk size exceeds the limit.
+res = st.s.adminCommand({getShardVersion: ns, fullMetadata: true});
+assert.commandWorked(res);
+assert.eq(res.version.t, 4);
+assert.eq(res.version.i, 1);
+assert.eq(undefined, res.chunks);
+
+st.stop();
+})();
diff --git a/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp b/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp
index 48f090d10ee..78b3021a698 100644
--- a/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp
+++ b/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp
@@ -107,12 +107,29 @@ public:
str::stream() << "Collection " << nss.ns() << " is not sharded.",
cachedCollInfo.cm());
const auto cm = cachedCollInfo.cm();
+ cm->getVersion().appendLegacyWithField(&result, "version");
- for (const auto& chunk : cm->chunks()) {
- log() << redact(chunk.toString());
+ if (cmdObj["fullMetadata"].trueValue()) {
+ BSONArrayBuilder chunksArrBuilder;
+ bool exceedsSizeLimit = false;
+
+ for (const auto& chunk : cm->chunks()) {
+ log() << redact(chunk.toString());
+ if (!exceedsSizeLimit) {
+ BSONArrayBuilder chunkBB(chunksArrBuilder.subarrayStart());
+ chunkBB.append(chunk.getMin());
+ chunkBB.append(chunk.getMax());
+ chunkBB.done();
+ if (chunksArrBuilder.len() + result.len() > BSONObjMaxUserSize) {
+ exceedsSizeLimit = true;
+ }
+ }
+ }
+
+ if (!exceedsSizeLimit) {
+ result.append("chunks", chunksArrBuilder.arr());
+ }
}
-
- cm->getVersion().appendLegacyWithField(&result, "version");
}
return true;