summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2021-03-02 16:04:42 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-17 21:35:07 +0000
commit9d1a5300f40c6b8969ea5643c2b48361c2582b2e (patch)
tree821bba0d88c140bb9d748a0b3f627a072dc5b2af
parenta100482f36a17780de17a768da4c8bd74713f727 (diff)
downloadmongo-9d1a5300f40c6b8969ea5643c2b48361c2582b2e.tar.gz
SERVER-54470 Use IDL to parse $collStats
-rw-r--r--jstests/aggregation/sources/collStats/count.js8
-rw-r--r--jstests/aggregation/sources/collStats/query_exec_stats.js4
-rw-r--r--src/mongo/db/commands/dbcommands.cpp4
-rw-r--r--src/mongo/db/pipeline/SConscript7
-rw-r--r--src/mongo/db/pipeline/document_source_coll_stats.cpp70
-rw-r--r--src/mongo/db/pipeline/document_source_coll_stats.h28
-rw-r--r--src/mongo/db/pipeline/document_source_coll_stats.idl69
-rw-r--r--src/mongo/db/pipeline/document_source_parsing_validators.cpp46
-rw-r--r--src/mongo/db/pipeline/document_source_parsing_validators.h38
-rw-r--r--src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp4
-rw-r--r--src/mongo/db/pipeline/process_interface/common_mongod_process_interface.h2
-rw-r--r--src/mongo/db/pipeline/process_interface/mongo_process_interface.h3
-rw-r--r--src/mongo/db/pipeline/process_interface/mongos_process_interface.h2
-rw-r--r--src/mongo/db/pipeline/process_interface/stub_mongo_process_interface.h2
-rw-r--r--src/mongo/db/pipeline/storage_stats_spec.idl50
-rw-r--r--src/mongo/db/stats/SConscript3
-rw-r--r--src/mongo/db/stats/storage_stats.cpp17
-rw-r--r--src/mongo/db/stats/storage_stats.h5
18 files changed, 266 insertions, 96 deletions
diff --git a/jstests/aggregation/sources/collStats/count.js b/jstests/aggregation/sources/collStats/count.js
index 334f42766e4..7b6117c1b94 100644
--- a/jstests/aggregation/sources/collStats/count.js
+++ b/jstests/aggregation/sources/collStats/count.js
@@ -21,9 +21,13 @@ assertErrorCode(coll, pipeline, 40602);
// Test that an error is returned if count is not an object.
pipeline = [{$collStats: {count: 1}}];
-assertErrorCode(coll, pipeline, 40480, "count spec must be an object");
+assertErrorCode(coll, pipeline, ErrorCodes.TypeMismatch, "count spec must be an object");
pipeline = [{$collStats: {count: "1"}}];
-assertErrorCode(coll, pipeline, 40480, "count spec must be an object");
+assertErrorCode(coll, pipeline, ErrorCodes.TypeMismatch, "count spec must be an object");
+
+// Test that an error is returned if count is not an empty object.
+pipeline = [{$collStats: {count: {unrecognized: 1}}}];
+assertErrorCode(coll, pipeline, 31170, "count spec must be an empty object");
// Test the accuracy of the record count as a standalone option.
pipeline = [{$collStats: {count: {}}}];
diff --git a/jstests/aggregation/sources/collStats/query_exec_stats.js b/jstests/aggregation/sources/collStats/query_exec_stats.js
index a5b5ee687de..7e4495befe6 100644
--- a/jstests/aggregation/sources/collStats/query_exec_stats.js
+++ b/jstests/aggregation/sources/collStats/query_exec_stats.js
@@ -27,9 +27,9 @@ for (let i = 0; i < nDocs; i++) {
// Test that an error is returned if queryExecStats is not an object.
let pipeline = [{$collStats: {queryExecStats: 1}}];
-assertErrorCode(coll, pipeline, 31141, "queryExecStats spec must be an object");
+assertErrorCode(coll, pipeline, ErrorCodes.TypeMismatch, "queryExecStats spec must be an object");
pipeline = [{$collStats: {queryExecStats: "1"}}];
-assertErrorCode(coll, pipeline, 31141, "queryExecStats spec must be an object");
+assertErrorCode(coll, pipeline, ErrorCodes.TypeMismatch, "queryExecStats spec must be an object");
// Test the accuracy of the result of queryExecStats as a standalone option.
pipeline = [{$collStats: {queryExecStats: {}}}];
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 0a8923e5097..85c1d0b5e01 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -75,6 +75,7 @@
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/insert.h"
#include "mongo/db/pipeline/document_source_internal_unpack_bucket.h"
+#include "mongo/db/pipeline/storage_stats_spec_gen.h"
#include "mongo/db/query/collation/collator_factory_interface.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/internal_plans.h"
@@ -513,7 +514,8 @@ public:
}
result.append("ns", nss.ns());
- Status status = appendCollectionStorageStats(opCtx, nss, jsobj, &result);
+ auto spec = StorageStatsSpec::parse(IDLParserErrorContext("collStats"), jsobj);
+ Status status = appendCollectionStorageStats(opCtx, nss, spec, &result);
if (!status.isOK() && status.code() != ErrorCodes::NamespaceNotFound) {
errmsg = status.reason();
return false;
diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript
index fd8e7f036ec..b73c1e533d5 100644
--- a/src/mongo/db/pipeline/SConscript
+++ b/src/mongo/db/pipeline/SConscript
@@ -329,16 +329,19 @@ env.Library(
target='document_sources_idl',
source=[
'document_source_change_stream.idl',
+ 'document_source_coll_stats.idl',
'document_source_list_sessions.idl',
'document_source_merge.idl',
'document_source_merge_modes.idl',
+ 'document_source_merge_spec.cpp',
+ 'document_source_parsing_validators.cpp',
'document_source_replace_root.idl',
'document_source_set_window_fields.idl',
'document_source_union_with.idl',
'exchange_spec.idl',
+ 'resume_token.cpp',
+ 'storage_stats_spec.idl',
'value.idl',
- 'document_source_merge_spec.cpp',
- 'resume_token.cpp'
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
diff --git a/src/mongo/db/pipeline/document_source_coll_stats.cpp b/src/mongo/db/pipeline/document_source_coll_stats.cpp
index 30b7255e1ce..84f57642004 100644
--- a/src/mongo/db/pipeline/document_source_coll_stats.cpp
+++ b/src/mongo/db/pipeline/document_source_coll_stats.cpp
@@ -55,48 +55,10 @@ intrusive_ptr<DocumentSource> DocumentSourceCollStats::createFromBson(
uassert(40166,
str::stream() << "$collStats must take a nested object but found: " << specElem,
specElem.type() == BSONType::Object);
- intrusive_ptr<DocumentSourceCollStats> collStats(new DocumentSourceCollStats(pExpCtx));
-
- for (const auto& elem : specElem.embeddedObject()) {
- StringData fieldName = elem.fieldNameStringData();
-
- if ("latencyStats" == fieldName) {
- uassert(40167,
- str::stream() << "latencyStats argument must be an object, but got " << elem
- << " of type " << typeName(elem.type()),
- elem.type() == BSONType::Object);
- if (!elem["histograms"].eoo()) {
- uassert(40305,
- str::stream() << "histograms option to latencyStats must be bool, got "
- << elem << "of type " << typeName(elem.type()),
- elem["histograms"].isBoolean());
- }
- } else if ("storageStats" == fieldName) {
- uassert(40279,
- str::stream() << "storageStats argument must be an object, but got " << elem
- << " of type " << typeName(elem.type()),
- elem.type() == BSONType::Object);
- } else if ("count" == fieldName) {
- uassert(40480,
- str::stream() << "count argument must be an object, but got " << elem
- << " of type " << typeName(elem.type()),
- elem.type() == BSONType::Object);
- } else if ("queryExecStats" == fieldName) {
- uassert(31141,
- str::stream() << "queryExecStats argument must be an empty object, but got "
- << elem << " of type " << typeName(elem.type()),
- elem.type() == BSONType::Object);
- uassert(31170,
- str::stream() << "queryExecStats argument must be an empty object, but got "
- << elem,
- elem.embeddedObject().isEmpty());
- } else {
- uasserted(40168, str::stream() << "unrecognized option to $collStats: " << fieldName);
- }
- }
+ auto spec = DocumentSourceCollStatsSpec::parse(IDLParserErrorContext(kStageName),
+ specElem.embeddedObject());
- collStats->_collStatsSpec = specElem.Obj().getOwned();
- return collStats;
+ return make_intrusive<DocumentSourceCollStats>(pExpCtx, std::move(spec));
}
DocumentSource::GetNextResult DocumentSourceCollStats::doGetNext() {
@@ -119,33 +81,27 @@ DocumentSource::GetNextResult DocumentSourceCollStats::doGetNext() {
builder.append("host", getHostNameCachedAndPort());
builder.appendDate("localTime", jsTime());
- if (_collStatsSpec.hasField("latencyStats")) {
- // If the latencyStats field exists, it must have been validated as an object when parsing.
- bool includeHistograms = false;
- if (_collStatsSpec["latencyStats"].type() == BSONType::Object) {
- includeHistograms = _collStatsSpec["latencyStats"]["histograms"].boolean();
- }
+ if (auto latencyStatsSpec = _collStatsSpec.getLatencyStats()) {
pExpCtx->mongoProcessInterface->appendLatencyStats(
- pExpCtx->opCtx, pExpCtx->ns, includeHistograms, &builder);
+ pExpCtx->opCtx, pExpCtx->ns, latencyStatsSpec->getHistograms(), &builder);
}
- if (_collStatsSpec.hasField("storageStats")) {
+ if (auto storageStats = _collStatsSpec.getStorageStats()) {
// If the storageStats field exists, it must have been validated as an object when parsing.
BSONObjBuilder storageBuilder(builder.subobjStart("storageStats"));
- uassertStatusOKWithContext(
- pExpCtx->mongoProcessInterface->appendStorageStats(
- pExpCtx->opCtx, pExpCtx->ns, _collStatsSpec["storageStats"].Obj(), &storageBuilder),
- "Unable to retrieve storageStats in $collStats stage");
+ uassertStatusOKWithContext(pExpCtx->mongoProcessInterface->appendStorageStats(
+ pExpCtx->opCtx, pExpCtx->ns, *storageStats, &storageBuilder),
+ "Unable to retrieve storageStats in $collStats stage");
storageBuilder.doneFast();
}
- if (_collStatsSpec.hasField("count")) {
+ if (_collStatsSpec.getCount()) {
uassertStatusOKWithContext(pExpCtx->mongoProcessInterface->appendRecordCount(
pExpCtx->opCtx, pExpCtx->ns, &builder),
"Unable to retrieve count in $collStats stage");
}
- if (_collStatsSpec.hasField("queryExecStats")) {
+ if (_collStatsSpec.getQueryExecStats()) {
uassertStatusOKWithContext(pExpCtx->mongoProcessInterface->appendQueryExecStats(
pExpCtx->opCtx, pExpCtx->ns, &builder),
"Unable to retrieve queryExecStats in $collStats stage");
@@ -155,7 +111,7 @@ DocumentSource::GetNextResult DocumentSourceCollStats::doGetNext() {
}
Value DocumentSourceCollStats::serialize(boost::optional<ExplainOptions::Verbosity> explain) const {
- return Value(Document{{getSourceName(), _collStatsSpec}});
+ return Value(Document{{getSourceName(), _collStatsSpec.toBSON()}});
}
-} // namespace mongo
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/pipeline/document_source_coll_stats.h b/src/mongo/db/pipeline/document_source_coll_stats.h
index 4d0be020523..bc701e14c44 100644
--- a/src/mongo/db/pipeline/document_source_coll_stats.h
+++ b/src/mongo/db/pipeline/document_source_coll_stats.h
@@ -30,6 +30,7 @@
#pragma once
#include "mongo/db/pipeline/document_source.h"
+#include "mongo/db/pipeline/document_source_coll_stats_gen.h"
namespace mongo {
@@ -44,15 +45,21 @@ public:
class LiteParsed final : public LiteParsedDocumentSource {
public:
static std::unique_ptr<LiteParsed> parse(const NamespaceString& nss,
- const BSONElement& spec) {
- bool hasCount = spec.isABSONObj() && spec.embeddedObject().hasField("count");
- return std::make_unique<LiteParsed>(spec.fieldName(), nss, hasCount);
+ const BSONElement& specElem) {
+ uassert(5447000,
+ str::stream() << "$collStats must take a nested object but found: " << specElem,
+ specElem.type() == BSONType::Object);
+ auto spec = DocumentSourceCollStatsSpec::parse(IDLParserErrorContext(kStageName),
+ specElem.embeddedObject());
+ return std::make_unique<LiteParsed>(specElem.fieldName(), nss, std::move(spec));
}
- explicit LiteParsed(std::string parseTimeName, NamespaceString nss, bool hasCount)
+ explicit LiteParsed(std::string parseTimeName,
+ NamespaceString nss,
+ DocumentSourceCollStatsSpec spec)
: LiteParsedDocumentSource(std::move(parseTimeName)),
_nss(std::move(nss)),
- _hasCount(hasCount) {}
+ _spec(std::move(spec)) {}
bool isCollStats() const final {
return true;
@@ -72,16 +79,17 @@ public:
}
bool isCollStatsWithCount() const final {
- return _hasCount;
+ return static_cast<bool>(_spec.getCount());
}
private:
const NamespaceString _nss;
- const bool _hasCount;
+ const DocumentSourceCollStatsSpec _spec;
};
- DocumentSourceCollStats(const boost::intrusive_ptr<ExpressionContext>& pExpCtx)
- : DocumentSource(kStageName, pExpCtx) {}
+ DocumentSourceCollStats(const boost::intrusive_ptr<ExpressionContext>& pExpCtx,
+ DocumentSourceCollStatsSpec spec)
+ : DocumentSource(kStageName, pExpCtx), _collStatsSpec(std::move(spec)) {}
const char* getSourceName() const final;
@@ -112,7 +120,7 @@ private:
GetNextResult doGetNext() final;
// The raw object given to $collStats containing user specified options.
- BSONObj _collStatsSpec;
+ DocumentSourceCollStatsSpec _collStatsSpec;
bool _finished = false;
};
diff --git a/src/mongo/db/pipeline/document_source_coll_stats.idl b/src/mongo/db/pipeline/document_source_coll_stats.idl
new file mode 100644
index 00000000000..89576b7ed00
--- /dev/null
+++ b/src/mongo/db/pipeline/document_source_coll_stats.idl
@@ -0,0 +1,69 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/pipeline/document_source_parsing_validators.h"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+ - "mongo/db/pipeline/storage_stats_spec.idl"
+
+structs:
+ LatencyStatsSpec:
+ description: Represents the 'latencyStats' argument to the $collStats stage.
+ strict: true
+ fields:
+ histograms:
+ description: Adds latency histogram information to the embedded documents in latencyStats if true.
+ type: optionalBool
+ DocumentSourceCollStatsSpec:
+ description: Specification for a $collStats stage.
+ strict: true
+ fields:
+ latencyStats:
+ description: A request to include latency stats in the $collStats output.
+ type: LatencyStatsSpec
+ optional: true
+ storageStats:
+ description: Adds storage statistics to the return document.
+ type: StorageStatsSpec
+ optional: true
+ count:
+ description: Adds the total number of documents in the collection to the return document.
+ type: object
+ validator:
+ callback: validateObjectIsEmpty
+ optional: true
+ queryExecStats:
+ description: Adds query execution statistics to the return document.
+ type: object
+ validator:
+ callback: validateObjectIsEmpty
+ optional: true \ No newline at end of file
diff --git a/src/mongo/db/pipeline/document_source_parsing_validators.cpp b/src/mongo/db/pipeline/document_source_parsing_validators.cpp
new file mode 100644
index 00000000000..f6a929ba36e
--- /dev/null
+++ b/src/mongo/db/pipeline/document_source_parsing_validators.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/pipeline/document_source_parsing_validators.h"
+#include "mongo/util/str.h"
+
+namespace mongo {
+
+Status validateObjectIsEmpty(const BSONObj& object) {
+ if (!object.isEmpty()) {
+ return {
+ ErrorCodes::Error{31170},
+ str::stream() << "expected an empty object, but got " << object,
+ };
+ }
+ return Status::OK();
+}
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/pipeline/document_source_parsing_validators.h b/src/mongo/db/pipeline/document_source_parsing_validators.h
new file mode 100644
index 00000000000..ea0c1b1e1f3
--- /dev/null
+++ b/src/mongo/db/pipeline/document_source_parsing_validators.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/base/status.h"
+#include "mongo/bson/bsonobj.h"
+
+namespace mongo {
+Status validateObjectIsEmpty(const BSONObj&);
+
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
index e38da1240ea..e4a5a266954 100644
--- a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
+++ b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
@@ -219,9 +219,9 @@ void CommonMongodProcessInterface::appendLatencyStats(OperationContext* opCtx,
Status CommonMongodProcessInterface::appendStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder) const {
- return appendCollectionStorageStats(opCtx, nss, param, builder);
+ return appendCollectionStorageStats(opCtx, nss, spec, builder);
}
Status CommonMongodProcessInterface::appendRecordCount(OperationContext* opCtx,
diff --git a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.h b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.h
index d8e542a859c..4706c259864 100644
--- a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.h
+++ b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.h
@@ -63,7 +63,7 @@ public:
BSONObjBuilder* builder) const final;
Status appendStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder) const final;
Status appendRecordCount(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/pipeline/process_interface/mongo_process_interface.h b/src/mongo/db/pipeline/process_interface/mongo_process_interface.h
index b88031f0277..379aa55230a 100644
--- a/src/mongo/db/pipeline/process_interface/mongo_process_interface.h
+++ b/src/mongo/db/pipeline/process_interface/mongo_process_interface.h
@@ -46,6 +46,7 @@
#include "mongo/db/ops/write_ops_exec.h"
#include "mongo/db/pipeline/field_path.h"
#include "mongo/db/pipeline/lite_parsed_document_source.h"
+#include "mongo/db/pipeline/storage_stats_spec_gen.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/repl/oplog_entry.h"
#include "mongo/db/resource_yielder.h"
@@ -198,7 +199,7 @@ public:
*/
virtual Status appendStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder) const = 0;
/**
diff --git a/src/mongo/db/pipeline/process_interface/mongos_process_interface.h b/src/mongo/db/pipeline/process_interface/mongos_process_interface.h
index 6439d6e54fe..f34021c38d6 100644
--- a/src/mongo/db/pipeline/process_interface/mongos_process_interface.h
+++ b/src/mongo/db/pipeline/process_interface/mongos_process_interface.h
@@ -103,7 +103,7 @@ public:
Status appendStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder) const final {
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/pipeline/process_interface/stub_mongo_process_interface.h b/src/mongo/db/pipeline/process_interface/stub_mongo_process_interface.h
index 243ca833061..5afb3a85135 100644
--- a/src/mongo/db/pipeline/process_interface/stub_mongo_process_interface.h
+++ b/src/mongo/db/pipeline/process_interface/stub_mongo_process_interface.h
@@ -99,7 +99,7 @@ public:
Status appendStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder) const override {
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/pipeline/storage_stats_spec.idl b/src/mongo/db/pipeline/storage_stats_spec.idl
new file mode 100644
index 00000000000..74c6775673c
--- /dev/null
+++ b/src/mongo/db/pipeline/storage_stats_spec.idl
@@ -0,0 +1,50 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+structs:
+ StorageStatsSpec:
+ description: Represents the 'storageStats' argument to the $collStats stage.
+ strict: false
+ fields:
+ scale:
+ description: A number to use as a scaling factor applied to reported metrics.
+ type: safeInt
+ optional: true
+ validator: { gte: 1 }
+ verbose:
+ type: optionalBool
+ default: false
+ waitForLock:
+ type: optionalBool
+ default: true
diff --git a/src/mongo/db/stats/SConscript b/src/mongo/db/stats/SConscript
index 86aa08006f2..81d74eb5a06 100644
--- a/src/mongo/db/stats/SConscript
+++ b/src/mongo/db/stats/SConscript
@@ -120,7 +120,7 @@ env.Library(
source=[
"latency_server_status_section.cpp",
"lock_server_status_section.cpp",
- 'storage_stats.cpp',
+ "storage_stats.cpp",
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
@@ -132,6 +132,7 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/catalog/database_holder',
'$BUILD_DIR/mongo/db/commands/server_status',
+ '$BUILD_DIR/mongo/db/pipeline/document_sources_idl',
'$BUILD_DIR/mongo/db/timeseries/bucket_catalog',
],
)
diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp
index 0cb59121b71..e7517e9cfbe 100644
--- a/src/mongo/db/stats/storage_stats.cpp
+++ b/src/mongo/db/stats/storage_stats.cpp
@@ -47,20 +47,11 @@ namespace mongo {
Status appendCollectionStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& storageStatsSpec,
BSONObjBuilder* result) {
- int scale = 1;
- if (param["scale"].isNumber()) {
- scale = param["scale"].numberInt();
- if (scale < 1) {
- return {ErrorCodes::BadValue, "scale has to be >= 1"};
- }
- } else if (param["scale"].trueValue()) {
- return {ErrorCodes::BadValue, "scale has to be a number >= 1"};
- }
-
- bool verbose = param["verbose"].trueValue();
- bool waitForLock = !param.hasField("waitForLock") || param["waitForLock"].trueValue();
+ auto scale = storageStatsSpec.getScale().value_or(1);
+ bool verbose = storageStatsSpec.getVerbose();
+ bool waitForLock = storageStatsSpec.getWaitForLock();
bool isTimeseries = false;
if (auto viewCatalog = DatabaseHolder::get(opCtx)->getViewCatalog(opCtx, nss.db())) {
diff --git a/src/mongo/db/stats/storage_stats.h b/src/mongo/db/stats/storage_stats.h
index 377210bb765..b2a5e3fee0f 100644
--- a/src/mongo/db/stats/storage_stats.h
+++ b/src/mongo/db/stats/storage_stats.h
@@ -34,6 +34,7 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/pipeline/storage_stats_spec_gen.h"
namespace mongo {
@@ -43,14 +44,14 @@ namespace mongo {
* Params:
* opCtx
* nss Fully qualified namespace.
- * param Uses "scale" (default = 1) and "verbose".
+ * spec Includes options such as "scale" (default = 1) and "verbose".
* builder out; object the stats will be appended to.
*
* returns Status, (note "NamespaceNotFound" will fill result with 0-ed stats)
*/
Status appendCollectionStorageStats(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& param,
+ const StorageStatsSpec& spec,
BSONObjBuilder* builder);
/**