summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Buerger <will.buerger@mongodb.com>2022-10-25 19:10:50 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-25 19:36:49 +0000
commita6d7c6b9ada09016da5868f23e3f199854210116 (patch)
treefbd3fd15ad4775eca71be75ee8903310a565d3b3
parent3e5eb8d128d8ab72c4f25e0392af333384bf6db5 (diff)
downloadmongo-a6d7c6b9ada09016da5868f23e3f199854210116.tar.gz
SERVER-69036: Avoid intermediate rounding in cluster_db_stats_cmd
-rw-r--r--jstests/noPassthrough/dbstats_sharded_collection.js101
-rw-r--r--src/mongo/s/commands/cluster_db_stats_cmd.cpp16
2 files changed, 109 insertions, 8 deletions
diff --git a/jstests/noPassthrough/dbstats_sharded_collection.js b/jstests/noPassthrough/dbstats_sharded_collection.js
new file mode 100644
index 00000000000..a724fc8b90b
--- /dev/null
+++ b/jstests/noPassthrough/dbstats_sharded_collection.js
@@ -0,0 +1,101 @@
+/**
+ * Tests that the dbStats command properly computes the stats by comparing the results from a
+ * sharded cluster to the summation of querying the mongod's directly.
+ *
+ * @tags: [requires_dbstats]
+ */
+
+(function() {
+"use strict";
+
+// Set up cluster with 2 shards, insert a batch of documents, and configure the cluster so both
+// shards have documents.
+const st = new ShardingTest({shards: 2, mongos: 1});
+const dbName = "db";
+const db = st.getDB(dbName);
+const collName = "foo";
+const ns = dbName + "." + collName;
+const numDocs = 100;
+
+assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
+
+let primaryShard = st.getPrimaryShard(dbName);
+let secondaryShard = st.getOther(primaryShard);
+
+let bulk = primaryShard.getCollection(ns).initializeUnorderedBulkOp();
+for (let i = 0; i < numDocs; i++) {
+ bulk.insert({_id: i, x: i, y: -i});
+}
+assert.commandWorked(bulk.execute());
+assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {_id: 1}}));
+assert.commandWorked(st.s.adminCommand({split: ns, middle: {_id: numDocs / 2}}));
+assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {_id: 0}, to: secondaryShard.name}));
+
+const scale = 1024 * 1024;
+let dbStats = db.runCommand({dbStats: 1, scale: scale});
+assert.commandWorked(dbStats);
+let shard0Stats = primaryShard.getDB(dbName).runCommand({dbStats: 1, scale: scale});
+assert.commandWorked(shard0Stats);
+let shard1Stats = secondaryShard.getDB(dbName).runCommand({dbStats: 1, scale: scale});
+assert.commandWorked(shard1Stats);
+
+// Compare each of the relevant fields in dbStats to make sure the individual shards' responses sum
+// to the overall cluster's value.
+let total = shard0Stats.collections + shard1Stats.collections;
+assert.eq(dbStats.collections,
+ total,
+ "Sharded collection dbStats returned " + dbStats.collections +
+ " collections total, but sum of inidividual shards' responses returned " + total +
+ " collections total");
+
+total = shard0Stats.views + shard1Stats.views;
+assert.eq(dbStats.views,
+ total,
+ "Sharded collection dbStats returned " + dbStats.views +
+ " views total, but sum of inidividual shards' responses returned " + total +
+ " views total");
+
+total = shard0Stats.objects + shard1Stats.objects;
+assert.eq(dbStats.objects,
+ total,
+ "Sharded collection dbStats returned " + dbStats.objects +
+ " objects total, but sum of inidividual shards' responses returned " + total +
+ " objects total");
+
+total = shard0Stats.dataSize + shard1Stats.dataSize;
+assert.eq(dbStats.dataSize,
+ total,
+ "Sharded collection dbStats returned " + dbStats.dataSize +
+ " dataSize total, but sum of inidividual shards' responses returned " + total +
+ " dataSize total");
+
+total = shard0Stats.storageSize + shard1Stats.storageSize;
+assert.eq(dbStats.storageSize,
+ total,
+ "Sharded collection dbStats returned " + dbStats.storageSize +
+ " storageSize total, but sum of inidividual shards' responses returned " + total +
+ " storageSize total");
+
+total = shard0Stats.indexes + shard1Stats.indexes;
+assert.eq(dbStats.indexes,
+ total,
+ "Sharded collection dbStats returned " + dbStats.indexes +
+ " indexes total, but sum of inidividual shards' responses returned " + total +
+ " indexes total");
+
+total = shard0Stats.indexSize + shard1Stats.indexSize;
+assert.eq(dbStats.indexSize,
+ total,
+ "Sharded collection dbStats returned " + dbStats.indexSize +
+ " indexSize total, but sum of inidividual shards' responses returned " + total +
+ " indexSize total");
+
+total = shard0Stats.totalSize + shard1Stats.totalSize;
+assert.eq(dbStats.totalSize,
+ total,
+ "Sharded collection dbStats returned " + dbStats.totalSize +
+ " totalSize total, but sum of inidividual shards' responses returned " + total +
+ " totalSize total");
+
+st.stop();
+})(); \ No newline at end of file
diff --git a/src/mongo/s/commands/cluster_db_stats_cmd.cpp b/src/mongo/s/commands/cluster_db_stats_cmd.cpp
index 16c3d17f91d..cbfa95d0192 100644
--- a/src/mongo/s/commands/cluster_db_stats_cmd.cpp
+++ b/src/mongo/s/commands/cluster_db_stats_cmd.cpp
@@ -47,14 +47,14 @@ void aggregateResults(int scale,
long long collections = 0;
long long views = 0;
long long objects = 0;
- long long unscaledDataSize = 0;
- long long dataSize = 0;
- long long storageSize = 0;
- long long totalSize = 0;
+ double unscaledDataSize = 0;
+ double dataSize = 0;
+ double storageSize = 0;
+ double totalSize = 0;
long long indexes = 0;
- long long indexSize = 0;
- long long fsUsedSize = 0;
- long long fsTotalSize = 0;
+ double indexSize = 0;
+ double fsUsedSize = 0;
+ double fsTotalSize = 0;
for (const auto& response : responses) {
invariant(response.swResponse.getStatus().isOK());
@@ -80,7 +80,7 @@ void aggregateResults(int scale,
// avgObjSize on mongod is not scaled based on the argument to db.stats(), so we use
// unscaledDataSize here for consistency. See SERVER-7347.
- output.append("avgObjSize", objects == 0 ? 0 : double(unscaledDataSize) / double(objects));
+ output.appendNumber("avgObjSize", objects == 0 ? 0 : unscaledDataSize / double(objects));
output.appendNumber("dataSize", dataSize);
output.appendNumber("storageSize", storageSize);
output.appendNumber("totalSize", totalSize);