summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorCheahuychou Mao <cheahuychou.mao@mongodb.com>2020-07-07 00:42:02 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-08 22:13:41 +0000
commit9f7dbe76058e0300d182f8f548f37dbf5d4ea16b (patch)
treeef9f9b292e2b76b1607c8bd3e0233bcc203f54ee /src/mongo
parentb9015cdc8aa845bf172d059c3c1b7f1f03147131 (diff)
downloadmongo-9f7dbe76058e0300d182f8f548f37dbf5d4ea16b.tar.gz
SERVER-49180 Make the donor's dataSync function reserve an OpTime at which to do the "start blocking" write
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/catalog/collection.h3
-rw-r--r--src/mongo/db/namespace_string.cpp3
-rw-r--r--src/mongo/db/namespace_string.h3
-rw-r--r--src/mongo/db/op_observer_impl.cpp3
-rw-r--r--src/mongo/db/repl/SConscript2
-rw-r--r--src/mongo/db/repl/migrate_tenant_state_machine.idl63
-rw-r--r--src/mongo/db/repl/migrating_tenant_donor_util.cpp100
-rw-r--r--src/mongo/db/repl/migrating_tenant_donor_util.h47
-rw-r--r--src/mongo/util/uuid.h1
9 files changed, 225 insertions, 0 deletions
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index c05226fb4ce..337e474e1dd 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -95,6 +95,9 @@ struct CollectionUpdateArgs {
StoreDocOption storeDocOption = StoreDocOption::None;
bool preImageRecordingEnabledForCollection = false;
+
+ // Set if an OpTime was reserved for the update ahead of time.
+ boost::optional<OplogSlot> oplogSlot = boost::none;
};
/**
diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp
index 9c01465712a..92c46ef6652 100644
--- a/src/mongo/db/namespace_string.cpp
+++ b/src/mongo/db/namespace_string.cpp
@@ -69,6 +69,9 @@ const NamespaceString NamespaceString::kTransactionCoordinatorsNamespace(
const NamespaceString NamespaceString::kMigrationCoordinatorsNamespace(NamespaceString::kConfigDb,
"migrationCoordinators");
+const NamespaceString NamespaceString::kMigrationDonorsNamespace(NamespaceString::kConfigDb,
+ "migrationDonors");
+
const NamespaceString NamespaceString::kShardConfigCollectionsNamespace(NamespaceString::kConfigDb,
"cache.collections");
const NamespaceString NamespaceString::kShardConfigDatabasesNamespace(NamespaceString::kConfigDb,
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index 3b15575292b..c80d9eb3bb1 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -106,6 +106,9 @@ public:
// Namespace for storing the persisted state of migration coordinators.
static const NamespaceString kMigrationCoordinatorsNamespace;
+ // Namespace for storing the persisted state of tenant migration donors.
+ static const NamespaceString kMigrationDonorsNamespace;
+
// Namespace for replica set configuration settings.
static const NamespaceString kSystemReplSetNamespace;
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index 92710526e59..f051925c4b4 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -192,6 +192,9 @@ OpTimeBundle replLogUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs&
oplogEntry.setFromMigrateIfTrue(args.updateArgs.fromMigrate);
// oplogLink could have been changed to include pre/postImageOpTime by the previous no-op write.
repl::appendOplogEntryChainInfo(opCtx, &oplogEntry, &oplogLink, args.updateArgs.stmtId);
+ if (args.updateArgs.oplogSlot) {
+ oplogEntry.setOpTime(*args.updateArgs.oplogSlot);
+ }
opTimes.writeOpTime = logOperation(opCtx, &oplogEntry);
opTimes.wallClockTime = oplogEntry.getWallClockTime();
return opTimes;
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index 2f89d244e6b..21d7b496a20 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -1181,9 +1181,11 @@ env.Library(
env.Library(
target="serveronly_repl",
source=[
+ 'migrating_tenant_donor_util.cpp',
'noop_writer.cpp',
"replication_coordinator_external_state_impl.cpp",
"sync_source_feedback.cpp",
+ env.Idlc('migrate_tenant_state_machine.idl')[0],
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
diff --git a/src/mongo/db/repl/migrate_tenant_state_machine.idl b/src/mongo/db/repl/migrate_tenant_state_machine.idl
new file mode 100644
index 00000000000..ba9cdba45b3
--- /dev/null
+++ b/src/mongo/db/repl/migrate_tenant_state_machine.idl
@@ -0,0 +1,63 @@
+# 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.
+#
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+enums:
+ TenantMigrationDonorState:
+ description: "The state of an in-progress tenant migration."
+ type: string
+ values:
+ kDataSync: "data sync"
+ kBlocking: "blocking"
+ kCommitted: "committed"
+ kAborted: "aborted"
+
+structs:
+ tenantMigrationDonorDocument:
+ description: "Represents an in-progress tenant migration on the migration donor."
+ strict: true
+ fields:
+ _id:
+ type: objectid
+ description: "A unique identifier for the document."
+ cpp_name: id
+ databasePrefix:
+ type: string
+ description: "The database prefix for the migration."
+ blockTimestamp:
+ type: timestamp
+ description: "The timestamp at which writes and causal reads against the databases
+ being migrated should start blocking."
+ optional: true
+ state:
+ type: TenantMigrationDonorState
+ description: "The state of the tenant migration."
diff --git a/src/mongo/db/repl/migrating_tenant_donor_util.cpp b/src/mongo/db/repl/migrating_tenant_donor_util.cpp
new file mode 100644
index 00000000000..5aac1584f02
--- /dev/null
+++ b/src/mongo/db/repl/migrating_tenant_donor_util.cpp
@@ -0,0 +1,100 @@
+/**
+ * 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/platform/basic.h"
+
+#include "mongo/db/repl/migrating_tenant_donor_util.h"
+
+#include "mongo/db/concurrency/write_conflict_exception.h"
+#include "mongo/db/db_raii.h"
+#include "mongo/db/dbhelpers.h"
+
+namespace mongo {
+
+namespace migrating_tenant_donor_util {
+void dataSync(OperationContext* opCtx, const TenantMigrationDonorDocument& originalDoc) {
+ // Send recipientSyncData.
+
+ // Call startBlockingWrites.
+
+ // Update the on-disk state of the migration to "blocking" state.
+ invariant(originalDoc.getState() == TenantMigrationDonorStateEnum::kDataSync);
+
+ uassertStatusOK(writeConflictRetry(
+ opCtx,
+ "doStartBlockingWrite",
+ NamespaceString::kMigrationDonorsNamespace.ns(),
+ [&]() -> Status {
+ AutoGetCollection autoCollection(
+ opCtx, NamespaceString::kMigrationDonorsNamespace, MODE_IX);
+ Collection* collection = autoCollection.getCollection();
+
+ if (!collection) {
+ return Status(ErrorCodes::NamespaceNotFound,
+ str::stream() << NamespaceString::kMigrationDonorsNamespace.ns()
+ << " does not exist");
+ }
+
+ WriteUnitOfWork wuow(opCtx);
+
+ const auto originalRecordId =
+ Helpers::findOne(opCtx, collection, originalDoc.toBSON(), false /* requireIndex */);
+ invariant(!originalRecordId.isNull());
+
+ // 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;
+ args.update = updatedDoc.toBSON();
+ args.criteria = BSON("_id" << originalDoc.getId());
+ args.oplogSlot = oplogSlot;
+
+ collection->updateDocument(
+ opCtx,
+ originalRecordId,
+ Snapshotted<BSONObj>(opCtx->recoveryUnit()->getSnapshotId(), originalDoc.toBSON()),
+ updatedDoc.toBSON(),
+ false,
+ nullptr /* OpDebug* */,
+ &args);
+
+ wuow.commit();
+
+ return Status::OK();
+ }));
+}
+} // 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
new file mode 100644
index 00000000000..14f93fd2bb5
--- /dev/null
+++ b/src/mongo/db/repl/migrating_tenant_donor_util.h
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+#include "mongo/db/operation_context.h"
+#include "mongo/db/repl/migrate_tenant_state_machine_gen.h"
+
+namespace mongo {
+
+namespace migrating_tenant_donor_util {
+
+/**
+ * Sends recipientSyncData to the recipient until success and starts blocking writes and causal
+ * reads.
+ */
+void dataSync(OperationContext* opCtx, const TenantMigrationDonorDocument& donorDoc);
+
+} // namespace migrating_tenant_donor_util
+
+} // namespace mongo
diff --git a/src/mongo/util/uuid.h b/src/mongo/util/uuid.h
index a9c087f7777..867f405dfcb 100644
--- a/src/mongo/util/uuid.h
+++ b/src/mongo/util/uuid.h
@@ -87,6 +87,7 @@ class UUID {
friend class repl::InitialSyncIdDocument;
friend class ResumeTokenInternal;
friend class ShardCollectionTypeBase;
+ friend class TenantMigrationDonorDocument;
friend class VoteCommitIndexBuild;
public: