diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2020-02-21 15:43:53 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-25 04:54:39 +0000 |
commit | 61ea39197455ca2e54135607e5625bb2c2796ec3 (patch) | |
tree | 3bd09fedce5fae037ac5f1d1b3473262de29a87a /src/mongo/db/storage/wiredtiger | |
parent | f83f9dcc22156cdf3c3e16a040914806e2e17cf7 (diff) | |
download | mongo-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/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp | 45 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h | 10 |
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) |