summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAmirsaman Memaripour <amirsaman.memaripour@mongodb.com>2022-05-10 17:33:32 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-10 20:50:30 +0000
commit8113aef47fab9d0d14c953b78032ab1661360438 (patch)
tree361fb0dcddab375966cce82d5accd751bd878c65 /src
parent589aa86a047d5f3d34294e054cd7b41cd74d9590 (diff)
downloadmongo-8113aef47fab9d0d14c953b78032ab1661360438.tar.gz
SERVER-66205 Merge `WriteConflictException` and `TemporarilyUnavailableException` into `assert_util.h`
Diffstat (limited to 'src')
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/base/error_codes.tpl.cpp2
-rw-r--r--src/mongo/db/catalog/collection_catalog.cpp6
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp4
-rw-r--r--src/mongo/db/catalog/collection_test.cpp2
-rw-r--r--src/mongo/db/catalog/database_impl.cpp6
-rw-r--r--src/mongo/db/catalog/multi_index_block_test.cpp4
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp2
-rw-r--r--src/mongo/db/commands/create_indexes.cpp4
-rw-r--r--src/mongo/db/commands/parameters.idl5
-rw-r--r--src/mongo/db/concurrency/d_concurrency_test.cpp4
-rw-r--r--src/mongo/db/concurrency/exception_util.cpp7
-rw-r--r--src/mongo/db/concurrency/exception_util.h26
-rw-r--r--src/mongo/db/concurrency/exception_util.idl14
-rw-r--r--src/mongo/db/concurrency/temporarily_unavailable_exception.h60
-rw-r--r--src/mongo/db/concurrency/write_conflict_exception.cpp46
-rw-r--r--src/mongo/db/concurrency/write_conflict_exception.h67
-rw-r--r--src/mongo/db/exec/batched_delete_stage.cpp4
-rw-r--r--src/mongo/db/exec/cached_plan.cpp4
-rw-r--r--src/mongo/db/exec/collection_scan.cpp2
-rw-r--r--src/mongo/db/exec/count_scan.cpp2
-rw-r--r--src/mongo/db/exec/delete_stage.cpp4
-rw-r--r--src/mongo/db/exec/distinct_scan.cpp2
-rw-r--r--src/mongo/db/exec/fetch.cpp2
-rw-r--r--src/mongo/db/exec/idhack.cpp2
-rw-r--r--src/mongo/db/exec/index_scan.cpp2
-rw-r--r--src/mongo/db/exec/multi_iterator.cpp2
-rw-r--r--src/mongo/db/exec/multi_plan.cpp4
-rw-r--r--src/mongo/db/exec/text_or.cpp2
-rw-r--r--src/mongo/db/exec/trial_stage.cpp4
-rw-r--r--src/mongo/db/exec/update_stage.cpp4
-rw-r--r--src/mongo/db/query/plan_executor_impl.cpp3
-rw-r--r--src/mongo/db/query/plan_yield_policy.cpp2
-rw-r--r--src/mongo/db/repl/oplog.cpp4
-rw-r--r--src/mongo/db/repl/oplog_applier_utils.cpp2
-rw-r--r--src/mongo/db/repl/transaction_oplog_application.cpp2
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_bump_collection_version_and_change_metadata_test.cpp4
-rw-r--r--src/mongo/db/s/range_deletion_util.cpp2
-rw-r--r--src/mongo/db/s/resharding/resharding_oplog_application.cpp2
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.cpp4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_column_store.cpp1
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp1
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp6
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp3
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp7
-rw-r--r--src/mongo/db/system_index.cpp1
-rw-r--r--src/mongo/db/timeseries/bucket_catalog.cpp4
-rw-r--r--src/mongo/db/timeseries/bucket_catalog_test.cpp2
-rw-r--r--src/mongo/db/transaction_participant.cpp4
-rw-r--r--src/mongo/db/ttl.cpp2
-rw-r--r--src/mongo/dbtests/catalogtests.cpp2
-rw-r--r--src/mongo/dbtests/dbhelper_tests.cpp2
-rw-r--r--src/mongo/s/write_ops/batch_write_exec_test.cpp2
-rw-r--r--src/mongo/util/assert_util.cpp6
-rw-r--r--src/mongo/util/assert_util.h35
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.