diff options
author | Mathias Stearn <mathias@10gen.com> | 2017-08-01 09:35:39 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2017-08-16 16:28:02 -0400 |
commit | 40036f67d0c15e2cd319e82f8c6a1e691fb74806 (patch) | |
tree | fd9744b756fb092c47c1b3fbcd15e349fe0e270a /src/mongo | |
parent | 53a9b329fbf1a6d8b620fee2cbb2ef1c27ddd3f3 (diff) | |
download | mongo-40036f67d0c15e2cd319e82f8c6a1e691fb74806.tar.gz |
SERVER-30580 No more status locations
Diffstat (limited to 'src/mongo')
38 files changed, 374 insertions, 532 deletions
diff --git a/src/mongo/base/parse_number.cpp b/src/mongo/base/parse_number.cpp index b9c81807b19..1c72e73db71 100644 --- a/src/mongo/base/parse_number.cpp +++ b/src/mongo/base/parse_number.cpp @@ -124,7 +124,7 @@ Status parseNumberFromStringWithBase(StringData stringValue, int base, NumberTyp typedef ::std::numeric_limits<NumberType> limits; if (base == 1 || base < 0 || base > 36) - return Status(ErrorCodes::BadValue, "Invalid base", 0); + return Status(ErrorCodes::BadValue, "Invalid base"); bool isNegative = false; StringData str = _extractBase(_extractSign(stringValue, &isNegative), base, &base); diff --git a/src/mongo/base/status-inl.h b/src/mongo/base/status-inl.h index a29678e67b2..7f69436834b 100644 --- a/src/mongo/base/status-inl.h +++ b/src/mongo/base/status-inl.h @@ -75,10 +75,6 @@ inline std::string Status::reason() const { return _error ? _error->reason : std::string(); } -inline int Status::location() const { - return _error ? _error->location : 0; -} - inline AtomicUInt32::WordType Status::refCount() const { return _error ? _error->refs.load() : 0; } diff --git a/src/mongo/base/status.cpp b/src/mongo/base/status.cpp index 2eef1946e75..57aedd11749 100644 --- a/src/mongo/base/status.cpp +++ b/src/mongo/base/status.cpp @@ -33,49 +33,24 @@ namespace mongo { -Status::ErrorInfo::ErrorInfo(ErrorCodes::Error aCode, std::string aReason, int aLocation) - : code(aCode), reason(std::move(aReason)), location(aLocation) {} +Status::ErrorInfo::ErrorInfo(ErrorCodes::Error aCode, std::string aReason) + : code(aCode), reason(std::move(aReason)) {} -Status::ErrorInfo* Status::ErrorInfo::create(ErrorCodes::Error c, std::string r, int l) { +Status::ErrorInfo* Status::ErrorInfo::create(ErrorCodes::Error c, std::string r) { if (c == ErrorCodes::OK) return nullptr; - return new ErrorInfo(c, std::move(r), l); + return new ErrorInfo(c, std::move(r)); } -Status::Status(ErrorCodes::Error code, std::string reason, int location) - : _error(ErrorInfo::create(code, std::move(reason), location)) { +Status::Status(ErrorCodes::Error code, std::string reason) + : _error(ErrorInfo::create(code, std::move(reason))) { ref(_error); } -Status::Status(ErrorCodes::Error code, const char* reason, int location) - : Status(code, std::string(reason), location) {} +Status::Status(ErrorCodes::Error code, const char* reason) : Status(code, std::string(reason)) {} -Status::Status(ErrorCodes::Error code, const mongoutils::str::stream& reason, int location) - : Status(code, std::string(reason), location) {} - -bool Status::compare(const Status& other) const { - return code() == other.code() && location() == other.location(); -} - -bool Status::operator==(const Status& other) const { - return compare(other); -} - -bool Status::operator!=(const Status& other) const { - return !compare(other); -} - -bool Status::compareCode(const ErrorCodes::Error other) const { - return code() == other; -} - -bool Status::operator==(const ErrorCodes::Error other) const { - return compareCode(other); -} - -bool Status::operator!=(const ErrorCodes::Error other) const { - return !compareCode(other); -} +Status::Status(ErrorCodes::Error code, const mongoutils::str::stream& reason) + : Status(code, std::string(reason)) {} std::ostream& operator<<(std::ostream& os, const Status& status) { return os << status.codeString() << " " << status.reason(); @@ -90,8 +65,6 @@ std::string Status::toString() const { ss << codeString(); if (!isOK()) ss << ": " << reason(); - if (location() != 0) - ss << " @ " << location(); return ss.str(); } diff --git a/src/mongo/base/status.h b/src/mongo/base/status.h index d8009ecc96e..91c5a5ce26e 100644 --- a/src/mongo/base/status.h +++ b/src/mongo/base/status.h @@ -47,8 +47,7 @@ namespace mongo { * * A Status uses the standardized error codes -- from file 'error_codes.h' -- to * determine an error's cause. It further clarifies the error with a textual - * description. Optionally, a Status may also have an error location number, which - * should be a unique, grep-able point in the code base (including assert numbers). + * description. * * Example usage: * @@ -60,10 +59,6 @@ namespace mongo { * *c = a+b; * return Status::OK(); * } - * - * TODO: expand base/error_codes.h to capture common errors in current code - * TODO: generate base/error_codes.h out of a description file - * TODO: check 'location' duplicates against assert numbers */ class MONGO_WARN_UNUSED_RESULT_CLASS Status { public: @@ -71,22 +66,16 @@ public: static inline Status OK(); /** - * Builds an error status given the error code, a textual description of what - * caused the error, and a unique position in the where the error occurred - * (similar to an assert number). + * Builds an error status given the error code and a textual description of what + * caused the error. * * For OK Statuses prefer using Status::OK(). If code is OK, the remaining arguments are * ignored. */ + MONGO_COMPILER_COLD_FUNCTION Status(ErrorCodes::Error code, std::string reason); + MONGO_COMPILER_COLD_FUNCTION Status(ErrorCodes::Error code, const char* reason); MONGO_COMPILER_COLD_FUNCTION Status(ErrorCodes::Error code, - std::string reason, - int location = 0); - MONGO_COMPILER_COLD_FUNCTION Status(ErrorCodes::Error code, - const char* reason, - int location = 0); - MONGO_COMPILER_COLD_FUNCTION Status(ErrorCodes::Error code, - const mongoutils::str::stream& reason, - int location = 0); + const mongoutils::str::stream& reason); inline Status(const Status& other); inline Status& operator=(const Status& other); @@ -97,20 +86,24 @@ public: inline ~Status(); /** - * Returns true if 'other's error code and location are equal/different to this - * instance's. Otherwise returns false. + * Only compares codes. Ignores reason strings. */ - bool compare(const Status& other) const; - bool operator==(const Status& other) const; - bool operator!=(const Status& other) const; + bool operator==(const Status& other) const { + return code() == other.code(); + } + bool operator!=(const Status& other) const { + return !(*this == other); + } /** - * Returns true if 'other's error code is equal/different to this instance's. - * Otherwise returns false. + * Compares this Status's code with an error code. */ - bool compareCode(const ErrorCodes::Error other) const; - bool operator==(const ErrorCodes::Error other) const; - bool operator!=(const ErrorCodes::Error other) const; + bool operator==(const ErrorCodes::Error other) const { + return code() == other; + } + bool operator!=(const ErrorCodes::Error other) const { + return !(*this == other); + } // // accessors @@ -124,8 +117,6 @@ public: inline std::string reason() const; - inline int location() const; - std::string toString() const; /** @@ -162,11 +153,10 @@ private: AtomicUInt32 refs; // reference counter const ErrorCodes::Error code; // error code const std::string reason; // description of error cause - const int location; // unique location of the triggering line in the code - static ErrorInfo* create(ErrorCodes::Error code, std::string reason, int location); + static ErrorInfo* create(ErrorCodes::Error code, std::string reason); - ErrorInfo(ErrorCodes::Error code, std::string reason, int location); + ErrorInfo(ErrorCodes::Error code, std::string reason); }; ErrorInfo* _error; diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp index 64af29a0ad5..a8840135624 100644 --- a/src/mongo/base/status_test.cpp +++ b/src/mongo/base/status_test.cpp @@ -42,10 +42,9 @@ using mongo::ErrorCodes; using mongo::Status; TEST(Basic, Accessors) { - Status status(ErrorCodes::MaxError, "error", 9999); + Status status(ErrorCodes::MaxError, "error"); ASSERT_EQUALS(status.code(), ErrorCodes::MaxError); ASSERT_EQUALS(status.reason(), "error"); - ASSERT_EQUALS(status.location(), 9999); } TEST(Basic, OKIsAValidStatus) { @@ -55,11 +54,8 @@ TEST(Basic, OKIsAValidStatus) { TEST(Basic, Compare) { Status errMax(ErrorCodes::MaxError, "error"); - ASSERT_TRUE(errMax.compare(errMax)); - ASSERT_FALSE(errMax.compare(Status::OK())); - - Status errMaxWithLoc(ErrorCodes::MaxError, "error", 9998); - ASSERT_FALSE(errMaxWithLoc.compare(errMax)); + ASSERT_EQ(errMax, errMax); + ASSERT_NE(errMax, Status::OK()); } TEST(Cloning, Copy) { diff --git a/src/mongo/base/status_with.h b/src/mongo/base/status_with.h index 9287e45d938..05b5731a78a 100644 --- a/src/mongo/base/status_with.h +++ b/src/mongo/base/status_with.h @@ -69,18 +69,13 @@ public: /** * for the error case */ + MONGO_COMPILER_COLD_FUNCTION StatusWith(ErrorCodes::Error code, std::string reason) + : _status(code, std::move(reason)) {} + MONGO_COMPILER_COLD_FUNCTION StatusWith(ErrorCodes::Error code, const char* reason) + : _status(code, reason) {} MONGO_COMPILER_COLD_FUNCTION StatusWith(ErrorCodes::Error code, - std::string reason, - int location = 0) - : _status(code, std::move(reason), location) {} - MONGO_COMPILER_COLD_FUNCTION StatusWith(ErrorCodes::Error code, - const char* reason, - int location = 0) - : _status(code, reason, location) {} - MONGO_COMPILER_COLD_FUNCTION StatusWith(ErrorCodes::Error code, - const mongoutils::str::stream& reason, - int location = 0) - : _status(code, reason, location) {} + const mongoutils::str::stream& reason) + : _status(code, reason) {} /** * for the error case diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index 0e97504b782..f0ebdba5881 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -416,8 +416,7 @@ Status AuthorizationManager::_initializeUserFromPrivilegeDocument(User* user, << userName << "\" doesn't match name of provided User \"" << user->getName().getUser() - << "\"", - 0); + << "\""); } Status status = parser.initializeUserCredentialsFromUserDocument(user, privDoc); diff --git a/src/mongo/db/auth/generate_action_types.py b/src/mongo/db/auth/generate_action_types.py index 6d14b0b583d..b712b29666a 100755 --- a/src/mongo/db/auth/generate_action_types.py +++ b/src/mongo/db/auth/generate_action_types.py @@ -175,8 +175,7 @@ namespace mongo { %(fromStringIfStatements)s return Status(ErrorCodes::FailedToParse, mongoutils::str::stream() << "Unrecognized action privilege string: " - << action, - 0); + << action); } // Takes an ActionType and returns the string representation diff --git a/src/mongo/db/auth/role_graph.cpp b/src/mongo/db/auth/role_graph.cpp index 56ce47f2ecb..b35df15d16d 100644 --- a/src/mongo/db/auth/role_graph.cpp +++ b/src/mongo/db/auth/role_graph.cpp @@ -79,8 +79,7 @@ Status RoleGraph::createRole(const RoleName& role) { if (roleExists(role)) { return Status(ErrorCodes::DuplicateKey, mongoutils::str::stream() << "Role: " << role.getFullName() - << " already exists", - 0); + << " already exists"); } _createRoleDontCheckIfRoleExists(role); @@ -102,14 +101,12 @@ Status RoleGraph::deleteRole(const RoleName& role) { if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(role)) { return Status(ErrorCodes::InvalidRoleModification, mongoutils::str::stream() << "Cannot delete built-in role: " - << role.getFullName(), - 0); + << role.getFullName()); } for (std::vector<RoleName>::iterator it = _roleToSubordinates[role].begin(); @@ -195,20 +192,17 @@ Status RoleGraph::removeRoleFromRole(const RoleName& recipient, const RoleName& if (!roleExists(recipient)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << recipient.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(recipient)) { return Status(ErrorCodes::InvalidRoleModification, mongoutils::str::stream() << "Cannot remove roles from built-in role: " - << role.getFullName(), - 0); + << role.getFullName()); } if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } std::vector<RoleName>::iterator itToRm = @@ -219,8 +213,7 @@ Status RoleGraph::removeRoleFromRole(const RoleName& recipient, const RoleName& return Status(ErrorCodes::RolesNotRelated, mongoutils::str::stream() << recipient.getFullName() << " is not a member" " of " - << role.getFullName(), - 0); + << role.getFullName()); } itToRm = std::find( @@ -235,14 +228,12 @@ Status RoleGraph::removeAllRolesFromRole(const RoleName& victim) { if (!roleExists(victim)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << victim.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(victim)) { return Status(ErrorCodes::InvalidRoleModification, mongoutils::str::stream() << "Cannot remove roles from built-in role: " - << victim.getFullName(), - 0); + << victim.getFullName()); } RoleNameVector& subordinatesOfVictim = _roleToSubordinates[victim]; @@ -264,14 +255,12 @@ Status RoleGraph::addPrivilegeToRole(const RoleName& role, const Privilege& priv if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(role)) { return Status(ErrorCodes::InvalidRoleModification, mongoutils::str::stream() << "Cannot grant privileges to built-in role: " - << role.getFullName(), - 0); + << role.getFullName()); } _addPrivilegeToRoleNoChecks(role, privilegeToAdd); @@ -291,14 +280,12 @@ Status RoleGraph::addPrivilegesToRole(const RoleName& role, if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(role)) { return Status(ErrorCodes::InvalidRoleModification, mongoutils::str::stream() << "Cannot grant privileges to built-in role: " - << role.getFullName(), - 0); + << role.getFullName()); } for (PrivilegeVector::const_iterator it = privilegesToAdd.begin(); it != privilegesToAdd.end(); @@ -313,8 +300,7 @@ Status RoleGraph::removePrivilegeFromRole(const RoleName& role, if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(role)) { return Status(ErrorCodes::InvalidRoleModification, @@ -337,8 +323,7 @@ Status RoleGraph::removePrivilegeFromRole(const RoleName& role, << " does not contain a privilege on " << privilegeToRemove.getResourcePattern().toString() << " with actions: " - << privilegeToRemove.getActions().toString(), - 0); + << privilegeToRemove.getActions().toString()); } curPrivilege.removeActions(privilegeToRemove.getActions()); @@ -352,8 +337,7 @@ Status RoleGraph::removePrivilegeFromRole(const RoleName& role, mongoutils::str::stream() << "Role: " << role.getFullName() << " does not " "contain any privileges on " - << privilegeToRemove.getResourcePattern().toString(), - 0); + << privilegeToRemove.getResourcePattern().toString()); } Status RoleGraph::removePrivilegesFromRole(const RoleName& role, @@ -373,8 +357,7 @@ Status RoleGraph::removeAllPrivilegesFromRole(const RoleName& role) { if (!roleExists(role)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << role.getFullName() - << " does not exist", - 0); + << " does not exist"); } if (isBuiltinRole(role)) { return Status(ErrorCodes::InvalidRoleModification, @@ -464,8 +447,7 @@ Status RoleGraph::_recomputePrivilegeDataHelper(const RoleName& startingRole, if (!roleExists(currentRole)) { return Status(ErrorCodes::RoleNotFound, mongoutils::str::stream() << "Role: " << currentRole.getFullName() - << " does not exist", - 0); + << " does not exist"); } // Check for cycles diff --git a/src/mongo/db/auth/user_document_parser.cpp b/src/mongo/db/auth/user_document_parser.cpp index aca408636a3..edf7e1c4f55 100644 --- a/src/mongo/db/auth/user_document_parser.cpp +++ b/src/mongo/db/auth/user_document_parser.cpp @@ -64,22 +64,22 @@ constexpr StringData AUTHENTICATION_RESTRICTIONS_FIELD_NAME = "authenticationRes constexpr StringData INHERITED_AUTHENTICATION_RESTRICTIONS_FIELD_NAME = "inheritedAuthenticationRestrictions"_sd; -inline Status _badValue(const char* reason, int location) { - return Status(ErrorCodes::BadValue, reason, location); +inline Status _badValue(const char* reason) { + return Status(ErrorCodes::BadValue, reason); } -inline Status _badValue(const std::string& reason, int location) { - return Status(ErrorCodes::BadValue, reason, location); +inline Status _badValue(const std::string& reason) { + return Status(ErrorCodes::BadValue, reason); } Status _checkV1RolesArray(const BSONElement& rolesElement) { if (rolesElement.type() != Array) { - return _badValue("Role fields must be an array when present in system.users entries", 0); + return _badValue("Role fields must be an array when present in system.users entries"); } for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { BSONElement element = *iter; if (element.type() != String || element.valueStringData().empty()) { - return _badValue("Roles must be non-empty strings.", 0); + return _badValue("Roles must be non-empty strings."); } } return Status::OK(); @@ -210,14 +210,14 @@ Status V1UserDocumentParser::initializeUserRolesFromUserDocument(User* user, Status _checkV2RolesArray(const BSONElement& rolesElement) { if (rolesElement.eoo()) { - return _badValue("User document needs 'roles' field to be provided", 0); + return _badValue("User document needs 'roles' field to be provided"); } if (rolesElement.type() != Array) { - return _badValue("'roles' field must be an array", 0); + return _badValue("'roles' field must be an array"); } for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { if ((*iter).type() != Object) { - return _badValue("Elements in 'roles' array must objects", 0); + return _badValue("Elements in 'roles' array must objects"); } Status status = V2UserDocumentParser::checkValidRoleObject((*iter).Obj()); if (!status.isOK()) @@ -234,41 +234,39 @@ Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const { // Validate the "user" element. if (userElement.type() != String) - return _badValue("User document needs 'user' field to be a string", 0); + return _badValue("User document needs 'user' field to be a string"); if (userElement.valueStringData().empty()) - return _badValue("User document needs 'user' field to be non-empty", 0); + return _badValue("User document needs 'user' field to be non-empty"); // Validate the "db" element if (userDBElement.type() != String || userDBElement.valueStringData().empty()) { - return _badValue("User document needs 'db' field to be a non-empty string", 0); + return _badValue("User document needs 'db' field to be a non-empty string"); } StringData userDBStr = userDBElement.valueStringData(); if (!NamespaceString::validDBName(userDBStr, NamespaceString::DollarInDbNameBehavior::Allow) && userDBStr != "$external") { return _badValue(mongoutils::str::stream() << "'" << userDBStr - << "' is not a valid value for the db field.", - 0); + << "' is not a valid value for the db field."); } // Validate the "credentials" element if (credentialsElement.eoo()) { - return _badValue("User document needs 'credentials' object", 0); + return _badValue("User document needs 'credentials' object"); } if (credentialsElement.type() != Object) { - return _badValue("User document needs 'credentials' field to be an object", 0); + return _badValue("User document needs 'credentials' field to be an object"); } BSONObj credentialsObj = credentialsElement.Obj(); if (credentialsObj.isEmpty()) { - return _badValue("User document needs 'credentials' field to be a non-empty object", 0); + return _badValue("User document needs 'credentials' field to be a non-empty object"); } if (userDBStr == "$external") { BSONElement externalElement = credentialsObj[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME]; if (externalElement.eoo() || externalElement.type() != Bool || !externalElement.Bool()) { return _badValue( "User documents for users defined on '$external' must have " - "'credentials' field set to {external: true}", - 0); + "'credentials' field set to {external: true}"); } } else { BSONElement scramElement = credentialsObj[SCRAM_CREDENTIAL_FIELD_NAME]; @@ -278,18 +276,16 @@ Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const { if (mongoCRElement.type() != String || mongoCRElement.valueStringData().empty()) { return _badValue( "MONGODB-CR credential must to be a non-empty string" - ", if present", - 0); + ", if present"); } } else if (!scramElement.eoo()) { if (scramElement.type() != Object) { - return _badValue("SCRAM credential must be an object, if present", 0); + return _badValue("SCRAM credential must be an object, if present"); } } else { return _badValue( "User document must provide credentials for all " - "non-external users", - 0); + "non-external users"); } } diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index b1d6bf24c3d..467f985de64 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -270,14 +270,14 @@ public: const std::vector<MultiIndexBlock*>& indexBlocks, bool enforceQuota) = 0; - virtual StatusWith<RecordId> updateDocument(OperationContext* opCtx, - const RecordId& oldLocation, - const Snapshotted<BSONObj>& oldDoc, - const BSONObj& newDoc, - bool enforceQuota, - bool indexesAffected, - OpDebug* opDebug, - OplogUpdateEntryArgs* args) = 0; + virtual RecordId updateDocument(OperationContext* opCtx, + const RecordId& oldLocation, + const Snapshotted<BSONObj>& oldDoc, + const BSONObj& newDoc, + bool enforceQuota, + bool indexesAffected, + OpDebug* opDebug, + OplogUpdateEntryArgs* args) = 0; virtual bool updateWithDamagesSupported() const = 0; @@ -539,14 +539,14 @@ public: * 'opDebug' Optional argument. When not null, will be used to record operation statistics. * @return the post update location of the doc (may or may not be the same as oldLocation) */ - inline StatusWith<RecordId> updateDocument(OperationContext* const opCtx, - const RecordId& oldLocation, - const Snapshotted<BSONObj>& oldDoc, - const BSONObj& newDoc, - const bool enforceQuota, - const bool indexesAffected, - OpDebug* const opDebug, - OplogUpdateEntryArgs* const args) { + inline RecordId updateDocument(OperationContext* const opCtx, + const RecordId& oldLocation, + const Snapshotted<BSONObj>& oldDoc, + const BSONObj& newDoc, + const bool enforceQuota, + const bool indexesAffected, + OpDebug* const opDebug, + OplogUpdateEntryArgs* const args) { return this->_impl().updateDocument( opCtx, oldLocation, oldDoc, newDoc, enforceQuota, indexesAffected, opDebug, args); } diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index eb096e7c331..3a58725d9b0 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -576,25 +576,25 @@ void CollectionImpl::deleteDocument(OperationContext* opCtx, Counter64 moveCounter; ServerStatusMetricField<Counter64> moveCounterDisplay("record.moves", &moveCounter); -StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, - const RecordId& oldLocation, - const Snapshotted<BSONObj>& oldDoc, - const BSONObj& newDoc, - bool enforceQuota, - bool indexesAffected, - OpDebug* opDebug, - OplogUpdateEntryArgs* args) { +RecordId CollectionImpl::updateDocument(OperationContext* opCtx, + const RecordId& oldLocation, + const Snapshotted<BSONObj>& oldDoc, + const BSONObj& newDoc, + bool enforceQuota, + bool indexesAffected, + OpDebug* opDebug, + OplogUpdateEntryArgs* args) { { auto status = checkValidation(opCtx, newDoc); if (!status.isOK()) { if (_validationLevel == ValidationLevel::STRICT_V) { - return status; + uassertStatusOK(status); } // moderate means we have to check the old doc auto oldDocStatus = checkValidation(opCtx, oldDoc.value()); if (oldDocStatus.isOK()) { // transitioning from good -> bad is not ok - return status; + uassertStatusOK(status); } // bad -> bad is ok in moderate mode } @@ -616,8 +616,7 @@ StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, BSONElement oldId = oldDoc.value()["_id"]; if (!oldId.eoo() && SimpleBSONElementComparator::kInstance.evaluate(oldId != newDoc["_id"])) - return StatusWith<RecordId>( - ErrorCodes::InternalError, "in Collection::updateDocument _id mismatch", 13596); + uasserted(13596, "in Collection::updateDocument _id mismatch"); // The MMAPv1 storage engine implements capped collections in a way that does not allow records // to grow beyond their original size. If MMAPv1 part of a replicaset with storage engines that @@ -628,11 +627,11 @@ StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, // all size changes. const auto oldSize = oldDoc.value().objsize(); if (_recordStore->isCapped() && oldSize != newDoc.objsize()) - return {ErrorCodes::CannotGrowDocumentInCappedNamespace, - str::stream() << "Cannot change the size of a document in a capped collection: " - << oldSize - << " != " - << newDoc.objsize()}; + uasserted(ErrorCodes::CannotGrowDocumentInCappedNamespace, + str::stream() << "Cannot change the size of a document in a capped collection: " + << oldSize + << " != " + << newDoc.objsize()); // At the end of this step, we will have a map of UpdateTickets, one per index, which // represent the index updates needed to be done, based on the changes between oldDoc and @@ -649,16 +648,13 @@ StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, IndexCatalog::prepareInsertDeleteOptions(opCtx, descriptor, &options); UpdateTicket* updateTicket = new UpdateTicket(); updateTickets.mutableMap()[descriptor] = updateTicket; - Status ret = iam->validateUpdate(opCtx, - oldDoc.value(), - newDoc, - oldLocation, - options, - updateTicket, - entry->getFilterExpression()); - if (!ret.isOK()) { - return StatusWith<RecordId>(ret); - } + uassertStatusOK(iam->validateUpdate(opCtx, + oldDoc.value(), + newDoc, + oldLocation, + options, + updateTicket, + entry->getFilterExpression())); } } @@ -666,11 +662,10 @@ StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, opCtx, oldLocation, newDoc.objdata(), newDoc.objsize(), _enforceQuota(enforceQuota), this); if (updateStatus == ErrorCodes::NeedsDocumentMove) { - return _updateDocumentWithMove( - opCtx, oldLocation, oldDoc, newDoc, enforceQuota, opDebug, args, sid); - } else if (!updateStatus.isOK()) { - return updateStatus; + return uassertStatusOK(_updateDocumentWithMove( + opCtx, oldLocation, oldDoc, newDoc, enforceQuota, opDebug, args, sid)); } + uassertStatusOK(updateStatus); // Object did not move. We update each index with each respective UpdateTicket. if (indexesAffected) { @@ -681,10 +676,8 @@ StatusWith<RecordId> CollectionImpl::updateDocument(OperationContext* opCtx, int64_t keysInserted; int64_t keysDeleted; - Status ret = iam->update( - opCtx, *updateTickets.mutableMap()[descriptor], &keysInserted, &keysDeleted); - if (!ret.isOK()) - return StatusWith<RecordId>(ret); + uassertStatusOK(iam->update( + opCtx, *updateTickets.mutableMap()[descriptor], &keysInserted, &keysDeleted)); if (opDebug) { opDebug->keysInserted += keysInserted; opDebug->keysDeleted += keysDeleted; diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h index 1fdfc40d1fa..b9132e26261 100644 --- a/src/mongo/db/catalog/collection_impl.h +++ b/src/mongo/db/catalog/collection_impl.h @@ -208,14 +208,14 @@ public: * 'opDebug' Optional argument. When not null, will be used to record operation statistics. * @return the post update location of the doc (may or may not be the same as oldLocation) */ - StatusWith<RecordId> updateDocument(OperationContext* opCtx, - const RecordId& oldLocation, - const Snapshotted<BSONObj>& oldDoc, - const BSONObj& newDoc, - bool enforceQuota, - bool indexesAffected, - OpDebug* opDebug, - OplogUpdateEntryArgs* args) final; + RecordId updateDocument(OperationContext* opCtx, + const RecordId& oldLocation, + const Snapshotted<BSONObj>& oldDoc, + const BSONObj& newDoc, + bool enforceQuota, + bool indexesAffected, + OpDebug* opDebug, + OplogUpdateEntryArgs* args) final; bool updateWithDamagesSupported() const final; diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h index 38339efb7df..a5bb17349ac 100644 --- a/src/mongo/db/catalog/collection_mock.h +++ b/src/mongo/db/catalog/collection_mock.h @@ -167,14 +167,14 @@ public: std::abort(); } - StatusWith<RecordId> updateDocument(OperationContext* opCtx, - const RecordId& oldLocation, - const Snapshotted<BSONObj>& oldDoc, - const BSONObj& newDoc, - bool enforceQuota, - bool indexesAffected, - OpDebug* opDebug, - OplogUpdateEntryArgs* args) { + RecordId updateDocument(OperationContext* opCtx, + const RecordId& oldLocation, + const Snapshotted<BSONObj>& oldDoc, + const BSONObj& newDoc, + bool enforceQuota, + bool indexesAffected, + OpDebug* opDebug, + OplogUpdateEntryArgs* args) { std::abort(); } diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp index 42e2bb3bf8f..0788a621ee9 100644 --- a/src/mongo/db/exec/update.cpp +++ b/src/mongo/db/exec/update.cpp @@ -87,16 +87,12 @@ Status ensureIdFieldIsFirst(mb::Document* doc) { return Status::OK(); } -Status addObjectIDIdField(mb::Document* doc) { +void addObjectIDIdField(mb::Document* doc) { const auto idElem = doc->makeElementNewOID(idFieldName); if (!idElem.ok()) - return {ErrorCodes::BadValue, "Could not create new ObjectId '_id' field.", 17268}; + uasserted(17268, "Could not create new ObjectId '_id' field."); - const auto s = doc->root().pushFront(idElem); - if (!s.isOK()) - return s; - - return Status::OK(); + uassertStatusOK(doc->root().pushFront(idElem)); } /** @@ -253,7 +249,7 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, Reco if (status.code() == ErrorCodes::InvalidIdField) { // Create ObjectId _id field if we are doing that if (createIdField) { - uassertStatusOK(addObjectIDIdField(&_doc)); + addObjectIDIdField(&_doc); } } else { uassertStatusOK(status); @@ -324,16 +320,14 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, Reco args.update = logObj; args.criteria = idQuery; args.fromMigrate = request->isFromMigration(); - StatusWith<RecordId> res = _collection->updateDocument(getOpCtx(), - recordId, - oldObj, - newObj, - true, - driver->modsAffectIndices(), - _params.opDebug, - &args); - uassertStatusOK(res.getStatus()); - newRecordId = res.getValue(); + newRecordId = _collection->updateDocument(getOpCtx(), + recordId, + oldObj, + newObj, + true, + driver->modsAffectIndices(), + _params.opDebug, + &args); } } @@ -362,15 +356,14 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, Reco return newObj; } -Status UpdateStage::applyUpdateOpsForInsert(OperationContext* opCtx, - const CanonicalQuery* cq, - const BSONObj& query, - UpdateDriver* driver, - mutablebson::Document* doc, - bool isInternalRequest, - const NamespaceString& ns, - UpdateStats* stats, - BSONObj* out) { +BSONObj UpdateStage::applyUpdateOpsForInsert(OperationContext* opCtx, + const CanonicalQuery* cq, + const BSONObj& query, + UpdateDriver* driver, + mutablebson::Document* doc, + bool isInternalRequest, + const NamespaceString& ns, + UpdateStats* stats) { // Since this is an insert (no docs found and upsert:true), we will be logging it // as an insert in the oplog. We don't need the driver's help to build the // oplog record, then. We also set the context of the update driver to the INSERT_CONTEXT. @@ -392,11 +385,7 @@ Status UpdateStage::applyUpdateOpsForInsert(OperationContext* opCtx, BSONObj original; if (cq) { - Status status = driver->populateDocumentWithQueryFields(*cq, immutablePaths, *doc); - if (!status.isOK()) { - return status; - } - + uassertStatusOK(driver->populateDocumentWithQueryFields(*cq, immutablePaths, *doc)); if (driver->isDocReplacement()) stats->fastmodinsert = true; original = doc->getObject(); @@ -416,17 +405,15 @@ Status UpdateStage::applyUpdateOpsForInsert(OperationContext* opCtx, Status updateStatus = driver->update(StringData(), original, doc, validateForStorage, immutablePaths); if (!updateStatus.isOK()) { - return Status(updateStatus.code(), updateStatus.reason(), 16836); + uasserted(16836, updateStatus.reason()); } // Ensure _id exists and is first auto idAndFirstStatus = ensureIdFieldIsFirst(doc); if (idAndFirstStatus.code() == ErrorCodes::InvalidIdField) { // _id field is missing - idAndFirstStatus = addObjectIDIdField(doc); - } - - if (!idAndFirstStatus.isOK()) { - return idAndFirstStatus; + addObjectIDIdField(doc); + } else { + uassertStatusOK(idAndFirstStatus); } // Validate that the object replacement or modifiers resulted in a document @@ -441,13 +428,11 @@ Status UpdateStage::applyUpdateOpsForInsert(OperationContext* opCtx, BSONObj newObj = doc->getObject(); if (newObj.objsize() > BSONObjMaxUserSize) { - return Status(ErrorCodes::InvalidBSON, - str::stream() << "Document to upsert is larger than " << BSONObjMaxUserSize, - 17420); + uasserted(17420, + str::stream() << "Document to upsert is larger than " << BSONObjMaxUserSize); } - *out = newObj; - return Status::OK(); + return newObj; } void UpdateStage::doInsert() { @@ -459,16 +444,14 @@ void UpdateStage::doInsert() { // Reset the document we will be writing to. _doc.reset(); - BSONObj newObj; - uassertStatusOK(applyUpdateOpsForInsert(getOpCtx(), - _params.canonicalQuery, - request->getQuery(), - _params.driver, - &_doc, - isInternalRequest, - request->getNamespaceString(), - &_specificStats, - &newObj)); + BSONObj newObj = applyUpdateOpsForInsert(getOpCtx(), + _params.canonicalQuery, + request->getQuery(), + _params.driver, + &_doc, + isInternalRequest, + request->getNamespaceString(), + &_specificStats); _specificStats.objInserted = newObj; @@ -722,7 +705,7 @@ PlanStage::StageState UpdateStage::doWork(WorkingSetID* out) { return status; } -Status UpdateStage::restoreUpdateState() { +void UpdateStage::doRestoreState() { const UpdateRequest& request = *_params.request; const NamespaceString& nsString(request.getNamespaceString()); @@ -731,9 +714,9 @@ Status UpdateStage::restoreUpdateState() { !repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(getOpCtx(), nsString); if (userInitiatedWritesAndNotPrimary) { - return Status(ErrorCodes::PrimarySteppedDown, - str::stream() << "Demoted from primary while performing update on " - << nsString.ns()); + uasserted(ErrorCodes::PrimarySteppedDown, + str::stream() << "Demoted from primary while performing update on " + << nsString.ns()); } if (request.getLifecycle()) { @@ -741,19 +724,11 @@ Status UpdateStage::restoreUpdateState() { lifecycle->setCollection(_collection); if (!lifecycle->canContinue()) { - return Status(ErrorCodes::IllegalOperation, - "Update aborted due to invalid state transitions after yield.", - 17270); + uasserted(17270, "Update aborted due to invalid state transitions after yield."); } _params.driver->refreshIndexKeys(lifecycle->getIndexKeys(getOpCtx())); } - - return Status::OK(); -} - -void UpdateStage::doRestoreState() { - uassertStatusOK(restoreUpdateState()); } unique_ptr<PlanStageStats> UpdateStage::getStats() { diff --git a/src/mongo/db/exec/update.h b/src/mongo/db/exec/update.h index fa866f87606..f5dccd1c7e6 100644 --- a/src/mongo/db/exec/update.h +++ b/src/mongo/db/exec/update.h @@ -132,17 +132,16 @@ public: * * Fills out whether or not this is a fastmodinsert in 'stats'. * - * Returns the document to insert in *out. + * Returns the document to insert. */ - static Status applyUpdateOpsForInsert(OperationContext* opCtx, - const CanonicalQuery* cq, - const BSONObj& query, - UpdateDriver* driver, - mutablebson::Document* doc, - bool isInternalRequest, - const NamespaceString& ns, - UpdateStats* stats, - BSONObj* out); + static BSONObj applyUpdateOpsForInsert(OperationContext* opCtx, + const CanonicalQuery* cq, + const BSONObj& query, + UpdateDriver* driver, + mutablebson::Document* doc, + bool isInternalRequest, + const NamespaceString& ns, + UpdateStats* stats); private: /** @@ -171,11 +170,6 @@ private: bool needInsert(); /** - * Helper for restoring the state of this update. - */ - Status restoreUpdateState(); - - /** * Stores 'idToRetry' in '_idRetrying' so the update can be retried during the next call to * work(). Always returns NEED_YIELD and sets 'out' to WorkingSet::INVALID_ID. */ diff --git a/src/mongo/db/pipeline/parsed_add_fields.cpp b/src/mongo/db/pipeline/parsed_add_fields.cpp index 0cbe513a720..bfd5774c3ba 100644 --- a/src/mongo/db/pipeline/parsed_add_fields.cpp +++ b/src/mongo/db/pipeline/parsed_add_fields.cpp @@ -41,11 +41,7 @@ namespace parsed_aggregation_projection { std::unique_ptr<ParsedAddFields> ParsedAddFields::create( const boost::intrusive_ptr<ExpressionContext>& expCtx, const BSONObj& spec) { // Verify that we don't have conflicting field paths, etc. - Status status = ProjectionSpecValidator::validate(spec); - if (!status.isOK()) { - uasserted(status.location(), - str::stream() << "Invalid $addFields specification: " << status.reason()); - } + ProjectionSpecValidator::uassertValid(spec, "$addFields"); std::unique_ptr<ParsedAddFields> parsedAddFields = stdx::make_unique<ParsedAddFields>(expCtx); // Actually parse the specification. diff --git a/src/mongo/db/pipeline/parsed_aggregation_projection.cpp b/src/mongo/db/pipeline/parsed_aggregation_projection.cpp index cfa7d6da39c..1588e796970 100644 --- a/src/mongo/db/pipeline/parsed_aggregation_projection.cpp +++ b/src/mongo/db/pipeline/parsed_aggregation_projection.cpp @@ -53,57 +53,56 @@ using TransformerType = // ProjectionSpecValidator // -Status ProjectionSpecValidator::validate(const BSONObj& spec) { - return ProjectionSpecValidator(spec).validate(); +void ProjectionSpecValidator::uassertValid(const BSONObj& spec, StringData stageName) { + try { + ProjectionSpecValidator(spec).validate(); + } catch (DBException& ex) { + ex.addContext("Invalid " + stageName.toString()); + throw; + } } -Status ProjectionSpecValidator::ensurePathDoesNotConflictOrThrow(StringData path) { +void ProjectionSpecValidator::ensurePathDoesNotConflictOrThrow(StringData path) { for (auto&& seenPath : _seenPaths) { if ((path == seenPath) || (expression::isPathPrefixOf(path, seenPath)) || (expression::isPathPrefixOf(seenPath, path))) { - return Status(ErrorCodes::FailedToParse, - str::stream() << "specification contains two conflicting paths. " - "Cannot specify both '" - << path - << "' and '" - << seenPath - << "': " - << _rawObj.toString(), - 40176); + uasserted(40176, + str::stream() << "specification contains two conflicting paths. " + "Cannot specify both '" + << path + << "' and '" + << seenPath + << "': " + << _rawObj.toString()); } } _seenPaths.emplace_back(path.toString()); - return Status::OK(); } -Status ProjectionSpecValidator::validate() { +void ProjectionSpecValidator::validate() { if (_rawObj.isEmpty()) { - return Status( - ErrorCodes::FailedToParse, "specification must have at least one field", 40177); + uasserted(40177, "specification must have at least one field"); } for (auto&& elem : _rawObj) { - Status status = parseElement(elem, FieldPath(elem.fieldName())); - if (!status.isOK()) - return status; + parseElement(elem, FieldPath(elem.fieldName())); } - return Status::OK(); } -Status ProjectionSpecValidator::parseElement(const BSONElement& elem, const FieldPath& pathToElem) { +void ProjectionSpecValidator::parseElement(const BSONElement& elem, const FieldPath& pathToElem) { if (elem.type() == BSONType::Object) { - return parseNestedObject(elem.Obj(), pathToElem); + parseNestedObject(elem.Obj(), pathToElem); + } else { + ensurePathDoesNotConflictOrThrow(pathToElem.fullPath()); } - return ensurePathDoesNotConflictOrThrow(pathToElem.fullPath()); } -Status ProjectionSpecValidator::parseNestedObject(const BSONObj& thisLevelSpec, - const FieldPath& prefix) { +void ProjectionSpecValidator::parseNestedObject(const BSONObj& thisLevelSpec, + const FieldPath& prefix) { if (thisLevelSpec.isEmpty()) { - return Status(ErrorCodes::FailedToParse, - str::stream() - << "an empty object is not a valid value. Found empty object at path " - << prefix.fullPath(), - 40180); + uasserted( + 40180, + str::stream() << "an empty object is not a valid value. Found empty object at path " + << prefix.fullPath()); } for (auto&& elem : thisLevelSpec) { auto fieldName = elem.fieldNameStringData(); @@ -112,34 +111,26 @@ Status ProjectionSpecValidator::parseNestedObject(const BSONObj& thisLevelSpec, // into an Expression later, but for now, just track that the prefix has been // specified and skip it. if (thisLevelSpec.nFields() != 1) { - return Status(ErrorCodes::FailedToParse, - str::stream() << "an expression specification must contain exactly " - "one field, the name of the expression. Found " - << thisLevelSpec.nFields() - << " fields in " - << thisLevelSpec.toString() - << ", while parsing object " - << _rawObj.toString(), - 40181); + uasserted(40181, + str::stream() << "an expression specification must contain exactly " + "one field, the name of the expression. Found " + << thisLevelSpec.nFields() + << " fields in " + << thisLevelSpec.toString() + << ", while parsing object " + << _rawObj.toString()); } - Status status = ensurePathDoesNotConflictOrThrow(prefix.fullPath()); - if (!status.isOK()) - return status; + ensurePathDoesNotConflictOrThrow(prefix.fullPath()); continue; } if (fieldName.find('.') != std::string::npos) { - return Status(ErrorCodes::FailedToParse, - str::stream() << "cannot use dotted field name '" << fieldName - << "' in a sub object: " - << _rawObj.toString(), - 40183); + uasserted(40183, + str::stream() << "cannot use dotted field name '" << fieldName + << "' in a sub object: " + << _rawObj.toString()); } - Status status = - parseElement(elem, FieldPath::getFullyQualifiedPath(prefix.fullPath(), fieldName)); - if (!status.isOK()) - return status; + parseElement(elem, FieldPath::getFullyQualifiedPath(prefix.fullPath(), fieldName)); } - return Status::OK(); } namespace { @@ -279,11 +270,7 @@ std::unique_ptr<ParsedAggregationProjection> ParsedAggregationProjection::create // Check that the specification was valid. Status returned is unspecific because validate() // is used by the $addFields stage as well as $project. // If there was an error, uassert with a $project-specific message. - Status status = ProjectionSpecValidator::validate(spec); - if (!status.isOK()) { - uasserted(status.location(), - str::stream() << "Invalid $project specification: " << status.reason()); - } + ProjectionSpecValidator::uassertValid(spec, "$project"); // Check for any conflicting specifications, and determine the type of the projection. auto projectionType = ProjectTypeParser::parse(spec); diff --git a/src/mongo/db/pipeline/parsed_aggregation_projection.h b/src/mongo/db/pipeline/parsed_aggregation_projection.h index 721c086f6e1..126254ce908 100644 --- a/src/mongo/db/pipeline/parsed_aggregation_projection.h +++ b/src/mongo/db/pipeline/parsed_aggregation_projection.h @@ -53,10 +53,10 @@ namespace parsed_aggregation_projection { class ProjectionSpecValidator { public: /** - * Returns a Status: either a Status::OK() if the specification is valid for a projection, or a - * non-OK Status, error number, and message with why not. + * Throws if the specification is not valid for a projection. The stageName is used to provide a + * more helpful error message. */ - static Status validate(const BSONObj& spec); + static void uassertValid(const BSONObj& spec, StringData stageName); private: ProjectionSpecValidator(const BSONObj& spec) : _rawObj(spec) {} @@ -67,12 +67,12 @@ private: * For example, a user is not allowed to specify {'a': 1, 'a.b': 1}, or some similar conflicting * paths. */ - Status ensurePathDoesNotConflictOrThrow(StringData path); + void ensurePathDoesNotConflictOrThrow(StringData path); /** - * Returns the relevant error if an invalid projection specification is detected. + * Throws if an invalid projection specification is detected. */ - Status validate(); + void validate(); /** * Parses a single BSONElement. 'pathToElem' should include the field name of 'elem'. @@ -80,19 +80,18 @@ private: * Delegates to parseSubObject() if 'elem' is an object. Otherwise adds the full path to 'elem' * to '_seenPaths'. * - * Calls ensurePathDoesNotConflictOrThrow with the path to this element, which sets the _status - * appropriately for conflicting path specifications. + * Calls ensurePathDoesNotConflictOrThrow with the path to this element, throws on conflicting + * path specifications. */ - Status parseElement(const BSONElement& elem, const FieldPath& pathToElem); + void parseElement(const BSONElement& elem, const FieldPath& pathToElem); /** * Traverses 'thisLevelSpec', parsing each element in turn. * - * Sets _status appropriately if any paths conflict with each other or existing paths, - * 'thisLevelSpec' contains a dotted path, or if 'thisLevelSpec' represents an invalid - * expression. + * Throws if any paths conflict with each other or existing paths, 'thisLevelSpec' contains a + * dotted path, or if 'thisLevelSpec' represents an invalid expression. */ - Status parseNestedObject(const BSONObj& thisLevelSpec, const FieldPath& prefix); + void parseNestedObject(const BSONObj& thisLevelSpec, const FieldPath& prefix); // The original object. Used to generate more helpful error messages. const BSONObj& _rawObj; diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp index 8b84fe36bff..5c2ce92237f 100644 --- a/src/mongo/db/pipeline/pipeline.cpp +++ b/src/mongo/db/pipeline/pipeline.cpp @@ -115,24 +115,28 @@ StatusWith<std::unique_ptr<Pipeline, Pipeline::Deleter>> Pipeline::createTopLeve const bool isFacetPipeline) { std::unique_ptr<Pipeline, Pipeline::Deleter> pipeline(new Pipeline(std::move(stages), expCtx), Pipeline::Deleter(expCtx->opCtx)); - auto status = - (isFacetPipeline ? pipeline->validateFacetPipeline() : pipeline->validatePipeline()); - if (!status.isOK()) { - return status; + try { + if (isFacetPipeline) { + pipeline->validateFacetPipeline(); + } else { + pipeline->validatePipeline(); + } + } catch (const DBException& ex) { + return ex.toStatus(); } pipeline->stitch(); return std::move(pipeline); } -Status Pipeline::validatePipeline() const { +void Pipeline::validatePipeline() const { // Verify that the specified namespace is valid for the initial stage of this pipeline. const NamespaceString& nss = pCtx->ns; if (_sources.empty()) { if (nss.isCollectionlessAggregateNS()) { - return {ErrorCodes::InvalidNamespace, - "{aggregate: 1} is not valid for an empty pipeline."}; + uasserted(ErrorCodes::InvalidNamespace, + "{aggregate: 1} is not valid for an empty pipeline."); } } else if (!dynamic_cast<DocumentSourceMergeCursors*>(_sources.front().get())) { // The $mergeCursors stage can take {aggregate: 1} or a normal namespace. Aside from this, @@ -141,35 +145,34 @@ Status Pipeline::validatePipeline() const { if (nss.isCollectionlessAggregateNS() && !firstStage->constraints().isIndependentOfAnyCollection) { - return {ErrorCodes::InvalidNamespace, - str::stream() << "{aggregate: 1} is not valid for '" - << firstStage->getSourceName() - << "'; a collection is required."}; + uasserted(ErrorCodes::InvalidNamespace, + str::stream() << "{aggregate: 1} is not valid for '" + << firstStage->getSourceName() + << "'; a collection is required."); } if (!nss.isCollectionlessAggregateNS() && firstStage->constraints().isIndependentOfAnyCollection) { - return {ErrorCodes::InvalidNamespace, - str::stream() << "'" << firstStage->getSourceName() - << "' can only be run with {aggregate: 1}"}; + uasserted(ErrorCodes::InvalidNamespace, + str::stream() << "'" << firstStage->getSourceName() + << "' can only be run with {aggregate: 1}"); } } // Verify that each stage is in a legal position within the pipeline. - return ensureAllStagesAreInLegalPositions(); + ensureAllStagesAreInLegalPositions(); } -Status Pipeline::validateFacetPipeline() const { +void Pipeline::validateFacetPipeline() const { if (_sources.empty()) { - return {ErrorCodes::BadValue, "sub-pipeline in $facet stage cannot be empty"}; + uasserted(ErrorCodes::BadValue, "sub-pipeline in $facet stage cannot be empty"); } for (auto&& stage : _sources) { auto stageConstraints = stage->constraints(); if (!stageConstraints.isAllowedInsideFacetStage) { - return {ErrorCodes::BadValue, - str::stream() << stage->getSourceName() - << " is not allowed to be used within a $facet stage", - 40550}; + uasserted(40600, + str::stream() << stage->getSourceName() + << " is not allowed to be used within a $facet stage"); } // We expect a stage within a $facet stage to have these properties. invariant(stageConstraints.requiresInputDocSource); @@ -180,35 +183,30 @@ Status Pipeline::validateFacetPipeline() const { // Facet pipelines cannot have any stages which are initial sources. We've already validated the // first stage, and the 'ensureAllStagesAreInLegalPositions' method checks that there are no // initial sources in positions 1...N, so we can just return its result directly. - return ensureAllStagesAreInLegalPositions(); + ensureAllStagesAreInLegalPositions(); } -Status Pipeline::ensureAllStagesAreInLegalPositions() const { +void Pipeline::ensureAllStagesAreInLegalPositions() const { size_t i = 0; for (auto&& stage : _sources) { if (stage->constraints().requiredPosition == PositionRequirement::kFirst && i != 0) { - return {ErrorCodes::BadValue, - str::stream() << stage->getSourceName() - << " is only valid as the first stage in a pipeline.", - 40549}; + uasserted(40602, + str::stream() << stage->getSourceName() + << " is only valid as the first stage in a pipeline."); } auto matchStage = dynamic_cast<DocumentSourceMatch*>(stage.get()); if (i != 0 && matchStage && matchStage->isTextQuery()) { - return {ErrorCodes::BadValue, - "$match with $text is only allowed as the first pipeline stage", - 17313}; + uasserted(17313, "$match with $text is only allowed as the first pipeline stage"); } if (stage->constraints().requiredPosition == PositionRequirement::kLast && i != _sources.size() - 1) { - return {ErrorCodes::BadValue, - str::stream() << stage->getSourceName() - << " can only be the final stage in the pipeline", - 40551}; + uasserted(40601, + str::stream() << stage->getSourceName() + << " can only be the final stage in the pipeline"); } ++i; } - return Status::OK(); } void Pipeline::optimizePipeline() { diff --git a/src/mongo/db/pipeline/pipeline.h b/src/mongo/db/pipeline/pipeline.h index ed19d44ae2b..6f46bf75476 100644 --- a/src/mongo/db/pipeline/pipeline.h +++ b/src/mongo/db/pipeline/pipeline.h @@ -320,17 +320,17 @@ private: void unstitch(); /** - * Returns a non-OK status if the pipeline fails any of a set of semantic checks. For example, - * if an $out stage is present then it must come last in the pipeline, while initial stages such - * as $indexStats must be at the start. + * Throws if the pipeline fails any of a set of semantic checks. For example, if an $out stage + * is present then it must come last in the pipeline, while initial stages such as $indexStats + * must be at the start. */ - Status validatePipeline() const; + void validatePipeline() const; /** - * Returns a non-OK status if the $facet pipeline fails any of a set of semantic checks. For - * example, the pipeline cannot be empty and may not contain any initial stages. + * Throws if the $facet pipeline fails any of a set of semantic checks. For example, the + * pipeline cannot be empty and may not contain any initial stages. */ - Status validateFacetPipeline() const; + void validateFacetPipeline() const; /** * Helper method which validates that each stage in pipeline is in a legal position. For @@ -338,7 +338,7 @@ private: * start. Note that this method accepts an initial source as the first stage, which is illegal * for $facet pipelines. */ - Status ensureAllStagesAreInLegalPositions() const; + void ensureAllStagesAreInLegalPositions() const; SourceContainer _sources; diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index fd407964a02..ac54c766727 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -1496,8 +1496,7 @@ TEST_F(PipelineInitialSourceNSTest, ChangeStreamIsNotValidIfNotFirstStage) { setMockReplicationCoordinatorOnOpCtx(ctx->opCtx); ctx->ns = NamespaceString("a.collection"); auto parseStatus = Pipeline::parse(rawPipeline, ctx).getStatus(); - ASSERT_EQ(parseStatus, ErrorCodes::BadValue); - ASSERT_EQ(parseStatus.location(), 40549); + ASSERT_EQ(parseStatus, ErrorCodes::fromInt(40602)); } TEST_F(PipelineInitialSourceNSTest, ChangeStreamIsNotValidIfNotFirstStageInFacet) { @@ -1507,8 +1506,7 @@ TEST_F(PipelineInitialSourceNSTest, ChangeStreamIsNotValidIfNotFirstStageInFacet setMockReplicationCoordinatorOnOpCtx(ctx->opCtx); ctx->ns = NamespaceString("a.collection"); auto parseStatus = Pipeline::parseFacetPipeline(rawPipeline, ctx).getStatus(); - ASSERT_EQ(parseStatus, ErrorCodes::BadValue); - ASSERT_EQ(parseStatus.location(), 40550); + ASSERT_EQ(parseStatus, ErrorCodes::fromInt(40600)); ASSERT(std::string::npos != parseStatus.reason().find("$changeStream")); } diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp index d83aabdf0fb..8adbe7de16c 100644 --- a/src/mongo/db/repl/rs_rollback.cpp +++ b/src/mongo/db/repl/rs_rollback.cpp @@ -1338,8 +1338,7 @@ Status _syncRollback(OperationContext* opCtx, str::stream() << "need to rollback, but unable to determine common point between" " local and remote oplog: " - << e.what(), - 18752); + << e.what()); } log() << "Rollback common point is " << how.commonPoint; @@ -1350,7 +1349,7 @@ Status _syncRollback(OperationContext* opCtx, }); syncFixUp(opCtx, how, rollbackSource, replCoord, replicationProcess); } catch (const RSFatalException& e) { - return Status(ErrorCodes::UnrecoverableRollbackError, e.what(), 18753); + return Status(ErrorCodes::UnrecoverableRollbackError, e.what()); } if (MONGO_FAIL_POINT(rollbackHangBeforeFinish)) { diff --git a/src/mongo/db/repl/rs_rollback_no_uuid.cpp b/src/mongo/db/repl/rs_rollback_no_uuid.cpp index 69975909f57..ca9d4e6a2c0 100644 --- a/src/mongo/db/repl/rs_rollback_no_uuid.cpp +++ b/src/mongo/db/repl/rs_rollback_no_uuid.cpp @@ -200,8 +200,7 @@ Status rollback_internal_no_uuid::updateFixUpInfoFromLocalOplogEntry(FixUpInfo& if (cmd == NULL) { severe() << "Rollback no such command " << first.fieldName(); return Status(ErrorCodes::UnrecoverableRollbackError, - str::stream() << "Rollback no such command " << first.fieldName(), - 18751); + str::stream() << "Rollback no such command " << first.fieldName()); } if (cmdname == "create") { // Create collection operation @@ -914,8 +913,7 @@ Status _syncRollback(OperationContext* opCtx, str::stream() << "need to rollback, but unable to determine common point between" " local and remote oplog: " - << e.what(), - 18752); + << e.what()); } log() << "Rollback common point is " << how.commonPoint; @@ -926,7 +924,7 @@ Status _syncRollback(OperationContext* opCtx, }); syncFixUp(opCtx, how, rollbackSource, replCoord, replicationProcess); } catch (const RSFatalException& e) { - return Status(ErrorCodes::UnrecoverableRollbackError, e.what(), 18753); + return Status(ErrorCodes::UnrecoverableRollbackError, e.what()); } if (MONGO_FAIL_POINT(rollbackHangBeforeFinish)) { diff --git a/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp b/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp index 57e2ca10c9f..8107507d487 100644 --- a/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp +++ b/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp @@ -159,7 +159,7 @@ TEST_F(RSRollbackTest, InconsistentMinValid) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); } TEST_F(RSRollbackTest, OplogStartMissing) { @@ -189,7 +189,7 @@ TEST_F(RSRollbackTest, NoRemoteOpLog) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); } TEST_F(RSRollbackTest, RemoteGetRollbackIdThrows) { @@ -407,7 +407,7 @@ TEST_F(RSRollbackTest, RollbackInsertDocumentWithNoId) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS(1, countLogLinesContaining("Cannot roll back op with no _id. ns: test.t,")); ASSERT_FALSE(rollbackSource.called); } @@ -580,7 +580,7 @@ TEST_F(RSRollbackTest, RollbackInsertSystemIndexesMissingNamespace) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS( 1, countLogLinesContaining("Missing collection namespace in system.indexes operation,")); ASSERT_FALSE(rollbackSource.called); @@ -628,7 +628,7 @@ TEST_F(RSRollbackTest, RollbackCreateIndexCommandInvalidNamespace) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS( 1, countLogLinesContaining("Invalid collection namespace in createIndexes operation,")); ASSERT_FALSE(rollbackSource.called); @@ -815,7 +815,7 @@ TEST_F(RSRollbackTest, RollbackInsertSystemIndexesCommandInvalidNamespace) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS( 1, countLogLinesContaining("Invalid collection namespace in createIndexes operation,")); ASSERT_FALSE(rollbackSource.called); @@ -861,7 +861,7 @@ TEST_F(RSRollbackTest, RollbackCreateIndexCommandMissingIndexName) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS(1, countLogLinesContaining("Missing index name in createIndexes operation,")); ASSERT_FALSE(rollbackSource.called); } @@ -897,7 +897,7 @@ TEST_F(RSRollbackTest, RollbackUnknownCommand) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18751, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "Rollback no such command"); } TEST_F(RSRollbackTest, RollbackDropCollectionCommand) { @@ -1229,7 +1229,7 @@ TEST_F(RSRollbackTest, RollbackCollectionModificationCommandInvalidCollectionOpt _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18753, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "Failed to parse options"); } TEST(RSRollbackTest, LocalEntryWithoutNsIsFatal) { @@ -1285,12 +1285,13 @@ TEST_F(RSRollbackTest, RollbackReturnsImmediatelyOnFailureToTransitionToRollback ASSERT_EQUALS(MemberState(MemberState::RS_SECONDARY), _coordinator->getMemberState()); } -DEATH_TEST_F(RSRollbackTest, - RollbackUnrecoverableRollbackErrorTriggersFatalAssertion, - "Unable to complete rollback. A full resync may be needed: " - "UnrecoverableRollbackError: need to rollback, but unable to determine common point " - "between local and remote oplog: InvalidSyncSource: remote oplog empty or unreadable " - "@ 18752") { +DEATH_TEST_F( + RSRollbackTest, + RollbackUnrecoverableRollbackErrorTriggersFatalAssertion, + "Unable to complete rollback. A full resync may be needed: " + "UnrecoverableRollbackError: need to rollback, but unable to determine common point " + "between local and remote oplog: InvalidSyncSource: remote oplog empty or unreadable") { + // rollback() should abort on getting UnrecoverableRollbackError from syncRollback(). An empty // local oplog will make syncRollback() return the intended error. OplogInterfaceMock localOplogWithSingleOplogEntry({makeNoopOplogEntryAndRecordId(Seconds(1))}); diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp index c2a67fe5c4a..99f18f723ea 100644 --- a/src/mongo/db/repl/rs_rollback_test.cpp +++ b/src/mongo/db/repl/rs_rollback_test.cpp @@ -248,7 +248,7 @@ TEST_F(RSRollbackTest, InconsistentMinValid) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); } TEST_F(RSRollbackTest, OplogStartMissing) { @@ -278,7 +278,7 @@ TEST_F(RSRollbackTest, NoRemoteOpLog) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); } TEST_F(RSRollbackTest, RemoteGetRollbackIdThrows) { @@ -514,7 +514,7 @@ TEST_F(RSRollbackTest, RollbackInsertDocumentWithNoId) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS(1, countLogLinesContaining("Cannot roll back op with no _id. ns: test.t,")); ASSERT_FALSE(rollbackSource.called); } @@ -832,7 +832,7 @@ TEST_F(RSRollbackTest, RollbackCreateIndexCommandMissingIndexName) { _replicationProcess.get()); stopCapturingLogMessages(); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); ASSERT_EQUALS(1, countLogLinesContaining( "Missing index name in createIndexes operation on rollback, document: ")); @@ -864,7 +864,7 @@ TEST_F(RSRollbackTest, RollbackUnknownCommand) { _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18752, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "unable to determine common point"); } TEST_F(RSRollbackTest, RollbackDropCollectionCommand) { @@ -1820,7 +1820,7 @@ TEST_F(RSRollbackTest, RollbackCollectionModificationCommandInvalidCollectionOpt _coordinator, _replicationProcess.get()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, status.code()); - ASSERT_EQUALS(18753, status.location()); + ASSERT_STRING_CONTAINS(status.reason(), "Failed to parse options"); } TEST(RSRollbackTest, LocalEntryWithoutNsIsFatal) { @@ -2048,12 +2048,12 @@ TEST_F(RSRollbackTest, RollbackReturnsImmediatelyOnFailureToTransitionToRollback ASSERT_EQUALS(MemberState(MemberState::RS_SECONDARY), _coordinator->getMemberState()); } -DEATH_TEST_F(RSRollbackTest, - RollbackUnrecoverableRollbackErrorTriggersFatalAssertion, - "Unable to complete rollback. A full resync may be needed: " - "UnrecoverableRollbackError: need to rollback, but unable to determine common point " - "between local and remote oplog: InvalidSyncSource: remote oplog empty or unreadable " - "@ 18752") { +DEATH_TEST_F( + RSRollbackTest, + RollbackUnrecoverableRollbackErrorTriggersFatalAssertion, + "Unable to complete rollback. A full resync may be needed: " + "UnrecoverableRollbackError: need to rollback, but unable to determine common point " + "between local and remote oplog: InvalidSyncSource: remote oplog empty or unreadable") { // rollback() should abort on getting UnrecoverableRollbackError from syncRollback(). An empty // local oplog will make syncRollback() return the intended error. OplogInterfaceMock localOplogWithSingleOplogEntry({makeNoopOplogEntryAndRecordId(Seconds(1))}); diff --git a/src/mongo/db/storage/mmap_v1/btree/btree_logic.cpp b/src/mongo/db/storage/mmap_v1/btree/btree_logic.cpp index cb35765e131..c50a8c15162 100644 --- a/src/mongo/db/storage/mmap_v1/btree/btree_logic.cpp +++ b/src/mongo/db/storage/mmap_v1/btree/btree_logic.cpp @@ -1058,7 +1058,7 @@ Status BtreeLogic<BtreeLayout>::_find(OperationContext* opCtx, dupsCheckedYet = true; if (exists(opCtx, key)) { if (wouldCreateDup(opCtx, key, genericRecordLoc)) { - return Status(ErrorCodes::DuplicateKey, dupKeyError(key), 11000); + return Status(ErrorCodes::DuplicateKey, dupKeyError(key)); } else { return Status(ErrorCodes::DuplicateKeyValue, "key/value already in index"); @@ -1069,7 +1069,7 @@ Status BtreeLogic<BtreeLayout>::_find(OperationContext* opCtx, if (fullKey.recordLoc == recordLoc) { return Status(ErrorCodes::DuplicateKeyValue, "key/value already in index"); } else { - return Status(ErrorCodes::DuplicateKey, dupKeyError(key), 11000); + return Status(ErrorCodes::DuplicateKey, dupKeyError(key)); } } } diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp index 47b65e7dd16..6a3c02b562f 100644 --- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp +++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp @@ -105,8 +105,7 @@ StatusWith<DiskLoc> CappedRecordStoreV1::allocRecord(OperationContext* opCtx, ErrorCodes::DocTooLargeForCapped, mongoutils::str::stream() << "document is larger than capped size " << lenToAlloc << " > " - << storageSize(opCtx), - 16328); + << storageSize(opCtx)); } } DiskLoc loc; @@ -165,8 +164,7 @@ StatusWith<DiskLoc> CappedRecordStoreV1::allocRecord(OperationContext* opCtx, << " size: " << lenToAlloc << " storageSize:" - << storageSize(opCtx), - 28575); + << storageSize(opCtx)); } continue; } diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp index f12f3328e72..2d95e1dad13 100644 --- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp +++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp @@ -381,7 +381,7 @@ TEST(CappedRecordStoreV1, OversizedRecordHuge) { StatusWith<RecordId> status = rs.insertRecord(&opCtx, zeros, 16000, false); ASSERT_EQUALS(status.getStatus(), ErrorCodes::DocTooLargeForCapped); - ASSERT_EQUALS(status.getStatus().location(), 16328); + ASSERT_STRING_CONTAINS(status.getStatus().reason(), "larger than capped size"); } // Smaller than storageSize, but larger than usable space (fails late) @@ -403,7 +403,7 @@ TEST(CappedRecordStoreV1, OversizedRecordMedium) { StatusWith<RecordId> status = rs.insertRecord(&opCtx, zeros, 1004 - MmapV1RecordHeader::HeaderSize, false); ASSERT_EQUALS(status.getStatus(), ErrorCodes::DocTooLargeForCapped); - ASSERT_EQUALS(status.getStatus().location(), 28575); + ASSERT_STRING_CONTAINS(status.getStatus().reason(), "doesn't fit"); } // diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index db1d8c048f4..dcfc241e9a4 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -256,14 +256,15 @@ WiredTigerIndex::WiredTigerIndex(OperationContext* ctx, auto version = WiredTigerUtil::checkApplicationMetadataFormatVersion( ctx, uri, kMinimumIndexVersion, kMaximumIndexVersion); if (!version.isOK()) { - str::stream ss; Status versionStatus = version.getStatus(); - ss << versionStatus.reason() << " Index: {name: " << desc->indexName() - << ", ns: " << desc->parentNS() << "} - version too new for this mongod." - << " See http://dochub.mongodb.org/core/3.4-index-downgrade for detailed" - << " instructions on how to handle this error."; Status indexVersionStatus( - ErrorCodes::UnsupportedFormat, ss.ss.str(), versionStatus.location()); + ErrorCodes::UnsupportedFormat, + str::stream() << versionStatus.reason() << " Index: {name: " << desc->indexName() + << ", ns: " + << desc->parentNS() + << "} - version too new for this mongod." + << " See http://dochub.mongodb.org/core/3.4-index-downgrade for detailed" + << " instructions on how to handle this error."); fassertFailedWithStatusNoTrace(28579, indexVersionStatus); } _keyStringVersion = diff --git a/src/mongo/db/views/durable_view_catalog.cpp b/src/mongo/db/views/durable_view_catalog.cpp index 9426e941cf7..bfec32e9409 100644 --- a/src/mongo/db/views/durable_view_catalog.cpp +++ b/src/mongo/db/views/durable_view_catalog.cpp @@ -154,15 +154,14 @@ void DurableViewCatalogImpl::upsert(OperationContext* opCtx, args.fromMigrate = false; const bool assumeIndexesAreAffected = true; - auto res = systemViews->updateDocument(opCtx, - id, - oldView, - view, - enforceQuota, - assumeIndexesAreAffected, - &CurOp::get(opCtx)->debug(), - &args); - uassertStatusOK(res); + systemViews->updateDocument(opCtx, + id, + oldView, + view, + enforceQuota, + assumeIndexesAreAffected, + &CurOp::get(opCtx)->debug(), + &args); } } diff --git a/src/mongo/dbtests/multikey_paths_test.cpp b/src/mongo/dbtests/multikey_paths_test.cpp index 6caa614c495..ed64a4c3045 100644 --- a/src/mongo/dbtests/multikey_paths_test.cpp +++ b/src/mongo/dbtests/multikey_paths_test.cpp @@ -293,16 +293,15 @@ TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdate) { const bool indexesAffected = true; OpDebug* opDebug = nullptr; OplogUpdateEntryArgs args; - collection - ->updateDocument(_opCtx.get(), - record->id, - oldDoc, - BSON("_id" << 0 << "a" << 5 << "b" << BSON_ARRAY(1 << 2 << 3)), - enforceQuota, - indexesAffected, - opDebug, - &args) - .status_with_transitional_ignore(); + collection->updateDocument( + _opCtx.get(), + record->id, + oldDoc, + BSON("_id" << 0 << "a" << 5 << "b" << BSON_ARRAY(1 << 2 << 3)), + enforceQuota, + indexesAffected, + opDebug, + &args); wuow.commit(); } } diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp index 0663a1ce626..a66c4d5ab38 100644 --- a/src/mongo/dbtests/query_stage_count.cpp +++ b/src/mongo/dbtests/query_stage_count.cpp @@ -126,16 +126,14 @@ public: BSONObj oldDoc = _coll->getRecordStore()->dataFor(&_opCtx, oldrecordId).releaseToBson(); OplogUpdateEntryArgs args; args.nss = _coll->ns(); - _coll - ->updateDocument(&_opCtx, - oldrecordId, - Snapshotted<BSONObj>(_opCtx.recoveryUnit()->getSnapshotId(), oldDoc), - newDoc, - false, - true, - NULL, - &args) - .status_with_transitional_ignore(); + _coll->updateDocument(&_opCtx, + oldrecordId, + Snapshotted<BSONObj>(_opCtx.recoveryUnit()->getSnapshotId(), oldDoc), + newDoc, + false, + true, + NULL, + &args); wunit.commit(); } diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp index bb9082c81fb..2c698748b6c 100644 --- a/src/mongo/dbtests/query_stage_sort.cpp +++ b/src/mongo/dbtests/query_stage_sort.cpp @@ -350,18 +350,19 @@ public: set<RecordId>::iterator it = recordIds.begin(); Snapshotted<BSONObj> oldDoc = coll->docFor(&_opCtx, *it); - OID updatedId = oldDoc.value().getField("_id").OID(); - SnapshotId idBeforeUpdate = oldDoc.snapshotId(); + const OID updatedId = oldDoc.value().getField("_id").OID(); + const SnapshotId idBeforeUpdate = oldDoc.snapshotId(); // We purposefully update the document to have a 'foo' value greater than limit(). // This allows us to check that we don't return the new copy of a doc by asserting // foo < limit(). - BSONObj newDoc = BSON("_id" << updatedId << "foo" << limit() + 10); + auto newDoc = [&](const Snapshotted<BSONObj>& oldDoc) { + return BSON("_id" << oldDoc.value()["_id"] << "foo" << limit() + 10); + }; OplogUpdateEntryArgs args; args.nss = coll->ns(); { WriteUnitOfWork wuow(&_opCtx); - coll->updateDocument(&_opCtx, *it, oldDoc, newDoc, false, false, NULL, &args) - .status_with_transitional_ignore(); + coll->updateDocument(&_opCtx, *it, oldDoc, newDoc(oldDoc), false, false, NULL, &args); wuow.commit(); } exec->restoreState(); @@ -379,8 +380,8 @@ public: oldDoc = coll->docFor(&_opCtx, *it); { WriteUnitOfWork wuow(&_opCtx); - coll->updateDocument(&_opCtx, *it++, oldDoc, newDoc, false, false, NULL, &args) - .status_with_transitional_ignore(); + coll->updateDocument( + &_opCtx, *it++, oldDoc, newDoc(oldDoc), false, false, NULL, &args); wuow.commit(); } } diff --git a/src/mongo/logger/redaction.cpp b/src/mongo/logger/redaction.cpp index 1ec2d1e7cf9..3fff4974f35 100644 --- a/src/mongo/logger/redaction.cpp +++ b/src/mongo/logger/redaction.cpp @@ -65,8 +65,6 @@ std::string redact(const Status& statusToRedact) { sb << statusToRedact.codeString(); if (!statusToRedact.isOK()) sb << ": " << kRedactionDefaultMask; - if (statusToRedact.location() != 0) - sb << " @ " << statusToRedact.location(); return sb.str(); } diff --git a/src/mongo/logger/redaction_test.cpp b/src/mongo/logger/redaction_test.cpp index 46c140eefb8..da8abc4ee96 100644 --- a/src/mongo/logger/redaction_test.cpp +++ b/src/mongo/logger/redaction_test.cpp @@ -46,12 +46,6 @@ TEST(RedactStatusTest, BasicStatus) { ASSERT_EQ(redact(status), "InternalError: " + kRedactionDefaultMask); } -TEST(RedactStatusTest, StatusWithLocation) { - logger::globalLogDomain()->setShouldRedactLogs(true); - Status status(ErrorCodes::InternalError, kMsg, 777); - ASSERT_EQ(redact(status), "InternalError: " + kRedactionDefaultMask + " @ 777"); -} - TEST(RedactStatusTest, StatusOK) { logger::globalLogDomain()->setShouldRedactLogs(true); ASSERT_EQ(redact(Status::OK()), "OK"); diff --git a/src/mongo/s/client/shard_remote.cpp b/src/mongo/s/client/shard_remote.cpp index e75af4c8554..4617ef23f50 100644 --- a/src/mongo/s/client/shard_remote.cpp +++ b/src/mongo/s/client/shard_remote.cpp @@ -336,7 +336,7 @@ StatusWith<Shard::QueryResponse> ShardRemote::_exhaustiveFindOnConfig( updateReplSetMonitor(host.getValue(), status); if (!status.isOK()) { - if (status.compareCode(ErrorCodes::ExceededTimeLimit)) { + if (status == ErrorCodes::ExceededTimeLimit) { LOG(0) << "Operation timed out " << causedBy(status); } return status; diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h index 99440a57503..f0f9e42424d 100644 --- a/src/mongo/util/assert_util.h +++ b/src/mongo/util/assert_util.h @@ -322,10 +322,7 @@ inline void fassertNoTraceWithLocation(int msgid, ::mongo::uassertStatusOKWithLocation(__VA_ARGS__, __FILE__, __LINE__) inline void uassertStatusOKWithLocation(const Status& status, const char* file, unsigned line) { if (MONGO_unlikely(!status.isOK())) { - uassertedWithLocation((status.location() != 0 ? status.location() : status.code()), - status.reason(), - file, - line); + uassertedWithLocation(status.code(), status.reason(), file, line); } } @@ -386,10 +383,7 @@ inline void fassertStatusOKWithLocation(int msgid, ::mongo::massertStatusOKWithLocation(__VA_ARGS__, __FILE__, __LINE__) inline void massertStatusOKWithLocation(const Status& status, const char* file, unsigned line) { if (MONGO_unlikely(!status.isOK())) { - msgassertedWithLocation((status.location() != 0 ? status.location() : status.code()), - status.reason(), - file, - line); + msgassertedWithLocation(status.code(), status.reason(), file, line); } } @@ -401,11 +395,7 @@ inline void massertNoTraceStatusOKWithLocation(const Status& status, unsigned line) { if (MONGO_unlikely(!status.isOK())) { [&]() MONGO_COMPILER_COLD_FUNCTION { - msgassertedNoTraceWithLocation( - (status.location() != 0 ? status.location() : status.code()), - status.reason(), - file, - line); + msgassertedNoTraceWithLocation(status.code(), status.reason(), file, line); }(); MONGO_COMPILER_UNREACHABLE; } |