diff options
author | Benety Goh <benety@mongodb.com> | 2017-01-19 17:23:28 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2017-01-19 17:23:28 -0500 |
commit | 7bf2874d0fe92c5503f9cde86ac9e341d1889000 (patch) | |
tree | 9856cc4b59d867a19e3a550acec9604ea6a3ad43 /src/mongo/db | |
parent | d3e67186d1f9c633e8e69ebb7bf2418d3850688a (diff) | |
download | mongo-7bf2874d0fe92c5503f9cde86ac9e341d1889000.tar.gz |
Revert "SERVER-27678 moved DataReplicator::OnCompletionGuard into its own library"
This reverts commit 9edfc4c8ba273d54ecdc31c1fc0eb8c6a42ccbc4.
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/repl/SConscript | 11 | ||||
-rw-r--r-- | src/mongo/db/repl/callback_completion_guard.cpp | 61 | ||||
-rw-r--r-- | src/mongo/db/repl/callback_completion_guard.h | 171 | ||||
-rw-r--r-- | src/mongo/db/repl/data_replicator.cpp | 40 | ||||
-rw-r--r-- | src/mongo/db/repl/data_replicator.h | 50 |
5 files changed, 86 insertions, 247 deletions
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 685454e3261..43bcca8288f 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -818,16 +818,6 @@ env.Library( ) env.Library( - target='callback_completion_guard', - source=[ - 'callback_completion_guard.cpp', - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/base', - ], -) - -env.Library( target='collection_cloner', source=[ 'collection_cloner.cpp', @@ -1059,7 +1049,6 @@ env.Library( 'data_replicator.cpp', ], LIBDEPS=[ - 'callback_completion_guard', 'collection_cloner', 'database_cloner', 'databases_cloner', diff --git a/src/mongo/db/repl/callback_completion_guard.cpp b/src/mongo/db/repl/callback_completion_guard.cpp deleted file mode 100644 index 100a7d74e30..00000000000 --- a/src/mongo/db/repl/callback_completion_guard.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (C) 2017 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * 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 GNU Affero General 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. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kReplication - -#include "mongo/platform/basic.h" - -#include "mongo/db/repl/callback_completion_guard.h" - -#include "mongo/util/assert_util.h" -#include "mongo/util/destructor_guard.h" -#include "mongo/util/log.h" - -namespace mongo { -namespace repl { - -// static -void CallbackCompletionGuardBase::logUnsetResultErrorAndTerminate() { - severe() << "It is a programming error to destroy this completion guard without the caller " - "providing a result for '_result'"; - fassertFailed(40370); -} - -// static -void CallbackCompletionGuardBase::ensureUniqueLockIsOwnedByUs( - const stdx::unique_lock<stdx::mutex>& lock) { - invariant(lock.owns_lock()); -} - -// static -void CallbackCompletionGuardBase::runInDestructorGuard(stdx::function<void()> destructorFn) { - MONGO_DESTRUCTOR_GUARD({ destructorFn(); }); -} - -} // namespace repl -} // namespace mongo diff --git a/src/mongo/db/repl/callback_completion_guard.h b/src/mongo/db/repl/callback_completion_guard.h deleted file mode 100644 index 9843d267334..00000000000 --- a/src/mongo/db/repl/callback_completion_guard.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright (C) 2017 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * 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 GNU Affero General 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 <boost/optional.hpp> - -#include "mongo/stdx/functional.h" -#include "mongo/stdx/mutex.h" - -namespace mongo { -namespace repl { - -/** - * Utility class used by CallbackCompletionGuard. - */ -class CallbackCompletionGuardBase { -public: - /** - * Called by CallbackCompletionGuard<Result> at destruction if caller has not provided a - * result for the completion function. - */ - static void logUnsetResultErrorAndTerminate(); - - /** - * Checks that the caller owns this unique lock. - */ - static void ensureUniqueLockIsOwnedByUs(const stdx::unique_lock<stdx::mutex>& lock); - - /** - * Run function in destructor guard. - */ - static void runInDestructorGuard(stdx::function<void()> destructorFn); - -private: - CallbackCompletionGuardBase(); -}; - -/** - * RAII type that stores the result of callbacks written using the executor::TaskExecutor framework. - * Only the first result passed to setResultAndCancelRemainingWork_inlock() is saved. - * Calls '_onCompletion' on destruction with result. - * We use an invariant to ensure that a result has been provided by the caller at destruction. - */ -template <typename Result> -class CallbackCompletionGuard { -public: - /** - * Function to invoke DataReplicator::_cancelRemainingWork_inlock(). - */ - using CancelRemainingWorkInLockFn = stdx::function<void()>; - - /** - * Callback function to pass result to caller at destruction. - */ - typedef stdx::function<void(const Result& result)> OnCompletionFn; - - /** - * Constructor for this completion guard. - * 'cancelRemainingWorkInLock' is called after setting the result to cancel any outstanding - * work in the caller. - * 'onCompletion' is called with the result at destruction. - */ - CallbackCompletionGuard(const CancelRemainingWorkInLockFn& cancelRemainingWorkInLock, - const OnCompletionFn& onCompletion); - - /** - * Invokes '_onCompletion' with the result. - * Aborts if result is not set. - */ - ~CallbackCompletionGuard(); - - /** - * Sets result if called for the first time. - * Cancels remaining work in caller. - * Requires either a unique_lock or lock_guard to be passed in to ensure that we call - * _cancelRemainingWork_inlock()) while we have a lock on the callers's mutex. - */ - void setResultAndCancelRemainingWork_inlock(const stdx::lock_guard<stdx::mutex>& lock, - const Result& result); - void setResultAndCancelRemainingWork_inlock(const stdx::unique_lock<stdx::mutex>& lock, - const Result& result); - -private: - /** - * Once we verified that we have the caller's lock, this function is called by both - * versions of setResultAndCancelRemainingWork_inlock() to set the result and cancel any - * remaining work in the caller. - */ - void _setResultAndCancelRemainingWork_inlock(const Result& result); - - // Called at most once after setting '_result'. - const CancelRemainingWorkInLockFn _cancelRemainingWorkInLock; - - // Called at destruction with '_result'. - const OnCompletionFn _onCompletion; - - // _result is guarded by the mutex of the caller instance that owns this guard object. - boost::optional<Result> _result; -}; - -template <typename Result> -CallbackCompletionGuard<Result>::CallbackCompletionGuard( - const CancelRemainingWorkInLockFn& cancelRemainingWorkInLock, - const OnCompletionFn& onCompletion) - : _cancelRemainingWorkInLock(cancelRemainingWorkInLock), _onCompletion(onCompletion) {} - -template <typename Result> -CallbackCompletionGuard<Result>::~CallbackCompletionGuard() { - CallbackCompletionGuardBase::runInDestructorGuard([this]() { - if (!_result) { - CallbackCompletionGuardBase::logUnsetResultErrorAndTerminate(); - } - // _onCompletion() must be called outside the caller's lock to avoid a deadlock. - _onCompletion(*_result); - }); -} - -template <typename Result> -void CallbackCompletionGuard<Result>::setResultAndCancelRemainingWork_inlock( - const stdx::lock_guard<stdx::mutex>& lock, const Result& result) { - _setResultAndCancelRemainingWork_inlock(result); -} - -template <typename Result> -void CallbackCompletionGuard<Result>::setResultAndCancelRemainingWork_inlock( - const stdx::unique_lock<stdx::mutex>& lock, const Result& result) { - CallbackCompletionGuardBase::ensureUniqueLockIsOwnedByUs(lock); - _setResultAndCancelRemainingWork_inlock(result); -} - -template <typename Result> -void CallbackCompletionGuard<Result>::_setResultAndCancelRemainingWork_inlock( - const Result& result) { - if (_result) { - return; - } - _result = result; - - // This is called at most once. - _cancelRemainingWorkInLock(); -} - -} // namespace repl -} // namespace mongo diff --git a/src/mongo/db/repl/data_replicator.cpp b/src/mongo/db/repl/data_replicator.cpp index ee990aab967..5282b4c5687 100644 --- a/src/mongo/db/repl/data_replicator.cpp +++ b/src/mongo/db/repl/data_replicator.cpp @@ -1497,6 +1497,46 @@ Status DataReplicator::_enqueueDocuments(Fetcher::Documents::const_iterator begi return Status::OK(); } +DataReplicator::OnCompletionGuard::OnCompletionGuard( + const CancelRemainingWorkInLockFn& cancelRemainingWorkInLock, + const OnCompletionFn& onCompletion) + : _cancelRemainingWorkInLock(cancelRemainingWorkInLock), _onCompletion(onCompletion) {} + +DataReplicator::OnCompletionGuard::~OnCompletionGuard() { + MONGO_DESTRUCTOR_GUARD({ + if (!_lastAppliedSet) { + severe() << "It is a programming error to destroy this initial sync attempt completion " + "guard without the caller providing a result for '_lastApplied'"; + } + invariant(_lastAppliedSet); + // _onCompletion() must be called outside the DataReplicator's lock to avoid a deadlock. + _onCompletion(_lastApplied); + }); +} + +void DataReplicator::OnCompletionGuard::setResultAndCancelRemainingWork_inlock( + const stdx::lock_guard<stdx::mutex>&, const StatusWith<OpTimeWithHash>& lastApplied) { + _setResultAndCancelRemainingWork_inlock(lastApplied); +} + +void DataReplicator::OnCompletionGuard::setResultAndCancelRemainingWork_inlock( + const stdx::unique_lock<stdx::mutex>& lock, const StatusWith<OpTimeWithHash>& lastApplied) { + invariant(lock.owns_lock()); + _setResultAndCancelRemainingWork_inlock(lastApplied); +} + +void DataReplicator::OnCompletionGuard::_setResultAndCancelRemainingWork_inlock( + const StatusWith<OpTimeWithHash>& lastApplied) { + if (_lastAppliedSet) { + return; + } + _lastApplied = lastApplied; + _lastAppliedSet = true; + + // It is fine to call this multiple times. + _cancelRemainingWorkInLock(); +} + std::string DataReplicator::Stats::toString() const { return toBSON().toString(); } diff --git a/src/mongo/db/repl/data_replicator.h b/src/mongo/db/repl/data_replicator.h index 7a7cd96512f..4ee9c3082e9 100644 --- a/src/mongo/db/repl/data_replicator.h +++ b/src/mongo/db/repl/data_replicator.h @@ -37,7 +37,6 @@ #include "mongo/bson/bsonobj.h" #include "mongo/bson/timestamp.h" #include "mongo/db/namespace_string.h" -#include "mongo/db/repl/callback_completion_guard.h" #include "mongo/db/repl/collection_cloner.h" #include "mongo/db/repl/data_replicator_external_state.h" #include "mongo/db/repl/multiapplier.h" @@ -156,9 +155,52 @@ public: typedef stdx::function<void(const StatusWith<OpTimeWithHash>& lastApplied)> OnCompletionFn; /** - * Callback completion guard for data replicator. - */ - using OnCompletionGuard = CallbackCompletionGuard<StatusWith<OpTimeWithHash>>; + * RAII type that stores the result of a single initial sync attempt. + * Only the first result passed to setResultAndCancelRemainingWork_inlock() is saved. + * Calls '_onCompletion' on destruction with result. + * We use an invariant to ensure that a result has been provided by the caller at destruction. + */ + class OnCompletionGuard { + MONGO_DISALLOW_COPYING(OnCompletionGuard); + + public: + // Function to invoke DataReplicator::_cancelRemainingWork_inlock(). + using CancelRemainingWorkInLockFn = stdx::function<void()>; + + OnCompletionGuard(const CancelRemainingWorkInLockFn& cancelRemainingWorkInLock, + const OnCompletionFn& onCompletion); + ~OnCompletionGuard(); + + /** + * Sets result if called for the first time. + * Cancels remaining work in DataReplicator. + * Requires either a unique_lock or lock_guard to be passed in to ensure that we call + * DataReplicator::_cancelRemainingWork_inlock()) while we have a lock on the data + * replicator's mutex. + */ + void setResultAndCancelRemainingWork_inlock(const stdx::lock_guard<stdx::mutex>& lock, + const StatusWith<OpTimeWithHash>& lastApplied); + void setResultAndCancelRemainingWork_inlock(const stdx::unique_lock<stdx::mutex>& lock, + const StatusWith<OpTimeWithHash>& lastApplied); + + private: + /** + * Once we verified that we have the data replicator lock, this function is called by both + * versions of setResultAndCancelRemainingWork_inlock() to set the result and cancel any + * remaining work in the data replicator. + */ + void _setResultAndCancelRemainingWork_inlock(const StatusWith<OpTimeWithHash>& lastApplied); + + const CancelRemainingWorkInLockFn _cancelRemainingWorkInLock; + const OnCompletionFn _onCompletion; + + // _lastAppliedSet and _lastApplied are guarded by the mutex of the DataReplicator instance + // that owns this guard object. + bool _lastAppliedSet = false; + StatusWith<OpTimeWithHash> _lastApplied = + Status(ErrorCodes::InternalError, + "This initial sync attempt finished without an explicit result."); + }; struct InitialSyncAttemptInfo { int durationMillis; |