summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-02-27 15:56:37 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-03-05 18:15:00 -0500
commit763f5905c2c8cc9ce67387434f7343b3250f3e9d (patch)
treee78a7e02380f3e1a20a6ff1151d040da459fdc53 /src/mongo
parentc207a0ced18bba58a8ad1b08df85b1e0a0b136f9 (diff)
downloadmongo-763f5905c2c8cc9ce67387434f7343b3250f3e9d.tar.gz
SERVER-27664 Use scatterGatherVersionedTargetByRoutingTable instead of passthrough in commands_public.cpp
This change replaces all usages of passthrough, which are used for sharded and unsharded collection routing from commands_public.cpp. All remaining usages of passthrough will be replaced with direct Shard::runCommand instead.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/sessions_collection_config_server.cpp1
-rw-r--r--src/mongo/s/async_requests_sender.cpp4
-rw-r--r--src/mongo/s/async_requests_sender.h2
-rw-r--r--src/mongo/s/commands/SConscript2
-rw-r--r--src/mongo/s/commands/cluster_aggregate.cpp5
-rw-r--r--src/mongo/s/commands/cluster_coll_stats_cmd.cpp211
-rw-r--r--src/mongo/s/commands/cluster_collection_mod_cmd.cpp1
-rw-r--r--src/mongo/s/commands/cluster_commands_helpers.cpp31
-rw-r--r--src/mongo/s/commands/cluster_commands_helpers.h6
-rw-r--r--src/mongo/s/commands/cluster_count_cmd.cpp8
-rw-r--r--src/mongo/s/commands/cluster_create_indexes_cmd.cpp1
-rw-r--r--src/mongo/s/commands/cluster_data_size_cmd.cpp140
-rw-r--r--src/mongo/s/commands/cluster_db_stats_cmd.cpp1
-rw-r--r--src/mongo/s/commands/cluster_distinct_cmd.cpp6
-rw-r--r--src/mongo/s/commands/cluster_drop_indexes_cmd.cpp1
-rw-r--r--src/mongo/s/commands/cluster_reindex_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_restart_catalog_command.cpp24
-rw-r--r--src/mongo/s/commands/cluster_validate_cmd.cpp5
-rw-r--r--src/mongo/s/commands/commands_public.cpp251
-rw-r--r--src/mongo/s/commands/strategy.cpp4
20 files changed, 393 insertions, 315 deletions
diff --git a/src/mongo/db/sessions_collection_config_server.cpp b/src/mongo/db/sessions_collection_config_server.cpp
index 8a4f97cdca9..179687e33d4 100644
--- a/src/mongo/db/sessions_collection_config_server.cpp
+++ b/src/mongo/db/sessions_collection_config_server.cpp
@@ -80,7 +80,6 @@ Status SessionsCollectionConfigServer::_shardCollectionIfNeeded(OperationContext
Status SessionsCollectionConfigServer::_generateIndexesIfNeeded(OperationContext* opCtx) {
try {
scatterGatherOnlyVersionIfUnsharded(opCtx,
- SessionsCollection::kSessionsDb.toString(),
NamespaceString(SessionsCollection::kSessionsFullNS),
SessionsCollection::generateCreateIndexesCmd(),
ReadPreferenceSetting::get(opCtx),
diff --git a/src/mongo/s/async_requests_sender.cpp b/src/mongo/s/async_requests_sender.cpp
index 8cdb7190050..69f61bf989b 100644
--- a/src/mongo/s/async_requests_sender.cpp
+++ b/src/mongo/s/async_requests_sender.cpp
@@ -52,13 +52,13 @@ const int kMaxNumFailedHostRetryAttempts = 3;
AsyncRequestsSender::AsyncRequestsSender(OperationContext* opCtx,
executor::TaskExecutor* executor,
- const std::string db,
+ StringData dbName,
const std::vector<AsyncRequestsSender::Request>& requests,
const ReadPreferenceSetting& readPreference,
Shard::RetryPolicy retryPolicy)
: _opCtx(opCtx),
_executor(executor),
- _db(std::move(db)),
+ _db(dbName.toString()),
_readPreference(readPreference),
_retryPolicy(retryPolicy) {
for (const auto& request : requests) {
diff --git a/src/mongo/s/async_requests_sender.h b/src/mongo/s/async_requests_sender.h
index 70d574a8ef7..bafeed53555 100644
--- a/src/mongo/s/async_requests_sender.h
+++ b/src/mongo/s/async_requests_sender.h
@@ -124,7 +124,7 @@ public:
*/
AsyncRequestsSender(OperationContext* opCtx,
executor::TaskExecutor* executor,
- const std::string db,
+ StringData dbName,
const std::vector<AsyncRequestsSender::Request>& requests,
const ReadPreferenceSetting& readPreference,
Shard::RetryPolicy retryPolicy);
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index 11765392956..9dc7ae2124a 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -28,6 +28,7 @@ env.Library(
'cluster_add_shard_to_zone_cmd.cpp',
'cluster_aggregate.cpp',
'cluster_available_query_options_cmd.cpp',
+ 'cluster_coll_stats_cmd.cpp',
'cluster_collection_mod_cmd.cpp',
'cluster_compact_cmd.cpp',
'cluster_control_balancer_cmd.cpp',
@@ -35,6 +36,7 @@ env.Library(
'cluster_create_cmd.cpp',
'cluster_create_indexes_cmd.cpp',
'cluster_current_op.cpp',
+ 'cluster_data_size_cmd.cpp',
'cluster_db_stats_cmd.cpp',
'cluster_distinct_cmd.cpp',
'cluster_drop_cmd.cpp',
diff --git a/src/mongo/s/commands/cluster_aggregate.cpp b/src/mongo/s/commands/cluster_aggregate.cpp
index 6c3f604bdd2..2550179e3de 100644
--- a/src/mongo/s/commands/cluster_aggregate.cpp
+++ b/src/mongo/s/commands/cluster_aggregate.cpp
@@ -443,8 +443,7 @@ DispatchShardPipelineResults dispatchShardPipeline(
// should not participate in the shard version protocol.
shardResults =
scatterGatherUnversionedTargetAllShards(opCtx,
- executionNss.db().toString(),
- executionNss,
+ executionNss.db(),
targetedCommand,
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent);
@@ -453,8 +452,8 @@ DispatchShardPipelineResults dispatchShardPipeline(
// shards, and should participate in the shard version protocol.
shardResults = scatterGatherVersionedTargetByRoutingTable(
opCtx,
- executionNss.db().toString(),
executionNss,
+ executionNsRoutingInfo,
targetedCommand,
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
diff --git a/src/mongo/s/commands/cluster_coll_stats_cmd.cpp b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp
new file mode 100644
index 00000000000..875a577b9ce
--- /dev/null
+++ b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp
@@ -0,0 +1,211 @@
+/**
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/commands.h"
+#include "mongo/rpc/get_status_from_command_result.h"
+#include "mongo/s/commands/cluster_commands_helpers.h"
+#include "mongo/s/grid.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+namespace {
+
+class CollectionStats : public BasicCommand {
+public:
+ CollectionStats() : BasicCommand("collStats", "collstats") {}
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ bool adminOnly() const override {
+ return false;
+ }
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) const override {
+ ActionSet actions;
+ actions.addAction(ActionType::collStats);
+ out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ const NamespaceString nss(parseNs(dbName, cmdObj));
+
+ auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
+ if (routingInfo.cm()) {
+ result.appendBool("sharded", true);
+ } else {
+ result.appendBool("sharded", false);
+ result.append("primary", routingInfo.primaryId().toString());
+ }
+
+ auto shardResults = scatterGatherVersionedTargetByRoutingTable(
+ opCtx,
+ nss,
+ routingInfo,
+ CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
+ ReadPreferenceSetting::get(opCtx),
+ Shard::RetryPolicy::kIdempotent,
+ {},
+ {});
+
+ BSONObjBuilder shardStats;
+ std::map<std::string, long long> counts;
+ std::map<std::string, long long> indexSizes;
+
+ long long maxSize = 0;
+ long long unscaledCollSize = 0;
+
+ int nindexes = 0;
+ bool warnedAboutIndexes = false;
+
+ for (const auto& shardResult : shardResults) {
+ const auto& shardId = shardResult.shardId;
+ const auto shardResponse = uassertStatusOK(std::move(shardResult.swResponse));
+ uassertStatusOK(shardResponse.status);
+
+ const auto& res = shardResponse.data;
+ uassertStatusOK(getStatusFromCommandResult(res));
+
+ // We don't know the order that we will encounter the count and size, so we save them
+ // until we've iterated through all the fields before updating unscaledCollSize
+ const auto shardObjCount = static_cast<long long>(res["count"].Number());
+
+ for (const auto& e : res) {
+ if (str::equals(e.fieldName(), "ns") || //
+ str::equals(e.fieldName(), "ok") || //
+ str::equals(e.fieldName(), "lastExtentSize") || //
+ str::equals(e.fieldName(), "paddingFactor")) {
+ // Ignored fields
+ continue;
+ } else if (str::equals(e.fieldName(), "userFlags") || //
+ str::equals(e.fieldName(), "capped") || //
+ str::equals(e.fieldName(), "max") || //
+ str::equals(e.fieldName(), "paddingFactorNote") || //
+ str::equals(e.fieldName(), "indexDetails") || //
+ str::equals(e.fieldName(), "wiredTiger")) {
+ // Fields that are copied from the first shard only, because they need to match
+ // across shards
+ if (!result.hasField(e.fieldName()))
+ result.append(e);
+ } else if (str::equals(e.fieldName(), "count") || //
+ str::equals(e.fieldName(), "size") || //
+ str::equals(e.fieldName(), "storageSize") || //
+ str::equals(e.fieldName(), "numExtents") || //
+ str::equals(e.fieldName(), "totalIndexSize")) {
+ counts[e.fieldName()] += e.numberLong();
+ } else if (str::equals(e.fieldName(), "avgObjSize")) {
+ const auto shardAvgObjSize = e.numberLong();
+ unscaledCollSize += shardAvgObjSize * shardObjCount;
+ } else if (str::equals(e.fieldName(), "maxSize")) {
+ const auto shardMaxSize = e.numberLong();
+ maxSize = std::max(maxSize, shardMaxSize);
+ } else if (str::equals(e.fieldName(), "indexSizes")) {
+ BSONObjIterator k(e.Obj());
+ while (k.more()) {
+ BSONElement temp = k.next();
+ indexSizes[temp.fieldName()] += temp.numberLong();
+ }
+ } else if (str::equals(e.fieldName(), "nindexes")) {
+ int myIndexes = e.numberInt();
+
+ if (nindexes == 0) {
+ nindexes = myIndexes;
+ } else if (nindexes == myIndexes) {
+ // no-op
+ } else {
+ // hopefully this means we're building an index
+
+ if (myIndexes > nindexes)
+ nindexes = myIndexes;
+
+ if (!warnedAboutIndexes) {
+ result.append("warning",
+ "indexes don't all match - ok if ensureIndex is running");
+ warnedAboutIndexes = true;
+ }
+ }
+ } else {
+ log() << "mongos collstats doesn't know about: " << e.fieldName();
+ }
+ }
+
+ shardStats.append(shardId.toString(), res);
+ }
+
+ result.append("ns", nss.ns());
+
+ for (const auto& countEntry : counts) {
+ result.appendNumber(countEntry.first, countEntry.second);
+ }
+
+ {
+ BSONObjBuilder ib(result.subobjStart("indexSizes"));
+ for (const auto& entry : indexSizes) {
+ ib.appendNumber(entry.first, entry.second);
+ }
+ ib.done();
+ }
+
+ // The unscaled avgObjSize for each shard is used to get the unscaledCollSize because the
+ // raw size returned by the shard is affected by the command's scale parameter
+ if (counts["count"] > 0)
+ result.append("avgObjSize", (double)unscaledCollSize / (double)counts["count"]);
+ else
+ result.append("avgObjSize", 0.0);
+
+ result.append("maxSize", maxSize);
+ result.append("nindexes", nindexes);
+ result.append("nchunks", (routingInfo.cm() ? routingInfo.cm()->numChunks() : 1));
+ result.append("shards", shardStats.obj());
+
+ return true;
+ }
+
+} collectionStatsCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
index ebb5d0fd788..27823d3ed8d 100644
--- a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
+++ b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
@@ -71,7 +71,6 @@ public:
auto shardResponses = scatterGatherOnlyVersionIfUnsharded(
opCtx,
- dbName,
nss,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
diff --git a/src/mongo/s/commands/cluster_commands_helpers.cpp b/src/mongo/s/commands/cluster_commands_helpers.cpp
index ab058a2661d..ec4d2b5e3fe 100644
--- a/src/mongo/s/commands/cluster_commands_helpers.cpp
+++ b/src/mongo/s/commands/cluster_commands_helpers.cpp
@@ -129,7 +129,7 @@ std::vector<AsyncRequestsSender::Request> buildVersionedRequestsForTargetedShard
*/
std::vector<AsyncRequestsSender::Response> gatherResponses(
OperationContext* opCtx,
- const std::string& dbName,
+ StringData dbName,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy,
const std::vector<AsyncRequestsSender::Request>& requests) {
@@ -190,50 +190,35 @@ BSONObj appendShardVersion(BSONObj cmdObj, ChunkVersion version) {
std::vector<AsyncRequestsSender::Response> scatterGatherUnversionedTargetAllShards(
OperationContext* opCtx,
- const std::string& dbName,
- boost::optional<NamespaceString> nss,
+ StringData dbName,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy) {
- // Some commands, such as $currentOp, operate on a collectionless namespace. If a full namespace
- // is specified, its database must match the dbName.
- invariant(!nss || (nss->db() == dbName));
-
- auto requests = buildUnversionedRequestsForAllShards(opCtx, cmdObj);
-
- return gatherResponses(opCtx, dbName, readPref, retryPolicy, requests);
+ return gatherResponses(
+ opCtx, dbName, readPref, retryPolicy, buildUnversionedRequestsForAllShards(opCtx, cmdObj));
}
std::vector<AsyncRequestsSender::Response> scatterGatherVersionedTargetByRoutingTable(
OperationContext* opCtx,
- const std::string& dbName,
const NamespaceString& nss,
+ const CachedCollectionRoutingInfo& routingInfo,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy,
const BSONObj& query,
const BSONObj& collation) {
- // The database in the full namespace must match the dbName.
- invariant(nss.db() == dbName);
-
- auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
- auto requests =
+ const auto requests =
buildVersionedRequestsForTargetedShards(opCtx, routingInfo, cmdObj, query, collation);
- return gatherResponses(opCtx, dbName, readPref, retryPolicy, requests);
+ return gatherResponses(opCtx, nss.db(), readPref, retryPolicy, requests);
}
std::vector<AsyncRequestsSender::Response> scatterGatherOnlyVersionIfUnsharded(
OperationContext* opCtx,
- const std::string& dbName,
const NamespaceString& nss,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy) {
- // The database in the full namespace must match the dbName.
- invariant(nss.db() == dbName);
-
auto routingInfo =
uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
@@ -251,7 +236,7 @@ std::vector<AsyncRequestsSender::Response> scatterGatherOnlyVersionIfUnsharded(
opCtx, routingInfo, cmdObj, BSONObj(), BSONObj());
}
- return gatherResponses(opCtx, dbName, readPref, retryPolicy, requests);
+ return gatherResponses(opCtx, nss.db(), readPref, retryPolicy, requests);
}
bool appendRawResponses(OperationContext* opCtx,
diff --git a/src/mongo/s/commands/cluster_commands_helpers.h b/src/mongo/s/commands/cluster_commands_helpers.h
index 10ba26784a4..458e0ac9d3c 100644
--- a/src/mongo/s/commands/cluster_commands_helpers.h
+++ b/src/mongo/s/commands/cluster_commands_helpers.h
@@ -68,8 +68,7 @@ BSONObj appendShardVersion(BSONObj cmdObj, ChunkVersion version);
*/
std::vector<AsyncRequestsSender::Response> scatterGatherUnversionedTargetAllShards(
OperationContext* opCtx,
- const std::string& dbName,
- boost::optional<NamespaceString> nss,
+ StringData dbName,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy);
@@ -84,8 +83,8 @@ std::vector<AsyncRequestsSender::Response> scatterGatherUnversionedTargetAllShar
*/
std::vector<AsyncRequestsSender::Response> scatterGatherVersionedTargetByRoutingTable(
OperationContext* opCtx,
- const std::string& dbName,
const NamespaceString& nss,
+ const CachedCollectionRoutingInfo& routingInfo,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
Shard::RetryPolicy retryPolicy,
@@ -105,7 +104,6 @@ std::vector<AsyncRequestsSender::Response> scatterGatherVersionedTargetByRouting
*/
std::vector<AsyncRequestsSender::Response> scatterGatherOnlyVersionIfUnsharded(
OperationContext* opCtx,
- const std::string& dbName,
const NamespaceString& nss,
const BSONObj& cmdObj,
const ReadPreferenceSetting& readPref,
diff --git a/src/mongo/s/commands/cluster_count_cmd.cpp b/src/mongo/s/commands/cluster_count_cmd.cpp
index 794cf1d9fb3..e5ddda0a004 100644
--- a/src/mongo/s/commands/cluster_count_cmd.cpp
+++ b/src/mongo/s/commands/cluster_count_cmd.cpp
@@ -142,10 +142,12 @@ public:
std::vector<AsyncRequestsSender::Response> shardResponses;
try {
+ const auto routingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
shardResponses =
scatterGatherVersionedTargetByRoutingTable(opCtx,
- dbname,
nss,
+ routingInfo,
countCmdObj,
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
@@ -251,10 +253,12 @@ public:
std::vector<AsyncRequestsSender::Response> shardResponses;
try {
+ const auto routingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
shardResponses =
scatterGatherVersionedTargetByRoutingTable(opCtx,
- dbname,
nss,
+ routingInfo,
explainCmd,
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
diff --git a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
index 67c63939043..84274d6f211 100644
--- a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
@@ -73,7 +73,6 @@ public:
auto shardResponses = scatterGatherOnlyVersionIfUnsharded(
opCtx,
- dbName,
nss,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
diff --git a/src/mongo/s/commands/cluster_data_size_cmd.cpp b/src/mongo/s/commands/cluster_data_size_cmd.cpp
new file mode 100644
index 00000000000..6cac20332c8
--- /dev/null
+++ b/src/mongo/s/commands/cluster_data_size_cmd.cpp
@@ -0,0 +1,140 @@
+/**
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/commands.h"
+#include "mongo/rpc/get_status_from_command_result.h"
+#include "mongo/s/commands/cluster_commands_helpers.h"
+#include "mongo/s/grid.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+namespace {
+
+class DataSizeCmd : public BasicCommand {
+public:
+ DataSizeCmd() : BasicCommand("dataSize", "datasize") {}
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsFullyQualified(dbname, cmdObj);
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ bool adminOnly() const override {
+ return false;
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) const override {
+ ActionSet actions;
+ actions.addAction(ActionType::find);
+ out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ const NamespaceString nss(parseNs(dbName, cmdObj));
+
+ auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
+ const auto cm = routingInfo.cm();
+
+ BSONObj min = cmdObj.getObjectField("min");
+ BSONObj max = cmdObj.getObjectField("max");
+
+ if (cm) {
+ auto keyPattern = cmdObj["keyPattern"];
+
+ uassert(ErrorCodes::BadValue,
+ "keyPattern must be empty or must be an object that equals the shard key",
+ !keyPattern || (keyPattern.type() == Object &&
+ SimpleBSONObjComparator::kInstance.evaluate(
+ cm->getShardKeyPattern().toBSON() == keyPattern.Obj())));
+
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "min value " << min << " does not have shard key",
+ cm->getShardKeyPattern().isShardKey(min));
+ min = cm->getShardKeyPattern().normalizeShardKey(min);
+
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "max value " << max << " does not have shard key",
+ cm->getShardKeyPattern().isShardKey(max));
+ max = cm->getShardKeyPattern().normalizeShardKey(max);
+ }
+
+ auto shardResults = scatterGatherVersionedTargetByRoutingTable(
+ opCtx,
+ nss,
+ routingInfo,
+ CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
+ ReadPreferenceSetting::get(opCtx),
+ Shard::RetryPolicy::kIdempotent,
+ {},
+ {});
+
+ // yes these are doubles...
+ double size = 0;
+ double numObjects = 0;
+ int millis = 0;
+
+ for (const auto& shardResult : shardResults) {
+ const auto shardResponse = uassertStatusOK(std::move(shardResult.swResponse));
+ uassertStatusOK(shardResponse.status);
+
+ const auto& res = shardResponse.data;
+ uassertStatusOK(getStatusFromCommandResult(res));
+
+ size += res["size"].number();
+ numObjects += res["numObjects"].number();
+ millis += res["millis"].numberInt();
+ }
+
+ result.append("size", size);
+ result.append("numObjects", numObjects);
+ result.append("millis", millis);
+
+ return true;
+ }
+
+} dataSizeCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_db_stats_cmd.cpp b/src/mongo/s/commands/cluster_db_stats_cmd.cpp
index 897d2a6130f..b40fb3dbd98 100644
--- a/src/mongo/s/commands/cluster_db_stats_cmd.cpp
+++ b/src/mongo/s/commands/cluster_db_stats_cmd.cpp
@@ -124,7 +124,6 @@ public:
auto shardResponses = scatterGatherUnversionedTargetAllShards(
opCtx,
dbName,
- boost::none,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent);
diff --git a/src/mongo/s/commands/cluster_distinct_cmd.cpp b/src/mongo/s/commands/cluster_distinct_cmd.cpp
index 1fb071ea75c..fe77b39aeaa 100644
--- a/src/mongo/s/commands/cluster_distinct_cmd.cpp
+++ b/src/mongo/s/commands/cluster_distinct_cmd.cpp
@@ -94,10 +94,12 @@ public:
std::vector<AsyncRequestsSender::Response> shardResponses;
try {
+ const auto routingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
shardResponses =
scatterGatherVersionedTargetByRoutingTable(opCtx,
- dbname,
nss,
+ routingInfo,
explainCmd,
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
@@ -171,8 +173,8 @@ public:
try {
shardResponses = scatterGatherVersionedTargetByRoutingTable(
opCtx,
- dbName,
nss,
+ routingInfo,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
diff --git a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
index e5a546ddc4e..824ddf958b8 100644
--- a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
@@ -78,7 +78,6 @@ public:
// receiving its first chunk for the collection (see SERVER-31715).
auto shardResponses = scatterGatherOnlyVersionIfUnsharded(
opCtx,
- dbName,
nss,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
diff --git a/src/mongo/s/commands/cluster_reindex_cmd.cpp b/src/mongo/s/commands/cluster_reindex_cmd.cpp
index 9a325330776..573bb3e515c 100644
--- a/src/mongo/s/commands/cluster_reindex_cmd.cpp
+++ b/src/mongo/s/commands/cluster_reindex_cmd.cpp
@@ -70,12 +70,10 @@ public:
const BSONObj& cmdObj,
std::string& errmsg,
BSONObjBuilder& output) override {
- const NamespaceString nss(CommandHelpers::parseNsCollectionRequired(dbName, cmdObj));
- LOG(1) << "reIndex: " << nss << " cmd:" << redact(cmdObj);
+ const NamespaceString nss(parseNs(dbName, cmdObj));
auto shardResponses = scatterGatherOnlyVersionIfUnsharded(
opCtx,
- dbName,
nss,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
diff --git a/src/mongo/s/commands/cluster_restart_catalog_command.cpp b/src/mongo/s/commands/cluster_restart_catalog_command.cpp
index 228f69aaa2f..949fce3c88c 100644
--- a/src/mongo/s/commands/cluster_restart_catalog_command.cpp
+++ b/src/mongo/s/commands/cluster_restart_catalog_command.cpp
@@ -34,13 +34,15 @@
namespace mongo {
namespace {
-/**
- * Forwards the testing-only restartCatalog command to all shards.
- */
class ClusterRestartCatalogCmd : public BasicCommand {
public:
ClusterRestartCatalogCmd() : BasicCommand("restartCatalog") {}
+ std::string help() const override {
+ return "Internal command for testing only. Forwards the restartCatalog command to all "
+ "shards.";
+ }
+
Status checkAuthForOperation(OperationContext* opCtx,
const std::string& dbname,
const BSONObj& cmdObj) const override {
@@ -68,33 +70,21 @@ public:
return false;
}
- std::string help() const override {
- return "restart catalog\n"
- "Internal command for testing only. Forwards the restartCatalog command to\n"
- "all shards.\n";
- }
-
bool run(OperationContext* opCtx,
const std::string& db,
const BSONObj& cmdObj,
BSONObjBuilder& result) override {
- // This command doesn't operate on a collection namespace, so just pass in an empty
- // NamespaceString.
- const auto namespaceStringForCommand = boost::none;
auto shardResponses = scatterGatherUnversionedTargetAllShards(
opCtx,
db,
- namespaceStringForCommand,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent);
- std::string errmsg;
- appendRawResponses(opCtx, &errmsg, &result, shardResponses);
-
// Intentionally not adding the error message to 'result', as it will already contain all
// the errors from the shards in a field named 'raw'.
- return errmsg.length() > 0 ? false : true;
+ std::string errmsg;
+ return appendRawResponses(opCtx, &errmsg, &result, shardResponses);
}
};
diff --git a/src/mongo/s/commands/cluster_validate_cmd.cpp b/src/mongo/s/commands/cluster_validate_cmd.cpp
index 7a63e9a4327..53db0e9f8e3 100644
--- a/src/mongo/s/commands/cluster_validate_cmd.cpp
+++ b/src/mongo/s/commands/cluster_validate_cmd.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/commands.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/s/commands/cluster_commands_helpers.h"
+#include "mongo/s/grid.h"
namespace mongo {
namespace {
@@ -71,10 +72,12 @@ public:
BSONObjBuilder& output) override {
const NamespaceString nss(parseNs(dbName, cmdObj));
+ const auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
auto results = scatterGatherVersionedTargetByRoutingTable(
opCtx,
- dbName,
nss,
+ routingInfo,
CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
diff --git a/src/mongo/s/commands/commands_public.cpp b/src/mongo/s/commands/commands_public.cpp
index 54499f66924..c979710fbc9 100644
--- a/src/mongo/s/commands/commands_public.cpp
+++ b/src/mongo/s/commands/commands_public.cpp
@@ -324,257 +324,6 @@ public:
} clusterCopyDBCmd;
-class CollectionStats : public PublicGridCommand {
-public:
- CollectionStats() : PublicGridCommand("collStats", "collstats") {}
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
- }
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
-
- void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) const override {
- ActionSet actions;
- actions.addAction(ActionType::collStats);
- out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- const NamespaceString nss(parseNs(dbName, cmdObj));
-
- auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
- if (!routingInfo.cm()) {
- result.appendBool("sharded", false);
- result.append("primary", routingInfo.primaryId().toString());
- return passthrough(opCtx, dbName, routingInfo.primaryId(), cmdObj, result);
- }
-
- const auto cm = routingInfo.cm();
-
- result.appendBool("sharded", true);
-
- BSONObjBuilder shardStats;
- std::map<std::string, long long> counts;
- std::map<std::string, long long> indexSizes;
-
- long long unscaledCollSize = 0;
-
- int nindexes = 0;
- bool warnedAboutIndexes = false;
-
- std::set<ShardId> shardIds;
- cm->getAllShardIds(&shardIds);
-
- for (const auto& shardId : shardIds) {
- const auto res = [&] {
- const auto shard =
- uassertStatusOK(Grid::get(opCtx)->shardRegistry()->getShard(opCtx, shardId));
- auto commandResponse = uassertStatusOK(shard->runCommandWithFixedRetryAttempts(
- opCtx,
- ReadPreferenceSetting::get(opCtx),
- dbName,
- appendShardVersion(CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
- cm->getVersion(shardId)),
- Shard::RetryPolicy::kIdempotent));
-
- uassertStatusOK(commandResponse.commandStatus);
- return commandResponse.response;
- }();
-
- // We don't know the order that we will encounter the count and size, so we save them
- // until we've iterated through all the fields before updating unscaledCollSize
- const auto shardObjCount = static_cast<long long>(res["count"].Number());
- long long shardAvgObjSize = 0;
-
- for (const auto& e : res) {
- if (str::equals(e.fieldName(), "ns") || //
- str::equals(e.fieldName(), "ok") || //
- str::equals(e.fieldName(), "lastExtentSize") || //
- str::equals(e.fieldName(), "paddingFactor")) {
- continue;
- } else if (str::equals(e.fieldName(), "count") || //
- str::equals(e.fieldName(), "size") || //
- str::equals(e.fieldName(), "storageSize") || //
- str::equals(e.fieldName(), "numExtents") || //
- str::equals(e.fieldName(), "totalIndexSize")) {
- counts[e.fieldName()] += e.numberLong();
- } else if (str::equals(e.fieldName(), "avgObjSize")) {
- shardAvgObjSize = e.numberLong();
- } else if (str::equals(e.fieldName(), "indexSizes")) {
- BSONObjIterator k(e.Obj());
- while (k.more()) {
- BSONElement temp = k.next();
- indexSizes[temp.fieldName()] += temp.numberLong();
- }
- } else if (str::equals(e.fieldName(), "userFlags")) {
- if (!result.hasField(e.fieldName()))
- result.append(e);
- } else if (str::equals(e.fieldName(), "capped")) {
- if (!result.hasField(e.fieldName()))
- result.append(e);
- } else if (str::equals(e.fieldName(), "paddingFactorNote")) {
- if (!result.hasField(e.fieldName()))
- result.append(e);
- } else if (str::equals(e.fieldName(), "indexDetails")) {
- // skip this field in the rollup
- } else if (str::equals(e.fieldName(), "nindexes")) {
- int myIndexes = e.numberInt();
-
- if (nindexes == 0) {
- nindexes = myIndexes;
- } else if (nindexes == myIndexes) {
- // no-op
- } else {
- // hopefully this means we're building an index
-
- if (myIndexes > nindexes)
- nindexes = myIndexes;
-
- if (!warnedAboutIndexes) {
- result.append("warning",
- "indexes don't all match - ok if ensureIndex is running");
- warnedAboutIndexes = true;
- }
- }
- } else {
- warning() << "mongos collstats doesn't know about: " << e.fieldName();
- }
- }
- shardStats.append(shardId.toString(), res);
- unscaledCollSize += shardAvgObjSize * shardObjCount;
- }
-
- result.append("ns", nss.ns());
-
- for (const auto& countEntry : counts) {
- result.appendNumber(countEntry.first, countEntry.second);
- }
-
- {
- BSONObjBuilder ib(result.subobjStart("indexSizes"));
- for (const auto& entry : indexSizes) {
- ib.appendNumber(entry.first, entry.second);
- }
- ib.done();
- }
-
- // The unscaled avgObjSize for each shard is used to get the unscaledCollSize
- // because the raw size returned by the shard is affected by the command's
- // scale parameter.
- if (counts["count"] > 0)
- result.append("avgObjSize", (double)unscaledCollSize / (double)counts["count"]);
- else
- result.append("avgObjSize", 0.0);
-
- result.append("nindexes", nindexes);
-
- result.append("nchunks", cm->numChunks());
- result.append("shards", shardStats.obj());
-
- return true;
- }
-
-} collectionStatsCmd;
-
-class DataSizeCmd : public PublicGridCommand {
-public:
- DataSizeCmd() : PublicGridCommand("dataSize", "datasize") {}
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsFullyQualified(dbname, cmdObj);
- }
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
-
- void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) const override {
- ActionSet actions;
- actions.addAction(ActionType::find);
- out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- const NamespaceString nss(parseNs(dbName, cmdObj));
-
- auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
- if (!routingInfo.cm()) {
- return passthrough(opCtx, dbName, routingInfo.primaryId(), cmdObj, result);
- }
-
- const auto cm = routingInfo.cm();
-
- BSONObj min = cmdObj.getObjectField("min");
- BSONObj max = cmdObj.getObjectField("max");
- BSONObj keyPattern = cmdObj.getObjectField("keyPattern");
-
- uassert(13408,
- "keyPattern must equal shard key",
- SimpleBSONObjComparator::kInstance.evaluate(cm->getShardKeyPattern().toBSON() ==
- keyPattern));
- uassert(13405,
- str::stream() << "min value " << min << " does not have shard key",
- cm->getShardKeyPattern().isShardKey(min));
- uassert(13406,
- str::stream() << "max value " << max << " does not have shard key",
- cm->getShardKeyPattern().isShardKey(max));
-
- min = cm->getShardKeyPattern().normalizeShardKey(min);
- max = cm->getShardKeyPattern().normalizeShardKey(max);
-
- // yes these are doubles...
- double size = 0;
- double numObjects = 0;
- int millis = 0;
-
- std::set<ShardId> shardIds;
- cm->getShardIdsForRange(min, max, &shardIds);
-
- for (const ShardId& shardId : shardIds) {
- const auto shardStatus = Grid::get(opCtx)->shardRegistry()->getShard(opCtx, shardId);
- if (!shardStatus.isOK()) {
- continue;
- }
-
- ScopedDbConnection conn(shardStatus.getValue()->getConnString());
- BSONObj res;
- bool ok = conn->runCommand(
- dbName, CommandHelpers::filterCommandRequestForPassthrough(cmdObj), res);
- conn.done();
-
- if (!ok) {
- CommandHelpers::filterCommandReplyForPassthrough(res, &result);
- return false;
- }
-
- size += res["size"].number();
- numObjects += res["numObjects"].number();
- millis += res["millis"].numberInt();
- }
-
- result.append("size", size);
- result.append("numObjects", numObjects);
- result.append("millis", millis);
- return true;
- }
-
-} dataSizeCmd;
-
class ConvertToCappedCmd : public NotAllowedOnShardedCollectionCmd {
public:
ConvertToCappedCmd() : NotAllowedOnShardedCollectionCmd("convertToCapped") {}
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 6a10b1b6856..20e01646cf6 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -609,10 +609,12 @@ void Strategy::explainFind(OperationContext* opCtx,
// We will time how long it takes to run the commands on the shards.
Timer timer;
+ const auto routingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, qr.nss()));
auto shardResponses =
scatterGatherVersionedTargetByRoutingTable(opCtx,
- qr.nss().db().toString(),
qr.nss(),
+ routingInfo,
explainCmd,
readPref,
Shard::RetryPolicy::kIdempotent,