diff options
Diffstat (limited to 'src/mongo')
21 files changed, 376 insertions, 14 deletions
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index 8dbfac9cfd9..542d75a8b93 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -224,7 +224,7 @@ error_code("IllegalOpMsgFlag", 223) error_code("QueryFeatureNotAllowed", 224) error_code("TransactionTooOld", 225) error_code("AtomicityFailure", 226) -error_code("CannotImplicitlyCreateCollection", 227); +error_code("CannotImplicitlyCreateCollection", 227, extra="CannotImplicitlyCreateCollectionInfo"); error_code("SessionTransferIncomplete", 228) error_code("MustDowngrade", 229) error_code("DNSHostNotFound", 230) diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript index 92a508ffeff..1c45edcd9d3 100644 --- a/src/mongo/db/catalog/SConscript +++ b/src/mongo/db/catalog/SConscript @@ -287,6 +287,7 @@ env.Library( '$BUILD_DIR/mongo/db/system_index', '$BUILD_DIR/mongo/db/ttl_collection_cache', '$BUILD_DIR/mongo/db/views/views_mongod', + '$BUILD_DIR/mongo/s/stale_config', ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/logical_clock', diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index 7206621a5f5..858a579982e 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -71,6 +71,7 @@ #include "mongo/db/system_index.h" #include "mongo/db/views/view_catalog.h" #include "mongo/platform/random.h" +#include "mongo/s/cannot_implicitly_create_collection_info.h" #include "mongo/stdx/memory.h" #include "mongo/util/assert_util.h" #include "mongo/util/fail_point_service.h" @@ -766,7 +767,7 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx, invariant(!options.isView()); NamespaceString nss(ns); - uassert(ErrorCodes::CannotImplicitlyCreateCollection, + uassert(CannotImplicitlyCreateCollectionInfo(nss), "request doesn't allow collection to be created implicitly", OperationShardingState::get(opCtx).allowImplicitCollectionCreation()); diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index 428fb40b7e2..a781b2682ed 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -99,13 +99,16 @@ void serializeReply(OperationContext* opCtx, if (shouldSkipOutput(opCtx)) return; - if (continueOnError && !result.results.empty() && - result.results.back() == ErrorCodes::StaleConfig) { - // For ordered:false commands we need to duplicate the StaleConfig result for all ops - // after we stopped. See handleError() in write_ops_exec.cpp for more info. - auto err = result.results.back(); - while (result.results.size() < opsInBatch) { - result.results.emplace_back(err); + if (continueOnError && !result.results.empty()) { + const auto& lastResult = result.results.back(); + if (lastResult == ErrorCodes::StaleConfig || + lastResult == ErrorCodes::CannotImplicitlyCreateCollection) { + // For ordered:false commands we need to duplicate these error results for all ops + // after we stopped. See handleError() in write_ops_exec.cpp for more info. + auto err = result.results.back(); + while (result.results.size() < opsInBatch) { + result.results.emplace_back(err); + } } } diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index ba28fca2ccb..413f729b347 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -62,6 +62,7 @@ #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/retryable_writes_stats.h" #include "mongo/db/s/collection_sharding_state.h" +#include "mongo/db/s/implicit_create_collection.h" #include "mongo/db/s/shard_filtering_metadata_refresh.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/session_catalog.h" @@ -69,6 +70,7 @@ #include "mongo/db/stats/top.h" #include "mongo/db/write_concern.h" #include "mongo/rpc/get_status_from_command_result.h" +#include "mongo/s/cannot_implicitly_create_collection_info.h" #include "mongo/stdx/memory.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" @@ -229,6 +231,17 @@ bool handleError(OperationContext* opCtx, // Command reply serializer will handle repeating this error if needed. out->results.emplace_back(ex.toStatus()); return false; + } else if (auto cannotImplicitCreateCollInfo = + ex.extraInfo<CannotImplicitlyCreateCollectionInfo>()) { + // Don't try doing more ops since they will fail with the same error. + // Command reply serializer will handle repeating this error if needed. + out->results.emplace_back(ex.toStatus()); + + if (ShardingState::get(opCtx)->enabled()) { + onCannotImplicitlyCreateCollection(opCtx, cannotImplicitCreateCollInfo->getNss()); + } + + return false; } out->results.emplace_back(ex.toStatus()); diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 99b820224da..f2fbcb15906 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -22,6 +22,7 @@ env.Library( env.Library( target='sharding_runtime_d', source=[ + 'implicit_create_collection.cpp', 'migration_destination_manager.cpp', 'session_catalog_migration_destination.cpp', 'shard_filtering_metadata_refresh.cpp', diff --git a/src/mongo/db/s/config/configsvr_create_collection_command.cpp b/src/mongo/db/s/config/configsvr_create_collection_command.cpp index 1e733dfda54..7eba3758208 100644 --- a/src/mongo/db/s/config/configsvr_create_collection_command.cpp +++ b/src/mongo/db/s/config/configsvr_create_collection_command.cpp @@ -109,7 +109,9 @@ public: IDLParserErrorContext("ConfigsvrCreateCollection"), cmdObj); CollectionOptions options; - uassertStatusOK(options.parse(createCmd.getOptions())); + if (auto requestOptions = createCmd.getOptions()) { + uassertStatusOK(options.parse(*requestOptions)); + } ShardingCatalogManager::get(opCtx)->createCollection(opCtx, createCmd.getNs(), options); diff --git a/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp index b0507b34451..806616b87e0 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp @@ -354,7 +354,9 @@ TEST_F(AddShardTest, CreateShardIdentityUpsertForAddShard) { << BSON("w" << "majority" << "wtimeout" - << 15000)); + << 15000) + << "allowImplicitCollectionCreation" + << true); ASSERT_BSONOBJ_EQ(expectedBSON, ShardingCatalogManager::get(operationContext()) ->createShardIdentityUpsertForAddShard(operationContext(), shardName)); diff --git a/src/mongo/db/s/implicit_create_collection.cpp b/src/mongo/db/s/implicit_create_collection.cpp new file mode 100644 index 00000000000..17f68349c30 --- /dev/null +++ b/src/mongo/db/s/implicit_create_collection.cpp @@ -0,0 +1,150 @@ +/** + * Copyright (C) 2018 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::kSharding + +#include "mongo/platform/basic.h" + +#include "mongo/db/s/implicit_create_collection.h" + +#include <map> +#include <memory> +#include <string> + +#include "mongo/db/catalog/catalog_raii.h" +#include "mongo/db/commands.h" +#include "mongo/db/namespace_string.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context.h" +#include "mongo/s/grid.h" +#include "mongo/s/request_types/create_collection_gen.h" + +#include "mongo/stdx/condition_variable.h" +#include "mongo/stdx/mutex.h" +#include "mongo/util/scopeguard.h" + +namespace mongo { + +namespace { + +/** + * Responsible for explicitly creating collections in the sharding catalog. Also takes care of + * making sure that concurrent attempts to create a collection for the same ns will be + * synchronized and avoid duplicate work as much as possible. + */ + +class CreateCollectionSerializer { +public: + explicit CreateCollectionSerializer(NamespaceString ns) : _ns(std::move(ns)) {} + + /** + * Initialize this collection so it will be officially tracked in a sharded environment + * by sending the command to the config server to create an entry for this collection in + * the sharding catalog. + */ + void onCannotImplicitlyCreateCollection(OperationContext* opCtx) { + invariant(!opCtx->lockState()->isLocked()); + + { + stdx::unique_lock<stdx::mutex> lg(_mutex); + while (_isInProgress) { + opCtx->waitForConditionOrInterrupt(_cvIsInProgress, lg); + } + + _isInProgress = true; + } + + ON_BLOCK_EXIT([&] { + stdx::lock_guard<stdx::mutex> lg(_mutex); + _isInProgress = false; + _cvIsInProgress.notify_one(); + }); + + { + AutoGetCollection autoColl(opCtx, _ns, MODE_IS); + if (autoColl.getCollection() != nullptr) { + // Collection already created, no more work needs to be done. + return; + } + } + + ConfigsvrCreateCollection configCreateCmd; + configCreateCmd.setNs(_ns); + + uassertStatusOK( + Grid::get(opCtx)->shardRegistry()->getConfigShard()->runCommandWithFixedRetryAttempts( + opCtx, + ReadPreferenceSetting{ReadPreference::PrimaryOnly}, + "admin", + CommandHelpers::appendMajorityWriteConcern(configCreateCmd.toBSON()), + Shard::RetryPolicy::kIdempotent)); + } + +private: + const NamespaceString _ns; + + stdx::mutex _mutex; + stdx::condition_variable _cvIsInProgress; + bool _isInProgress = false; +}; + +class CreateCollectionSerializerMap { +public: + std::shared_ptr<CreateCollectionSerializer> getForNs(const NamespaceString& ns) { + stdx::lock_guard<stdx::mutex> lg(_mutex); + auto iter = _inProgressMap.find(ns.ns()); + if (iter == _inProgressMap.end()) { + std::tie(iter, std::ignore) = + _inProgressMap.emplace(ns.ns(), std::make_shared<CreateCollectionSerializer>(ns)); + } + + return iter->second; + } + + void cleanupNs(const NamespaceString& ns) { + stdx::lock_guard<stdx::mutex> lg(_mutex); + _inProgressMap.erase(ns.ns()); + } + +private: + stdx::mutex _mutex; + std::map<std::string, std::shared_ptr<CreateCollectionSerializer>> _inProgressMap; +}; + +const auto createCollectionSerializerMap = + ServiceContext::declareDecoration<CreateCollectionSerializerMap>(); + +} // unnamed namespace + +void onCannotImplicitlyCreateCollection(OperationContext* opCtx, const NamespaceString& ns) { + auto& handlerMap = createCollectionSerializerMap(opCtx->getServiceContext()); + handlerMap.getForNs(ns)->onCannotImplicitlyCreateCollection(opCtx); + handlerMap.cleanupNs(ns); +} + +} // namespace mongo diff --git a/src/mongo/db/s/implicit_create_collection.h b/src/mongo/db/s/implicit_create_collection.h new file mode 100644 index 00000000000..0f3120572ac --- /dev/null +++ b/src/mongo/db/s/implicit_create_collection.h @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2018 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. + */ + +#pragma once + +namespace mongo { + +class NamespaceString; +class OperationContext; + +/** + * Initialize this collection so it will be officially tracked in a sharded environment + * by sending the command to the config server to create an entry for this collection in + * the sharding catalog. + */ +void onCannotImplicitlyCreateCollection(OperationContext* opCtx, const NamespaceString& ns); + +} // namespace mongo diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index 250708fa8c2..c6d286efa4b 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -285,6 +285,7 @@ env.Library( env.Library( target='stale_config', source=[ + 'cannot_implicitly_create_collection_info.cpp', 'stale_exception.cpp', ], LIBDEPS=[ diff --git a/src/mongo/s/cannot_implicitly_create_collection_info.cpp b/src/mongo/s/cannot_implicitly_create_collection_info.cpp new file mode 100644 index 00000000000..5beb1701e85 --- /dev/null +++ b/src/mongo/s/cannot_implicitly_create_collection_info.cpp @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2018 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. + */ + +#include <mongo/platform/basic.h> + +#include "mongo/s/cannot_implicitly_create_collection_info.h" + +#include "mongo/base/init.h" + +namespace mongo { + +MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(CannotImplicitlyCreateCollectionInfo); + +void CannotImplicitlyCreateCollectionInfo::serialize(BSONObjBuilder* bob) const { + bob->append("ns", _ns.ns()); +} + +std::shared_ptr<const ErrorExtraInfo> CannotImplicitlyCreateCollectionInfo::parse( + const BSONObj& obj) { + NamespaceString ns(obj["ns"].str()); + return std::make_shared<CannotImplicitlyCreateCollectionInfo>(std::move(ns)); +} + +} // namespace mongo diff --git a/src/mongo/s/cannot_implicitly_create_collection_info.h b/src/mongo/s/cannot_implicitly_create_collection_info.h new file mode 100644 index 00000000000..0978f838e21 --- /dev/null +++ b/src/mongo/s/cannot_implicitly_create_collection_info.h @@ -0,0 +1,59 @@ +/** +* Copyright (C) 2018 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. +*/ + +#pragma once + +#include "mongo/base/error_codes.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/namespace_string.h" +#include "mongo/util/assert_util.h" +//#include "mongo/util/mongoutils/str.h" + +namespace mongo { + +class CannotImplicitlyCreateCollectionInfo final : public ErrorExtraInfo { +public: + static constexpr auto code = ErrorCodes::CannotImplicitlyCreateCollection; + + CannotImplicitlyCreateCollectionInfo(NamespaceString ns) : _ns(std::move(ns)) {} + + NamespaceString getNss() const { + return _ns; + } + + void serialize(BSONObjBuilder* bob) const final; + static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj&); + +private: + NamespaceString _ns; +}; + +using ImplicitCreateCollectionException = + ExceptionFor<ErrorCodes::CannotImplicitlyCreateCollection>; + +} // namespace mongo diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp index 9ea306bd545..516cc2d7b82 100644 --- a/src/mongo/s/commands/cluster_write_cmd.cpp +++ b/src/mongo/s/commands/cluster_write_cmd.cpp @@ -196,7 +196,12 @@ public: bool enhancedRun(OperationContext* opCtx, const OpMsgRequest& request, BSONObjBuilder& result) final { - const auto batchedRequest(parseRequest(_writeType, request)); + auto batchedRequest(parseRequest(_writeType, request)); + + auto db = batchedRequest.getNS().db(); + if (db != NamespaceString::kAdminDb && db != NamespaceString::kConfigDb) { + batchedRequest.setAllowImplicitCreate(false); + } BatchWriteExecStats stats; BatchedCommandResponse response; diff --git a/src/mongo/s/request_types/create_collection.idl b/src/mongo/s/request_types/create_collection.idl index e34f5b2e55c..d7257f1d599 100644 --- a/src/mongo/s/request_types/create_collection.idl +++ b/src/mongo/s/request_types/create_collection.idl @@ -43,4 +43,5 @@ structs: description: "The namespace of the collection to be created." options: type: object + optional: true description: "collection creation options" diff --git a/src/mongo/s/write_ops/batch_write_exec.cpp b/src/mongo/s/write_ops/batch_write_exec.cpp index 9ee10f364b3..f2882370c56 100644 --- a/src/mongo/s/write_ops/batch_write_exec.cpp +++ b/src/mongo/s/write_ops/batch_write_exec.cpp @@ -261,6 +261,7 @@ void BatchWriteExec::executeBatch(OperationContext* opCtx, if (responseStatus.isOK()) { TrackedErrors trackedErrors; trackedErrors.startTracking(ErrorCodes::StaleShardVersion); + trackedErrors.startTracking(ErrorCodes::CannotImplicitlyCreateCollection); LOG(4) << "Write results received from " << shardHost.toString() << ": " << redact(batchedCommandResponse.toString()); @@ -276,6 +277,14 @@ void BatchWriteExec::executeBatch(OperationContext* opCtx, ++stats->numStaleBatches; } + const auto& cannotImplicitlyCreateErrors = + trackedErrors.getErrors(ErrorCodes::CannotImplicitlyCreateCollection); + if (!cannotImplicitlyCreateErrors.empty()) { + // This forces the chunk manager to reload so we can attach the correct + // version on retry and make sure we route to the correct shard. + targeter.noteCouldNotTarget(); + } + // Remember that we successfully wrote to this shard // NOTE: This will record lastOps for shards where we actually didn't update // or delete any documents, which preserves old behavior but is conservative diff --git a/src/mongo/s/write_ops/batch_write_op.cpp b/src/mongo/s/write_ops/batch_write_op.cpp index 4c1aacff063..7948a7a9cae 100644 --- a/src/mongo/s/write_ops/batch_write_op.cpp +++ b/src/mongo/s/write_ops/batch_write_op.cpp @@ -451,6 +451,8 @@ BatchedCommandRequest BatchWriteOp::buildBatchRequest( } } + request.setAllowImplicitCreate(_clientRequest.isImplicitCreateAllowed()); + return request; } diff --git a/src/mongo/s/write_ops/batched_command_request.cpp b/src/mongo/s/write_ops/batched_command_request.cpp index 2f7c9fcd269..087018b7829 100644 --- a/src/mongo/s/write_ops/batched_command_request.cpp +++ b/src/mongo/s/write_ops/batched_command_request.cpp @@ -36,6 +36,7 @@ namespace mongo { namespace { const auto kWriteConcern = "writeConcern"_sd; +const auto kAllowImplicitCollectionCreation = "allowImplicitCollectionCreation"_sd; template <class T> BatchedCommandRequest constructBatchedCommandRequest(const OpMsgRequest& request) { @@ -51,6 +52,10 @@ BatchedCommandRequest constructBatchedCommandRequest(const OpMsgRequest& request batchRequest.setWriteConcern(writeConcernField.Obj()); } + if (auto allowImplicitElement = request.body[kAllowImplicitCollectionCreation]) { + batchRequest.setAllowImplicitCreate(allowImplicitElement.boolean()); + } + return batchRequest; } @@ -161,6 +166,8 @@ void BatchedCommandRequest::serialize(BSONObjBuilder* builder) const { if (_writeConcern) { builder->append(kWriteConcern, *_writeConcern); } + + builder->append(kAllowImplicitCollectionCreation, _allowImplicitCollectionCreation); } BSONObj BatchedCommandRequest::toBSON() const { diff --git a/src/mongo/s/write_ops/batched_command_request.h b/src/mongo/s/write_ops/batched_command_request.h index 5c416679060..02236e203ce 100644 --- a/src/mongo/s/write_ops/batched_command_request.h +++ b/src/mongo/s/write_ops/batched_command_request.h @@ -127,6 +127,14 @@ public: BSONObj toBSON() const; std::string toString() const; + void setAllowImplicitCreate(bool doAllow) { + _allowImplicitCollectionCreation = doAllow; + } + + bool isImplicitCreateAllowed() const { + return _allowImplicitCollectionCreation; + } + /** * Generates a new request, the same as the old, but with insert _ids if required. */ @@ -142,6 +150,7 @@ private: boost::optional<ChunkVersion> _shardVersion; boost::optional<BSONObj> _writeConcern; + bool _allowImplicitCollectionCreation = true; }; /** diff --git a/src/mongo/s/write_ops/batched_command_request_test.cpp b/src/mongo/s/write_ops/batched_command_request_test.cpp index 33f64fb0592..437655463a0 100644 --- a/src/mongo/s/write_ops/batched_command_request_test.cpp +++ b/src/mongo/s/write_ops/batched_command_request_test.cpp @@ -47,7 +47,9 @@ TEST(BatchedCommandRequest, BasicInsert) { << "writeConcern" << BSON("w" << 1) << "ordered" - << true); + << true + << "allowImplicitCollectionCreation" + << false); for (auto docSeq : {false, true}) { const auto opMsgRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq)); @@ -55,6 +57,7 @@ TEST(BatchedCommandRequest, BasicInsert) { ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest().getNamespace().ns()); ASSERT(!insertRequest.hasShardVersion()); + ASSERT_FALSE(insertRequest.isImplicitCreateAllowed()); } } diff --git a/src/mongo/s/write_ops/write_op.cpp b/src/mongo/s/write_ops/write_op.cpp index 474d33854cd..b125f35a970 100644 --- a/src/mongo/s/write_ops/write_op.cpp +++ b/src/mongo/s/write_ops/write_op.cpp @@ -117,7 +117,8 @@ size_t WriteOp::getNumTargeted() { } static bool isRetryErrCode(int errCode) { - return errCode == ErrorCodes::StaleShardVersion; + return errCode == ErrorCodes::StaleShardVersion || + errCode == ErrorCodes::CannotImplicitlyCreateCollection; } // Aggregate a bunch of errors for a single op together |