diff options
-rw-r--r-- | jstests/replsets/migrating_tenant_mtab_blocks_writes.js | 71 | ||||
-rw-r--r-- | src/mongo/db/commands/migrate_tenant_cmds.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/commands/migrate_tenant_cmds.h | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/migrate_tenant_state_machine.idl | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/migrating_tenant_donor_util.cpp | 82 | ||||
-rw-r--r-- | src/mongo/db/repl/migrating_tenant_donor_util.h | 5 |
6 files changed, 98 insertions, 100 deletions
diff --git a/jstests/replsets/migrating_tenant_mtab_blocks_writes.js b/jstests/replsets/migrating_tenant_mtab_blocks_writes.js index ca8dcdcc2d9..7afc1467e79 100644 --- a/jstests/replsets/migrating_tenant_mtab_blocks_writes.js +++ b/jstests/replsets/migrating_tenant_mtab_blocks_writes.js @@ -3,43 +3,46 @@ * @tags: [requires_fcv_46] */ -(function () { - "use strict"; - const runDonorStartMigrationCommand = - (primaryConnection, migrationId, recipientConnectionString, dbPrefix, readPreference) => { - return primaryConnection.adminCommand({ - donorStartMigration: 1, - migrationId, - recipientConnectionString, - databasePrefix: dbPrefix, - readPreference - }); - }; - - // the value of the access enum in MigratingTenantAccessBlocker for the 'kBlockWritesAndReads' access state. - const kBlockReadsAndWrites = 2; - const rst = new ReplSetTest({ nodes: 1 }); - rst.startSet(); - rst.initiate(); - - const donorPrimary = rst.getPrimary(); - - const kMigrationId = new UUID(); - const kRecipientConnectionString = new ReplSetTest({ nodes: 1 }).getURL(); - - const kReadPreference = { - mode: "primary" +(function() { +"use strict"; +const runDonorStartMigrationCommand = + (primaryConnection, migrationId, recipientConnectionString, dbPrefix, readPreference) => { + return primaryConnection.adminCommand({ + donorStartMigration: 1, + migrationId, + recipientConnectionString, + databasePrefix: dbPrefix, + readPreference + }); }; - const kDBPrefixes = 'databaseABC'; - jsTest.log('Running donorStartMigration command.') - assert.commandWorked(runDonorStartMigrationCommand(donorPrimary, kMigrationId, kRecipientConnectionString, kDBPrefixes, kReadPreference)); +// the value of the access enum in MigratingTenantAccessBlocker for the 'kBlockWritesAndReads' +// access state. +const kBlockReadsAndWrites = 2; +const rst = new ReplSetTest({nodes: 1}); +rst.startSet(); +rst.initiate(); - jsTest.log('Running the serverStatus command.') - const migratingTenantServerStatus = donorPrimary.adminCommand({ serverStatus: 1 }).migratingTenantAccessBlocker; +const donorPrimary = rst.getPrimary(); - assert.eq(migratingTenantServerStatus.access, kBlockReadsAndWrites); - assert(migratingTenantServerStatus.blockTimestamp); +const kMigrationId = new UUID(); +const kRecipientConnectionString = new ReplSetTest({nodes: 1}).getURL(); - rst.stopSet(); +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 migratingTenantServerStatus = + donorPrimary.adminCommand({serverStatus: 1}).migratingTenantAccessBlocker; + +assert.eq(migratingTenantServerStatus.access, kBlockReadsAndWrites); +assert(migratingTenantServerStatus.blockTimestamp); + +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 e25721e54ad..2a5a95fcd6c 100644 --- a/src/mongo/db/commands/migrate_tenant_cmds.cpp +++ b/src/mongo/db/commands/migrate_tenant_cmds.cpp @@ -39,23 +39,24 @@ namespace mongo { namespace { -class DonorStartMigrationCmd : public MigrationDonorCmdBase<DonorStartMigrationCmd> { +class DonorStartMigrationCmd : public TenantMigrationDonorCmdBase<DonorStartMigrationCmd> { public: using Request = DonorStartMigration; - using ParentInvocation = MigrationDonorCmdBase<DonorStartMigrationCmd>::Invocation; + using ParentInvocation = TenantMigrationDonorCmdBase<DonorStartMigrationCmd>::Invocation; class Invocation : public ParentInvocation { using ParentInvocation::ParentInvocation; public: void typedRun(OperationContext* opCtx) { const auto requestBody = request(); - auto donorDocument = getDonorDocumentFromRequest(requestBody); + auto donorStateDocument = getDonorStateDocumentFromRequest(requestBody); - migrating_tenant_donor_util::persistDonorStateDocument(opCtx, donorDocument); - migrating_tenant_donor_util::dataSync(opCtx, donorDocument); + migrating_tenant_donor_util::persistDonorStateDocument(opCtx, donorStateDocument); + migrating_tenant_donor_util::dataSync(opCtx, donorStateDocument); } - TenantMigrationDonorDocument getDonorDocumentFromRequest(const RequestType& requestBody) { + TenantMigrationDonorDocument getDonorStateDocumentFromRequest( + const RequestType& requestBody) { mongo::UUID migrationId = requestBody.getMigrationId(); std::string recipientURI = requestBody.getRecipientConnectionString().toString(); @@ -63,10 +64,10 @@ public: auto donorStartState = TenantMigrationDonorStateEnum::kDataSync; bool garbageCollect = false; - const TenantMigrationDonorDocument donorDocument( - OID::gen(), migrationId, recipientURI, dbPrefix, donorStartState, garbageCollect); + const TenantMigrationDonorDocument donorStateDocument( + migrationId, recipientURI, dbPrefix, donorStartState, garbageCollect); - return donorDocument; + return donorStateDocument; } private: @@ -81,10 +82,11 @@ public: } donorStartMigrationCmd; class DonorWaitForMigrationToCommitCmd - : public MigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd> { + : public TenantMigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd> { public: using Request = DonorWaitForMigrationToCommit; - using ParentInvocation = MigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd>::Invocation; + using ParentInvocation = + TenantMigrationDonorCmdBase<DonorWaitForMigrationToCommitCmd>::Invocation; class Invocation : public ParentInvocation { using ParentInvocation::ParentInvocation; @@ -101,10 +103,10 @@ public: } donorWaitForMigrationToCommit; -class DonorForgetMigrationCmd : public MigrationDonorCmdBase<DonorForgetMigrationCmd> { +class DonorForgetMigrationCmd : public TenantMigrationDonorCmdBase<DonorForgetMigrationCmd> { public: using Request = DonorForgetMigration; - using ParentInvocation = MigrationDonorCmdBase<DonorForgetMigrationCmd>::Invocation; + using ParentInvocation = TenantMigrationDonorCmdBase<DonorForgetMigrationCmd>::Invocation; class Invocation : public ParentInvocation { using ParentInvocation::ParentInvocation; diff --git a/src/mongo/db/commands/migrate_tenant_cmds.h b/src/mongo/db/commands/migrate_tenant_cmds.h index 77fc3f6a48f..7224b2ad1a1 100644 --- a/src/mongo/db/commands/migrate_tenant_cmds.h +++ b/src/mongo/db/commands/migrate_tenant_cmds.h @@ -33,7 +33,7 @@ namespace mongo { template <typename DerivedT> -class MigrationDonorCmdBase : public TypedCommand<DerivedT> { +class TenantMigrationDonorCmdBase : public TypedCommand<DerivedT> { public: using TC = TypedCommand<DerivedT>; diff --git a/src/mongo/db/repl/migrate_tenant_state_machine.idl b/src/mongo/db/repl/migrate_tenant_state_machine.idl index 970e33f814c..ce3f3f059e0 100644 --- a/src/mongo/db/repl/migrate_tenant_state_machine.idl +++ b/src/mongo/db/repl/migrate_tenant_state_machine.idl @@ -52,12 +52,9 @@ structs: strict: true fields: _id: - type: objectid - description: "A unique identifier for the document." - cpp_name: id - migrationId: type: uuid description: "Unique identifier for the tenant migration." + cpp_name: id recipientConnectionString: type: string description: "The URI string that the donor will utilize to create a connection with the recipient." @@ -82,12 +79,9 @@ structs: strict: true fields: _id: - type: objectid - description: "A unique identifier for the document." - cpp_name: id - migrationId: type: uuid description: "Unique identifier for the tenant migration." + cpp_name: id donorConnectionString: type: string description: "The URI string that the donor will utilize to create a connection with the recipient." diff --git a/src/mongo/db/repl/migrating_tenant_donor_util.cpp b/src/mongo/db/repl/migrating_tenant_donor_util.cpp index f61e54a959f..aa04d54c57a 100644 --- a/src/mongo/db/repl/migrating_tenant_donor_util.cpp +++ b/src/mongo/db/repl/migrating_tenant_donor_util.cpp @@ -97,8 +97,8 @@ void onTransitionToBlocking(OperationContext* opCtx, TenantMigrationDonorDocumen * the key. */ void startTenantMigrationBlockOnPrimary(OperationContext* opCtx, - const TenantMigrationDonorDocument& donorDoc) { - invariant(donorDoc.getState() == TenantMigrationDonorStateEnum::kDataSync); + const TenantMigrationDonorDocument& donorStateDocument) { + invariant(donorStateDocument.getState() == TenantMigrationDonorStateEnum::kDataSync); auto serviceContext = opCtx->getServiceContext(); executor::TaskExecutor* mtabExecutor = getTenantMigrationExecutor(serviceContext).get(); @@ -107,7 +107,7 @@ void startTenantMigrationBlockOnPrimary(OperationContext* opCtx, mtab->startBlockingWrites(); auto& mtabByPrefix = MigratingTenantAccessBlockerByPrefix::get(serviceContext); - mtabByPrefix.add(donorDoc.getDatabasePrefix(), mtab); + mtabByPrefix.add(donorStateDocument.getDatabasePrefix(), mtab); } /** @@ -115,8 +115,8 @@ void startTenantMigrationBlockOnPrimary(OperationContext* opCtx, * state set to blocking and the blockTimestamp set to the reserved Optime. */ TenantMigrationDonorDocument createUpdatedDonorStateDocument( - const TenantMigrationDonorDocument& originalDoc, const OplogSlot& oplogSlot) { - TenantMigrationDonorDocument updatedDoc = originalDoc; + const TenantMigrationDonorDocument& originalDonorStateDocument, const OplogSlot& oplogSlot) { + TenantMigrationDonorDocument updatedDoc = originalDonorStateDocument; updatedDoc.setState(TenantMigrationDonorStateEnum::kBlocking); updatedDoc.setBlockTimestamp(oplogSlot.getTimestamp()); return updatedDoc; @@ -127,66 +127,62 @@ TenantMigrationDonorDocument createUpdatedDonorStateDocument( * opTime as the oplogSlot. */ CollectionUpdateArgs createUpdateArgumentsForDonorStateDocument( - const TenantMigrationDonorDocument& originalDoc, + const TenantMigrationDonorDocument& originalDonorStateDocument, const OplogSlot& oplogSlot, - const BSONObj& parsedUpdatedDoc) { + const BSONObj& serializedUpdatedDonorStateDocument) { CollectionUpdateArgs args; - args.criteria = BSON("_id" << originalDoc.getId()); + args.criteria = BSON("_id" << originalDonorStateDocument.getId()); args.oplogSlot = oplogSlot; - args.update = parsedUpdatedDoc; + args.update = serializedUpdatedDonorStateDocument; return args; } /** - * Returns the collection that stores the state machine documents for the donor. - */ -Collection* getTenantMigrationDonorsCollection(OperationContext* opCtx) { - AutoGetCollection autoCollection(opCtx, NamespaceString::kMigrationDonorsNamespace, MODE_IX); - return autoCollection.getCollection(); -} - -/** * After reserving the opTime for the write and creating the new updated document with the necessary * update arguments. It will send the update command to the tenant migration donors collection. */ void updateDonorStateDocument(OperationContext* opCtx, Collection* collection, - const TenantMigrationDonorDocument& originalDoc) { + const TenantMigrationDonorDocument& originalDonorStateDocument) { - // Reserve an opTime for the write and use it as the blockTimestamp for the migration. - const auto originalRecordId = - Helpers::findOne(opCtx, collection, originalDoc.toBSON(), false /* requireIndex */); + const auto originalRecordId = Helpers::findOne( + opCtx, collection, originalDonorStateDocument.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]; - BSONObj parsedUpdatedDoc = createUpdatedDonorStateDocument(originalDoc, oplogSlot).toBSON(); - - CollectionUpdateArgs args = - createUpdateArgumentsForDonorStateDocument(originalDoc, oplogSlot, parsedUpdatedDoc); - - collection->updateDocument( - opCtx, - originalRecordId, - Snapshotted<BSONObj>(opCtx->recoveryUnit()->getSnapshotId(), originalDoc.toBSON()), - parsedUpdatedDoc, - false, - nullptr /* OpDebug* */, - &args); + BSONObj serializedUpdatedDonorDoc = + createUpdatedDonorStateDocument(originalDonorStateDocument, oplogSlot).toBSON(); + + CollectionUpdateArgs args = createUpdateArgumentsForDonorStateDocument( + originalDonorStateDocument, oplogSlot, serializedUpdatedDonorDoc); + + const auto originalSnapshot = Snapshotted<BSONObj>(opCtx->recoveryUnit()->getSnapshotId(), + originalDonorStateDocument.toBSON()); + collection->updateDocument(opCtx, + originalRecordId, + originalSnapshot, + serializedUpdatedDonorDoc, + false, + nullptr /* OpDebug* */, + &args); } } // namespace /** * TODO - Implement recipientSyncData command */ -void dataSync(OperationContext* opCtx, const TenantMigrationDonorDocument& originalDoc) { +void dataSync(OperationContext* opCtx, + const TenantMigrationDonorDocument& originalDonorStateDocument) { + invariant(originalDonorStateDocument.getState() == TenantMigrationDonorStateEnum::kDataSync); + // Send recipientSyncData. - startTenantMigrationBlockOnPrimary(opCtx, originalDoc); + startTenantMigrationBlockOnPrimary(opCtx, originalDonorStateDocument); // Update the on-disk state of the migration to "blocking" state. - invariant(originalDoc.getState() == TenantMigrationDonorStateEnum::kDataSync); uassertStatusOK(writeConflictRetry( opCtx, @@ -204,7 +200,7 @@ void dataSync(OperationContext* opCtx, const TenantMigrationDonorDocument& origi } WriteUnitOfWork wuow(opCtx); - updateDonorStateDocument(opCtx, collection, originalDoc); + updateDonorStateDocument(opCtx, collection, originalDonorStateDocument); wuow.commit(); return Status::OK(); @@ -226,14 +222,16 @@ std::shared_ptr<executor::TaskExecutor> getTenantMigrationExecutor(ServiceContex executor::makeNetworkInterface(kNetName, nullptr, nullptr)); } -void onTenantMigrationDonorStateTransition(OperationContext* opCtx, const BSONObj& doc) { - auto donorDoc = TenantMigrationDonorDocument::parse(IDLParserErrorContext("donorDoc"), doc); +void onTenantMigrationDonorStateTransition(OperationContext* opCtx, + const BSONObj& serializedDonorStateDocument) { + auto donorStateDoc = TenantMigrationDonorDocument::parse(IDLParserErrorContext("donorDoc"), + serializedDonorStateDocument); - switch (donorDoc.getState()) { + switch (donorStateDoc.getState()) { case TenantMigrationDonorStateEnum::kDataSync: break; case TenantMigrationDonorStateEnum::kBlocking: - onTransitionToBlocking(opCtx, donorDoc); + onTransitionToBlocking(opCtx, donorStateDoc); break; case TenantMigrationDonorStateEnum::kCommitted: break; diff --git a/src/mongo/db/repl/migrating_tenant_donor_util.h b/src/mongo/db/repl/migrating_tenant_donor_util.h index 1cc74db8f9d..b2cd40e7fb8 100644 --- a/src/mongo/db/repl/migrating_tenant_donor_util.h +++ b/src/mongo/db/repl/migrating_tenant_donor_util.h @@ -41,7 +41,8 @@ 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); +void dataSync(OperationContext* opCtx, + const TenantMigrationDonorDocument& originalDonorStateDocument); /** * Creates a task executor to be used for tenant migration. @@ -55,7 +56,7 @@ std::shared_ptr<executor::TaskExecutor> getTenantMigrationExecutor(ServiceContex void onTenantMigrationDonorStateTransition(OperationContext* opCtx, const BSONObj& doc); void persistDonorStateDocument(OperationContext* opCtx, - const TenantMigrationDonorDocument& donorDoc); + const TenantMigrationDonorDocument& donorStateDocument); } // namespace migrating_tenant_donor_util } // namespace mongo |