diff options
Diffstat (limited to 'src')
29 files changed, 326 insertions, 207 deletions
diff --git a/src/mongo/client/dbclient_base.cpp b/src/mongo/client/dbclient_base.cpp index 04748a525af..9a7c87eed66 100644 --- a/src/mongo/client/dbclient_base.cpp +++ b/src/mongo/client/dbclient_base.cpp @@ -49,8 +49,8 @@ #include "mongo/client/constants.h" #include "mongo/client/dbclient_cursor.h" #include "mongo/config.h" +#include "mongo/db/api_parameters_gen.h" #include "mongo/db/commands.h" -#include "mongo/db/initialize_api_parameters_gen.h" #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/kill_cursors_gen.h" diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 2d90253f008..a0c8de84714 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -869,6 +869,7 @@ env.Library( '$BUILD_DIR/mongo/db/storage/storage_engine_lock_file', '$BUILD_DIR/mongo/db/storage/storage_engine_metadata', 'commands/server_status_core', + 'initialize_api_parameters', 'introspect', 'lasterror', 'query_exec', @@ -1460,17 +1461,39 @@ env.Library( env.Library( target='shared_request_handling', source=[ - 'initialize_api_parameters.cpp', 'transaction_validation.cpp', - env.Idlc('initialize_api_parameters.idl')[0], ], LIBDEPS=[ + 'api_parameters', 'error_labels', 'logical_session_cache_impl', ], ) env.Library( + target='api_parameters', + source=[ + 'api_parameters.cpp', + env.Idlc('api_parameters.idl')[0], + ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/idl/idl_parser', + '$BUILD_DIR/mongo/idl/server_parameter', + ], +) + +env.Library( + target='initialize_api_parameters', + source=[ + 'initialize_api_parameters.cpp', + ], + LIBDEPS_PRIVATE=[ + 'api_parameters', + 'commands', + ], +) + +env.Library( target='logical_time', source=[ 'logical_time.cpp', diff --git a/src/mongo/db/api_parameters.cpp b/src/mongo/db/api_parameters.cpp new file mode 100644 index 00000000000..05ffe9c49cb --- /dev/null +++ b/src/mongo/db/api_parameters.cpp @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2020-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. + */ + +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand + +#include "mongo/platform/basic.h" + +#include "mongo/db/api_parameters.h" + +namespace mongo { + +const OperationContext::Decoration<APIParameters> APIParameters::get = + OperationContext::declareDecoration<APIParameters>(); + +APIParameters APIParameters::fromClient(const APIParametersFromClient& apiParamsFromClient) { + APIParameters apiParameters = APIParameters(); + auto apiVersion = apiParamsFromClient.getApiVersion(); + auto apiStrict = apiParamsFromClient.getApiStrict(); + auto apiDeprecationErrors = apiParamsFromClient.getApiDeprecationErrors(); + + if (apiVersion) { + apiParameters.setAPIVersion(apiVersion.value()); + } + + if (apiStrict) { + apiParameters.setAPIStrict(apiStrict.value()); + } + + if (apiDeprecationErrors) { + apiParameters.setAPIDeprecationErrors(apiDeprecationErrors.value()); + } + + return apiParameters; +} + +APIParameters APIParameters::fromBSON(const BSONObj& cmdObj) { + return APIParameters::fromClient( + APIParametersFromClient::parse("APIParametersFromClient"_sd, cmdObj)); +} + +void APIParameters::appendInfo(BSONObjBuilder* builder) const { + if (_apiVersion) { + builder->append(kAPIVersionFieldName, *_apiVersion); + } + if (_apiStrict) { + builder->append(kAPIStrictFieldName, *_apiStrict); + } + if (_apiDeprecationErrors) { + builder->append(kAPIDeprecationErrorsFieldName, *_apiDeprecationErrors); + } +} + +} // namespace mongo diff --git a/src/mongo/db/api_parameters.h b/src/mongo/db/api_parameters.h new file mode 100644 index 00000000000..7539dcb345e --- /dev/null +++ b/src/mongo/db/api_parameters.h @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2020-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/db/api_parameters_gen.h" +#include "mongo/db/operation_context.h" + +namespace mongo { + +/** + * Decorates operation context with methods to retrieve apiVersion, apiStrict, and + * apiDeprecationErrors. + */ +class APIParameters { + +public: + static constexpr StringData kAPIVersionFieldName = "apiVersion"_sd; + static constexpr StringData kAPIStrictFieldName = "apiStrict"_sd; + static constexpr StringData kAPIDeprecationErrorsFieldName = "apiDeprecationErrors"_sd; + + static const OperationContext::Decoration<APIParameters> get; + static APIParameters fromClient(const APIParametersFromClient& apiParamsFromClient); + static APIParameters fromBSON(const BSONObj& cmdObj); + + void appendInfo(BSONObjBuilder* builder) const; + + const boost::optional<std::string>& getAPIVersion() const { + return _apiVersion; + } + + void setAPIVersion(StringData apiVersion) { + _apiVersion = apiVersion.toString(); + } + + const boost::optional<bool>& getAPIStrict() const { + return _apiStrict; + } + + void setAPIStrict(bool apiStrict) { + _apiStrict = apiStrict; + } + + const boost::optional<bool>& getAPIDeprecationErrors() const { + return _apiDeprecationErrors; + } + + void setAPIDeprecationErrors(bool apiDeprecationErrors) { + _apiDeprecationErrors = apiDeprecationErrors; + } + + const bool getParamsPassed() const { + return _apiVersion || _apiStrict || _apiDeprecationErrors; + } + +private: + boost::optional<std::string> _apiVersion; + boost::optional<bool> _apiStrict; + boost::optional<bool> _apiDeprecationErrors; +}; + + +/** + * Temporarily remove the user's API parameters from an OperationContext. + */ +class IgnoreAPIParametersBlock { +public: + IgnoreAPIParametersBlock() = delete; + IgnoreAPIParametersBlock(const IgnoreAPIParametersBlock&) = delete; + IgnoreAPIParametersBlock& operator=(const IgnoreAPIParametersBlock&) = delete; + + explicit IgnoreAPIParametersBlock(OperationContext* opCtx) : _opCtx(opCtx) { + _apiParams = APIParameters::get(_opCtx); + APIParameters::get(_opCtx) = APIParameters(); + } + + void release() { + if (_released) { + return; + } + + APIParameters::get(_opCtx) = _apiParams; + _released = true; + } + + ~IgnoreAPIParametersBlock() { + release(); + } + +private: + OperationContext* _opCtx; + APIParameters _apiParams; + bool _released = false; +}; + +} // namespace mongo diff --git a/src/mongo/db/initialize_api_parameters.idl b/src/mongo/db/api_parameters.idl index cc3a3d13e6c..cc3a3d13e6c 100644 --- a/src/mongo/db/initialize_api_parameters.idl +++ b/src/mongo/db/api_parameters.idl diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h index ee2040764b6..f4d7960a759 100644 --- a/src/mongo/db/clientcursor.h +++ b/src/mongo/db/clientcursor.h @@ -32,10 +32,10 @@ #include <boost/optional.hpp> #include <functional> +#include "mongo/db/api_parameters.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/auth/user_name.h" #include "mongo/db/cursor_id.h" -#include "mongo/db/initialize_api_parameters.h" #include "mongo/db/jsobj.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/query/plan_executor.h" diff --git a/src/mongo/db/command_generic_argument.cpp b/src/mongo/db/command_generic_argument.cpp index 8434b65a3c3..e15c2498a97 100644 --- a/src/mongo/db/command_generic_argument.cpp +++ b/src/mongo/db/command_generic_argument.cpp @@ -56,9 +56,9 @@ static constexpr std::array<SpecialArgRecord, 34> specials{{ // /-isGeneric // | /-stripFromRequest // | | /-stripFromReply - {"apiVersion"_sd, 1, 0, 0}, - {"apiStrict"_sd, 1, 0, 0}, - {"apiDeprecationErrors"_sd, 1, 0, 0}, + {"apiVersion"_sd, 1, 1, 0}, + {"apiStrict"_sd, 1, 1, 0}, + {"apiDeprecationErrors"_sd, 1, 1, 0}, {"$audit"_sd, 1, 1, 0}, {"$client"_sd, 1, 1, 0}, {"$configServerState"_sd, 1, 1, 1}, diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index f9ef6f72574..8d9a8de296b 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -867,6 +867,14 @@ Command::Command(StringData name, std::vector<StringData> aliases) globalCommandRegistry()->registerCommand(this, _name, _aliases); } +const std::set<std::string>& Command::apiVersions() const { + return kNoApiVersions; +} + +const std::set<std::string>& Command::deprecatedApiVersions() const { + return kNoApiVersions; +} + bool Command::hasAlias(const StringData& alias) const { return globalCommandRegistry()->findCommand(alias) == this; } diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 1877556f356..57b3ce272ca 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -358,16 +358,12 @@ public: /* * Returns the list of API versions that include this command. */ - virtual const std::set<std::string>& apiVersions() const { - return kNoApiVersions; - } + virtual const std::set<std::string>& apiVersions() const; /* * Returns the list of API versions in which this command is deprecated. */ - virtual const std::set<std::string>& deprecatedApiVersions() const { - return kNoApiVersions; - } + virtual const std::set<std::string>& deprecatedApiVersions() const; /** * Like adminOnly, but even stricter: we must either be authenticated for admin db, diff --git a/src/mongo/db/commands/test_api_version_2_commands.cpp b/src/mongo/db/commands/test_api_version_2_commands.cpp index b2c79a7ef70..738e13b1366 100644 --- a/src/mongo/db/commands/test_api_version_2_commands.cpp +++ b/src/mongo/db/commands/test_api_version_2_commands.cpp @@ -27,8 +27,8 @@ * it in the license file. */ +#include "mongo/db/api_parameters.h" #include "mongo/db/commands.h" -#include "mongo/db/initialize_api_parameters.h" namespace mongo { diff --git a/src/mongo/db/commands/test_deprecation_command.cpp b/src/mongo/db/commands/test_deprecation_command.cpp index 44e61edb4a0..74d93942ddd 100644 --- a/src/mongo/db/commands/test_deprecation_command.cpp +++ b/src/mongo/db/commands/test_deprecation_command.cpp @@ -27,8 +27,8 @@ * it in the license file. */ +#include "mongo/db/api_parameters.h" #include "mongo/db/commands.h" -#include "mongo/db/initialize_api_parameters.h" namespace mongo { diff --git a/src/mongo/db/dbdirectclient.cpp b/src/mongo/db/dbdirectclient.cpp index 5386bf567d2..bb1f5553906 100644 --- a/src/mongo/db/dbdirectclient.cpp +++ b/src/mongo/db/dbdirectclient.cpp @@ -143,6 +143,7 @@ DbResponse loopbackBuildResponse(OperationContext* const opCtx, toSend.header().setId(nextMessageId()); toSend.header().setResponseToMsgId(0); + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); return opCtx->getServiceContext()->getServiceEntryPoint()->handleRequest(opCtx, toSend).get(); } } // namespace diff --git a/src/mongo/db/initialize_api_parameters.cpp b/src/mongo/db/initialize_api_parameters.cpp index 11a5b68ae10..9ad9fc4d026 100644 --- a/src/mongo/db/initialize_api_parameters.cpp +++ b/src/mongo/db/initialize_api_parameters.cpp @@ -27,8 +27,17 @@ * it in the license file. */ +#include "mongo/platform/basic.h" + #include "mongo/db/initialize_api_parameters.h" +#include <string> + +#include "mongo/db/commands.h" +#include "mongo/db/operation_context.h" +#include "mongo/util/assert_util.h" +#include "mongo/util/str.h" + namespace mongo { const APIParametersFromClient initializeAPIParameters(OperationContext* opCtx, @@ -88,44 +97,4 @@ const APIParametersFromClient initializeAPIParameters(OperationContext* opCtx, return apiParamsFromClient; } -const OperationContext::Decoration<APIParameters> handle = - OperationContext::declareDecoration<APIParameters>(); - -APIParameters& APIParameters::get(OperationContext* opCtx) { - return handle(opCtx); -} - -APIParameters APIParameters::fromClient(const APIParametersFromClient& apiParamsFromClient) { - APIParameters apiParameters = APIParameters(); - auto apiVersion = apiParamsFromClient.getApiVersion(); - auto apiStrict = apiParamsFromClient.getApiStrict(); - auto apiDeprecationErrors = apiParamsFromClient.getApiDeprecationErrors(); - - if (apiVersion) { - apiParameters.setAPIVersion(apiVersion.value()); - } - - if (apiStrict) { - apiParameters.setAPIStrict(apiStrict.value()); - } - - if (apiDeprecationErrors) { - apiParameters.setAPIDeprecationErrors(apiDeprecationErrors.value()); - } - - return apiParameters; -} - -void APIParameters::appendInfo(BSONObjBuilder* builder) const { - if (_apiVersion) { - builder->append(kAPIVersionFieldName, *_apiVersion); - } - if (_apiStrict) { - builder->append(kAPIStrictFieldName, *_apiStrict); - } - if (_apiDeprecationErrors) { - builder->append(kAPIDeprecationErrorsFieldName, *_apiDeprecationErrors); - } -} - } // namespace mongo diff --git a/src/mongo/db/initialize_api_parameters.h b/src/mongo/db/initialize_api_parameters.h index 73215f607c8..e62d0defecc 100644 --- a/src/mongo/db/initialize_api_parameters.h +++ b/src/mongo/db/initialize_api_parameters.h @@ -29,73 +29,19 @@ #pragma once -#include "mongo/db/commands.h" -#include "mongo/db/initialize_api_parameters_gen.h" -#include "mongo/db/operation_context.h" +#include "api_parameters.h" namespace mongo { +class BSONObj; +class Command; +class OperationContext; + /** - * See VERSIONED_API_README.md for an overview of the Versioned API. - * - * This function parses a command's API Version parameters from a request and stores the apiVersion, + * Parse a command's API Version parameters from a request and store the apiVersion, * apiStrict, and apiDeprecationErrors fields. */ const APIParametersFromClient initializeAPIParameters(OperationContext* opCtx, const BSONObj& requestBody, Command* command); - -/** - * Decorates operation context with methods to retrieve apiVersion, apiStrict, and - * apiDeprecationErrors. - */ -class APIParameters { - -public: - static constexpr StringData kAPIVersionFieldName = "apiVersion"_sd; - static constexpr StringData kAPIStrictFieldName = "apiStrict"_sd; - static constexpr StringData kAPIDeprecationErrorsFieldName = "apiDeprecationErrors"_sd; - - APIParameters() = default; - static APIParameters& get(OperationContext* opCtx); - static APIParameters fromClient(const APIParametersFromClient& apiParamsFromClient); - - void appendInfo(BSONObjBuilder* builder) const; - - const boost::optional<std::string>& getAPIVersion() const { - return _apiVersion; - } - - void setAPIVersion(StringData apiVersion) { - _apiVersion = apiVersion.toString(); - } - - const boost::optional<bool>& getAPIStrict() const { - return _apiStrict; - } - - void setAPIStrict(bool apiStrict) { - _apiStrict = apiStrict; - } - - const boost::optional<bool>& getAPIDeprecationErrors() const { - return _apiDeprecationErrors; - } - - void setAPIDeprecationErrors(bool apiDeprecationErrors) { - _apiDeprecationErrors = apiDeprecationErrors; - } - - bool getParamsPassed() const { - return _apiVersion || _apiStrict || _apiDeprecationErrors; - } - - BSONObj toBSON() const; - -private: - boost::optional<std::string> _apiVersion; - boost::optional<bool> _apiStrict; - boost::optional<bool> _apiDeprecationErrors; -}; - } // namespace mongo diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript index eada898eafb..b57c45a30e4 100644 --- a/src/mongo/db/query/SConscript +++ b/src/mongo/db/query/SConscript @@ -179,6 +179,7 @@ env.Library( ], LIBDEPS=[ "$BUILD_DIR/mongo/base", + "$BUILD_DIR/mongo/db/api_parameters", "$BUILD_DIR/mongo/db/catalog/collection_catalog", # TODO: This dependency edge can be removed when the 'allowDiskUse' option no longer depends # on enabling test commands. diff --git a/src/mongo/db/s/config/configsvr_drop_database_command.cpp b/src/mongo/db/s/config/configsvr_drop_database_command.cpp index eb3ef547e70..91513e5d2e4 100644 --- a/src/mongo/db/s/config/configsvr_drop_database_command.cpp +++ b/src/mongo/db/s/config/configsvr_drop_database_command.cpp @@ -29,6 +29,7 @@ #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding +#include "mongo/db/api_parameters.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" @@ -177,6 +178,7 @@ public: status, str::stream() << "Could not remove database '" << dbname << "' from metadata"); // Send _flushDatabaseCacheUpdates to all shards + IgnoreAPIParametersBlock ignoreApiParametersBlock{opCtx}; for (const ShardId& shardId : allShardIds) { const auto shard = uassertStatusOK(Grid::get(opCtx)->shardRegistry()->getShard(opCtx, shardId)); diff --git a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp index d6544e922d2..381a5e62029 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp @@ -42,6 +42,7 @@ #include "mongo/client/read_preference.h" #include "mongo/client/remote_command_targeter.h" #include "mongo/client/replica_set_monitor.h" +#include "mongo/db/api_parameters.h" #include "mongo/db/auth/authorization_session_impl.h" #include "mongo/db/catalog/collection_options.h" #include "mongo/db/client.h" @@ -398,6 +399,7 @@ void sendSSVToAllShards(OperationContext* opCtx, const NamespaceString& nss) { auto* const shardRegistry = Grid::get(opCtx)->shardRegistry(); + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); for (const auto& shardEntry : allShards) { const auto& shard = uassertStatusOK(shardRegistry->getShard(opCtx, shardEntry.getName())); @@ -417,6 +419,7 @@ void sendSSVToAllShards(OperationContext* opCtx, const NamespaceString& nss) { } void removeChunksAndTagsForDroppedCollection(OperationContext* opCtx, const NamespaceString& nss) { + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); const auto catalogClient = Grid::get(opCtx)->catalogClient(); // Remove chunk data @@ -502,6 +505,8 @@ void ShardingCatalogManager::ensureDropCollectionCompleted(OperationContext* opC "Ensuring config entries from previous dropCollection are cleared", "namespace"_attr = nss.ns()); sendDropCollectionToAllShards(opCtx, nss); + + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); removeChunksAndTagsForDroppedCollection(opCtx, nss); sendSSVToAllShards(opCtx, nss); } diff --git a/src/mongo/db/stats/api_version_metrics.h b/src/mongo/db/stats/api_version_metrics.h index fc1de1d9766..354312a3992 100644 --- a/src/mongo/db/stats/api_version_metrics.h +++ b/src/mongo/db/stats/api_version_metrics.h @@ -29,7 +29,7 @@ #pragma once -#include "mongo/db/initialize_api_parameters.h" +#include "mongo/db/api_parameters.h" #include "mongo/db/service_context.h" #include "mongo/platform/mutex.h" #include "mongo/rpc/metadata/client_metadata.h" @@ -70,4 +70,4 @@ private: APIVersionMetricsMap _apiVersionMetrics; }; -} // namespace mongo
\ No newline at end of file +} // namespace mongo diff --git a/src/mongo/db/transaction_participant.h b/src/mongo/db/transaction_participant.h index f898b21c112..37b71ce8589 100644 --- a/src/mongo/db/transaction_participant.h +++ b/src/mongo/db/transaction_participant.h @@ -33,11 +33,11 @@ #include <iostream> #include <map> +#include "mongo/db/api_parameters.h" #include "mongo/db/catalog/uncommitted_collections.h" #include "mongo/db/commands/txn_cmds_gen.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/concurrency/locker.h" -#include "mongo/db/initialize_api_parameters.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/multi_key_path_tracker.h" #include "mongo/db/ops/update_request.h" diff --git a/src/mongo/executor/SConscript b/src/mongo/executor/SConscript index 76956c8818e..b10cf01369a 100644 --- a/src/mongo/executor/SConscript +++ b/src/mongo/executor/SConscript @@ -31,6 +31,7 @@ env.Library( 'remote_command_response.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/api_parameters', '$BUILD_DIR/mongo/rpc/metadata', '$BUILD_DIR/mongo/util/net/network', ] diff --git a/src/mongo/executor/remote_command_request.cpp b/src/mongo/executor/remote_command_request.cpp index 875da25ef9f..4c35525e6a9 100644 --- a/src/mongo/executor/remote_command_request.cpp +++ b/src/mongo/executor/remote_command_request.cpp @@ -34,6 +34,7 @@ #include <fmt/format.h> #include "mongo/bson/simple_bsonobj_comparator.h" +#include "mongo/db/api_parameters.h" #include "mongo/db/operation_context.h" #include "mongo/db/query/query_request.h" #include "mongo/platform/atomic_word.h" @@ -86,6 +87,12 @@ RemoteCommandRequestBase::RemoteCommandRequestBase(RequestId requestId, cmdObj = cmdObj.addField(BSON("clientOperationKey" << operationKey.get()).firstElement()); } + if (opCtx && APIParameters::get(opCtx).getParamsPassed()) { + BSONObjBuilder bob(std::move(cmdObj)); + APIParameters::get(opCtx).appendInfo(&bob); + cmdObj = bob.obj(); + } + _updateTimeoutFromOpCtxDeadline(opCtx); } diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript index 780d4d4bc9a..8fc761a2e0b 100644 --- a/src/mongo/s/commands/SConscript +++ b/src/mongo/s/commands/SConscript @@ -124,6 +124,7 @@ env.Library( '$BUILD_DIR/mongo/db/commands/test_commands_enabled', '$BUILD_DIR/mongo/db/commands/write_commands_common', '$BUILD_DIR/mongo/db/ftdc/ftdc_server', + '$BUILD_DIR/mongo/db/initialize_api_parameters', '$BUILD_DIR/mongo/db/logical_session_cache_impl', '$BUILD_DIR/mongo/db/pipeline/aggregation', '$BUILD_DIR/mongo/db/query/command_request_response', diff --git a/src/mongo/s/query/async_results_merger.cpp b/src/mongo/s/query/async_results_merger.cpp index 2ad05010afb..98aec3332ec 100644 --- a/src/mongo/s/query/async_results_merger.cpp +++ b/src/mongo/s/query/async_results_merger.cpp @@ -462,8 +462,11 @@ Status AsyncResultsMerger::_askForNextBatch(WithLock, size_t remoteIndex) { cmdObj = newCmdBob.obj(); } + // Never pass API parameters with getMore. + IgnoreAPIParametersBlock ignoreApiParametersBlock(_opCtx); executor::RemoteCommandRequest request( remote.getTargetHost(), remote.cursorNss.db().toString(), cmdObj, _opCtx); + ignoreApiParametersBlock.release(); auto callbackStatus = _executor->scheduleRemoteCommand(request, [this, remoteIndex](auto const& cbData) { diff --git a/src/mongo/s/query/cluster_client_cursor.h b/src/mongo/s/query/cluster_client_cursor.h index 44aae05e34d..87e3271e692 100644 --- a/src/mongo/s/query/cluster_client_cursor.h +++ b/src/mongo/s/query/cluster_client_cursor.h @@ -32,8 +32,8 @@ #include <boost/optional.hpp> #include "mongo/client/read_preference.h" +#include "mongo/db/api_parameters.h" #include "mongo/db/auth/user_name.h" -#include "mongo/db/initialize_api_parameters.h" #include "mongo/db/jsobj.h" #include "mongo/db/logical_session_id.h" #include "mongo/s/query/cluster_client_cursor_params.h" diff --git a/src/mongo/s/query/cluster_client_cursor_params.h b/src/mongo/s/query/cluster_client_cursor_params.h index d8bb0ae8da0..b0fae249884 100644 --- a/src/mongo/s/query/cluster_client_cursor_params.h +++ b/src/mongo/s/query/cluster_client_cursor_params.h @@ -36,10 +36,10 @@ #include "mongo/bson/bsonobj.h" #include "mongo/client/read_preference.h" +#include "mongo/db/api_parameters.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/auth/user_name.h" #include "mongo/db/cursor_id.h" -#include "mongo/db/initialize_api_parameters.h" #include "mongo/db/namespace_string.h" #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/query/cursor_response.h" diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp index 12073508642..57925b873ed 100644 --- a/src/mongo/s/query/cluster_find.cpp +++ b/src/mongo/s/query/cluster_find.cpp @@ -772,6 +772,7 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx, StatusWith<ClusterQueryResult> next = Status{ErrorCodes::InternalError, "uninitialized cluster query result"}; try { + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); next = pinnedCursor.getValue()->next(context); } catch (const ExceptionFor<ErrorCodes::CloseChangeStream>&) { // This exception is thrown when a $changeStream stage encounters an event diff --git a/src/mongo/s/transaction_router.cpp b/src/mongo/s/transaction_router.cpp index b7b26698e78..c269d734365 100644 --- a/src/mongo/s/transaction_router.cpp +++ b/src/mongo/s/transaction_router.cpp @@ -125,7 +125,6 @@ BSONObj appendReadConcernForTxn(BSONObj cmd, } BSONObjBuilder appendFieldsForStartTransaction(BSONObj cmd, - APIParameters apiParameters, repl::ReadConcernArgs readConcernArgs, boost::optional<LogicalTime> atClusterTime, bool doAppendStartTransaction) { @@ -134,8 +133,6 @@ BSONObjBuilder appendFieldsForStartTransaction(BSONObj cmd, appendReadConcernForTxn(std::move(cmd), readConcernArgs, atClusterTime); BSONObjBuilder bob(std::move(cmdWithReadConcern)); - - apiParameters.appendInfo(&bob); if (doAppendStartTransaction) { bob.append(OperationSessionInfoFromClient::kStartTransactionFieldName, true); } @@ -433,7 +430,6 @@ BSONObj TransactionRouter::Participant::attachTxnFieldsIfNeeded( BSONObjBuilder newCmd = mustStartTransaction ? appendFieldsForStartTransaction(std::move(cmd), - sharedOptions.apiParameters, sharedOptions.readConcernArgs, sharedOptions.atClusterTime, !hasStartTxn) @@ -1203,6 +1199,8 @@ BSONObj TransactionRouter::Router::abortTransaction(OperationContext* opCtx) { "txnNumber"_attr = o().txnNumber, "numParticipantShards"_attr = o().participants.size()); + // Omit API parameters from abortTransaction. + IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx); const auto responses = gatherResponses(opCtx, NamespaceString::kAdminDb, ReadPreferenceSetting{ReadPreference::PrimaryOnly}, diff --git a/src/mongo/s/transaction_router.h b/src/mongo/s/transaction_router.h index 25ce17831fe..3d6be675077 100644 --- a/src/mongo/s/transaction_router.h +++ b/src/mongo/s/transaction_router.h @@ -31,8 +31,8 @@ #include <boost/optional.hpp> +#include "mongo/db/api_parameters.h" #include "mongo/db/commands/txn_cmds_gen.h" -#include "mongo/db/initialize_api_parameters.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/operation_context.h" #include "mongo/db/repl/read_concern_args.h" diff --git a/src/mongo/s/transaction_router_test.cpp b/src/mongo/s/transaction_router_test.cpp index eb827201e84..a507d3e4f3f 100644 --- a/src/mongo/s/transaction_router_test.cpp +++ b/src/mongo/s/transaction_router_test.cpp @@ -316,16 +316,9 @@ TEST_F(TransactionRouterTestWithDefaultSession, CannotContiueTxnWithoutStarting) ErrorCodes::NoSuchTransaction); } -TEST_F(TransactionRouterTestWithDefaultSession, - NewParticipantMustAttachTxnAndReadConcernAndAPIParams) { +TEST_F(TransactionRouterTestWithDefaultSession, NewParticipantMustAttachTxnAndReadConcern) { TxnNumber txnNum{3}; - APIParameters apiParameters = APIParameters(); - apiParameters.setAPIVersion("1"); - apiParameters.setAPIStrict(false); - apiParameters.setAPIDeprecationErrors(false); - APIParameters::get(operationContext()) = apiParameters; - auto txnRouter = TransactionRouter::get(operationContext()); txnRouter.beginOrContinueTxn( operationContext(), txnNum, TransactionRouter::TransactionActions::kStart); @@ -337,9 +330,6 @@ TEST_F(TransactionRouterTestWithDefaultSession, << BSON("level" << "snapshot" << "atClusterTime" << kInMemoryLogicalTime.asTimestamp()) - << "apiVersion" - << "1" - << "apiStrict" << false << "apiDeprecationErrors" << false << "startTransaction" << true << "coordinator" << true << "autocommit" << false << "txnNumber" << txnNum); @@ -369,9 +359,6 @@ TEST_F(TransactionRouterTestWithDefaultSession, << BSON("level" << "snapshot" << "atClusterTime" << kInMemoryLogicalTime.asTimestamp()) - << "apiVersion" - << "1" - << "apiStrict" << false << "apiDeprecationErrors" << false << "startTransaction" << true << "autocommit" << false << "txnNumber" << txnNum); @@ -735,40 +722,6 @@ TEST_F(TransactionRouterTestWithDefaultSession, AttachTxnValidatesReadConcernIfA } } -TEST_F(TransactionRouterTestWithDefaultSession, AttachTxnAttachesAPIParameters) { - APIParameters apiParams = APIParameters(); - apiParams.setAPIVersion("2"); - apiParams.setAPIStrict(true); - apiParams.setAPIDeprecationErrors(true); - - APIParameters::get(operationContext()) = apiParams; - - TxnNumber txnNum{3}; - auto txnRouter = TransactionRouter::get(operationContext()); - txnRouter.beginOrContinueTxn( - operationContext(), txnNum, TransactionRouter::TransactionActions::kStart); - txnRouter.setDefaultAtClusterTime(operationContext()); - - { - auto newCmd = txnRouter.attachTxnFieldsIfNeeded(operationContext(), - shard1, - BSON("insert" - << "test")); - ASSERT_BSONOBJ_EQ(BSON("insert" - << "test" - << "readConcern" - << BSON("level" - << "snapshot" - << "atClusterTime" << kInMemoryLogicalTime.asTimestamp()) - << "apiVersion" - << "2" - << "apiStrict" << true << "apiDeprecationErrors" << true - << "startTransaction" << true << "coordinator" << true - << "autocommit" << false << "txnNumber" << txnNum), - newCmd); - } -} - TEST_F(TransactionRouterTestWithDefaultSession, CannotSpecifyAPIParametersAfterFirstStatement) { APIParameters apiParameters = APIParameters(); apiParameters.setAPIVersion("1"); @@ -787,40 +740,6 @@ TEST_F(TransactionRouterTestWithDefaultSession, CannotSpecifyAPIParametersAfterF 4937701); } -TEST_F(TransactionRouterTestWithDefaultSession, PassesThroughAPIParametersToParticipants) { - APIParameters apiParams = APIParameters(); - apiParams.setAPIVersion("2"); - apiParams.setAPIStrict(true); - apiParams.setAPIDeprecationErrors(true); - - APIParameters::get(operationContext()) = apiParams; - - TxnNumber txnNum{3}; - - auto txnRouter = TransactionRouter::get(operationContext()); - txnRouter.beginOrContinueTxn( - operationContext(), txnNum, TransactionRouter::TransactionActions::kStart); - txnRouter.setDefaultAtClusterTime(operationContext()); - - BSONObj expectedNewObj = BSON("insert" - << "test" - << "readConcern" - << BSON("level" - << "snapshot" - << "atClusterTime" << kInMemoryLogicalTime.asTimestamp()) - << "apiVersion" - << "2" - << "apiStrict" << true << "apiDeprecationErrors" << true - << "startTransaction" << true << "coordinator" << true - << "autocommit" << false << "txnNumber" << txnNum); - - auto newCmd = txnRouter.attachTxnFieldsIfNeeded(operationContext(), - shard1, - BSON("insert" - << "test")); - ASSERT_BSONOBJ_EQ(expectedNewObj, newCmd); -} - TEST_F(TransactionRouterTestWithDefaultSession, CannotSpecifyReadConcernAfterFirstStatement) { TxnNumber txnNum{3}; @@ -3294,6 +3213,43 @@ TEST_F(TransactionRouterMetricsTest, LogsTransactionsOverSlowMSThreshold) { assertPrintedExactlyOneSlowLogLine(); } +TEST_F(TransactionRouterMetricsTest, LogsTransactionsWithAPIParameters) { + const auto originalSlowMS = serverGlobalParams.slowMS; + const auto originalSampleRate = serverGlobalParams.sampleRate; + + serverGlobalParams.slowMS = 100; + serverGlobalParams.sampleRate = 1; + + // Reset the global parameters to their original values after this test exits. + ON_BLOCK_EXIT([originalSlowMS, originalSampleRate] { + serverGlobalParams.slowMS = originalSlowMS; + serverGlobalParams.sampleRate = originalSampleRate; + }); + + APIParameters::get(operationContext()).setAPIVersion("1"); + APIParameters::get(operationContext()).setAPIStrict(true); + APIParameters::get(operationContext()).setAPIDeprecationErrors(false); + beginTxnWithDefaultTxnNumber(); + tickSource()->advance(Milliseconds(101)); + runCommit(kDummyOkRes); + assertPrintedExactlyOneSlowLogLine(); + + int nFound = 0; + for (auto&& bson : getCapturedBSONFormatLogMessages()) { + if (bson["id"].Int() != 51805) { + continue; + } + + auto parameters = bson["attr"]["parameters"]; + ASSERT_EQUALS(parameters["apiVersion"].String(), "1"); + ASSERT_EQUALS(parameters["apiStrict"].Bool(), true); + ASSERT_EQUALS(parameters["apiDeprecationErrors"].Bool(), false); + ++nFound; + } + + ASSERT_EQUALS(nFound, 1); +} + TEST_F(TransactionRouterMetricsTest, DoesNotLogTransactionsWithSampleRateZero) { const auto originalSlowMS = serverGlobalParams.slowMS; const auto originalSampleRate = serverGlobalParams.sampleRate; |