summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMatthew Russotto <matthew.russotto@mongodb.com>2021-02-12 10:43:46 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-18 22:45:49 +0000
commit23d05fa8b976208fd5564ace429d90d9f6c93509 (patch)
treea5bcd1f641cd56c2eb03f68452030a27db517259 /src/mongo
parent70f68a9cf7077af529fd305fa7789ab0d26dd3d1 (diff)
downloadmongo-23d05fa8b976208fd5564ace429d90d9f6c93509.tar.gz
SERVER-53553 Make tenant migration recipient to start cloning tenant data only after the donor node's lastCommittedOpTime is >= startMigrationDonorTimestamp
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.cpp3
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp12
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.cpp55
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.h4
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service_test.cpp130
-rw-r--r--src/mongo/db/repl/tenant_migration_state_machine.idl8
6 files changed, 192 insertions, 20 deletions
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
index 0ca25375e55..7d8a25623ba 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
@@ -67,6 +67,7 @@ public:
TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
cmd.getDonorConnectionString().toString(),
cmd.getTenantId().toString(),
+ cmd.getStartMigrationDonorTimestamp(),
cmd.getReadPreference());
if (!repl::tenantMigrationDisableX509Auth) {
@@ -176,9 +177,11 @@ public:
// recipientSyncData. But even if that's the case, we still need to create an instance
// and persist a state document that's marked garbage collectable (which is done by the
// main chain).
+ const Timestamp kUnusedStartMigrationTimestamp(1, 1);
TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
cmd.getDonorConnectionString().toString(),
cmd.getTenantId().toString(),
+ kUnusedStartMigrationTimestamp,
cmd.getReadPreference());
if (!repl::tenantMigrationDisableX509Auth) {
uassert(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
index fff534b61c0..980f5243591 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
@@ -46,6 +46,8 @@ namespace repl {
using namespace tenantMigrationRecipientEntryHelpers;
+const Timestamp kDefaultStartMigrationTimestamp(1, 1);
+
class TenantMigrationRecipientEntryHelpersTest : public ServiceContextMongoDTest {
public:
void setUp() override {
@@ -113,6 +115,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
migrationUUID,
"donor-rs0/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
activeTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), activeTenantAStateDoc));
@@ -122,6 +125,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc1(migrationUUID,
"donor-rs1/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto status = insertStateDoc(opCtx.get(), stateDoc1);
@@ -132,6 +136,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc2(migrationUUID,
"donor-rs0/localhost:12345",
"tenantB",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
@@ -142,6 +147,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc3(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
status = insertStateDoc(opCtx.get(), stateDoc3);
@@ -152,6 +158,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc4(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantB",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
@@ -167,6 +174,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
migrationUUID,
"donor-rs0/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
inactiveTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
inactiveTenantAStateDoc.setExpireAt(Date_t::now());
@@ -177,6 +185,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc1(migrationUUID,
"donor-rs1/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
@@ -187,6 +196,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc2(migrationUUID,
"donor-rs0/localhost:12345",
"tenantB",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
@@ -197,6 +207,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc3(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc3));
@@ -206,6 +217,7 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc4(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantC",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.cpp b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
index c40612d3045..1768100e54a 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
@@ -515,31 +515,46 @@ TenantMigrationRecipientService::Instance::_createAndConnectClients() {
auto client = _connectAndAuth(serverAddress, applicationName);
boost::optional<repl::OpTime> startApplyingOpTime;
+ Timestamp startMigrationDonorTimestamp;
{
stdx::lock_guard lk(_mutex);
startApplyingOpTime = _stateDoc.getStartApplyingDonorOpTime();
+ startMigrationDonorTimestamp =
+ _stateDoc.getStartMigrationDonorTimestamp();
}
- if (startApplyingOpTime) {
- auto majoritySnapshotOpTime = _getDonorMajorityOpTime(client);
-
- if (majoritySnapshotOpTime < *startApplyingOpTime) {
- stdx::lock_guard lk(_mutex);
- const auto now =
- getGlobalServiceContext()->getFastClockSource()->now();
- _excludeDonorHost(
- lk,
- serverAddress,
- now + Milliseconds(tenantMigrationExcludeDonorHostTimeoutMS));
- uasserted(
- kDelayedMajorityOpTimeErrorCode,
- str::stream()
- << "majoritySnapshotOpTime on donor host must not be behind "
- "startApplyingDonorOpTime, majoritySnapshotOpTime: "
- << majoritySnapshotOpTime.toString()
- << "; startApplyingDonorOpTime: "
- << (*startApplyingOpTime).toString());
- }
+ auto majoritySnapshotOpTime = _getDonorMajorityOpTime(client);
+ if (majoritySnapshotOpTime.getTimestamp() < startMigrationDonorTimestamp) {
+ stdx::lock_guard lk(_mutex);
+ const auto now = getGlobalServiceContext()->getFastClockSource()->now();
+ _excludeDonorHost(
+ lk,
+ serverAddress,
+ now + Milliseconds(tenantMigrationExcludeDonorHostTimeoutMS));
+ uasserted(
+ kDelayedMajorityOpTimeErrorCode,
+ str::stream()
+ << "majoritySnapshotOpTime on donor host must not be behind "
+ "startMigrationDonorTimestamp, majoritySnapshotOpTime: "
+ << majoritySnapshotOpTime.toString()
+ << "; startMigrationDonorTimestamp: "
+ << startMigrationDonorTimestamp.toString());
+ }
+ if (startApplyingOpTime && majoritySnapshotOpTime < *startApplyingOpTime) {
+ stdx::lock_guard lk(_mutex);
+ const auto now = getGlobalServiceContext()->getFastClockSource()->now();
+ _excludeDonorHost(
+ lk,
+ serverAddress,
+ now + Milliseconds(tenantMigrationExcludeDonorHostTimeoutMS));
+ uasserted(
+ kDelayedMajorityOpTimeErrorCode,
+ str::stream()
+ << "majoritySnapshotOpTime on donor host must not be behind "
+ "startApplyingDonorOpTime, majoritySnapshotOpTime: "
+ << majoritySnapshotOpTime.toString()
+ << "; startApplyingDonorOpTime: "
+ << (*startApplyingOpTime).toString());
}
// Application name is constructed such that it doesn't exceed
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.h b/src/mongo/db/repl/tenant_migration_recipient_service.h
index dae86b0dd74..504fffb0596 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.h
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.h
@@ -176,6 +176,10 @@ public:
_excludeDonorHost(lk, host, until);
}
+ const auto& getExcludedDonorHosts_forTest() {
+ return _excludedDonorHosts;
+ }
+
private:
friend class TenantMigrationRecipientServiceTest;
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
index 6e3e78787be..ab6829fb324 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
@@ -76,6 +76,7 @@ namespace repl {
namespace {
constexpr std::int32_t stopFailPointErrorCode = 4880402;
+const Timestamp kDefaultStartMigrationTimestamp(1, 1);
OplogEntry makeOplogEntry(OpTime opTime,
OpTypeEnum opType,
@@ -444,6 +445,7 @@ TEST_F(TenantMigrationRecipientServiceTest, BasicTenantMigrationRecipientService
migrationUUID,
"donor-rs/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -469,6 +471,7 @@ TEST_F(TenantMigrationRecipientServiceTest, InstanceReportsErrorOnFailureWhilePe
migrationUUID,
"donor-rs/localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -497,10 +500,13 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -545,10 +551,13 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_S
MockReplicaSet replSet("donorSet", 2, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::SecondaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -594,10 +603,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
MockReplicaSet replSet("donorSet", 2);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -666,10 +678,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
MockReplicaSet replSet("donorSet", 2);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -735,10 +750,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
MockReplicaSet replSet("donorSet", 2);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::Nearest));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -810,10 +828,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
MockReplicaSet replSet("donorSet", 2);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -876,10 +897,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
MockReplicaSet replSet("donorSet", 2);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -957,6 +981,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
initialStateDocument.setStartApplyingDonorOpTime(startApplyingOpTime);
@@ -989,6 +1014,70 @@ TEST_F(TenantMigrationRecipientServiceTest,
taskFp->setMode(FailPoint::off, 0);
}
+TEST_F(TenantMigrationRecipientServiceTest,
+ TenantMigrationRecipientConnection_RemoteMajorityOpTimeBehindStartMigrationDonorTimestamp) {
+ stopFailPointEnableBlock fp("fpAfterConnectingTenantMigrationRecipientInstance");
+
+ const UUID migrationUUID = UUID::gen();
+ const OpTime remoteMajorityOpTime(Timestamp(5, 1), 1);
+ const Timestamp startMigrationDonorTimestamp(6, 1);
+
+ auto taskFp = globalFailPointRegistry().find("hangBeforeTaskCompletion");
+ auto timesEntered = taskFp->setMode(FailPoint::alwaysOn, 0);
+
+ // Insert the remote majority optime into the oplogs of the first two hosts.
+ MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ const auto hosts = replSet.getHosts();
+ const std::vector<HostAndPort> advancedOpTimeHosts = {hosts[0], hosts[1]};
+
+ insertTopOfOplog(&replSet, remoteMajorityOpTime, advancedOpTimeHosts);
+ insertTopOfOplog(&replSet, OpTime(startMigrationDonorTimestamp, 1), {hosts.at(2)});
+
+ TenantMigrationRecipientDocument initialStateDocument(
+ migrationUUID,
+ replSet.getConnectionString(),
+ "tenantA",
+ startMigrationDonorTimestamp,
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
+
+ // Create and start the instance.
+ auto opCtx = makeOperationContext();
+ auto instance = TenantMigrationRecipientService::Instance::getOrCreate(
+ opCtx.get(), _service, initialStateDocument.toBSON());
+ ASSERT(instance.get());
+ ASSERT_EQ(migrationUUID, instance->getMigrationUUID());
+
+ taskFp->waitForTimesEntered(timesEntered + 1);
+
+ auto* client = getClient(instance.get());
+ auto* oplogFetcherClient = getOplogFetcherClient(instance.get());
+ // Both clients should be populated.
+ ASSERT(client);
+ ASSERT(oplogFetcherClient);
+
+ // Clients should be distinct.
+ ASSERT(client != oplogFetcherClient);
+
+ // Clients should be connected to donor node at index 2.
+ auto donorHost = hosts[2].toString();
+ ASSERT_EQ(donorHost, client->getServerAddress());
+ ASSERT(client->isStillConnected());
+ ASSERT_EQ(donorHost, oplogFetcherClient->getServerAddress());
+ ASSERT(oplogFetcherClient->isStillConnected());
+
+ // Since we were using primaryPreferred read preference, we should have tried hosts[0]
+ // and had it rejected.
+ const auto& excludedHosts = instance->getExcludedDonorHosts_forTest();
+ ASSERT_TRUE(std::find_if(excludedHosts.begin(),
+ excludedHosts.end(),
+ [hosts](const std::pair<HostAndPort, Date_t>& a) {
+ return a.first == hosts[0];
+ }) != excludedHosts.end());
+
+ taskFp->setMode(FailPoint::off, 0);
+}
+
TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_PrimaryFailsOver) {
stopFailPointEnableBlock fp("fpAfterConnectingTenantMigrationRecipientInstance");
@@ -999,6 +1088,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
MockReplicaSet replSet("donorSet", 2, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
// Primary is unavailable.
replSet.kill(replSet.getHosts()[0].toString());
@@ -1006,6 +1097,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1049,6 +1141,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_B
migrationUUID,
"broken,connect,string,no,set,name",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1070,6 +1163,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
"localhost:12345",
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1094,6 +1188,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1131,6 +1226,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1173,6 +1269,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1217,6 +1314,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1251,6 +1349,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1284,6 +1383,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartOplogFe
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1337,6 +1437,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartsCloner
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1390,6 +1491,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherFailsDuringOplogApplicat
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1444,6 +1546,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherResumesFromTopOfOplogBuf
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1546,6 +1649,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherNoDocInBufferToResumeFro
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1650,6 +1754,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromLastNoOpOplog
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1768,6 +1873,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromStartDonorApp
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -1924,6 +2030,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2028,6 +2135,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierFails) {
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2092,6 +2200,7 @@ TEST_F(TenantMigrationRecipientServiceTest, StoppingApplierAllowsCompletion) {
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2145,6 +2254,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientAddResumeTok
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2245,6 +2355,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_BeforeRun)
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2280,6 +2391,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToIniti
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2312,6 +2424,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_WaitUntilSt
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2392,6 +2505,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterStartO
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2453,6 +2567,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterConsis
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2539,6 +2654,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterFail)
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2618,6 +2734,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToMarkG
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2663,10 +2780,13 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientServiceRecor
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2695,10 +2815,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2731,10 +2854,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2776,10 +2902,13 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
@@ -2813,6 +2942,7 @@ TEST_F(TenantMigrationRecipientServiceTest, WaitUntilTimestampIsMajorityCommitte
migrationUUID,
replSet.getConnectionString(),
"tenantA",
+ kDefaultStartMigrationTimestamp,
ReadPreferenceSetting(ReadPreference::PrimaryOnly));
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
diff --git a/src/mongo/db/repl/tenant_migration_state_machine.idl b/src/mongo/db/repl/tenant_migration_state_machine.idl
index e57961e674b..296fd91dd72 100644
--- a/src/mongo/db/repl/tenant_migration_state_machine.idl
+++ b/src/mongo/db/repl/tenant_migration_state_machine.idl
@@ -153,6 +153,14 @@ structs:
description: "The tenantId for the migration."
validator:
callback: "tenant_migration_util::validateDatabasePrefix"
+ startMigrationDonorTimestamp:
+ type: timestamp
+ description: >-
+ Timestamp after all index builds for tenant are complete or aborted. Recipient
+ must not start cloning/fetching oplog entries from the donor until this
+ timestamp is majority committed.
+ validator:
+ callback: "tenant_migration_util::validateTimestampNotNull"
readPreference:
type: readPreference
description: >-