diff options
author | Will Buerger <will.buerger@mongodb.com> | 2022-10-25 19:10:50 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-10-25 19:36:49 +0000 |
commit | a6d7c6b9ada09016da5868f23e3f199854210116 (patch) | |
tree | fbd3fd15ad4775eca71be75ee8903310a565d3b3 | |
parent | 3e5eb8d128d8ab72c4f25e0392af333384bf6db5 (diff) | |
download | mongo-a6d7c6b9ada09016da5868f23e3f199854210116.tar.gz |
SERVER-69036: Avoid intermediate rounding in cluster_db_stats_cmd
-rw-r--r-- | jstests/noPassthrough/dbstats_sharded_collection.js | 101 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_db_stats_cmd.cpp | 16 |
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); |