diff options
author | Cheahuychou Mao <cheahuychou.mao@mongodb.com> | 2020-07-07 00:42:02 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-08 22:13:41 +0000 |
commit | 9f7dbe76058e0300d182f8f548f37dbf5d4ea16b (patch) | |
tree | ef9f9b292e2b76b1607c8bd3e0233bcc203f54ee /src/mongo | |
parent | b9015cdc8aa845bf172d059c3c1b7f1f03147131 (diff) | |
download | mongo-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.h | 3 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.h | 3 | ||||
-rw-r--r-- | src/mongo/db/op_observer_impl.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/migrate_tenant_state_machine.idl | 63 | ||||
-rw-r--r-- | src/mongo/db/repl/migrating_tenant_donor_util.cpp | 100 | ||||
-rw-r--r-- | src/mongo/db/repl/migrating_tenant_donor_util.h | 47 | ||||
-rw-r--r-- | src/mongo/util/uuid.h | 1 |
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: |