summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/resmokeconfig/suites/tenant_migration_jscore_passthrough.yml2
-rw-r--r--jstests/libs/override_methods/inject_tenant_prefix.js6
-rw-r--r--jstests/replsets/reads_during_tenant_migration.js36
-rw-r--r--jstests/replsets/writes_during_tenant_migration.js28
-rw-r--r--src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.cpp18
-rw-r--r--src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.h9
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_util.cpp15
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_util.h2
8 files changed, 79 insertions, 37 deletions
diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_jscore_passthrough.yml
index 240a9c94609..0dc9bb17995 100644
--- a/buildscripts/resmokeconfig/suites/tenant_migration_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/tenant_migration_jscore_passthrough.yml
@@ -67,7 +67,7 @@ executor:
load('jstests/libs/override_methods/inject_tenant_prefix.js');
global_vars:
TestData: &TestData
- dbPrefix: "tenantMigrationDbPrefix_"
+ dbPrefix: "tenantMigrationDbPrefix"
# TODO (SERVER-50494): Implement proxy's retry logic for batch write commands.
disableBatchWrites: true
readMode: commands
diff --git a/jstests/libs/override_methods/inject_tenant_prefix.js b/jstests/libs/override_methods/inject_tenant_prefix.js
index 3d180875019..0f87ca1af4c 100644
--- a/jstests/libs/override_methods/inject_tenant_prefix.js
+++ b/jstests/libs/override_methods/inject_tenant_prefix.js
@@ -30,7 +30,7 @@ function prependDbPrefixToDbNameIfApplicable(dbName) {
// ignored.
return dbName;
}
- return isBlacklistedDb(dbName) ? dbName : TestData.dbPrefix + dbName;
+ return isBlacklistedDb(dbName) ? dbName : TestData.tenantMigrationDbPrefix + "_" + dbName;
}
/**
@@ -51,7 +51,7 @@ function prependDbPrefixToNsIfApplicable(ns) {
* If the given database name starts TestData.dbPrefix, removes the prefix.
*/
function extractOriginalDbName(dbName) {
- return dbName.replace(TestData.dbPrefix, "");
+ return dbName.replace(TestData.tenantMigrationDbPrefix + "_", "");
}
/**
@@ -67,7 +67,7 @@ function extractOriginalNs(ns) {
* Removes all occurrences of TestDatabase.dbPrefix in the string.
*/
function removeDbPrefixFromString(string) {
- return string.replace(new RegExp(TestData.dbPrefix, "g"), "");
+ return string.replace(new RegExp(TestData.tenantMigrationDbPrefix + "_", "g"), "");
}
/**
diff --git a/jstests/replsets/reads_during_tenant_migration.js b/jstests/replsets/reads_during_tenant_migration.js
index 330cc3b604c..7a64864217d 100644
--- a/jstests/replsets/reads_during_tenant_migration.js
+++ b/jstests/replsets/reads_during_tenant_migration.js
@@ -28,18 +28,19 @@ recipientRst.startSet();
recipientRst.initiate();
const kCollName = "testColl";
+const kTenantDefinedDbName = "0";
const kRecipientConnString = recipientRst.getURL();
const kMaxTimeMS = 5 * 1000;
const kConfigDonorsNS = "config.tenantMigrationDonors";
-function startMigration(host, dbName, recipientConnString) {
+function startMigration(host, dbPrefix, recipientConnString) {
const primary = new Mongo(host);
return primary.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: recipientConnString,
- databasePrefix: dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
});
}
@@ -81,12 +82,13 @@ function runCommand(db, cmd, expectedError) {
*/
function testReadIsRejectedIfSentAfterMigrationHasCommitted(rst, testCase, dbName, collName) {
let primary = rst.getPrimary();
+ const dbPrefix = dbName.split('_')[0];
assert.commandWorked(primary.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: kRecipientConnString,
- databasePrefix: dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
}));
@@ -96,7 +98,7 @@ function testReadIsRejectedIfSentAfterMigrationHasCommitted(rst, testCase, dbNam
// atClusterTime have read timestamp >= commitTimestamp.
rst.awaitLastOpCommitted();
- const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbName});
+ const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbPrefix});
const nodes = testCase.isSupportedOnSecondaries ? rst.nodes : [primary];
nodes.forEach(node => {
const db = node.getDB(dbName);
@@ -117,6 +119,7 @@ function testReadIsRejectedIfSentAfterMigrationHasCommitted(rst, testCase, dbNam
* Tests that the donor does not reject reads after the migration aborts.
*/
function testReadIsAcceptedIfSentAfterMigrationHasAborted(rst, testCase, dbName, collName) {
+ const dbPrefix = dbName.split('_')[0];
const primary = rst.getPrimary();
let abortFp = configureFailPoint(primary, "abortTenantMigrationAfterBlockingStarts");
@@ -124,7 +127,7 @@ function testReadIsAcceptedIfSentAfterMigrationHasAborted(rst, testCase, dbName,
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: kRecipientConnString,
- databasePrefix: dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
}),
ErrorCodes.TenantMigrationAborted);
@@ -136,7 +139,7 @@ function testReadIsAcceptedIfSentAfterMigrationHasAborted(rst, testCase, dbName,
// atClusterTime have read timestamp >= abortTimestamp.
rst.awaitLastOpCommitted();
- const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbName});
+ const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbPrefix});
const nodes = testCase.isSupportedOnSecondaries ? rst.nodes : [primary];
nodes.forEach(node => {
const db = node.getDB(dbName);
@@ -154,10 +157,11 @@ function testReadIsAcceptedIfSentAfterMigrationHasAborted(rst, testCase, dbName,
* blockingTimestamp but does not block linearizable reads.
*/
function testReadBlocksIfMigrationIsInBlocking(rst, testCase, dbName, collName) {
+ const dbPrefix = dbName.split('_')[0];
const primary = rst.getPrimary();
let blockingFp = configureFailPoint(primary, "pauseTenantMigrationAfterBlockingStarts");
- let migrationThread = new Thread(startMigration, primary.host, dbName, kRecipientConnString);
+ let migrationThread = new Thread(startMigration, primary.host, dbPrefix, kRecipientConnString);
// Wait for the migration to enter the blocking state.
migrationThread.start();
@@ -168,7 +172,7 @@ function testReadBlocksIfMigrationIsInBlocking(rst, testCase, dbName, collName)
// unspecified atClusterTime have read timestamp >= blockTimestamp.
rst.awaitLastOpCommitted();
- const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbName});
+ const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbPrefix});
const command = testCase.requiresReadTimestamp
? testCase.command(collName, donorDoc.blockTimestamp)
: testCase.command(collName);
@@ -196,6 +200,7 @@ function testBlockedReadGetsUnblockedAndRejectedIfMigrationCommits(
return;
}
+ const dbPrefix = dbName.split('_')[0];
const primary = rst.getPrimary();
let blockingFp = configureFailPoint(primary, "pauseTenantMigrationAfterBlockingStarts");
@@ -206,7 +211,7 @@ function testBlockedReadGetsUnblockedAndRejectedIfMigrationCommits(
.count +
1;
- let migrationThread = new Thread(startMigration, primary.host, dbName, kRecipientConnString);
+ let migrationThread = new Thread(startMigration, primary.host, dbPrefix, kRecipientConnString);
let resumeMigrationThread =
new Thread(resumeMigrationAfterBlockingRead, primary.host, targetBlockedReads);
@@ -220,7 +225,7 @@ function testBlockedReadGetsUnblockedAndRejectedIfMigrationCommits(
// unspecified atClusterTime have read timestamp >= blockTimestamp.
rst.awaitLastOpCommitted();
- const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbName});
+ const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbPrefix});
const command = testCase.requiresReadTimestamp
? testCase.command(collName, donorDoc.blockTimestamp)
: testCase.command(collName);
@@ -249,6 +254,7 @@ function testBlockedReadGetsUnblockedAndSucceedsIfMigrationAborts(rst, testCase,
return;
}
+ const dbPrefix = dbName.split('_')[0];
const primary = rst.getPrimary();
let blockingFp = configureFailPoint(primary, "pauseTenantMigrationAfterBlockingStarts");
@@ -260,7 +266,7 @@ function testBlockedReadGetsUnblockedAndSucceedsIfMigrationAborts(rst, testCase,
.count +
1;
- let migrationThread = new Thread(startMigration, primary.host, dbName, kRecipientConnString);
+ let migrationThread = new Thread(startMigration, primary.host, dbPrefix, kRecipientConnString);
let resumeMigrationThread =
new Thread(resumeMigrationAfterBlockingRead, primary.host, targetBlockedReads);
@@ -274,7 +280,7 @@ function testBlockedReadGetsUnblockedAndSucceedsIfMigrationAborts(rst, testCase,
// unspecified atClusterTime have read timestamp >= blockTimestamp.
rst.awaitLastOpCommitted();
- const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbName});
+ const donorDoc = primary.getCollection(kConfigDonorsNS).findOne({databasePrefix: dbPrefix});
const command = testCase.requiresReadTimestamp
? testCase.command(collName, donorDoc.blockTimestamp)
: testCase.command(collName);
@@ -370,7 +376,6 @@ const testCases = {
}
};
-// Run test cases.
const testFuncs = {
inCommitted: testReadIsRejectedIfSentAfterMigrationHasCommitted,
inAborted: testReadIsAcceptedIfSentAfterMigrationHasAborted,
@@ -380,8 +385,9 @@ const testFuncs = {
};
for (const [testName, testFunc] of Object.entries(testFuncs)) {
- for (const [commandName, testCase] of Object.entries(testCases)) {
- let dbName = commandName + "-" + testName + "0";
+ for (const [testCaseName, testCase] of Object.entries(testCases)) {
+ // Database name is [tenant_id (database prefix)]_[tenant defined database name]
+ let dbName = testCaseName + "-" + testName + "_" + kTenantDefinedDbName;
testFunc(donorRst, testCase, dbName, kCollName);
}
}
diff --git a/jstests/replsets/writes_during_tenant_migration.js b/jstests/replsets/writes_during_tenant_migration.js
index 174c25bd17b..33f1c97b878 100644
--- a/jstests/replsets/writes_during_tenant_migration.js
+++ b/jstests/replsets/writes_during_tenant_migration.js
@@ -29,6 +29,7 @@ const primary = donorRst.getPrimary();
const kRecipientConnString = recipientRst.getURL();
const kCollName = "testColl";
+const kTenantDefinedDbName = "0";
const kTestDoc = {
x: -1
};
@@ -50,11 +51,12 @@ const kMaxTimeMS = 1 * 1000;
function startMigration(host, dbName, recipientConnString) {
const primary = new Mongo(host);
+ const dbPrefix = dbName.split('_')[0];
return primary.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: recipientConnString,
- databasePrefix: dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
});
}
@@ -229,11 +231,12 @@ function testWriteNoMigration(testCase, testOpts) {
* Tests that the donor rejects writes after the migration commits.
*/
function testWriteIsRejectedIfSentAfterMigrationHasCommitted(testCase, testOpts) {
+ const dbPrefix = testOpts.dbName.split('_')[0];
assert.commandWorked(testOpts.primaryDB.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: kRecipientConnString,
- databasePrefix: testOpts.dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
}));
@@ -246,11 +249,12 @@ function testWriteIsRejectedIfSentAfterMigrationHasCommitted(testCase, testOpts)
*/
function testWriteIsAcceptedIfSentAfterMigrationHasAborted(testCase, testOpts) {
let abortFp = configureFailPoint(testOpts.primaryDB, "abortTenantMigrationAfterBlockingStarts");
+ const dbPrefix = testOpts.dbName.split('_')[0];
assert.commandFailedWithCode(testOpts.primaryDB.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: kRecipientConnString,
- databasePrefix: testOpts.dbName,
+ databasePrefix: dbPrefix,
readPreference: {mode: "primary"}
}),
ErrorCodes.TenantMigrationAborted);
@@ -845,6 +849,7 @@ const testFuncs = {
for (const [testName, testFunc] of Object.entries(testFuncs)) {
for (const [commandName, testCase] of Object.entries(testCases)) {
+ // Database name is [tenant_id (database prefix)]_[tenant defined database name]
let baseDbName = commandName + "-" + testName + "0";
if (testCase.skip) {
@@ -852,7 +857,12 @@ for (const [testName, testFunc] of Object.entries(testFuncs)) {
continue;
}
- runTest(primary, testCase, testFunc, baseDbName + "Basic", kCollName);
+ runTest(primary,
+ testCase,
+ testFunc,
+ baseDbName + "Basic" +
+ "_" + kTenantDefinedDbName,
+ kCollName);
// TODO (SERVER-49844): Test transactional writes during migration.
if (testCase.isSupportedInTransaction && testName == "noMigration") {
@@ -861,9 +871,13 @@ for (const [testName, testFunc] of Object.entries(testFuncs)) {
}
if (testCase.isRetryableWriteCommand) {
- runTest(primary, testCase, testFunc, baseDbName + "Retryable", kCollName, {
- useRetryableWrite: true
- });
+ runTest(primary,
+ testCase,
+ testFunc,
+ baseDbName + "Retryable" +
+ "_" + kTenantDefinedDbName,
+ kCollName,
+ {useRetryableWrite: true});
}
}
}
diff --git a/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.cpp b/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.cpp
index ff8a63467b0..ff8abd87672 100644
--- a/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.cpp
+++ b/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.cpp
@@ -63,17 +63,16 @@ void TenantMigrationAccessBlockerByPrefix::remove(StringData dbPrefix) {
}
std::shared_ptr<TenantMigrationAccessBlocker>
-TenantMigrationAccessBlockerByPrefix::getTenantMigrationAccessBlocker(StringData dbName) {
+TenantMigrationAccessBlockerByPrefix::getTenantMigrationAccessBlockerForDbName(StringData dbName) {
stdx::lock_guard<Latch> lg(_mutex);
- // TODO (SERVER-50440): Make TenantMigrationAccessBlockerByPrefix include '_' when doing lookup.
auto it = std::find_if(
_tenantMigrationAccessBlockers.begin(),
_tenantMigrationAccessBlockers.end(),
[dbName](
const std::pair<std::string, std::shared_ptr<TenantMigrationAccessBlocker>>& blocker) {
StringData dbPrefix = blocker.first;
- return dbName.startsWith(dbPrefix);
+ return dbName.startsWith(dbPrefix + "_");
});
if (it == _tenantMigrationAccessBlockers.end()) {
@@ -83,6 +82,19 @@ TenantMigrationAccessBlockerByPrefix::getTenantMigrationAccessBlocker(StringData
}
}
+std::shared_ptr<TenantMigrationAccessBlocker>
+TenantMigrationAccessBlockerByPrefix::getTenantMigrationAccessBlockerForDbPrefix(
+ StringData dbPrefix) {
+ stdx::lock_guard<Latch> lg(_mutex);
+
+ auto it = _tenantMigrationAccessBlockers.find(dbPrefix);
+ if (it != _tenantMigrationAccessBlockers.end()) {
+ return it->second;
+ } else {
+ return nullptr;
+ }
+}
+
void TenantMigrationAccessBlockerByPrefix::appendInfoForServerStatus(BSONObjBuilder* builder) {
stdx::lock_guard<Latch> lg(_mutex);
diff --git a/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.h b/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.h
index 208ef7595bd..c8e513f378e 100644
--- a/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.h
+++ b/src/mongo/db/repl/tenant_migration_access_blocker_by_prefix.h
@@ -60,10 +60,17 @@ public:
* returns the first TenantMigrationAccessBlocker it finds whose dbPrefix is a prefix for
* dbName.
*/
- std::shared_ptr<TenantMigrationAccessBlocker> getTenantMigrationAccessBlocker(
+ std::shared_ptr<TenantMigrationAccessBlocker> getTenantMigrationAccessBlockerForDbName(
StringData dbName);
/**
+ * Searches through TenantMigrationAccessBlockers and
+ * returns the TenantMigrationAccessBlocker that matches dbPrefix.
+ */
+ std::shared_ptr<TenantMigrationAccessBlocker> getTenantMigrationAccessBlockerForDbPrefix(
+ StringData dbPrefix);
+
+ /**
* Iterates through each of the TenantMigrationAccessBlockers stored by the mapping
* and appends the server status of each blocker to the BSONObjBuilder.
*/
diff --git a/src/mongo/db/repl/tenant_migration_donor_util.cpp b/src/mongo/db/repl/tenant_migration_donor_util.cpp
index 90d50cfa444..296e041658d 100644
--- a/src/mongo/db/repl/tenant_migration_donor_util.cpp
+++ b/src/mongo/db/repl/tenant_migration_donor_util.cpp
@@ -63,7 +63,8 @@ void onTransitionToBlocking(OperationContext* opCtx, TenantMigrationDonorDocumen
invariant(donorStateDoc.getBlockTimestamp());
auto& mtabByPrefix = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext());
- auto mtab = mtabByPrefix.getTenantMigrationAccessBlocker(donorStateDoc.getDatabasePrefix());
+ auto mtab =
+ mtabByPrefix.getTenantMigrationAccessBlockerForDbPrefix(donorStateDoc.getDatabasePrefix());
if (!opCtx->writesAreReplicated()) {
// A primary must create the TenantMigrationAccessBlocker and call startBlockingWrites on it
@@ -95,7 +96,8 @@ void onTransitionToCommitted(OperationContext* opCtx, TenantMigrationDonorDocume
invariant(donorStateDoc.getCommitOrAbortOpTime());
auto& mtabByPrefix = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext());
- auto mtab = mtabByPrefix.getTenantMigrationAccessBlocker(donorStateDoc.getDatabasePrefix());
+ auto mtab =
+ mtabByPrefix.getTenantMigrationAccessBlockerForDbPrefix(donorStateDoc.getDatabasePrefix());
invariant(mtab);
mtab->commit(donorStateDoc.getCommitOrAbortOpTime().get());
}
@@ -108,7 +110,8 @@ void onTransitionToAborted(OperationContext* opCtx, TenantMigrationDonorDocument
invariant(donorStateDoc.getCommitOrAbortOpTime());
auto& mtabByPrefix = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext());
- auto mtab = mtabByPrefix.getTenantMigrationAccessBlocker(donorStateDoc.getDatabasePrefix());
+ auto mtab =
+ mtabByPrefix.getTenantMigrationAccessBlockerForDbPrefix(donorStateDoc.getDatabasePrefix());
invariant(mtab);
mtab->abort(donorStateDoc.getCommitOrAbortOpTime().get());
}
@@ -150,7 +153,7 @@ void onDonorStateTransition(OperationContext* opCtx, const BSONObj& donorStateDo
void checkIfCanReadOrBlock(OperationContext* opCtx, StringData dbName) {
auto mtab = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext())
- .getTenantMigrationAccessBlocker(dbName);
+ .getTenantMigrationAccessBlockerForDbName(dbName);
if (!mtab) {
return;
@@ -179,7 +182,7 @@ void checkIfLinearizableReadWasAllowedOrThrow(OperationContext* opCtx, StringDat
if (repl::ReadConcernArgs::get(opCtx).getLevel() ==
repl::ReadConcernLevel::kLinearizableReadConcern) {
if (auto mtab = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext())
- .getTenantMigrationAccessBlocker(dbName)) {
+ .getTenantMigrationAccessBlockerForDbName(dbName)) {
mtab->checkIfLinearizableReadWasAllowedOrThrow(opCtx);
}
}
@@ -187,7 +190,7 @@ void checkIfLinearizableReadWasAllowedOrThrow(OperationContext* opCtx, StringDat
void onWriteToDatabase(OperationContext* opCtx, StringData dbName) {
auto& mtabByPrefix = TenantMigrationAccessBlockerByPrefix::get(opCtx->getServiceContext());
- auto mtab = mtabByPrefix.getTenantMigrationAccessBlocker(dbName);
+ auto mtab = mtabByPrefix.getTenantMigrationAccessBlockerForDbName(dbName);
if (mtab) {
mtab->checkIfCanWriteOrThrow();
diff --git a/src/mongo/db/repl/tenant_migration_donor_util.h b/src/mongo/db/repl/tenant_migration_donor_util.h
index 15fce6eedd6..5b1d9ef4168 100644
--- a/src/mongo/db/repl/tenant_migration_donor_util.h
+++ b/src/mongo/db/repl/tenant_migration_donor_util.h
@@ -107,7 +107,7 @@ void migrationConflictHandler(OperationContext* opCtx,
auto migrationConflictInfo = ex.extraInfo<TenantMigrationConflictInfo>();
invariant(migrationConflictInfo);
- if (auto mtab = mtabByPrefix.getTenantMigrationAccessBlocker(
+ if (auto mtab = mtabByPrefix.getTenantMigrationAccessBlockerForDbPrefix(
migrationConflictInfo->getDatabasePrefix())) {
replyBuilder->getBodyBuilder().resetToEmpty();
mtab->checkIfCanWriteOrBlock(opCtx);