summaryrefslogtreecommitdiff
path: root/src/mongo/db/s/active_move_primaries_registry.cpp
diff options
context:
space:
mode:
authorBlake Oler <blake.oler@mongodb.com>2018-02-26 15:50:19 -0500
committerBlake Oler <blake.oler@mongodb.com>2018-02-27 16:05:14 -0500
commitcbe3e978d9fd41b85f2f394ce6182e6579667fd1 (patch)
tree0655752d8862b0588eb6261a5d9c6a6a580e990d /src/mongo/db/s/active_move_primaries_registry.cpp
parent044b03fc7e01c3cc0df135566432837568cb78a3 (diff)
downloadmongo-cbe3e978d9fd41b85f2f394ce6182e6579667fd1.tar.gz
SERVER-33197 Implement joining behavior for movePrimary on shards
Diffstat (limited to 'src/mongo/db/s/active_move_primaries_registry.cpp')
-rw-r--r--src/mongo/db/s/active_move_primaries_registry.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/mongo/db/s/active_move_primaries_registry.cpp b/src/mongo/db/s/active_move_primaries_registry.cpp
new file mode 100644
index 00000000000..eaf2a01a74e
--- /dev/null
+++ b/src/mongo/db/s/active_move_primaries_registry.cpp
@@ -0,0 +1,124 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#include "mongo/db/s/active_move_primaries_registry.h"
+
+#include "mongo/util/assert_util.h"
+
+namespace mongo {
+
+ActiveMovePrimariesRegistry::ActiveMovePrimariesRegistry() = default;
+
+ActiveMovePrimariesRegistry::~ActiveMovePrimariesRegistry() {
+ invariant(!_activeMovePrimaryState);
+}
+
+StatusWith<ScopedMovePrimary> ActiveMovePrimariesRegistry::registerMovePrimary(
+ const ShardMovePrimary& requestArgs) {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ if (_activeMovePrimaryState) {
+ if (_activeMovePrimaryState->requestArgs == requestArgs) {
+ return {ScopedMovePrimary(nullptr, false, _activeMovePrimaryState->notification)};
+ }
+
+ return _activeMovePrimaryState->constructErrorStatus();
+ }
+
+ _activeMovePrimaryState.emplace(requestArgs);
+
+ return {ScopedMovePrimary(this, true, _activeMovePrimaryState->notification)};
+}
+
+boost::optional<NamespaceString> ActiveMovePrimariesRegistry::getActiveMovePrimaryNss() {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ if (_activeMovePrimaryState) {
+ return _activeMovePrimaryState->requestArgs.get_movePrimary();
+ }
+
+ return boost::none;
+}
+
+void ActiveMovePrimariesRegistry::_clearMovePrimary() {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ invariant(_activeMovePrimaryState);
+ _activeMovePrimaryState.reset();
+}
+
+Status ActiveMovePrimariesRegistry::ActiveMovePrimaryState::constructErrorStatus() const {
+ return {ErrorCodes::ConflictingOperationInProgress,
+ str::stream()
+ << "Unable to start new movePrimary operation because this shard is currently "
+ "moving its primary for namespace "
+ << requestArgs.get_movePrimary().ns()
+ << " to "
+ << requestArgs.getTo()};
+}
+
+ScopedMovePrimary::ScopedMovePrimary(ActiveMovePrimariesRegistry* registry,
+ bool shouldExecute,
+ std::shared_ptr<Notification<Status>> completionNotification)
+ : _registry(registry),
+ _shouldExecute(shouldExecute),
+ _completionNotification(std::move(completionNotification)) {}
+
+ScopedMovePrimary::~ScopedMovePrimary() {
+ if (_registry) {
+ // If this is a movePrimary that didn't join an existing movePrimary, the caller must
+ // signal on completion.
+ invariant(_shouldExecute);
+ invariant(*_completionNotification);
+ _registry->_clearMovePrimary();
+ }
+}
+
+ScopedMovePrimary::ScopedMovePrimary(ScopedMovePrimary&& other) {
+ *this = std::move(other);
+}
+
+ScopedMovePrimary& ScopedMovePrimary::operator=(ScopedMovePrimary&& other) {
+ if (&other != this) {
+ _registry = other._registry;
+ other._registry = nullptr;
+ _shouldExecute = other._shouldExecute;
+ _completionNotification = std::move(other._completionNotification);
+ }
+
+ return *this;
+}
+
+void ScopedMovePrimary::signalComplete(Status status) {
+ invariant(_shouldExecute);
+ _completionNotification->set(status);
+}
+
+Status ScopedMovePrimary::waitForCompletion(OperationContext* opCtx) {
+ invariant(!_shouldExecute);
+ return _completionNotification->get(opCtx);
+}
+
+} // namespace mongo