summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Osta <luis.osta@mongodb.com>2020-07-15 21:30:17 +0000
committerLuis Osta <luis.osta@mongodb.com>2020-07-17 15:26:06 +0000
commita701b8503794223b2ae81b7aa7214b4775562ed1 (patch)
tree1ee8bfb54fdb9170063834f3a3f1c00964e45755
parent39ca11ba8370f2078c13996f243e03fb9efa070b (diff)
downloadmongo-a701b8503794223b2ae81b7aa7214b4775562ed1.tar.gz
implemented basic persistance and fixed class command issue
-rw-r--r--jstests/replsets/migrating_tenant_mtab_blocks_writes.js28
-rw-r--r--src/mongo/db/commands/migrate_tenant_cmds.cpp83
-rw-r--r--src/mongo/db/commands/migrate_tenant_cmds.h60
-rw-r--r--src/mongo/db/repl/migrating_tenant_donor_util.cpp25
-rw-r--r--src/mongo/db/repl/migrating_tenant_donor_util.h3
5 files changed, 150 insertions, 49 deletions
diff --git a/jstests/replsets/migrating_tenant_mtab_blocks_writes.js b/jstests/replsets/migrating_tenant_mtab_blocks_writes.js
index a77e7f8328d..5206426b98f 100644
--- a/jstests/replsets/migrating_tenant_mtab_blocks_writes.js
+++ b/jstests/replsets/migrating_tenant_mtab_blocks_writes.js
@@ -5,13 +5,37 @@
(function () {
"use strict";
-
+ const runDonorStartMigrationCommand =
+ (primaryConnection, migrationId, recipientConnectionString, dbPrefix, readPreference) => {
+ return primaryConnection.adminCommand({
+ donorStartMigration: 1,
+ migrationId,
+ recipientConnectionString,
+ databasePrefix: dbPrefix,
+ readPreference
+ });
+ };
const rst = new ReplSetTest({ nodes: 1 });
rst.startSet();
rst.initiate();
- assert(true)
+ const donorPrimary = rst.getPrimary();
+
+ const kMigrationId = new UUID();
+ const kRecipientConnectionString = new ReplSetTest({ nodes: 1 }).getURL();
+
+ const kReadPreference = {
+ mode: "primary"
+ };
+ const kDBPrefixes = 'databaseABC';
+
+ jsTest.log('Running donorStartMigration command.')
+ assert.commandWorked(runDonorStartMigrationCommand(donorPrimary, kMigrationId, kRecipientConnectionString, kDBPrefixes, kReadPreference));
+
+ jsTest.log('Running the serverStatus command.')
+ const res = donorPrimary.adminCommand({ serverStatus: 1 });
+ jsTest.log(tojson(res));
rst.stopSet();
})(); \ No newline at end of file
diff --git a/src/mongo/db/commands/migrate_tenant_cmds.cpp b/src/mongo/db/commands/migrate_tenant_cmds.cpp
index 14eb45c7506..b75dbfbd99f 100644
--- a/src/mongo/db/commands/migrate_tenant_cmds.cpp
+++ b/src/mongo/db/commands/migrate_tenant_cmds.cpp
@@ -26,59 +26,36 @@
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kReplication;
-#include "mongo/db/commands.h"
+#include "mongo/db/commands/migrate_tenant_cmds.h"
#include "mongo/db/commands/migrate_tenant_cmds_gen.h"
#include "mongo/db/repl/migrate_tenant_state_machine_gen.h"
#include "mongo/db/repl/migrating_tenant_donor_util.h"
+#include "mongo/logv2/log.h"
namespace mongo {
namespace {
-template <typename RequestT>
-class MigrationDonorCmdBase : public TypedCommand<MigrationDonorCmdBase<RequestT>> {
+
+class DonorStartMigrationCmd : public MigrationDonorCmdBase<DonorStartMigrationCmd> {
public:
- using Request = RequestT;
- using TC = TypedCommand<MigrationDonorCmdBase<RequestT>>;
+ using Request = DonorStartMigration;
+ using ParentInvocation = MigrationDonorCmdBase<DonorStartMigrationCmd>::Invocation;
+ class Invocation : public ParentInvocation {
+ using ParentInvocation::ParentInvocation;
- class Invocation : public TC::InvocationBase {
public:
- using TC::InvocationBase::InvocationBase;
- using TC::InvocationBase::request;
-
- void typedRun(OperationContext* opCtx) {}
+ void typedRun(OperationContext* opCtx) {
+ const auto requestBody = request();
+ auto donorDocument = getDonorDocumentFromRequest(requestBody);
- private:
- bool supportsWriteConcern() const override {
- return false;
- }
- NamespaceString ns() const override {
- return NamespaceString(request().getDbName(), "");
+ migrating_tenant_donor_util::persistDonorStateMachine(opCtx, donorDocument);
+ migrating_tenant_donor_util::dataSync(opCtx, donorDocument);
}
- void doCheckAuthorization(OperationContext* opCtx) const override {}
- };
-
- bool adminOnly() const override {
- return true;
- }
-
- std::string help() const override {
- return "Multi-tenant migration command on the donor.";
- }
- BasicCommand::AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return BasicCommand::AllowedOnSecondary::kNever;
- }
-};
-
-class DonorStartMigrationCmd : public MigrationDonorCmdBase<DonorStartMigration> {
-public:
- using ParentInvocation = MigrationDonorCmdBase<DonorStartMigration>::Invocation;
- class Invocation final : public ParentInvocation {
- public:
- void typedRun(OperationContext* opCtx) {
- const auto requestBody = request();
+ TenantMigrationDonorDocument getDonorDocumentFromRequest(const RequestType& requestBody) {
mongo::UUID migrationId = requestBody.getMigrationId();
std::string recipientURI = requestBody.getRecipientConnectionString().toString();
@@ -89,14 +66,14 @@ public:
const TenantMigrationDonorDocument donorDocument(
OID::gen(), migrationId, recipientURI, dbPrefix, donorStartState, garbageCollect);
- migrating_tenant_donor_util::dataSync(opCtx, donorDocument);
+ return donorDocument;
}
private:
- void doCheckAuthorization(OperationContext* opCtx) const override {}
+ void doCheckAuthorization(OperationContext* opCtx) const {}
};
- std::string help() const override {
+ std::string help() const {
return "Start migrating databases whose names match the specified prefix to the specified "
"replica set.";
}
@@ -104,12 +81,18 @@ public:
} donorStartMigrationCmd;
class DonorWaitForMigrationToCommitCmd
- : public MigrationDonorCmdBase<DonorWaitForMigrationToCommit> {
+ : public MigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd> {
public:
- using ParentInvocation = MigrationDonorCmdBase<DonorWaitForMigrationToCommit>::Invocation;
- class Invocation final : public ParentInvocation {
+ using Request = DonorWaitForMigrationToCommit;
+ using ParentInvocation = MigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd>::Invocation;
+ class Invocation : public ParentInvocation {
+ using ParentInvocation::ParentInvocation;
+
public:
void typedRun(OperationContext* opCtx) {}
+
+ private:
+ void doCheckAuthorization(OperationContext* opCtx) const {}
};
std::string help() const override {
@@ -118,12 +101,18 @@ public:
} donorWaitForMigrationToCommit;
-class DonorForgetMigrationCmd : public MigrationDonorCmdBase<DonorForgetMigration> {
+class DonorForgetMigrationCmd : public MigrationDonorCmdBase<DonorForgetMigrationCmd> {
public:
- using ParentInvocation = MigrationDonorCmdBase<DonorWaitForMigrationToCommit>::Invocation;
- class Invocation final : public ParentInvocation {
+ using Request = DonorForgetMigration;
+ using ParentInvocation = MigrationDonorCmdBase<DonorForgetMigrationCmd>::Invocation;
+ class Invocation : public ParentInvocation {
+ using ParentInvocation::ParentInvocation;
+
public:
void typedRun(OperationContext* opCtx) {}
+
+ private:
+ void doCheckAuthorization(OperationContext* opCtx) const {}
};
std::string help() const override {
diff --git a/src/mongo/db/commands/migrate_tenant_cmds.h b/src/mongo/db/commands/migrate_tenant_cmds.h
new file mode 100644
index 00000000000..77fc3f6a48f
--- /dev/null
+++ b/src/mongo/db/commands/migrate_tenant_cmds.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2020-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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/commands.h"
+
+namespace mongo {
+
+template <typename DerivedT>
+class MigrationDonorCmdBase : public TypedCommand<DerivedT> {
+public:
+ using TC = TypedCommand<DerivedT>;
+
+ class Invocation : public TC::InvocationBase {
+ using TC::InvocationBase::InvocationBase;
+
+ private:
+ bool supportsWriteConcern() const override {
+ return false;
+ }
+ NamespaceString ns() const {
+ return NamespaceString(TC::InvocationBase::request().getDbName(), "");
+ }
+ };
+
+ bool adminOnly() const override {
+ return true;
+ }
+
+ BasicCommand::AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return BasicCommand::AllowedOnSecondary::kNever;
+ }
+};
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/repl/migrating_tenant_donor_util.cpp b/src/mongo/db/repl/migrating_tenant_donor_util.cpp
index 826551972a6..84c93afacfd 100644
--- a/src/mongo/db/repl/migrating_tenant_donor_util.cpp
+++ b/src/mongo/db/repl/migrating_tenant_donor_util.cpp
@@ -27,7 +27,10 @@
* it in the license file.
*/
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kReplication;
+
#include "mongo/platform/basic.h"
+#include "mongo/util/str.h"
#include "mongo/db/repl/migrating_tenant_donor_util.h"
@@ -36,10 +39,13 @@
#include "mongo/db/dbhelpers.h"
#include "mongo/db/repl/migrate_tenant_state_machine_gen.h"
#include "mongo/db/repl/migrating_tenant_access_blocker_by_prefix.h"
+#include "mongo/db/s/persistent_task_store.h"
#include "mongo/executor/network_interface_factory.h"
#include "mongo/executor/thread_pool_task_executor.h"
+#include "mongo/logv2/log.h"
#include "mongo/util/concurrency/thread_pool.h"
+
namespace mongo {
namespace migrating_tenant_donor_util {
@@ -137,13 +143,16 @@ void dataSync(OperationContext* opCtx, const TenantMigrationDonorDocument& origi
// Reserve an opTime for the write and use it as the blockTimestamp for the migration.
auto oplogSlot = repl::LocalOplogInfo::get(opCtx)->getNextOpTimes(opCtx, 1U)[0];
+
TenantMigrationDonorDocument updatedDoc;
updatedDoc.setId(originalDoc.getId());
updatedDoc.setDatabasePrefix(originalDoc.getDatabasePrefix());
updatedDoc.setState(TenantMigrationDonorStateEnum::kBlocking);
updatedDoc.setBlockTimestamp(oplogSlot.getTimestamp());
+
CollectionUpdateArgs args;
+ // ! Since the updatedDoc isn't properly created, this will throw an error
args.update = updatedDoc.toBSON();
args.criteria = BSON("_id" << originalDoc.getId());
args.oplogSlot = oplogSlot;
@@ -196,6 +205,22 @@ void onTenantMigrationDonorStateTransition(OperationContext* opCtx, const BSONOb
}
}
+void persistDonorStateMachine(OperationContext* opCtx,
+ const TenantMigrationDonorDocument& donorDoc) {
+ PersistentTaskStore<TenantMigrationDonorDocument> store(
+ NamespaceString::kMigrationDonorsNamespace);
+ try {
+ store.add(opCtx, donorDoc);
+ } catch (const ExceptionFor<ErrorCodes::DuplicateKey>&) {
+ uasserted(
+ 4917300,
+ str::stream()
+ << "While attempting to persist the donor state machine for tenant migration"
+ << ", found another document with the same migration id. Attempted migration: "
+ << donorDoc.toBSON());
+ }
+}
+
} // namespace migrating_tenant_donor_util
} // namespace mongo
diff --git a/src/mongo/db/repl/migrating_tenant_donor_util.h b/src/mongo/db/repl/migrating_tenant_donor_util.h
index 64bfe1474ec..fd48b203057 100644
--- a/src/mongo/db/repl/migrating_tenant_donor_util.h
+++ b/src/mongo/db/repl/migrating_tenant_donor_util.h
@@ -53,6 +53,9 @@ std::shared_ptr<executor::TaskExecutor> getTenantMigrationExecutor(ServiceContex
* config.migrationDonors document.
*/
void onTenantMigrationDonorStateTransition(OperationContext* opCtx, const BSONObj& doc);
+
+void persistDonorStateMachine(OperationContext* opCtx,
+ const TenantMigrationDonorDocument& donorDoc);
} // namespace migrating_tenant_donor_util
} // namespace mongo