summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2021-10-21 18:14:18 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-21 19:08:28 +0000
commiteedf0b9248334af020e16c7de6d5c9392d1981d7 (patch)
treea4ab47eda0069083c1b71eae2f5557fffa905729 /src/mongo
parent065c37d4162355caadddf32d49360ee417b6fa86 (diff)
downloadmongo-eedf0b9248334af020e16c7de6d5c9392d1981d7.tar.gz
SERVER-59219 Check oplog visibility lock semantics for possible deadlock
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/SConscript41
-rw-r--r--src/mongo/db/catalog/SConscript1
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp3
-rw-r--r--src/mongo/db/concurrency/lock_state.h9
-rw-r--r--src/mongo/db/concurrency/locker.h17
-rw-r--r--src/mongo/db/concurrency/locker_noop.h8
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/storage/SConscript64
-rw-r--r--src/mongo/db/storage/devnull/SConscript1
-rw-r--r--src/mongo/db/storage/devnull/devnull_kv_engine.cpp5
-rw-r--r--src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h4
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/SConscript1
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.cpp8
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h13
-rw-r--r--src/mongo/db/storage/record_store.cpp62
-rw-r--r--src/mongo/db/storage/record_store.h18
-rw-r--r--src/mongo/db/storage/wiredtiger/SConscript11
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp9
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h12
-rw-r--r--src/mongo/s/concurrency/locker_mongos.h8
20 files changed, 218 insertions, 78 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index c93d4a783d0..f1ac5d97bed 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -58,8 +58,8 @@ env.SConscript(
#
env.Library(
- target= 'common',
- source= [
+ target='common',
+ source=[
'field_ref.cpp',
'field_ref_set.cpp',
'field_parser.cpp',
@@ -78,7 +78,7 @@ env.Library(
env.Library(
target='shutdown_in_progress_quiesce_info',
- source= [
+ source=[
'shutdown_in_progress_quiesce_info.cpp',
],
LIBDEPS=[
@@ -88,7 +88,7 @@ env.Library(
env.Library(
target='initialize_snmp',
- source= [
+ source=[
'initialize_snmp.cpp',
],
LIBDEPS=[
@@ -158,7 +158,8 @@ env.Library(
'$BUILD_DIR/mongo/db/stats/timer_stats',
'$BUILD_DIR/mongo/rpc/client_metadata',
'$BUILD_DIR/mongo/transport/service_executor',
- '$BUILD_DIR/mongo/util/diagnostic_info' if get_option('use-diagnostic-latches') == 'on' else [],
+ '$BUILD_DIR/mongo/util/diagnostic_info' if get_option(
+ 'use-diagnostic-latches') == 'on' else [],
'$BUILD_DIR/mongo/util/fail_point',
'$BUILD_DIR/mongo/util/net/network',
'$BUILD_DIR/mongo/util/progress_meter',
@@ -1343,6 +1344,7 @@ env.Library(
'$BUILD_DIR/mongo/db/catalog/local_oplog_info',
'$BUILD_DIR/mongo/db/commands/server_status_core',
'$BUILD_DIR/mongo/db/stats/resource_consumption_metrics',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/timeseries/timeseries_options',
'kill_sessions',
'not_primary_error_tracker',
@@ -1842,11 +1844,11 @@ env.Library(
)
env.Library(
- target= 'logical_time_metadata_hook',
- source= [
+ target='logical_time_metadata_hook',
+ source=[
'vector_clock_metadata_hook.cpp',
],
- LIBDEPS= [
+ LIBDEPS=[
'$BUILD_DIR/mongo/rpc/metadata',
'logical_time',
'vector_clock',
@@ -1865,11 +1867,11 @@ env.Library(
)
env.Library(
- target= 'vector_clock_test_fixture',
- source= [
+ target='vector_clock_test_fixture',
+ source=[
'vector_clock_test_fixture.cpp',
],
- LIBDEPS= [
+ LIBDEPS=[
'$BUILD_DIR/mongo/db/auth/authmocks',
'$BUILD_DIR/mongo/util/clock_source_mock',
's/sharding_mongod_test_fixture',
@@ -1894,8 +1896,8 @@ env.Library(
)
env.Library(
- target= 'service_context_d_test_fixture',
- source= [
+ target='service_context_d_test_fixture',
+ source=[
'service_context_d_test_fixture.cpp',
],
LIBDEPS=[
@@ -1917,8 +1919,8 @@ env.Library(
)
env.Library(
- target= 'service_context_devnull_test_fixture',
- source= [
+ target='service_context_devnull_test_fixture',
+ source=[
'service_context_devnull_test_fixture.cpp',
],
LIBDEPS=[
@@ -2077,7 +2079,8 @@ env.Library(
'$BUILD_DIR/mongo/base',
],
LIBDEPS_PRIVATE=[
- '$BUILD_DIR/mongo/util/net/ssl_options_server' if get_option('ssl') == 'on' else '',
+ '$BUILD_DIR/mongo/util/net/ssl_options_server' if get_option(
+ 'ssl') == 'on' else '',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
'mongod_options',
]
@@ -2103,7 +2106,8 @@ env.Library(
'$BUILD_DIR/mongo/util/clock_sources',
'$BUILD_DIR/mongo/util/elapsed_tracker',
'$BUILD_DIR/mongo/util/fail_point',
- '$BUILD_DIR/mongo/util/latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [],
+ '$BUILD_DIR/mongo/util/latch_analyzer' if get_option(
+ 'use-diagnostic-latches') == 'on' else [],
'$BUILD_DIR/mongo/util/net/network',
'$BUILD_DIR/mongo/util/ntservice',
'$BUILD_DIR/mongo/util/options_parser/options_parser_init',
@@ -2226,7 +2230,8 @@ env.Library(
'$BUILD_DIR/mongo/transport/transport_layer_manager',
'$BUILD_DIR/mongo/util/cmdline_utils/cmdline_utils',
'$BUILD_DIR/mongo/util/concurrency/thread_pool',
- '$BUILD_DIR/mongo/util/latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [],
+ '$BUILD_DIR/mongo/util/latch_analyzer' if get_option(
+ 'use-diagnostic-latches') == 'on' else [],
'$BUILD_DIR/mongo/util/net/http_client_impl',
'$BUILD_DIR/mongo/util/net/ssl_manager',
'$BUILD_DIR/mongo/util/signal_handlers',
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript
index fc4358eef4b..ea111a7f1c1 100644
--- a/src/mongo/db/catalog/SConscript
+++ b/src/mongo/db/catalog/SConscript
@@ -439,6 +439,7 @@ env.Library(
'$BUILD_DIR/mongo/db/repl/optime',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_interface',
'$BUILD_DIR/mongo/db/storage/flow_control',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/vector_clock_mutable',
'collection',
],
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp
index d83bb5b515f..4322718a5d5 100644
--- a/src/mongo/db/catalog/rename_collection.cpp
+++ b/src/mongo/db/catalog/rename_collection.cpp
@@ -42,6 +42,7 @@
#include "mongo/db/catalog/list_indexes.h"
#include "mongo/db/catalog/local_oplog_info.h"
#include "mongo/db/client.h"
+#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/curop.h"
#include "mongo/db/db_raii.h"
@@ -934,6 +935,8 @@ Status renameCollectionForApplyOps(OperationContext* opCtx,
str::stream() << "Cannot rename collection to the oplog");
}
+ // Take global IX lock explicitly to avoid upgrading from IS later
+ Lock::GlobalLock globalLock(opCtx, MODE_IX);
AutoGetCollectionForRead sourceColl(
opCtx, sourceNss, AutoGetCollectionViewMode::kViewsPermitted);
diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h
index c266269d47a..445c24235b8 100644
--- a/src/mongo/db/concurrency/lock_state.h
+++ b/src/mongo/db/concurrency/lock_state.h
@@ -32,6 +32,7 @@
#include <queue>
#include "mongo/db/concurrency/fast_map_noalloc.h"
+#include "mongo/db/concurrency/lock_manager_defs.h"
#include "mongo/db/concurrency/locker.h"
#include "mongo/db/operation_context.h"
#include "mongo/platform/atomic_word.h"
@@ -206,6 +207,14 @@ public:
virtual void releaseTicket();
virtual void reacquireTicket(OperationContext* opCtx);
+ bool hasReadTicket() const override {
+ return _modeForTicket == MODE_IS || _modeForTicket == MODE_S;
+ }
+
+ bool hasWriteTicket() const override {
+ return _modeForTicket == MODE_IX || _modeForTicket == MODE_X;
+ }
+
void getFlowControlTicket(OperationContext* opCtx, LockMode lockMode) override;
FlowControlTicketholder::CurOp getFlowControlStats() const override;
diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h
index 7a0ca285c1c..37b6dbeedb8 100644
--- a/src/mongo/db/concurrency/locker.h
+++ b/src/mongo/db/concurrency/locker.h
@@ -438,6 +438,23 @@ public:
*/
virtual void reacquireTicket(OperationContext* opCtx) = 0;
+ /**
+ * Returns true if a read ticket is held for the Locker.
+ */
+ virtual bool hasReadTicket() const = 0;
+
+ /**
+ * Returns true if a write ticket is held for the Locker.
+ */
+ virtual bool hasWriteTicket() const = 0;
+
+ /**
+ * Returns true if uninterruptible locks were requested for the Locker.
+ */
+ bool uninterruptibleLocksRequested() const {
+ return _uninterruptibleLocksRequested > 0;
+ }
+
//
// These methods are legacy from LockerImpl and will eventually go away or be converted to
// calls into the Locker methods
diff --git a/src/mongo/db/concurrency/locker_noop.h b/src/mongo/db/concurrency/locker_noop.h
index 058788e971c..7ce27af01fa 100644
--- a/src/mongo/db/concurrency/locker_noop.h
+++ b/src/mongo/db/concurrency/locker_noop.h
@@ -206,6 +206,14 @@ public:
MONGO_UNREACHABLE;
}
+ virtual bool hasReadTicket() const {
+ MONGO_UNREACHABLE;
+ }
+
+ virtual bool hasWriteTicket() const {
+ MONGO_UNREACHABLE;
+ }
+
virtual void dump() const {
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index e1a8a9c66cc..2a35874c14b 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -229,6 +229,7 @@ env.Library(
'$BUILD_DIR/mongo/db/index_builds_coordinator_interface',
'$BUILD_DIR/mongo/db/record_id_helpers',
'$BUILD_DIR/mongo/db/storage/oplog_cap_maintainer_thread',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/storage/storage_control',
'$BUILD_DIR/mongo/db/vector_clock',
'repl_server_parameters',
diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript
index 07f9101e20c..31a97c44c42 100644
--- a/src/mongo/db/storage/SConscript
+++ b/src/mongo/db/storage/SConscript
@@ -19,41 +19,41 @@ env.Library(
target='index_entry_comparison',
source=[
'index_entry_comparison.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/namespace_string',
'duplicate_key_error_info',
'key_string',
- ],
- )
+ ],
+)
env.Library(
target='snapshot_helper',
source=[
'snapshot_helper.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/namespace_string',
- ],
+ ],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/concurrency/lock_manager_defs',
'$BUILD_DIR/mongo/db/repl/read_concern_args',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_interface',
'recovery_unit_base',
- ],
- )
+ ],
+)
env.Library(
target='duplicate_key_error_info',
source=[
'duplicate_key_error_info.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
- ],
- )
+ ],
+)
env.Library(
target='recovery_unit_base',
@@ -69,40 +69,53 @@ env.Library(
)
env.Library(
+ target='record_store_base',
+ source=[
+ 'record_store.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/service_context',
+ ],
+)
+
+env.Library(
target='key_string',
source=[
'key_string.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
- ],
- )
+ ],
+)
env.Library(
target='execution_context',
source=[
'execution_context.cpp',
- ],
+ ],
LIBDEPS=[
'key_string',
'storage_options',
- ],
- )
+ ],
+)
env.Library(
target='bson_collection_catalog_entry',
source=[
'bson_collection_catalog_entry.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/db/catalog/collection_options',
'$BUILD_DIR/mongo/db/common',
'$BUILD_DIR/mongo/db/service_context',
- ],
+ ],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/server_options',
- ],
- )
+ ],
+)
env.Library(
target='storage_control',
@@ -129,7 +142,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/namespace_string',
- '$BUILD_DIR/mongo/util/background_job',
+ '$BUILD_DIR/mongo/util/background_job',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/base',
@@ -177,7 +190,7 @@ env.Library(
source=[
'encryption_hooks.cpp',
],
- LIBDEPS= [
+ LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/service_context'
],
@@ -246,6 +259,7 @@ env.Library(
'$BUILD_DIR/mongo/db/catalog/collection_options',
'$BUILD_DIR/mongo/db/record_id_helpers',
'$BUILD_DIR/mongo/db/service_context',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/storage/storage_options',
'$BUILD_DIR/mongo/db/update/update_document_diff',
'$BUILD_DIR/mongo/unittest/unittest',
@@ -270,12 +284,12 @@ env.Library(
source=[
'storage_engine_lock_file.cpp',
'storage_engine_lock_file_${TARGET_OS_FAMILY}.cpp',
- ],
+ ],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/service_context',
- ],
- )
+ ],
+)
env.Library(
target='storage_engine_common',
diff --git a/src/mongo/db/storage/devnull/SConscript b/src/mongo/db/storage/devnull/SConscript
index d1f22c92a51..b13b49a5f09 100644
--- a/src/mongo/db/storage/devnull/SConscript
+++ b/src/mongo/db/storage/devnull/SConscript
@@ -12,6 +12,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/record_id_helpers',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/storage/recovery_unit_base',
],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
index 4b8ef17e47d..02f0d13cb9d 100644
--- a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
+++ b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
@@ -150,12 +150,13 @@ public:
result->appendNumber("numInserts", _numInserts);
}
- void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const override {}
-
virtual void updateStatsAfterRepair(OperationContext* opCtx,
long long numRecords,
long long dataSize) {}
+protected:
+ void waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const override {}
+
private:
CollectionOptions _options;
KeyFormat _keyFormat;
diff --git a/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h b/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
index 2945975a56f..7b8a0a9e905 100644
--- a/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
+++ b/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
@@ -106,8 +106,6 @@ public:
return _data->records.size();
}
- void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const override {}
-
virtual void updateStatsAfterRepair(OperationContext* opCtx,
long long numRecords,
long long dataSize) {
@@ -131,6 +129,8 @@ protected:
virtual const EphemeralForTestRecord* recordFor(WithLock, const RecordId& loc) const;
virtual EphemeralForTestRecord* recordFor(WithLock, const RecordId& loc);
+ void waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const override {}
+
public:
//
diff --git a/src/mongo/db/storage/ephemeral_for_test/SConscript b/src/mongo/db/storage/ephemeral_for_test/SConscript
index 27655b355db..c651aa81101 100644
--- a/src/mongo/db/storage/ephemeral_for_test/SConscript
+++ b/src/mongo/db/storage/ephemeral_for_test/SConscript
@@ -27,6 +27,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/concurrency/write_conflict_exception',
'$BUILD_DIR/mongo/db/storage/index_entry_comparison',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/storage/recovery_unit_base',
],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.cpp
index 2ab6152b2a4..181ca7a17a8 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.cpp
@@ -299,13 +299,13 @@ void RecordStore::updateStatsAfterRepair(OperationContext* opCtx,
_dataSize.store(dataSize);
}
-void RecordStore::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const {
+void RecordStore::waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const {
_visibilityManager->waitForAllEarlierOplogWritesToBeVisible(opCtx);
}
-Status RecordStore::oplogDiskLocRegister(OperationContext* opCtx,
- const Timestamp& opTime,
- bool orderedCommit) {
+Status RecordStore::oplogDiskLocRegisterImpl(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit) {
if (!orderedCommit) {
return opCtx->recoveryUnit()->setTimestamp(opTime);
}
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
index cb7966500aa..4adb042cfae 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
@@ -88,10 +88,6 @@ public:
const char* damageSource,
const mutablebson::DamageVector& damages);
- Status oplogDiskLocRegister(OperationContext* opCtx,
- const Timestamp& opTime,
- bool orderedCommit) override;
-
std::unique_ptr<SeekableRecordCursor> getCursor(OperationContext* opCtx,
bool forward) const final;
@@ -104,12 +100,17 @@ public:
BSONObjBuilder* result,
double scale) const {}
- void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const override;
-
virtual void updateStatsAfterRepair(OperationContext* opCtx,
long long numRecords,
long long dataSize);
+protected:
+ Status oplogDiskLocRegisterImpl(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit) override;
+
+ void waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const override;
+
private:
friend class VisibilityManagerChange;
diff --git a/src/mongo/db/storage/record_store.cpp b/src/mongo/db/storage/record_store.cpp
new file mode 100644
index 00000000000..fa008a406b1
--- /dev/null
+++ b/src/mongo/db/storage/record_store.cpp
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/operation_context.h"
+#include "mongo/db/storage/record_store.h"
+
+namespace mongo {
+
+Status RecordStore::oplogDiskLocRegister(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit) {
+ // Callers should be updating visibility as part of a write operation. We want to ensure that
+ // we never get here while holding an uninterruptible, read-ticketed lock. That would indicate
+ // that we are operating with the wrong global lock semantics, and either hold too weak a lock
+ // (e.g. IS) or that we upgraded in a way we shouldn't (e.g. IS -> IX).
+ invariant(opCtx->lockState()->isNoop() || !opCtx->lockState()->hasReadTicket() ||
+ !opCtx->lockState()->uninterruptibleLocksRequested());
+
+ return oplogDiskLocRegisterImpl(opCtx, opTime, orderedCommit);
+}
+
+void RecordStore::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const {
+ // Callers are waiting for other operations to finish updating visibility. We want to ensure
+ // that we never get here while holding an uninterruptible, write-ticketed lock. That could
+ // indicate we are holding a stronger lock than we need to, and that we could actually
+ // contribute to ticket-exhaustion. That could prevent the write we are waiting on from
+ // acquiring the lock it needs to update the oplog visibility.
+ invariant(opCtx->lockState()->isNoop() || !opCtx->lockState()->hasWriteTicket() ||
+ !opCtx->lockState()->uninterruptibleLocksRequested());
+
+ waitForAllEarlierOplogWritesToBeVisibleImpl(opCtx);
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/record_store.h b/src/mongo/db/storage/record_store.h
index fc279494b82..7da8d424936 100644
--- a/src/mongo/db/storage/record_store.h
+++ b/src/mongo/db/storage/record_store.h
@@ -501,11 +501,9 @@ public:
* visibility management. Calls with `orderedCommit` true will not be concurrent with calls of
* `orderedCommit` false.
*/
- virtual Status oplogDiskLocRegister(OperationContext* opCtx,
- const Timestamp& opTime,
- bool orderedCommit) {
- return Status::OK();
- }
+ Status oplogDiskLocRegister(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit);
/**
* Waits for all writes that completed before this call to be visible to forward scans.
@@ -514,7 +512,7 @@ public:
* It is only legal to call this on an oplog. It is illegal to call this inside a
* WriteUnitOfWork.
*/
- virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const = 0;
+ void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const;
/**
* Called after a repair operation is run with the recomputed numRecords and dataSize.
@@ -583,6 +581,14 @@ public:
}
protected:
+ virtual Status oplogDiskLocRegisterImpl(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit) {
+ return Status::OK();
+ }
+
+ virtual void waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const = 0;
+
std::string _ns;
};
diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript
index 203df8aacaa..4d1b8d7fe6c 100644
--- a/src/mongo/db/storage/wiredtiger/SConscript
+++ b/src/mongo/db/storage/wiredtiger/SConscript
@@ -9,11 +9,11 @@ env = env.Clone()
env.Library(
target='storage_wiredtiger_customization_hooks',
- source= [
+ source=[
'wiredtiger_customization_hooks.cpp',
'wiredtiger_extensions.cpp',
],
- LIBDEPS= [
+ LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/service_context'
],
@@ -27,7 +27,7 @@ wtEnv.InjectThirdParty(libraries=['valgrind'])
# This is the smallest possible set of files that wraps WT
wtEnv.Library(
target='storage_wiredtiger_core',
- source= [
+ source=[
'oplog_stones_server_status_section.cpp',
'wiredtiger_begin_transaction_block.cpp',
'wiredtiger_cursor.cpp',
@@ -46,7 +46,7 @@ wtEnv.Library(
'wiredtiger_util.cpp',
'wiredtiger_parameters.idl',
],
- LIBDEPS= [
+ LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/catalog/collection',
@@ -65,6 +65,7 @@ wtEnv.Library(
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/db/storage/index_entry_comparison',
'$BUILD_DIR/mongo/db/storage/key_string',
+ '$BUILD_DIR/mongo/db/storage/record_store_base',
'$BUILD_DIR/mongo/db/storage/recovery_unit_base',
'$BUILD_DIR/mongo/db/storage/storage_file_util',
'$BUILD_DIR/mongo/db/storage/storage_options',
@@ -76,7 +77,7 @@ wtEnv.Library(
'$BUILD_DIR/third_party/shim_zlib',
'storage_wiredtiger_customization_hooks',
],
- LIBDEPS_PRIVATE= [
+ LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/catalog/database_holder',
'$BUILD_DIR/mongo/db/commands/server_status',
'$BUILD_DIR/mongo/db/db_raii',
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index 14cfea1e6e3..8ce5277ac24 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -1707,7 +1707,8 @@ void WiredTigerRecordStore::appendCustomStats(OperationContext* opCtx,
}
}
-void WiredTigerRecordStore::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const {
+void WiredTigerRecordStore::waitForAllEarlierOplogWritesToBeVisibleImpl(
+ OperationContext* opCtx) const {
// Make sure that callers do not hold an active snapshot so it will be able to see the oplog
// entries it waited for afterwards.
if (opCtx->recoveryUnit()->isActive()) {
@@ -1968,9 +1969,9 @@ void WiredTigerRecordStore::cappedTruncateAfter(OperationContext* opCtx,
}
}
-Status WiredTigerRecordStore::oplogDiskLocRegister(OperationContext* opCtx,
- const Timestamp& ts,
- bool orderedCommit) {
+Status WiredTigerRecordStore::oplogDiskLocRegisterImpl(OperationContext* opCtx,
+ const Timestamp& ts,
+ bool orderedCommit) {
opCtx->recoveryUnit()->setOrderedCommit(orderedCommit);
if (!orderedCommit) {
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
index d4f012d7541..6e5a8b0c9d5 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
@@ -193,17 +193,11 @@ public:
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive);
- virtual Status oplogDiskLocRegister(OperationContext* opCtx,
- const Timestamp& opTime,
- bool orderedCommit);
-
virtual void updateStatsAfterRepair(OperationContext* opCtx,
long long numRecords,
long long dataSize);
- void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const override;
-
Status updateOplogSize(long long newOplogSize) final;
void setCappedCallback(CappedCallback* cb) {
@@ -276,6 +270,12 @@ protected:
virtual void setKey(WT_CURSOR* cursor, const CursorKey* key) const = 0;
+ Status oplogDiskLocRegisterImpl(OperationContext* opCtx,
+ const Timestamp& opTime,
+ bool orderedCommit) override;
+
+ void waitForAllEarlierOplogWritesToBeVisibleImpl(OperationContext* opCtx) const override;
+
private:
class RandomCursor;
diff --git a/src/mongo/s/concurrency/locker_mongos.h b/src/mongo/s/concurrency/locker_mongos.h
index 915105b77bd..f4c3d72894e 100644
--- a/src/mongo/s/concurrency/locker_mongos.h
+++ b/src/mongo/s/concurrency/locker_mongos.h
@@ -202,6 +202,14 @@ public:
MONGO_UNREACHABLE;
}
+ virtual bool hasReadTicket() const {
+ MONGO_UNREACHABLE;
+ }
+
+ virtual bool hasWriteTicket() const {
+ MONGO_UNREACHABLE;
+ }
+
void dump() const override {
MONGO_UNREACHABLE;
}