summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-01-19 17:23:28 -0500
committerBenety Goh <benety@mongodb.com>2017-01-19 17:23:28 -0500
commit7bf2874d0fe92c5503f9cde86ac9e341d1889000 (patch)
tree9856cc4b59d867a19e3a550acec9604ea6a3ad43 /src/mongo/db
parentd3e67186d1f9c633e8e69ebb7bf2418d3850688a (diff)
downloadmongo-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/SConscript11
-rw-r--r--src/mongo/db/repl/callback_completion_guard.cpp61
-rw-r--r--src/mongo/db/repl/callback_completion_guard.h171
-rw-r--r--src/mongo/db/repl/data_replicator.cpp40
-rw-r--r--src/mongo/db/repl/data_replicator.h50
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;