summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/wiredtiger
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-02-21 15:43:53 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-25 04:54:39 +0000
commit61ea39197455ca2e54135607e5625bb2c2796ec3 (patch)
tree3bd09fedce5fae037ac5f1d1b3473262de29a87a /src/mongo/db/storage/wiredtiger
parentf83f9dcc22156cdf3c3e16a040914806e2e17cf7 (diff)
downloadmongo-61ea39197455ca2e54135607e5625bb2c2796ec3.tar.gz
SERVER-46334 Eliminate the mutex held across JournalListener calls.
delete mode 100644 src/mongo/db/storage/journal_listener.cpp
Diffstat (limited to 'src/mongo/db/storage/wiredtiger')
-rw-r--r--src/mongo/db/storage/wiredtiger/SConscript1
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp45
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h10
3 files changed, 40 insertions, 16 deletions
diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript
index 88451147071..6ea520aab53 100644
--- a/src/mongo/db/storage/wiredtiger/SConscript
+++ b/src/mongo/db/storage/wiredtiger/SConscript
@@ -69,7 +69,6 @@ if wiredtiger:
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/db/storage/index_entry_comparison',
- '$BUILD_DIR/mongo/db/storage/journal_listener',
'$BUILD_DIR/mongo/db/storage/key_string',
'$BUILD_DIR/mongo/db/storage/kv/kv_prefix',
'$BUILD_DIR/mongo/db/storage/oplog_hack',
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp
index 64ef2d146ed..b56f31fc455 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp
@@ -249,9 +249,15 @@ void WiredTigerSessionCache::waitUntilDurable(OperationContext* opCtx,
if (isEphemeral()) {
// Update the JournalListener before we return. As far as listeners are concerned, all
// writes are as 'durable' as they are ever going to get on an inMemory storage engine.
- stdx::unique_lock<Latch> lk(_journalListenerMutex, stdx::defer_lock);
- if (useListener == UseJournalListener::kUpdate) {
- auto token = _journalListener->getToken(opCtx, lk);
+ auto journalListener = [&]() -> JournalListener* {
+ // The JournalListener may not be set immediately, so we must check under a mutex so
+ // as not to access the variable while setting a JournalListener. A JournalListener
+ // is only allowed to be set once, so using the pointer outside of a mutex is safe.
+ stdx::unique_lock<Latch> lk(_journalListenerMutex);
+ return _journalListener;
+ }();
+ if (journalListener && useListener == UseJournalListener::kUpdate) {
+ auto token = _journalListener->getToken(opCtx);
_journalListener->onDurable(token);
}
return;
@@ -283,12 +289,16 @@ void WiredTigerSessionCache::waitUntilDurable(OperationContext* opCtx,
// Update a value that tracks the latest write that is safe across startup recovery (in
// the repl layer) and then report the time of that write as durable after we flush
// in-memory to disk.
- // Defer locking the mutex so that it can be locked after any collection locks that
- // may be acquired, which avoids deadlocks.
- stdx::unique_lock<Latch> lk(_journalListenerMutex, stdx::defer_lock);
+ auto journalListener = [&]() -> JournalListener* {
+ // The JournalListener may not be set immediately, so we must check under a mutex so
+ // as not to access the variable while setting a JournalListener. A JournalListener
+ // is only allowed to be set once, so using the pointer outside of a mutex is safe.
+ stdx::unique_lock<Latch> lk(_journalListenerMutex);
+ return _journalListener;
+ }();
boost::optional<JournalListener::Token> token;
- if (useListener == UseJournalListener::kUpdate) {
- token = _journalListener->getToken(opCtx, lk);
+ if (journalListener && useListener == UseJournalListener::kUpdate) {
+ token = _journalListener->getToken(opCtx);
}
auto config = syncType == Fsync::kCheckpointStableTimestamp ? "use_timestamp=true"
@@ -322,12 +332,16 @@ void WiredTigerSessionCache::waitUntilDurable(OperationContext* opCtx,
// Update a value that tracks the latest write that is safe across startup recovery (in the repl
// layer) and then report the time of that write as durable after we flush in-memory to disk.
- // Defer locking the mutex so that it can be locked after any collection locks that may be
- // acquired, which avoids deadlocks.
- stdx::unique_lock<Latch> jlk(_journalListenerMutex, stdx::defer_lock);
+ auto journalListener = [&]() -> JournalListener* {
+ // The JournalListener may not be set immediately, so we must check under a mutex so as not
+ // to access the variable while setting a JournalListener. A JournalListener is only allowed
+ // to be set once, so using the pointer outside of a mutex is safe.
+ stdx::unique_lock<Latch> lk(_journalListenerMutex);
+ return _journalListener;
+ }();
boost::optional<JournalListener::Token> token;
- if (useListener == UseJournalListener::kUpdate) {
- token = _journalListener->getToken(opCtx, jlk);
+ if (journalListener && useListener == UseJournalListener::kUpdate) {
+ token = _journalListener->getToken(opCtx);
}
// Initialize on first use.
@@ -525,6 +539,11 @@ void WiredTigerSessionCache::releaseSession(WiredTigerSession* session) {
void WiredTigerSessionCache::setJournalListener(JournalListener* jl) {
stdx::unique_lock<Latch> lk(_journalListenerMutex);
+
+ // A JournalListener can only be set once. Otherwise, accessing a copy of the _journalListener
+ // pointer without a mutex would be unsafe.
+ invariant(!_journalListener);
+
_journalListener = jl;
}
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h
index a1bb96ad915..e488b73cd65 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h
@@ -392,10 +392,16 @@ private:
stdx::condition_variable _prepareCommittedOrAbortedCond;
AtomicWord<std::uint64_t> _prepareCommitOrAbortCounter{0};
- // Protects _journalListener.
+ // Protects getting and setting the _journalListener below.
Mutex _journalListenerMutex = MONGO_MAKE_LATCH("WiredTigerSessionCache::_journalListenerMutex");
+
// Notified when we commit to the journal.
- JournalListener* _journalListener = &NoOpJournalListener::instance;
+ //
+ // This variable should be accessed under the _journalListenerMutex above and saved in a local
+ // variable before use. That way, we can avoid holding a mutex across calls on the object. It is
+ // only allowed to be set once, in order to ensure the memory to which a copy of the pointer
+ // points is always valid.
+ JournalListener* _journalListener = nullptr;
WT_SESSION* _waitUntilDurableSession = nullptr; // owned, and never explicitly closed
// (uses connection close to clean up)