diff options
34 files changed, 194 insertions, 59 deletions
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml index 62549ec9346..ca1b1aaba0d 100644 --- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml +++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml @@ -169,8 +169,8 @@ executor: assert.commandWorked(res); } else { // If 'username' already exists, then attempts to create a user with the same name - // will fail with a duplicate key error. - assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey); + // will fail with error code 51003. + assert.commandFailedWithCode(res, 51003); } // Log out as the __system user and auth as the newly created user. diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index c46116b6c11..5dcfaf5d878 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -281,7 +281,7 @@ error_code("OBSOLETE_RecvStaleConfig", 9996) error_code("NotMaster", 10107) error_code("CannotGrowDocumentInCappedNamespace", 10003) error_code("BSONObjectTooLarge", 10334) -error_code("DuplicateKey", 11000) +error_code("DuplicateKey", 11000, extra="DuplicateKeyErrorInfo") error_code("InterruptedAtShutdown", 11600) error_code("Interrupted", 11601) error_code("InterruptedDueToStepDown", 11602) diff --git a/src/mongo/base/initializer_dependency_graph.cpp b/src/mongo/base/initializer_dependency_graph.cpp index 7469f7e1138..c07b993ce36 100644 --- a/src/mongo/base/initializer_dependency_graph.cpp +++ b/src/mongo/base/initializer_dependency_graph.cpp @@ -49,7 +49,7 @@ Status InitializerDependencyGraph::addInitializer(std::string name, InitializerDependencyNode& newNode = _nodes[name]; if (newNode.initFn) { - return Status(ErrorCodes::DuplicateKey, name); + return Status(ErrorCodes::Error(50999), name); } newNode.initFn = std::move(initFn); diff --git a/src/mongo/base/initializer_dependency_graph_test.cpp b/src/mongo/base/initializer_dependency_graph_test.cpp index 20bb5c6ebb3..890ddba60c1 100644 --- a/src/mongo/base/initializer_dependency_graph_test.cpp +++ b/src/mongo/base/initializer_dependency_graph_test.cpp @@ -75,8 +75,8 @@ TEST(InitializerDependencyGraphTest, InsertSameNameTwiceFails) { InitializerDependencyGraph graph; ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS); ASSERT_EQUALS( - ErrorCodes::DuplicateKey, - ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS)); + 50999, + ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS).code()); } TEST(InitializerDependencyGraphTest, TopSortEmptyGraph) { diff --git a/src/mongo/bson/util/bson_check.h b/src/mongo/bson/util/bson_check.h index 250256208ba..ba9407353cf 100644 --- a/src/mongo/bson/util/bson_check.h +++ b/src/mongo/bson/util/bson_check.h @@ -43,8 +43,8 @@ namespace mongo { * Confirms that obj only contains field names where allowed(name) returns true, * and that no field name occurs multiple times. * - * On failure, returns BadValue and a message naming the unexpected field or DuplicateKey and a - * message naming the repeated field. "objectName" is included in the message, for reporting + * On failure, returns BadValue and a message naming the unexpected field or error code 51000 with + * a message naming a repeated field. "objectName" is included in the message, for reporting * purposes. */ template <typename Condition> @@ -65,7 +65,7 @@ Status bsonCheckOnlyHasFieldsImpl(StringData objectName, if (!seenBefore) { seenBefore = true; } else { - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51000), str::stream() << "Field " << name << " appears multiple times in " << objectName); } diff --git a/src/mongo/bson/util/bson_check_test.cpp b/src/mongo/bson/util/bson_check_test.cpp index 6c2fa1e0ca7..955af664a21 100644 --- a/src/mongo/bson/util/bson_check_test.cpp +++ b/src/mongo/bson/util/bson_check_test.cpp @@ -77,9 +77,10 @@ TEST(BsonCheck, CheckHasOnlyLegalFields) { } TEST(BsonCheck, CheckNoDuplicates) { - ASSERT_EQUALS(ErrorCodes::DuplicateKey, + ASSERT_EQUALS(51000, bsonCheckOnlyHasFields( - "", BSON("aField" << 1 << "anotherField" << 2 << "aField" << 3), legals)); + "", BSON("aField" << 1 << "anotherField" << 2 << "aField" << 3), legals) + .code()); } } // namespace diff --git a/src/mongo/db/auth/role_graph.cpp b/src/mongo/db/auth/role_graph.cpp index 0ed793d1052..db93d71ab00 100644 --- a/src/mongo/db/auth/role_graph.cpp +++ b/src/mongo/db/auth/role_graph.cpp @@ -81,7 +81,7 @@ bool RoleGraph::_roleExistsDontCreateBuiltin(const RoleName& role) { Status RoleGraph::createRole(const RoleName& role) { if (roleExists(role)) { - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51007), mongoutils::str::stream() << "Role: " << role.getFullName() << " already exists"); } @@ -403,7 +403,7 @@ Status RoleGraph::replaceRole(const RoleName& roleName, for (size_t i = 0; i < roles.size(); ++i) { const RoleName& grantedRole = roles[i]; status = createRole(grantedRole); - fassert(17170, status.isOK() || status == ErrorCodes::DuplicateKey); + fassert(17170, status.isOK() || status.code() == 51007); fassert(17171, addRoleToRole(roleName, grantedRole)); } fassert(17172, addPrivilegesToRole(roleName, privileges)); diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index f190e6c41e4..18d112112b9 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -419,7 +419,7 @@ Status insertRoleDocument(OperationContext* opCtx, const BSONObj& roleObj) { if (status.code() == ErrorCodes::DuplicateKey) { std::string name = roleObj[AuthorizationManager::ROLE_NAME_FIELD_NAME].String(); std::string source = roleObj[AuthorizationManager::ROLE_DB_FIELD_NAME].String(); - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51002), str::stream() << "Role \"" << name << "@" << source << "\" already exists"); } if (status.code() == ErrorCodes::UnknownError) { @@ -478,7 +478,7 @@ Status insertPrivilegeDocument(OperationContext* opCtx, const BSONObj& userObj) if (status.code() == ErrorCodes::DuplicateKey) { std::string name = userObj[AuthorizationManager::USER_NAME_FIELD_NAME].String(); std::string source = userObj[AuthorizationManager::USER_DB_FIELD_NAME].String(); - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51003), str::stream() << "User \"" << name << "@" << source << "\" already exists"); } if (status.code() == ErrorCodes::UnknownError) { diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index 5d980e5814c..ed2fee3df8a 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -51,6 +51,7 @@ #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/server_parameters.h" #include "mongo/db/stats/counters.h" +#include "mongo/db/storage/duplicate_key_error_info.h" #include "mongo/db/transaction_participant.h" #include "mongo/db/write_concern.h" #include "mongo/s/stale_exception.h" @@ -150,7 +151,11 @@ void serializeReply(OperationContext* opCtx, } } else { error.append("code", int(status.code())); + if (auto const extraInfo = status.extraInfo()) { + extraInfo->serialize(&error); + } } + error.append("errmsg", errorMessage(status.reason())); errors.push_back(error.obj()); } diff --git a/src/mongo/db/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp index 9edb6be9bc8..ff37a113538 100644 --- a/src/mongo/db/repl/apply_ops.cpp +++ b/src/mongo/db/repl/apply_ops.cpp @@ -551,7 +551,7 @@ Status applyOps(OperationContext* opCtx, result->append("codeName", ErrorCodes::errorString(ex.code())); result->append("errmsg", ex.what()); result->append("results", ab.arr()); - return Status(ex.code(), ex.what()); + return ex.toStatus(); } return Status::OK(); diff --git a/src/mongo/db/repl/database_cloner.cpp b/src/mongo/db/repl/database_cloner.cpp index b9c1e23edea..e23e2ea145e 100644 --- a/src/mongo/db/repl/database_cloner.cpp +++ b/src/mongo/db/repl/database_cloner.cpp @@ -346,7 +346,7 @@ void DatabaseCloner::_listCollectionsCallback(const StatusWith<Fetcher::QueryRes const std::string collectionName = nameElement.String(); if (seen.find(collectionName) != seen.end()) { _finishCallback_inlock(lk, - {ErrorCodes::DuplicateKey, + {ErrorCodes::Error(51005), str::stream() << "collection info contains duplicate collection name " << "'" diff --git a/src/mongo/db/repl/database_cloner_test.cpp b/src/mongo/db/repl/database_cloner_test.cpp index 83c428340a7..7e594adbc59 100644 --- a/src/mongo/db/repl/database_cloner_test.cpp +++ b/src/mongo/db/repl/database_cloner_test.cpp @@ -541,7 +541,7 @@ TEST_F(DatabaseClonerTest, CollectionInfoNameDuplicate) { << _options2.toBSON())))); } - ASSERT_EQUALS(ErrorCodes::DuplicateKey, getStatus().code()); + ASSERT_EQUALS(51005, getStatus().code()); ASSERT_STRING_CONTAINS(getStatus().reason(), "duplicate collection name 'a'"); ASSERT_FALSE(_databaseCloner->isActive()); ASSERT_EQUALS(DatabaseCloner::State::kComplete, _databaseCloner->getState_forTest()); diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp index e79ffa8fe89..731b2ed8f9f 100644 --- a/src/mongo/db/repl/repl_set_config.cpp +++ b/src/mongo/db/repl/repl_set_config.cpp @@ -353,7 +353,7 @@ Status ReplSetConfig::_parseSettingsSubdocument(const BSONObj& settings) { for (auto&& modeElement : gleModes) { if (_customWriteConcernModes.find(modeElement.fieldNameStringData()) != _customWriteConcernModes.end()) { - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51001), str::stream() << kSettingsFieldName << '.' << kGetLastErrorModesFieldName << " contains multiple fields named " << modeElement.fieldName()); diff --git a/src/mongo/db/repl/repl_set_config_checks.cpp b/src/mongo/db/repl/repl_set_config_checks.cpp index 4105db31efe..07cff16f595 100644 --- a/src/mongo/db/repl/repl_set_config_checks.cpp +++ b/src/mongo/db/repl/repl_set_config_checks.cpp @@ -79,7 +79,7 @@ StatusWith<int> findSelfInConfig(ReplicationCoordinatorExternalState* externalSt << " all map to this node in new configuration version " << newConfig.getConfigVersion() << " for replica set " << newConfig.getReplSetName(); - return StatusWith<int>(ErrorCodes::DuplicateKey, message); + return StatusWith<int>(ErrorCodes::InvalidReplicaSetConfig, message); } int myIndex = std::distance(newConfig.membersBegin(), meConfigs.front()); diff --git a/src/mongo/db/repl/repl_set_config_checks_test.cpp b/src/mongo/db/repl/repl_set_config_checks_test.cpp index 482ca06e992..edea5453109 100644 --- a/src/mongo/db/repl/repl_set_config_checks_test.cpp +++ b/src/mongo/db/repl/repl_set_config_checks_test.cpp @@ -90,7 +90,7 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_MustFindSelf) { validateConfigForInitiate(¬PresentExternalState, config, getGlobalServiceContext()) .getStatus()); ASSERT_EQUALS( - ErrorCodes::DuplicateKey, + ErrorCodes::InvalidReplicaSetConfig, validateConfigForInitiate(&presentTwiceExternalState, config, getGlobalServiceContext()) .getStatus()); ASSERT_EQUALS(1, @@ -703,7 +703,7 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_MustFindSelf) { ¬PresentExternalState, oldConfig, newConfig, getGlobalServiceContext(), false) .getStatus()); ASSERT_EQUALS( - ErrorCodes::DuplicateKey, + ErrorCodes::InvalidReplicaSetConfig, validateConfigForReconfig( &presentThriceExternalState, oldConfig, newConfig, getGlobalServiceContext(), false) .getStatus()); @@ -718,7 +718,7 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_MustFindSelf) { ¬PresentExternalState, oldConfig, newConfig, getGlobalServiceContext(), true) .getStatus()); ASSERT_EQUALS( - ErrorCodes::DuplicateKey, + ErrorCodes::InvalidReplicaSetConfig, validateConfigForReconfig( &presentThriceExternalState, oldConfig, newConfig, getGlobalServiceContext(), true) .getStatus()); diff --git a/src/mongo/db/repl/repl_set_config_test.cpp b/src/mongo/db/repl/repl_set_config_test.cpp index ebcc4b62773..8da994e68d7 100644 --- a/src/mongo/db/repl/repl_set_config_test.cpp +++ b/src/mongo/db/repl/repl_set_config_test.cpp @@ -820,7 +820,7 @@ TEST(ReplSetConfig, ParseFailsWithDuplicateGetLastErrorModesField) { << BSON("getLastErrorModes" << BSON("one" << BSON("tag" << 1) << "one" << BSON("tag" << 1))))); - ASSERT_EQUALS(ErrorCodes::DuplicateKey, status); + ASSERT_EQUALS(51001, status.code()); } TEST(ReplSetConfig, ParseFailsWithNonObjectGetLastErrorModesEntryField) { diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index eaca1134471..3f237917497 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -556,7 +556,7 @@ void ReplicationCoordinatorImpl::_finishLoadLocalConfig( validateConfigForStartUp(_externalState.get(), localConfig, getServiceContext()); if (!myIndex.isOK()) { if (myIndex.getStatus() == ErrorCodes::NodeNotFound || - myIndex.getStatus() == ErrorCodes::DuplicateKey) { + myIndex.getStatus() == ErrorCodes::InvalidReplicaSetConfig) { warning() << "Locally stored replica set configuration does not have a valid entry " "for the current node; waiting for reconfig or remote heartbeat; Got \"" << myIndex.getStatus() << "\" while validating " << localConfig.toBSON(); diff --git a/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp b/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp index f61fcd057b6..72fc9a9cbfe 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_heartbeat.cpp @@ -594,7 +594,7 @@ void ReplicationCoordinatorImpl::_heartbeatReconfigFinish( log() << "Cannot find self in new replica set configuration; I must be removed; " << myIndex.getStatus(); break; - case ErrorCodes::DuplicateKey: + case ErrorCodes::InvalidReplicaSetConfig: error() << "Several entries in new config represent this node; " "Removing self until an acceptable configuration arrives; " << myIndex.getStatus(); diff --git a/src/mongo/db/s/migration_destination_manager.cpp b/src/mongo/db/s/migration_destination_manager.cpp index 8e19ad74a65..4511d070a79 100644 --- a/src/mongo/db/s/migration_destination_manager.cpp +++ b/src/mongo/db/s/migration_destination_manager.cpp @@ -401,7 +401,7 @@ void MigrationDestinationManager::cloneDocumentsFromDonor( } } catch (...) { stdx::lock_guard<Client> lk(*opCtx->getClient()); - opCtx->getServiceContext()->killOperation(opCtx, exceptionToStatus().code()); + opCtx->getServiceContext()->killOperation(opCtx, ErrorCodes::Error(51008)); log() << "Batch insertion failed " << causedBy(redact(exceptionToStatus())); } }}; diff --git a/src/mongo/db/s/migration_destination_manager_test.cpp b/src/mongo/db/s/migration_destination_manager_test.cpp index 3d2b7fb4ba3..1b1cf8e12f3 100644 --- a/src/mongo/db/s/migration_destination_manager_test.cpp +++ b/src/mongo/db/s/migration_destination_manager_test.cpp @@ -152,10 +152,10 @@ TEST_F(MigrationDestinationManagerTest, CloneDocumentsCatchesInsertErrors) { ASSERT_THROWS_CODE_AND_WHAT(MigrationDestinationManager::cloneDocumentsFromDonor( operationContext(), insertBatchFn, fetchBatchFn), DBException, - ErrorCodes::FailedToParse, + 51008, "operation was interrupted"); - ASSERT_EQ(operationContext()->getKillStatus(), ErrorCodes::FailedToParse); + ASSERT_EQ(operationContext()->getKillStatus(), 51008); } } // namespace diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript index ad1295dfb0a..f25c138ced7 100644 --- a/src/mongo/db/storage/SConscript +++ b/src/mongo/db/storage/SConscript @@ -33,6 +33,17 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + 'duplicate_key_error_info', + ], + ) + +env.Library( + target='duplicate_key_error_info', + source=[ + 'duplicate_key_error_info.cpp', + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/base', ], ) diff --git a/src/mongo/db/storage/duplicate_key_error_info.cpp b/src/mongo/db/storage/duplicate_key_error_info.cpp new file mode 100644 index 00000000000..911b3de0381 --- /dev/null +++ b/src/mongo/db/storage/duplicate_key_error_info.cpp @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2018-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/storage/duplicate_key_error_info.h" + +#include "mongo/base/init.h" +#include "mongo/bson/bsonobjbuilder.h" +#include "mongo/util/assert_util.h" + +namespace mongo { +namespace { + +MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(DuplicateKeyErrorInfo); + +} // namespace + +void DuplicateKeyErrorInfo::serialize(BSONObjBuilder* bob) const { + bob->append("keyPattern", _keyPattern); +} + +std::shared_ptr<const ErrorExtraInfo> DuplicateKeyErrorInfo::parse(const BSONObj& obj) { + return std::make_shared<DuplicateKeyErrorInfo>(obj["keyPattern"].Obj()); +} + +} // namespace mongo diff --git a/src/mongo/db/storage/duplicate_key_error_info.h b/src/mongo/db/storage/duplicate_key_error_info.h new file mode 100644 index 00000000000..06a17cce94c --- /dev/null +++ b/src/mongo/db/storage/duplicate_key_error_info.h @@ -0,0 +1,67 @@ +/** + * Copyright (C) 2018-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include "mongo/base/error_extra_info.h" +#include "mongo/bson/bsonobj.h" +#include "mongo/bson/bsonobjbuilder.h" + +namespace mongo { + +/** + * Represents an error returned from the storage engine when an attempt to insert a + * key into a unique index fails because the same key already exists. + */ +class DuplicateKeyErrorInfo final : public ErrorExtraInfo { +public: + static constexpr auto code = ErrorCodes::DuplicateKey; + + static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj&); + + explicit DuplicateKeyErrorInfo(const BSONObj& keyPattern) + : _keyPattern(keyPattern.getOwned()) {} + + void serialize(BSONObjBuilder* bob) const override; + + BSONObj toBSON() const { + BSONObjBuilder bob; + serialize(&bob); + return bob.obj(); + } + + const BSONObj& getKeyPattern() const { + return _keyPattern; + } + +private: + const BSONObj _keyPattern; +}; + +} // namespace mongo diff --git a/src/mongo/db/storage/index_entry_comparison.cpp b/src/mongo/db/storage/index_entry_comparison.cpp index 242df839462..67613639633 100644 --- a/src/mongo/db/storage/index_entry_comparison.cpp +++ b/src/mongo/db/storage/index_entry_comparison.cpp @@ -29,10 +29,12 @@ */ #include "mongo/platform/basic.h" +#include "mongo/db/storage/index_entry_comparison.h" + #include <ostream> #include "mongo/db/jsobj.h" -#include "mongo/db/storage/index_entry_comparison.h" +#include "mongo/db/storage/duplicate_key_error_info.h" namespace mongo { @@ -193,7 +195,7 @@ Status buildDupKeyErrorStatus(const BSONObj& key, } sb << builder.obj(); - return Status(ErrorCodes::DuplicateKey, sb.str()); + return Status(DuplicateKeyErrorInfo(keyPattern), sb.str()); } } // namespace mongo diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp index f02781c956d..fb524735923 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp @@ -188,7 +188,7 @@ Status WiredTigerUtil::getApplicationMetadata(OperationContext* opCtx, while ((ret = parser.next(&keyItem, &valueItem)) == 0) { const StringData key(keyItem.str, keyItem.len); if (keysSeen.count(key)) { - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(50998), str::stream() << "app_metadata must not contain duplicate keys. " << "Found multiple instances of key '" << key diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_util_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_util_test.cpp index 58f9aa63548..a3431d77cd3 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_util_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_util_test.cpp @@ -186,7 +186,7 @@ TEST_F(WiredTigerUtilMetadataTest, GetApplicationMetadataDuplicateKeys) { StatusWith<BSONObj> result = WiredTigerUtil::getApplicationMetadata(getOperationContext(), getURI()); ASSERT_NOT_OK(result.getStatus()); - ASSERT_EQUALS(ErrorCodes::DuplicateKey, result.getStatus().code()); + ASSERT_EQUALS(50998, result.getStatus().code()); } TEST_F(WiredTigerUtilMetadataTest, GetApplicationMetadataTypes) { diff --git a/src/mongo/s/catalog/SConscript b/src/mongo/s/catalog/SConscript index f37bf3fefc6..72d095847c9 100644 --- a/src/mongo/s/catalog/SConscript +++ b/src/mongo/s/catalog/SConscript @@ -77,6 +77,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/repl/read_concern_args', + '$BUILD_DIR/mongo/db/storage/duplicate_key_error_info', '$BUILD_DIR/mongo/executor/network_interface', '$BUILD_DIR/mongo/s/client/sharding_client', '$BUILD_DIR/mongo/s/coreshard', @@ -127,6 +128,7 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/storage/duplicate_key_error_info', '$BUILD_DIR/mongo/s/catalog/dist_lock_catalog_mock', '$BUILD_DIR/mongo/s/catalog/sharding_catalog_client_mock', '$BUILD_DIR/mongo/s/shard_server_test_fixture', @@ -142,6 +144,7 @@ env.CppUnitTest( 'sharding_catalog_write_retry_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/storage/duplicate_key_error_info', '$BUILD_DIR/mongo/s/sharding_router_test_fixture', ] ) diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp index f09b53fa36a..8eac156a8ba 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp @@ -37,6 +37,7 @@ #include "mongo/db/commands.h" #include "mongo/db/query/find_and_modify_request.h" #include "mongo/db/repl/read_concern_args.h" +#include "mongo/db/storage/duplicate_key_error_info.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/network_test_env.h" #include "mongo/s/catalog/dist_lock_catalog_impl.h" @@ -437,11 +438,7 @@ TEST_F(DistLockCatalogTest, GrabLockDupKeyError) { }); onCommand([](const RemoteCommandRequest& request) -> StatusWith<BSONObj> { - return fromjson(R"({ - ok: 0, - errmsg: "duplicate key error", - code: 11000 - })"); + return Status({DuplicateKeyErrorInfo(BSON("x" << 1)), "Mock duplicate key error"}); }); future.timed_get(kFutureTimeout); diff --git a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp index 048656f4426..b0370563860 100644 --- a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp +++ b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp @@ -793,11 +793,10 @@ Status ShardingCatalogClientImpl::insertConfigDocument(OperationContext* opCtx, auto existingDocs = fetchDuplicate.getValue().value; if (existingDocs.empty()) { - return {ErrorCodes::DuplicateKey, - stream() << "DuplicateKey error was returned after a retry attempt, but no " - "documents were found. This means a concurrent change occurred " - "together with the retries. Original error was " - << status.toString()}; + return {status.withContext( + stream() << "DuplicateKey error was returned after a retry attempt, but no " + "documents were found. This means a concurrent change occurred " + "together with the retries.")}; } invariant(existingDocs.size() == 1); diff --git a/src/mongo/s/catalog/sharding_catalog_test.cpp b/src/mongo/s/catalog/sharding_catalog_test.cpp index af95c186612..5b7703dd0f7 100644 --- a/src/mongo/s/catalog/sharding_catalog_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_test.cpp @@ -1221,7 +1221,7 @@ TEST_F(ShardingCatalogClientTest, ApplyChunkOpsDeprecatedSuccessfulWithCheck) { onCommand([&](const RemoteCommandRequest& request) { BSONObjBuilder responseBuilder; CommandHelpers::appendCommandStatusNoThrow( - responseBuilder, Status(ErrorCodes::DuplicateKey, "precondition failed")); + responseBuilder, Status(ErrorCodes::Error(51004), "precondition failed")); return responseBuilder.obj(); }); diff --git a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp index 03aa7a924e6..7ce5acce70c 100644 --- a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp +++ b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp @@ -40,6 +40,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/ops/write_ops.h" +#include "mongo/db/storage/duplicate_key_error_info.h" #include "mongo/db/write_concern.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor.h" @@ -78,6 +79,10 @@ const NamespaceString kTestNamespace("config.TestColl"); const HostAndPort kTestHosts[] = { HostAndPort("TestHost1:12345"), HostAndPort("TestHost2:12345"), HostAndPort("TestHost3:12345")}; +Status getMockDuplicateKeyError() { + return {DuplicateKeyErrorInfo(BSON("mock" << 1)), "Mock duplicate key error"}; +} + TEST_F(InsertRetryTest, RetryOnInterruptedAndNetworkErrorSuccess) { configTargeter()->setFindHostReturnValue({kTestHosts[0]}); @@ -168,7 +173,7 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterNetworkErrorMatch) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQ(request.target, kTestHosts[1]); - return Status(ErrorCodes::DuplicateKey, "Duplicate key"); + return getMockDuplicateKeyError(); }); onFindCommand([&](const RemoteCommandRequest& request) { @@ -206,7 +211,7 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterNetworkErrorNotFound) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQ(request.target, kTestHosts[1]); - return Status(ErrorCodes::DuplicateKey, "Duplicate key"); + return getMockDuplicateKeyError(); }); onFindCommand([&](const RemoteCommandRequest& request) { @@ -244,7 +249,7 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterNetworkErrorMismatch) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQ(request.target, kTestHosts[1]); - return Status(ErrorCodes::DuplicateKey, "Duplicate key"); + return getMockDuplicateKeyError(); }); onFindCommand([&](const RemoteCommandRequest& request) { @@ -300,7 +305,7 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterWriteConcernFailureMatch) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQ(request.target, kTestHosts[0]); - return Status(ErrorCodes::DuplicateKey, "Duplicate key"); + return getMockDuplicateKeyError(); }); onFindCommand([&](const RemoteCommandRequest& request) { diff --git a/src/mongo/s/write_ops/batch_downconvert.cpp b/src/mongo/s/write_ops/batch_downconvert.cpp index 58b1a6fdd25..cb34dc39b44 100644 --- a/src/mongo/s/write_ops/batch_downconvert.cpp +++ b/src/mongo/s/write_ops/batch_downconvert.cpp @@ -33,6 +33,7 @@ #include "mongo/s/write_ops/batch_downconvert.h" #include "mongo/bson/bsonmisc.h" +#include "mongo/db/storage/duplicate_key_error_info.h" namespace mongo { @@ -100,16 +101,6 @@ Status extractGLEErrors(const BSONObj& gleResponse, GLEErrors* errors) { // Write error errors->writeError.reset(new WriteErrorDetail); int writeErrorCode = code == 0 ? ErrorCodes::UnknownError : code; - - // COMPATIBILITY - // Certain clients expect write commands to always report 11000 for duplicate key - // errors, while legacy GLE can return additional codes. - if (writeErrorCode == 11001 /* dup key in update */ - || - writeErrorCode == 12582 /* dup key capped */) { - writeErrorCode = ErrorCodes::DuplicateKey; - } - errors->writeError->setStatus({ErrorCodes::Error(writeErrorCode), err}); } else if (!jNote.empty()) { // Know this is legacy gle and the journaling not enforced - write concern error in 2.4 diff --git a/src/mongo/scripting/SConscript b/src/mongo/scripting/SConscript index edbc90ce365..75d36873081 100644 --- a/src/mongo/scripting/SConscript +++ b/src/mongo/scripting/SConscript @@ -153,6 +153,7 @@ if usemozjs: 'scripting_common', '$BUILD_DIR/mongo/shell/mongojs', '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/storage/duplicate_key_error_info', ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/client/clientdriver_network', diff --git a/src/mongo/util/fail_point_registry.cpp b/src/mongo/util/fail_point_registry.cpp index e00afc617a2..0a71e4a5f82 100644 --- a/src/mongo/util/fail_point_registry.cpp +++ b/src/mongo/util/fail_point_registry.cpp @@ -48,7 +48,7 @@ Status FailPointRegistry::addFailPoint(const string& name, FailPoint* failPoint) } if (_fpMap.count(name) > 0) { - return Status(ErrorCodes::DuplicateKey, + return Status(ErrorCodes::Error(51006), stream() << "Fail point already registered: " << name); } |