diff options
author | Amirsaman Memaripour <amirsaman.memaripour@mongodb.com> | 2022-05-10 17:33:32 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-10 20:50:30 +0000 |
commit | 8113aef47fab9d0d14c953b78032ab1661360438 (patch) | |
tree | 361fb0dcddab375966cce82d5accd751bd878c65 /src | |
parent | 589aa86a047d5f3d34294e054cd7b41cd74d9590 (diff) | |
download | mongo-8113aef47fab9d0d14c953b78032ab1661360438.tar.gz |
SERVER-66205 Merge `WriteConflictException` and `TemporarilyUnavailableException` into `assert_util.h`
Diffstat (limited to 'src')
59 files changed, 142 insertions, 273 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index ed4abf47767..8696da79339 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -160,7 +160,6 @@ baseEnv.Library( 'bson/simple_bsonobj_comparator.cpp', 'bson/timestamp.cpp', 'bson/util/builder.cpp', - 'db/concurrency/write_conflict_exception.cpp', 'logv2/attributes.cpp', 'logv2/bson_formatter.cpp', 'logv2/console.cpp', diff --git a/src/mongo/base/error_codes.tpl.cpp b/src/mongo/base/error_codes.tpl.cpp index bd2071c2627..a51621590c5 100644 --- a/src/mongo/base/error_codes.tpl.cpp +++ b/src/mongo/base/error_codes.tpl.cpp @@ -32,8 +32,6 @@ #include "mongo/base/error_codes.h" #include "mongo/base/static_assert.h" -#include "mongo/db/concurrency/temporarily_unavailable_exception.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/util/assert_util.h" #include "mongo/util/str.h" diff --git a/src/mongo/db/catalog/collection_catalog.cpp b/src/mongo/db/catalog/collection_catalog.cpp index 2c6daea298d..ba7ad287051 100644 --- a/src/mongo/db/catalog/collection_catalog.cpp +++ b/src/mongo/db/catalog/collection_catalog.cpp @@ -33,8 +33,8 @@ #include "mongo/db/catalog/database.h" #include "mongo/db/catalog/uncommitted_catalog_updates.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/concurrency/lock_manager_defs.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/server_options.h" #include "mongo/db/storage/recovery_unit.h" #include "mongo/db/storage/snapshot_helper.h" @@ -1252,7 +1252,7 @@ void CollectionCatalog::_ensureNamespaceDoesNotExist(OperationContext* opCtx, LOGV2(5725001, "Conflicted registering namespace, already have a collection with the same namespace", "nss"_attr = nss); - throw WriteConflictException(); + throwWriteConflictException(); } if (type == NamespaceType::kAll) { @@ -1260,7 +1260,7 @@ void CollectionCatalog::_ensureNamespaceDoesNotExist(OperationContext* opCtx, LOGV2(5725002, "Conflicted registering namespace, already have a view with the same namespace", "nss"_attr = nss); - throw WriteConflictException(); + throwWriteConflictException(); } if (auto viewsForDb = _getViewsForDatabase(opCtx, DatabaseName(boost::none, nss.db()))) { diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index d98d0eb19fb..a920e11d85c 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -49,7 +49,7 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/commands/server_status_metric.h" #include "mongo/db/concurrency/d_concurrency.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" @@ -931,7 +931,7 @@ Status CollectionImpl::insertDocumentForBulkLoader( "Failpoint failAfterBulkLoadDocInsert enabled. Throwing " "WriteConflictException", logAttrs(_ns)); - throw WriteConflictException(); + throwWriteConflictException(); } std::vector<InsertStatement> inserts; diff --git a/src/mongo/db/catalog/collection_test.cpp b/src/mongo/db/catalog/collection_test.cpp index 4b70b4489f2..3037e9c23ea 100644 --- a/src/mongo/db/catalog/collection_test.cpp +++ b/src/mongo/db/catalog/collection_test.cpp @@ -37,11 +37,11 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/collection_mock.h" #include "mongo/db/catalog/collection_validation.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/db_raii.h" #include "mongo/db/repl/storage_interface_impl.h" #include "mongo/stdx/thread.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" #include "mongo/util/fail_point.h" #define ASSERT_ID_EQ(EXPR, ID) \ diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index f2891a24585..573ed2be469 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -52,7 +52,7 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/commands/feature_compatibility_version_parser.h" #include "mongo/db/concurrency/d_concurrency.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index_builds_coordinator.h" @@ -747,7 +747,7 @@ void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx, str::stream() << "Cannot create collection " << nss << " - collection already exists."); } else { - throw WriteConflictException(); + throwWriteConflictException(); } } @@ -755,7 +755,7 @@ void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx, opCtx->inMultiDocumentTransaction()) { LOGV2(4696600, "Throwing WriteConflictException due to failpoint 'throwWCEDuringTxnCollCreate'"); - throw WriteConflictException(); + throwWriteConflictException(); } uassert(28838, "cannot create a non-capped oplog collection", options.capped || !nss.isOplog()); diff --git a/src/mongo/db/catalog/multi_index_block_test.cpp b/src/mongo/db/catalog/multi_index_block_test.cpp index 2fb9caf7371..33874c6e92a 100644 --- a/src/mongo/db/catalog/multi_index_block_test.cpp +++ b/src/mongo/db/catalog/multi_index_block_test.cpp @@ -33,7 +33,7 @@ #include "mongo/db/catalog/catalog_test_fixture.h" #include "mongo/db/catalog_raii.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/unittest/unittest.h" @@ -176,7 +176,7 @@ TEST_F(MultiIndexBlockTest, InitWriteConflictException) { coll, {spec}, [](std::vector<BSONObj>& specs) -> Status { - throw WriteConflictException(); + throwWriteConflictException(); }), DBException, ErrorCodes::WriteConflict); diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp index 623662bb041..38066226874 100644 --- a/src/mongo/db/catalog/rename_collection.cpp +++ b/src/mongo/db/catalog/rename_collection.cpp @@ -716,7 +716,7 @@ Status renameBetweenDBs(OperationContext* opCtx, // Used to make sure that a WCE can be handled by this logic without data loss. if (MONGO_unlikely(writeConflictInRenameCollCopyToTmp.shouldFail())) { - throw WriteConflictException(); + throwWriteConflictException(); } wunit.commit(); diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp index 787d027a184..56fe8853d06 100644 --- a/src/mongo/db/commands/create_indexes.cpp +++ b/src/mongo/db/commands/create_indexes.cpp @@ -398,7 +398,7 @@ CreateIndexesReply runCreateIndexesOnNewCollection( createCollection(opCtx, ns.db().toString(), builder.obj().getOwned(), idIndexSpec); if (createStatus == ErrorCodes::NamespaceExists) { - throw WriteConflictException( + throwWriteConflictException( str::stream() << "Failed to create indexes on new collection: namespace "_sd << ns.ns() << " exists. Status: "_sd << createStatus.toString()); } @@ -433,7 +433,7 @@ CreateIndexesReply runCreateIndexesOnNewCollection( const int numIndexesAfter = IndexBuildsCoordinator::getNumIndexesTotal(opCtx, collection.get()); if (MONGO_unlikely(createIndexesWriteConflict.shouldFail())) { - throw WriteConflictException(); + throwWriteConflictException(); } wunit.commit(); diff --git a/src/mongo/db/commands/parameters.idl b/src/mongo/db/commands/parameters.idl index b2b378ac049..95409832661 100644 --- a/src/mongo/db/commands/parameters.idl +++ b/src/mongo/db/commands/parameters.idl @@ -45,6 +45,11 @@ server_parameters: set_at: runtime cpp_varname: "DBException::traceExceptions" + traceWriteConflictExceptions: + description: "Call printStackTrace on every WriteConflictException created" + set_at: ["startup", "runtime"] + cpp_varname: "DBException::traceWriteConflictExceptions" + logLevel: description: "Specifies the verbosity of logging" set_at: ["startup", "runtime"] diff --git a/src/mongo/db/concurrency/d_concurrency_test.cpp b/src/mongo/db/concurrency/d_concurrency_test.cpp index 90473d76edf..16ce4092f1b 100644 --- a/src/mongo/db/concurrency/d_concurrency_test.cpp +++ b/src/mongo/db/concurrency/d_concurrency_test.cpp @@ -150,7 +150,7 @@ TEST_F(DConcurrencyTestFixture, WriteConflictRetryRetriesFunctionOnWriteConflict ASSERT_EQUALS(0, opDebug.additiveMetrics.writeConflicts.load()); ASSERT_EQUALS(100, writeConflictRetry(opCtx.get(), "", "", [&opDebug] { if (0 == opDebug.additiveMetrics.writeConflicts.load()) { - throw WriteConflictException(); + throwWriteConflictException(); } return 100; })); @@ -177,7 +177,7 @@ TEST_F(DConcurrencyTestFixture, getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::GlobalWrite globalWrite(opCtx.get()); WriteUnitOfWork wuow(opCtx.get()); - ASSERT_THROWS(writeConflictRetry(opCtx.get(), "", "", [] { throw WriteConflictException(); }), + ASSERT_THROWS(writeConflictRetry(opCtx.get(), "", "", [] { throwWriteConflictException(); }), WriteConflictException); } diff --git a/src/mongo/db/concurrency/exception_util.cpp b/src/mongo/db/concurrency/exception_util.cpp index 95242d3e299..989cf54b320 100644 --- a/src/mongo/db/concurrency/exception_util.cpp +++ b/src/mongo/db/concurrency/exception_util.cpp @@ -32,6 +32,7 @@ #include "mongo/base/counter.h" #include "mongo/db/commands/server_status_metric.h" +#include "mongo/db/concurrency/exception_util_gen.h" #include "mongo/db/namespace_string.h" #include "mongo/logv2/log.h" #include "mongo/util/duration.h" @@ -78,7 +79,7 @@ void handleTemporarilyUnavailableException(OperationContext* opCtx, opCtx->recoveryUnit()->abandonSnapshot(); temporarilyUnavailableErrors.increment(1); if (opCtx->getClient()->isFromUserConnection() && - attempts > TemporarilyUnavailableException::maxRetryAttempts.load()) { + attempts > gTemporarilyUnavailableExceptionMaxRetryAttempts.load()) { LOGV2_DEBUG(6083901, 1, "Too many TemporarilyUnavailableException's, giving up", @@ -92,7 +93,7 @@ void handleTemporarilyUnavailableException(OperationContext* opCtx, // Back off linearly with the retry attempt number. auto sleepFor = - Milliseconds(TemporarilyUnavailableException::retryBackoffBaseMs.load()) * attempts; + Milliseconds(gTemporarilyUnavailableExceptionRetryBackoffBaseMs.load()) * attempts; LOGV2_DEBUG(6083900, 1, "Caught TemporarilyUnavailableException", @@ -113,7 +114,7 @@ void handleTemporarilyUnavailableExceptionInTransaction(OperationContext* opCtx, // transactions to retry without changing any behavior. Otherwise, we let the error escape as // usual. temporarilyUnavailableErrorsConvertedToWriteConflict.increment(1); - throw WriteConflictException(e.reason()); + throwWriteConflictException(e.reason()); } } // namespace mongo diff --git a/src/mongo/db/concurrency/exception_util.h b/src/mongo/db/concurrency/exception_util.h index 718ee08339f..6cfe238ca7d 100644 --- a/src/mongo/db/concurrency/exception_util.h +++ b/src/mongo/db/concurrency/exception_util.h @@ -30,8 +30,6 @@ #pragma once #include "mongo/base/string_data.h" -#include "mongo/db/concurrency/temporarily_unavailable_exception.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" #include "mongo/db/operation_context.h" #include "mongo/util/assert_util.h" @@ -64,6 +62,30 @@ void handleTemporarilyUnavailableExceptionInTransaction(OperationContext* opCtx, const TemporarilyUnavailableException& e); /** + * A `WriteConflictException` is thrown if during a write, two or more operations conflict with each + * other. For example if two operations get the same version of a document, and then both try to + * modify that document, this exception will get thrown by one of them. + */ +[[noreturn]] inline void throwWriteConflictException(StringData context = {}) { + Status status{ErrorCodes::WriteConflict, + "WriteConflict error: this operation conflicted with another operation. " + "Please retry your operation or multi-document transaction."_sd}; + if (!context.empty()) + status.addContext(context); + iasserted(status); +} + +/** + * A `TemporarilyUnavailableException` is thrown if an operation aborts due to the server being + * temporarily unavailable, e.g. due to excessive load. For user-originating operations, this will + * be retried internally by the `writeConflictRetry` helper a finite number of times before + * eventually being returned. + */ +[[noreturn]] inline void throwTemporarilyUnavailableException(StringData context) { + iasserted({ErrorCodes::TemporarilyUnavailable, context}); +} + +/** * Runs the argument function f as many times as needed for f to complete or throw an exception * other than WriteConflictException or TemporarilyUnavailableException. For each time f throws an * one of these exceptions, logs the error, waits a spell, cleans up, and then tries f again. diff --git a/src/mongo/db/concurrency/exception_util.idl b/src/mongo/db/concurrency/exception_util.idl index 200ce5c75a1..29339e762c2 100644 --- a/src/mongo/db/concurrency/exception_util.idl +++ b/src/mongo/db/concurrency/exception_util.idl @@ -28,16 +28,8 @@ global: cpp_namespace: "mongo" - cpp_includes: - - "mongo/db/concurrency/temporarily_unavailable_exception.h" - - "mongo/db/concurrency/write_conflict_exception.h" server_parameters: - traceWriteConflictExceptions: - description: 'Call printStackTrace on every WriteConflictException created' - set_at: [ startup, runtime ] - cpp_varname: 'WriteConflictException::trace' - enableTemporarilyUnavailableExceptions: description: 'Enables the use of TemporarilyUnavailableExceptions. When disabled, reverts to throwing WriteConflictException.' @@ -49,7 +41,8 @@ server_parameters: temporarilyUnavailableMaxRetries: description: 'The number of times to retry a TemporarilyUnavailable error internally' set_at: [ startup, runtime ] - cpp_varname: 'TemporarilyUnavailableException::maxRetryAttempts' + cpp_varname: 'gTemporarilyUnavailableExceptionMaxRetryAttempts' + cpp_vartype: AtomicWord<long long> default: 10 validator: gte: 0 @@ -59,7 +52,8 @@ server_parameters: attempt. The backoff time is linear such that the Nth retry waits for N times the base backoff period.' set_at: [ startup, runtime ] - cpp_varname: 'TemporarilyUnavailableException::retryBackoffBaseMs' + cpp_varname: 'gTemporarilyUnavailableExceptionRetryBackoffBaseMs' + cpp_vartype: AtomicWord<long long> default: 1000 validator: gte: 0 diff --git a/src/mongo/db/concurrency/temporarily_unavailable_exception.h b/src/mongo/db/concurrency/temporarily_unavailable_exception.h deleted file mode 100644 index d58f743b04f..00000000000 --- a/src/mongo/db/concurrency/temporarily_unavailable_exception.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2022-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_codes.h" -#include "mongo/base/string_data.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/util/assert_util.h" - -namespace mongo { - -/** - * This exception is thrown if an operation aborts due to the server being temporarily - * unavailable, e.g. due to excessive load. For user-originating operations, this will be retried - * internally by the writeConflictRetry helper a finite number of times before eventually being - * returned. - */ -class TemporarilyUnavailableException final : public DBException { -public: - // These are initialized by IDL as server parameters. - static inline AtomicWord<long long> maxRetryAttempts; - static inline AtomicWord<long long> retryBackoffBaseMs; - - TemporarilyUnavailableException(StringData context) - : DBException({ErrorCodes::TemporarilyUnavailable, context}) {} - - TemporarilyUnavailableException(const Status& status) : DBException(status) {} - -private: - void defineOnlyInFinalSubclassToPreventSlicing() final {} -}; - -} // namespace mongo diff --git a/src/mongo/db/concurrency/write_conflict_exception.cpp b/src/mongo/db/concurrency/write_conflict_exception.cpp deleted file mode 100644 index d5d40dbc4da..00000000000 --- a/src/mongo/db/concurrency/write_conflict_exception.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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/db/concurrency/write_conflict_exception.h" - -#include "mongo/base/error_codes.h" -#include "mongo/util/stacktrace.h" - -namespace mongo { - -WriteConflictException::WriteConflictException() - : DBException(Status(ErrorCodes::WriteConflict, - "WriteConflict error: this operation conflicted with another operation. " - "Please retry your operation or multi-document transaction.")) { - if (trace.load()) { - printStackTrace(); - } -} - -} // namespace mongo diff --git a/src/mongo/db/concurrency/write_conflict_exception.h b/src/mongo/db/concurrency/write_conflict_exception.h deleted file mode 100644 index bc95825a131..00000000000 --- a/src/mongo/db/concurrency/write_conflict_exception.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * 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/string_data.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/util/assert_util.h" - -namespace mongo { - -/** - * This is thrown if during a write, two or more operations conflict with each other. - * For example if two operations get the same version of a document, and then both try to - * modify that document, this exception will get thrown by one of them. - */ -class WriteConflictException final : public DBException { -public: - WriteConflictException(); - - WriteConflictException(StringData context) : WriteConflictException() { - // Avoid unnecessary update to embedded Status within DBException. - if (context.empty()) { - return; - } - addContext(context); - } - - WriteConflictException(const Status& status) : DBException(status) {} - - /** - * If true, will call printStackTrace on every WriteConflictException created. - * Can be set via setParameter named traceWriteConflictExceptions. - */ - static inline AtomicWord<bool> trace{false}; - -private: - void defineOnlyInFinalSubclassToPreventSlicing() final {} -}; - -} // namespace mongo diff --git a/src/mongo/db/exec/batched_delete_stage.cpp b/src/mongo/db/exec/batched_delete_stage.cpp index 32f5bfe5d99..8b66cc8143f 100644 --- a/src/mongo/db/exec/batched_delete_stage.cpp +++ b/src/mongo/db/exec/batched_delete_stage.cpp @@ -34,7 +34,7 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/commands/server_status.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" @@ -279,7 +279,7 @@ PlanStage::StageState BatchedDeleteStage::_deleteBatch(WorkingSetID* out) { bool groupedWuowActive = true; for (; bufferOffset < _stagedDeletesBuffer.size(); ++bufferOffset) { if (MONGO_unlikely(throwWriteConflictExceptionInBatchedDeleteStage.shouldFail())) { - throw WriteConflictException(); + throwWriteConflictException(); } auto workingSetMemberID = _stagedDeletesBuffer.at(bufferOffset); diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp index 67197c174ea..43d1e10c3b4 100644 --- a/src/mongo/db/exec/cached_plan.cpp +++ b/src/mongo/db/exec/cached_plan.cpp @@ -35,7 +35,7 @@ #include <memory> #include "mongo/db/catalog/collection.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/exec/multi_plan.h" #include "mongo/db/exec/plan_cache_util.h" #include "mongo/db/exec/scoped_timer.h" @@ -145,7 +145,7 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { } else if (PlanStage::NEED_YIELD == state) { invariant(id == WorkingSet::INVALID_ID); if (!yieldPolicy->canAutoYield()) { - throw WriteConflictException(); + throwWriteConflictException(); } if (yieldPolicy->canAutoYield()) { diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp index 51e06abbace..b8f0df82dcd 100644 --- a/src/mongo/db/exec/collection_scan.cpp +++ b/src/mongo/db/exec/collection_scan.cpp @@ -35,7 +35,6 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/collection_scan_common.h" #include "mongo/db/exec/filter.h" #include "mongo/db/exec/scoped_timer.h" @@ -44,6 +43,7 @@ #include "mongo/db/record_id_helpers.h" #include "mongo/db/repl/optime.h" #include "mongo/logv2/log.h" +#include "mongo/util/assert_util.h" #include "mongo/util/fail_point.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery diff --git a/src/mongo/db/exec/count_scan.cpp b/src/mongo/db/exec/count_scan.cpp index b37ac05a2d6..5a6c8aafe94 100644 --- a/src/mongo/db/exec/count_scan.cpp +++ b/src/mongo/db/exec/count_scan.cpp @@ -32,9 +32,9 @@ #include <memory> #include "mongo/db/catalog/index_catalog.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/index/index_access_method.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/exec/delete_stage.cpp b/src/mongo/db/exec/delete_stage.cpp index 43150dec4c9..75ae33e9dc8 100644 --- a/src/mongo/db/exec/delete_stage.cpp +++ b/src/mongo/db/exec/delete_stage.cpp @@ -33,7 +33,7 @@ #include "mongo/db/exec/delete_stage.h" #include "mongo/db/catalog/collection.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" @@ -173,7 +173,7 @@ PlanStage::StageState DeleteStage::doWork(WorkingSetID* out) { // Either the document has already been deleted, or it has been updated such that it no // longer matches the predicate. if (shouldRestartDeleteIfNoLongerMatches(_params.get())) { - throw WriteConflictException(); + throwWriteConflictException(); } return PlanStage::NEED_TIME; } diff --git a/src/mongo/db/exec/distinct_scan.cpp b/src/mongo/db/exec/distinct_scan.cpp index 7be30af453a..59afba20815 100644 --- a/src/mongo/db/exec/distinct_scan.cpp +++ b/src/mongo/db/exec/distinct_scan.cpp @@ -32,11 +32,11 @@ #include <memory> #include "mongo/db/catalog/index_catalog.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/filter.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/exec/fetch.cpp b/src/mongo/db/exec/fetch.cpp index 9d51dad5ca4..32ea838220f 100644 --- a/src/mongo/db/exec/fetch.cpp +++ b/src/mongo/db/exec/fetch.cpp @@ -34,10 +34,10 @@ #include <memory> #include "mongo/db/catalog/collection.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/filter.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/util/assert_util.h" #include "mongo/util/fail_point.h" #include "mongo/util/str.h" diff --git a/src/mongo/db/exec/idhack.cpp b/src/mongo/db/exec/idhack.cpp index 091a1a5381e..9cdc9f9efa2 100644 --- a/src/mongo/db/exec/idhack.cpp +++ b/src/mongo/db/exec/idhack.cpp @@ -34,12 +34,12 @@ #include <memory> #include "mongo/db/catalog/index_catalog.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/index_scan.h" #include "mongo/db/exec/projection.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/index/btree_access_method.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/exec/index_scan.cpp b/src/mongo/db/exec/index_scan.cpp index 9b9c4455d96..86e585b0285 100644 --- a/src/mongo/db/exec/index_scan.cpp +++ b/src/mongo/db/exec/index_scan.cpp @@ -35,12 +35,12 @@ #include <memory> #include "mongo/db/catalog/index_catalog.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/filter.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index_names.h" #include "mongo/db/query/index_bounds_builder.h" +#include "mongo/util/assert_util.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery diff --git a/src/mongo/db/exec/multi_iterator.cpp b/src/mongo/db/exec/multi_iterator.cpp index ca6dfe67210..77ed0ced99a 100644 --- a/src/mongo/db/exec/multi_iterator.cpp +++ b/src/mongo/db/exec/multi_iterator.cpp @@ -33,8 +33,8 @@ #include <memory> -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index 397393c8cd5..1db8860dc2e 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -38,7 +38,7 @@ #include "mongo/db/catalog/database.h" #include "mongo/db/client.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/exec/histogram_server_status_metric.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/trial_period_utils.h" @@ -338,7 +338,7 @@ bool MultiPlanStage::workAllPlans(size_t numResults, PlanYieldPolicy* yieldPolic } else if (PlanStage::NEED_YIELD == state) { invariant(id == WorkingSet::INVALID_ID); if (!yieldPolicy->canAutoYield()) { - throw WriteConflictException(); + throwWriteConflictException(); } if (yieldPolicy->canAutoYield()) { diff --git a/src/mongo/db/exec/text_or.cpp b/src/mongo/db/exec/text_or.cpp index a0ba3eb347e..28f9397cd31 100644 --- a/src/mongo/db/exec/text_or.cpp +++ b/src/mongo/db/exec/text_or.cpp @@ -33,7 +33,6 @@ #include <memory> #include <vector> -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/filter.h" #include "mongo/db/exec/index_scan.h" #include "mongo/db/exec/scoped_timer.h" @@ -41,6 +40,7 @@ #include "mongo/db/exec/working_set_common.h" #include "mongo/db/jsobj.h" #include "mongo/db/record_id.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/exec/trial_stage.cpp b/src/mongo/db/exec/trial_stage.cpp index 66442c21eda..0ab003df090 100644 --- a/src/mongo/db/exec/trial_stage.cpp +++ b/src/mongo/db/exec/trial_stage.cpp @@ -34,7 +34,7 @@ #include <algorithm> #include <memory> -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/exec/or.h" #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/exec/working_set_common.h" @@ -75,7 +75,7 @@ Status TrialStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { const bool mustYield = (work(&id) == PlanStage::NEED_YIELD); if (mustYield || yieldPolicy->shouldYieldOrInterrupt(expCtx()->opCtx)) { if (mustYield && !yieldPolicy->canAutoYield()) { - throw WriteConflictException(); + throwWriteConflictException(); } auto yieldStatus = yieldPolicy->yieldOrInterrupt(expCtx()->opCtx); if (!yieldStatus.isOK()) { diff --git a/src/mongo/db/exec/update_stage.cpp b/src/mongo/db/exec/update_stage.cpp index 500ba42ca1f..74dc3aaba5a 100644 --- a/src/mongo/db/exec/update_stage.cpp +++ b/src/mongo/db/exec/update_stage.cpp @@ -39,7 +39,7 @@ #include "mongo/bson/bson_comparator_interface_base.h" #include "mongo/bson/mutable/algorithm.h" #include "mongo/db/catalog/document_validation.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/shard_filterer_impl.h" #include "mongo/db/exec/working_set_common.h" @@ -454,7 +454,7 @@ PlanStage::StageState UpdateStage::doWork(WorkingSetID* out) { // Either the document has been deleted, or it has been updated such that it no longer // matches the predicate. if (shouldRestartUpdateIfNoLongerMatches(_params)) { - throw WriteConflictException(); + throwWriteConflictException(); } return PlanStage::NEED_TIME; } diff --git a/src/mongo/db/query/plan_executor_impl.cpp b/src/mongo/db/query/plan_executor_impl.cpp index 47eb8935927..76559f3d003 100644 --- a/src/mongo/db/query/plan_executor_impl.cpp +++ b/src/mongo/db/query/plan_executor_impl.cpp @@ -37,7 +37,6 @@ #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/concurrency/exception_util.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" #include "mongo/db/exec/cached_plan.h" #include "mongo/db/exec/collection_scan.h" @@ -425,7 +424,7 @@ PlanExecutor::ExecState PlanExecutorImpl::_getNextImpl(Snapshotted<Document>* ob invariant(id == WorkingSet::INVALID_ID); if (!_yieldPolicy->canAutoYield() || MONGO_unlikely(skipWriteConflictRetries.shouldFail())) { - throw WriteConflictException(); + throwWriteConflictException(); } CurOp::get(_opCtx)->debug().additiveMetrics.incrementWriteConflicts(1); diff --git a/src/mongo/db/query/plan_yield_policy.cpp b/src/mongo/db/query/plan_yield_policy.cpp index b19edc274f1..545460f083e 100644 --- a/src/mongo/db/query/plan_yield_policy.cpp +++ b/src/mongo/db/query/plan_yield_policy.cpp @@ -33,8 +33,8 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/concurrency/exception_util.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/operation_context.h" +#include "mongo/util/assert_util.h" #include "mongo/util/scopeguard.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index ff034ab3575..3cbb52cc972 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -304,7 +304,7 @@ void writeToImageCollection(OperationContext* opCtx, } catch (const ExceptionFor<ErrorCodes::DuplicateKey>&) { // We can get a duplicate key when two upserts race on inserting a document. *upsertConfigImage = false; - throw WriteConflictException(); + throwWriteConflictException(); } } @@ -1919,7 +1919,7 @@ Status applyCommand_inlock(OperationContext* opCtx, case ErrorCodes::WriteConflict: { // Need to throw this up to a higher level where it will be caught and the // operation retried. - throw WriteConflictException(); + throwWriteConflictException(); } case ErrorCodes::BackgroundOperationInProgressForDatabase: { invariant(mode == OplogApplication::Mode::kInitialSync); diff --git a/src/mongo/db/repl/oplog_applier_utils.cpp b/src/mongo/db/repl/oplog_applier_utils.cpp index 44d115b79da..7c5c78a63dc 100644 --- a/src/mongo/db/repl/oplog_applier_utils.cpp +++ b/src/mongo/db/repl/oplog_applier_utils.cpp @@ -241,7 +241,7 @@ Status OplogApplierUtils::applyOplogEntryOrGroupedInsertsCommon( isDataConsistent, incrementOpsAppliedStats); if (!status.isOK() && status.code() == ErrorCodes::WriteConflict) { - throw WriteConflictException(); + throwWriteConflictException(); } return status; } catch (ExceptionFor<ErrorCodes::NamespaceNotFound>& ex) { diff --git a/src/mongo/db/repl/transaction_oplog_application.cpp b/src/mongo/db/repl/transaction_oplog_application.cpp index 4c551bd6187..d55bcdbd710 100644 --- a/src/mongo/db/repl/transaction_oplog_application.cpp +++ b/src/mongo/db/repl/transaction_oplog_application.cpp @@ -489,7 +489,7 @@ Status _applyPrepareTransaction(OperationContext* opCtx, } if (status == ErrorCodes::WriteConflict) { - throw WriteConflictException(); + throwWriteConflictException(); } fassert(31137, status); diff --git a/src/mongo/db/s/config/sharding_catalog_manager_bump_collection_version_and_change_metadata_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_bump_collection_version_and_change_metadata_test.cpp index c921f7507a1..ab5fced5419 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_bump_collection_version_and_change_metadata_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_bump_collection_version_and_change_metadata_test.cpp @@ -29,7 +29,7 @@ #include "mongo/platform/basic.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/logical_session_cache_noop.h" #include "mongo/db/repl/wait_for_majority_service.h" @@ -199,7 +199,7 @@ TEST_F(ShardingCatalogManagerBumpCollectionVersionAndChangeMetadataTest, operationContext(), kNss, [&](OperationContext*, TxnNumber) { ++numCalls; if (numCalls < 5) { - throw WriteConflictException(); + throwWriteConflictException(); } }); diff --git a/src/mongo/db/s/range_deletion_util.cpp b/src/mongo/db/s/range_deletion_util.cpp index 92d388f8748..8bf9d4e65eb 100644 --- a/src/mongo/db/s/range_deletion_util.cpp +++ b/src/mongo/db/s/range_deletion_util.cpp @@ -194,7 +194,7 @@ StatusWith<int> deleteNextBatch(OperationContext* opCtx, BSONObj deletedObj; if (throwWriteConflictExceptionInDeleteRange.shouldFail()) { - throw WriteConflictException(); + throwWriteConflictException(); } if (throwInternalErrorInDeleteRange.shouldFail()) { diff --git a/src/mongo/db/s/resharding/resharding_oplog_application.cpp b/src/mongo/db/s/resharding/resharding_oplog_application.cpp index 6b1a1b1882f..139357b11de 100644 --- a/src/mongo/db/s/resharding/resharding_oplog_application.cpp +++ b/src/mongo/db/s/resharding/resharding_oplog_application.cpp @@ -216,7 +216,7 @@ Status ReshardingOplogApplicationRules::applyOperation(OperationContext* opCtx, return Status::OK(); } catch (const DBException& ex) { if (ex.code() == ErrorCodes::WriteConflict || ex.code() == ErrorCodes::LockTimeout) { - throw WriteConflictException(); + throwWriteConflictException(); } return ex.toStatus(); diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp index 41ae75e0626..b31b7c44173 100644 --- a/src/mongo/db/storage/durable_catalog_impl.cpp +++ b/src/mongo/db/storage/durable_catalog_impl.cpp @@ -37,7 +37,7 @@ #include "mongo/bson/util/bson_extract.h" #include "mongo/bson/util/builder.h" #include "mongo/db/concurrency/d_concurrency.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" @@ -599,7 +599,7 @@ StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> DurableCatalogImpl invariant(nss.coll().size() > 0); if (CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss)) { - throw WriteConflictException(); + throwWriteConflictException(); } StatusWith<Entry> swEntry = _addEntry(opCtx, nss, options); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_column_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_column_store.cpp index e36f3d9a1da..db5933605ab 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_column_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_column_store.cpp @@ -30,7 +30,6 @@ #include "mongo/platform/basic.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/global_settings.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/storage/wiredtiger/wiredtiger_column_store.h" diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index 68f6395d482..7f572360979 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -39,7 +39,6 @@ #include "mongo/base/checked_cast.h" #include "mongo/db/catalog/index_catalog_entry.h" #include "mongo/db/catalog/validate_results.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/global_settings.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/json.h" diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp index 2d0acf965da..296e1873756 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp @@ -60,8 +60,8 @@ #include "mongo/db/catalog/collection_catalog.h" #include "mongo/db/client.h" #include "mongo/db/commands/server_status_metric.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/concurrency/locker.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/global_settings.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/mongod_options_storage_gen.h" @@ -1469,7 +1469,7 @@ Status WiredTigerKVEngine::importRecordStore(OperationContext* opCtx, "Failpoint WTWriteConflictExceptionForImportCollection enabled. Throwing " "WriteConflictException", "ident"_attr = ident); - throw WriteConflictException(); + throwWriteConflictException(); } std::string config = uassertStatusOK( @@ -1678,7 +1678,7 @@ Status WiredTigerKVEngine::importSortedDataInterface(OperationContext* opCtx, "Failpoint WTWriteConflictExceptionForImportIndex enabled. Throwing " "WriteConflictException", "ident"_attr = ident); - throw WriteConflictException(); + throwWriteConflictException(); } std::string config = uassertStatusOK( diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h b/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h index 28cc3304412..72a6cb5df72 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h @@ -29,7 +29,7 @@ #pragma once -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" #include "mongo/db/prepare_conflict_tracker.h" #include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h" @@ -83,7 +83,7 @@ int wiredTigerPrepareConflictRetry(OperationContext* opCtx, F&& f) { // be blocking on a prepared update that requires replication to make progress, creating a // stall in the MDB cluster. wiredTigerPrepareConflictOplogResourceLog(); - throw WriteConflictException(); + throwWriteConflictException(); } auto recoveryUnit = WiredTigerRecoveryUnit::get(opCtx); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 6a71038a93a..f30fa2118fa 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -1950,7 +1950,7 @@ void WiredTigerRecordStore::_initNextIdIfNeeded(OperationContext* opCtx) { // Force the caller to rollback its transaction if we can't make progess with eviction. // TODO (SERVER-63620): Convert this to a different error code that is distinguishable from // a true write conflict. - throw WriteConflictException( + throwWriteConflictException( fmt::format("Cache full while performing initial write to '{}'", _ns)); } else if (ret != WT_NOTFOUND) { invariantWTOK(ret, wtSession); @@ -2228,7 +2228,7 @@ boost::optional<Record> WiredTigerRecordStoreCursorBase::next() { // Force a retry of the operation from our last known position by acting as-if // we received a WT_ROLLBACK error. - throw WriteConflictException(); + throwWriteConflictException(); } WT_ITEM value; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp index 32e0257fc4a..6ea8f367b4c 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp @@ -39,7 +39,6 @@ #include "mongo/base/string_data.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/catalog/clustered_collection_util.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/json.h" #include "mongo/db/operation_context_noop.h" #include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h" @@ -51,6 +50,7 @@ #include "mongo/unittest/barrier.h" #include "mongo/unittest/temp_dir.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" #include "mongo/util/fail_point.h" #include "mongo/util/scopeguard.h" diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp index d841071a6f2..5b05f9e3c22 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp @@ -33,6 +33,7 @@ #include "mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h" #include "mongo/bson/bsonobjbuilder.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/server_options.h" #include "mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h" #include "mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h" @@ -423,7 +424,7 @@ void WiredTigerRecoveryUnit::_txnClose(bool commit) { LOGV2_ERROR(5703401, "Found a violation of multi-timestamp constraint. Retrying operation to " "collect extra debugging context for the involved writes."); - throw WriteConflictException(); + throwWriteConflictException(); } if (commit) { LOGV2_FATAL( diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp index 6ed86d9fadc..6b5294edf39 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp @@ -30,7 +30,6 @@ #include "mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h" #include "mongo/base/checked_cast.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context.h" @@ -43,6 +42,7 @@ #include "mongo/unittest/death_test.h" #include "mongo/unittest/temp_dir.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" #include "mongo/util/clock_source_mock.h" namespace mongo { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp index 4819f5f2a7c..37be17dc2f4 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp @@ -40,9 +40,8 @@ #include "mongo/base/simple_string_data_comparator.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/bson/json.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/concurrency/exception_util_gen.h" -#include "mongo/db/concurrency/temporarily_unavailable_exception.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/global_settings.h" #include "mongo/db/server_options_general_gen.h" #include "mongo/db/snapshot_window_options_gen.h" @@ -190,10 +189,10 @@ Status wtRCToStatus_slow(int retCode, WT_SESSION* session, StringData prefix) { if (!prefix.empty()) s << prefix << " "; s << retCode << ": " << WT_TXN_ROLLBACK_REASON_CACHE; - throw TemporarilyUnavailableException(s); + throwTemporarilyUnavailableException(s); } - throw WriteConflictException(prefix); + throwWriteConflictException(prefix); } // Don't abort on WT_PANIC when repairing, as the error will be handled at a higher layer. diff --git a/src/mongo/db/system_index.cpp b/src/mongo/db/system_index.cpp index 0e98bddd767..d9daf28b194 100644 --- a/src/mongo/db/system_index.cpp +++ b/src/mongo/db/system_index.cpp @@ -40,7 +40,6 @@ #include "mongo/db/catalog/commit_quorum_options.h" #include "mongo/db/catalog/index_catalog.h" #include "mongo/db/catalog/index_key_validate.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/index_builds_coordinator.h" diff --git a/src/mongo/db/timeseries/bucket_catalog.cpp b/src/mongo/db/timeseries/bucket_catalog.cpp index aaada4f6bf9..deb907343ca 100644 --- a/src/mongo/db/timeseries/bucket_catalog.cpp +++ b/src/mongo/db/timeseries/bucket_catalog.cpp @@ -36,7 +36,7 @@ #include "mongo/db/catalog/database_holder.h" #include "mongo/db/commands/server_status.h" -#include "mongo/db/concurrency/write_conflict_exception.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/operation_context.h" #include "mongo/db/timeseries/timeseries_options.h" #include "mongo/platform/compiler.h" @@ -842,7 +842,7 @@ void BucketCatalog::clear(const OID& oid) { auto result = _setBucketState(oid, BucketState::kCleared); if (result && *result == BucketState::kPreparedAndCleared) { hangTimeseriesDirectModificationBeforeWriteConflict.pauseWhileSet(); - throw WriteConflictException(); + throwWriteConflictException(); } } diff --git a/src/mongo/db/timeseries/bucket_catalog_test.cpp b/src/mongo/db/timeseries/bucket_catalog_test.cpp index b39b1065b89..ccc3b06a2fb 100644 --- a/src/mongo/db/timeseries/bucket_catalog_test.cpp +++ b/src/mongo/db/timeseries/bucket_catalog_test.cpp @@ -31,11 +31,11 @@ #include "mongo/db/catalog/catalog_test_fixture.h" #include "mongo/db/catalog/create_collection.h" #include "mongo/db/catalog_raii.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/timeseries/bucket_catalog.h" #include "mongo/stdx/future.h" #include "mongo/unittest/bson_test_util.h" #include "mongo/unittest/death_test.h" +#include "mongo/util/assert_util.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/str.h" diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index 14a8a7a3add..1816e326fde 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -405,7 +405,7 @@ void updateSessionEntry(OperationContext* opCtx, auto status = collection->insertDocument(opCtx, InsertStatement(updateMod), nullptr, false); if (status == ErrorCodes::DuplicateKey) { - throw WriteConflictException( + throwWriteConflictException( str::stream() << "Updating session entry failed with duplicate key, session "_sd << sessionId << ", transaction "_sd << txnNum); } @@ -433,7 +433,7 @@ void updateSessionEntry(OperationContext* opCtx, fassert(40673, MatchExpressionParser::parse(updateRequest.getQuery(), std::move(expCtx))); if (!matcher->matchesBSON(originalDoc)) { // Document no longer match what we expect so throw WCE to make the caller re-examine. - throw WriteConflictException( + throwWriteConflictException( str::stream() << "Updating session entry failed as document no longer matches, "_sd << "session "_sd << sessionId << ", transaction "_sd << txnNum); } diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp index b879181d885..2ed821e10e9 100644 --- a/src/mongo/db/ttl.cpp +++ b/src/mongo/db/ttl.cpp @@ -42,7 +42,6 @@ #include "mongo/db/client.h" #include "mongo/db/commands/fsync_locked.h" #include "mongo/db/commands/server_status_metric.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/delete_stage.h" #include "mongo/db/index/index_descriptor.h" @@ -62,6 +61,7 @@ #include "mongo/db/ttl_gen.h" #include "mongo/logv2/log.h" #include "mongo/s/grid.h" +#include "mongo/util/assert_util.h" #include "mongo/util/background.h" #include "mongo/util/concurrency/idle_thread_block.h" #include "mongo/util/log_with_sampling.h" diff --git a/src/mongo/dbtests/catalogtests.cpp b/src/mongo/dbtests/catalogtests.cpp index 09de106d4b9..685ff8e66db 100644 --- a/src/mongo/dbtests/catalogtests.cpp +++ b/src/mongo/dbtests/catalogtests.cpp @@ -35,11 +35,11 @@ #include "mongo/db/catalog/uncommitted_catalog_updates.h" #include "mongo/db/catalog_raii.h" #include "mongo/db/client.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/dbtests/dbtests.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" namespace mongo { namespace { diff --git a/src/mongo/dbtests/dbhelper_tests.cpp b/src/mongo/dbtests/dbhelper_tests.cpp index 05463795cfd..841f6de76a1 100644 --- a/src/mongo/dbtests/dbhelper_tests.cpp +++ b/src/mongo/dbtests/dbhelper_tests.cpp @@ -33,7 +33,6 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database_holder.h" #include "mongo/db/client.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/dbhelpers.h" @@ -47,6 +46,7 @@ #include "mongo/db/write_concern_options.h" #include "mongo/dbtests/dbtests.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/s/write_ops/batch_write_exec_test.cpp b/src/mongo/s/write_ops/batch_write_exec_test.cpp index 1381756da21..a0ec8867628 100644 --- a/src/mongo/s/write_ops/batch_write_exec_test.cpp +++ b/src/mongo/s/write_ops/batch_write_exec_test.cpp @@ -33,7 +33,6 @@ #include "mongo/client/remote_command_targeter_factory_mock.h" #include "mongo/client/remote_command_targeter_mock.h" #include "mongo/db/commands.h" -#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/vector_clock.h" #include "mongo/s/catalog/type_shard.h" @@ -47,6 +46,7 @@ #include "mongo/s/write_ops/batched_command_request.h" #include "mongo/s/write_ops/batched_command_response.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" namespace mongo { namespace { diff --git a/src/mongo/util/assert_util.cpp b/src/mongo/util/assert_util.cpp index 07ab283fdb0..42d2962adf4 100644 --- a/src/mongo/util/assert_util.cpp +++ b/src/mongo/util/assert_util.cpp @@ -78,10 +78,10 @@ void AssertionCount::condrollover(int newvalue) { rollover(); } -AtomicWord<bool> DBException::traceExceptions(false); - void DBException::traceIfNeeded(const DBException& e) { - if (traceExceptions.load()) { + const bool traceNeeded = traceExceptions.load() || + (e.code() == ErrorCodes::WriteConflict && traceWriteConflictExceptions.load()); + if (traceNeeded) { LOGV2_WARNING(23075, "DBException thrown {error}", "DBException thrown", "error"_attr = e); printStackTrace(); } diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h index 048aaea5a01..e3ca9855b4c 100644 --- a/src/mongo/util/assert_util.h +++ b/src/mongo/util/assert_util.h @@ -124,7 +124,14 @@ public: return _status.extraInfo<ErrorDetail>(); } - static AtomicWord<bool> traceExceptions; + static inline AtomicWord<bool> traceExceptions{false}; + + /** + * Allows handling `ErrorCodes::WriteConflict` as a special case and if true, will call + * `printStackTrace` on every `WriteConflict` error. Can be set via the + * `traceWriteConflictExceptions` server parameter. + */ + static inline AtomicWord<bool> traceWriteConflictExceptions{false}; protected: DBException(const Status& status) : _status(status) { @@ -150,6 +157,29 @@ public: }; /** + * Use `throwWriteConflictException()` instead of throwing `WriteConflictException` directly. + */ +class WriteConflictException final : public DBException { +public: + WriteConflictException(const Status& status) : DBException(status) {} + +private: + void defineOnlyInFinalSubclassToPreventSlicing() final {} +}; + +/** + * Use `throwTemporarilyUnavailableException()` instead of throwing + * `TemporarilyUnavailableException` directly. + */ +class TemporarilyUnavailableException final : public DBException { +public: + TemporarilyUnavailableException(const Status& status) : DBException(status) {} + +private: + void defineOnlyInFinalSubclassToPreventSlicing() final {} +}; + +/** * The base class of all DBExceptions for codes of the given ErrorCategory to allow catching by * category. */ @@ -165,9 +195,6 @@ protected: } }; -class WriteConflictException; -class TemporarilyUnavailableException; - /** * This namespace contains implementation details for our error handling code and should not be used * directly in general code. |