summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2022-03-15 20:54:08 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-03-15 21:27:02 +0000
commit6076dff1727970e6f94d1d89f6e3a0b2eefd381c (patch)
tree8610cd3534fe42209e6fe371d85070969e54e2a0
parent077b55e6330264b262d87d296a7f7006fece669e (diff)
downloadmongo-6076dff1727970e6f94d1d89f6e3a0b2eefd381c.tar.gz
SERVER-64487 Fix donor access blocker cleanup
-rw-r--r--jstests/replsets/tenant_migration_advance_stable_ts_after_clone.js2
-rw-r--r--jstests/replsets/tenant_migration_multi_writes.js7
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_op_observer.cpp17
-rw-r--r--src/mongo/db/repl/tenant_migration_util.h10
4 files changed, 25 insertions, 11 deletions
diff --git a/jstests/replsets/tenant_migration_advance_stable_ts_after_clone.js b/jstests/replsets/tenant_migration_advance_stable_ts_after_clone.js
index f59d22a17c2..01e903dd52d 100644
--- a/jstests/replsets/tenant_migration_advance_stable_ts_after_clone.js
+++ b/jstests/replsets/tenant_migration_advance_stable_ts_after_clone.js
@@ -26,7 +26,7 @@ const kTenantIdPrefix = "testTenantId";
const kUnrelatedDbNameDonor = "unrelatedDBDonor";
const kUnrelatedDbNameRecipient = "unrelatedDBRecipient";
const collName = "foo";
-const tenantId = kTenantIdPrefix + "_0";
+const tenantId = kTenantIdPrefix + "-0";
const migrationId = UUID();
const migrationOpts = {
migrationIdString: extractUUIDFromObject(migrationId),
diff --git a/jstests/replsets/tenant_migration_multi_writes.js b/jstests/replsets/tenant_migration_multi_writes.js
index c825c29a264..aa05e251432 100644
--- a/jstests/replsets/tenant_migration_multi_writes.js
+++ b/jstests/replsets/tenant_migration_multi_writes.js
@@ -39,7 +39,8 @@ const donorRst = new ReplSetTest({
const oplogMinRetentionHours = 2; // Set to standard Evergreen task timeout time
donorRst.startSet({oplogMinRetentionHours});
donorRst.initiateWithHighElectionTimeout();
-const tenantMigrationTest = new TenantMigrationTest({name: jsTestName(), donorRst: donorRst});
+const tenantMigrationTest =
+ new TenantMigrationTest({name: jsTestName(), donorRst: donorRst, quickGarbageCollection: true});
const recipientRst = tenantMigrationTest.getRecipientRst();
const donorPrimary = donorRst.getPrimary();
@@ -134,6 +135,7 @@ function testMultiWritesWhileInBlockingState(readConcern, writeConcern) {
jsTest.log('Drop DB and wait for garbage collection after test cycle.');
assert.commandWorked(recipientRst.getPrimary().getDB(kDbName).dropDatabase());
+ tenantMigrationTest.waitForMigrationGarbageCollection(migrationId, kTenantId);
}
writesThread.join();
@@ -144,7 +146,8 @@ readWriteConcerns.push({writeConcern: 1, readConcern: 'local'});
readWriteConcerns.push({writeConcern: 'majority', readConcern: 'majority'});
readWriteConcerns.forEach(concerns => {
- jsTest.log(`Test sending multi write while in migration blocking state with ${concerns}`);
+ jsTest.log(
+ `Test sending multi write while in migration blocking state with ${tojson(concerns)}`);
testMultiWritesWhileInBlockingState(concerns.readConcern, concerns.writeConcern);
});
diff --git a/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp b/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp
index 7bb9f9822f1..44640ebb6e7 100644
--- a/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp
+++ b/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp
@@ -78,7 +78,9 @@ void onTransitionToAbortingIndexBuilds(OperationContext* opCtx,
});
}
} else {
- // The protocol is kShardMerge.
+ tassert(6448702,
+ "Bad protocol",
+ donorStateDoc.getProtocol() == MigrationProtocolEnum::kShardMerge);
auto mtab = std::make_shared<TenantMigrationDonorAccessBlocker>(
opCtx->getServiceContext(),
donorStateDoc.getId(),
@@ -195,11 +197,16 @@ public:
// The migration durably aborted and is now marked as garbage collectable,
// remove its TenantMigrationDonorAccessBlocker right away to allow back-to-back
// migration retries.
- if (_donorStateDoc.getProtocol() == MigrationProtocolEnum::kMultitenantMigrations) {
+ if (_donorStateDoc.getProtocol().value_or(
+ MigrationProtocolEnum::kMultitenantMigrations) ==
+ MigrationProtocolEnum::kMultitenantMigrations) {
TenantMigrationAccessBlockerRegistry::get(_opCtx->getServiceContext())
.remove(_donorStateDoc.getTenantId(),
TenantMigrationAccessBlocker::BlockerType::kDonor);
} else {
+ tassert(6448701,
+ "Bad protocol",
+ _donorStateDoc.getProtocol() == MigrationProtocolEnum::kShardMerge);
TenantMigrationAccessBlockerRegistry::get(_opCtx->getServiceContext())
.removeDonorAccessBlocker(_donorStateDoc.getId());
}
@@ -305,12 +312,16 @@ void TenantMigrationDonorOpObserver::aboutToDelete(OperationContext* opCtx,
// TenantMigrationDonorAccessBlocker as soon as its donor state doc is marked as garbage
// collectable. So onDelete should skip removing the TenantMigrationDonorAccessBlocker for
// aborted migrations.
- if (donorStateDoc.getProtocol() == MigrationProtocolEnum::kMultitenantMigrations) {
+ if (donorStateDoc.getProtocol().value_or(MigrationProtocolEnum::kMultitenantMigrations) ==
+ MigrationProtocolEnum::kMultitenantMigrations) {
tenantIdToDeleteDecoration(opCtx) =
donorStateDoc.getState() == TenantMigrationDonorStateEnum::kAborted
? boost::none
: boost::make_optional(donorStateDoc.getTenantId().toString());
} else {
+ tassert(6448700,
+ "Bad protocol",
+ donorStateDoc.getProtocol() == MigrationProtocolEnum::kShardMerge);
migrationIdToDeleteDecoration(opCtx) =
donorStateDoc.getState() == TenantMigrationDonorStateEnum::kAborted
? boost::none
diff --git a/src/mongo/db/repl/tenant_migration_util.h b/src/mongo/db/repl/tenant_migration_util.h
index f3350458182..dff6e245c3c 100644
--- a/src/mongo/db/repl/tenant_migration_util.h
+++ b/src/mongo/db/repl/tenant_migration_util.h
@@ -59,7 +59,8 @@ namespace tenant_migration_util {
inline Status validateDatabasePrefix(const std::string& tenantId) {
const bool isPrefixSupported =
- kUnsupportedTenantIds.find(tenantId) == kUnsupportedTenantIds.end();
+ kUnsupportedTenantIds.find(tenantId) == kUnsupportedTenantIds.end() &&
+ tenantId.find("_") == std::string::npos;
return isPrefixSupported
? Status::OK()
@@ -69,10 +70,9 @@ inline Status validateDatabasePrefix(const std::string& tenantId) {
inline Status validateDatabasePrefix(const std::vector<std::string>& tenantsId) {
for (const auto& tenantId : tenantsId) {
- if (kUnsupportedTenantIds.find(tenantId) != kUnsupportedTenantIds.end()) {
- return Status(ErrorCodes::BadValue,
- str::stream()
- << "cannot migrate databases for tenant \'" << tenantId << "'");
+ auto status = validateDatabasePrefix(tenantId);
+ if (!status.isOK()) {
+ return status;
}
}