diff options
author | Vishnu Kaushik <vishnu.kaushik@mongodb.com> | 2021-06-09 20:04:10 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-10 20:27:13 +0000 |
commit | 0d7c224fc2671e939ea97d94237003dd74805b54 (patch) | |
tree | 68a2a4ede2cb8c822df9ea70d14f5ab6fa75073f | |
parent | efec3cc4b253d02fa9e11947ce92d53b727181b0 (diff) | |
download | mongo-0d7c224fc2671e939ea97d94237003dd74805b54.tar.gz |
SERVER-57532 Use donor specs for _id index in tenant migration collection cloner
-rw-r--r-- | jstests/replsets/tenant_migration_v1_id_index.js | 64 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface.h | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_impl.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_impl.h | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_mock.h | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/tenant_collection_cloner.cpp | 6 |
6 files changed, 82 insertions, 6 deletions
diff --git a/jstests/replsets/tenant_migration_v1_id_index.js b/jstests/replsets/tenant_migration_v1_id_index.js new file mode 100644 index 00000000000..52196aa489b --- /dev/null +++ b/jstests/replsets/tenant_migration_v1_id_index.js @@ -0,0 +1,64 @@ +/** + * Tests that the index spec used for the '_id' index on the donor for a particular collection is + * maintained on the recipient after migration. + * + * @tags: [requires_fcv_49, requires_majority_read_concern, requires_persistence, + * incompatible_with_eft, incompatible_with_windows_tls, incompatible_with_macos] + */ + +(function() { +"use strict"; + +load("jstests/libs/uuid_util.js"); +load("jstests/replsets/libs/tenant_migration_test.js"); + +const tenantMigrationTest = new TenantMigrationTest({name: jsTestName()}); +if (!tenantMigrationTest.isFeatureFlagEnabled()) { + jsTestLog("Skipping test because the tenant migrations feature flag is disabled"); + return; +} + +const tenantId = 'testTenantId'; +const migrationOpts = { + migrationIdString: extractUUIDFromObject(UUID()), + tenantId: tenantId +}; +const dbName = tenantMigrationTest.tenantDB(tenantId, "testDB"); + +// Collection names for the collections with "v: 1" and "v: 2" '_id' indexes. +const collWithV1Index = "testCollV1"; +const collWithV2Index = "testCollV2"; + +const donorPrimary = tenantMigrationTest.getDonorPrimary(); +const tenantDb = donorPrimary.getDB(dbName); + +jsTestLog("Creating collections on donor."); +// Create collections with the appropriate default '_id' indexes. +assert.commandWorked( + tenantDb.createCollection(collWithV1Index, {idIndex: {key: {_id: 1}, name: "_id_", v: 1}})); +assert.commandWorked( + tenantDb.createCollection(collWithV2Index, {idIndex: {key: {_id: 1}, name: "_id_", v: 2}})); + +// Insert documents into the collections. +tenantMigrationTest.insertDonorDB( + dbName, + collWithV1Index, + [...Array(30).keys()].map((i) => ({a: i, job: "Musician", name: "Dr. BMK"}))); +tenantMigrationTest.insertDonorDB( + dbName, + collWithV2Index, + [...Array(30).keys()].map((i) => ({a: i, job: "Professor", name: "Donald Knuth"}))); + +jsTestLog(`Starting a tenant migration with migrationID ${ + migrationOpts.migrationIdString}, and tenantId ${tenantId}`); +assert.commandWorked(tenantMigrationTest.startMigration(migrationOpts)); + +// Allow the migration to run to completion. This will check the db hashes between the donor and +// recipient to make sure everything (including collection attributes such as indexes) is identical. +jsTestLog("Allowing migration to run to completion."); +TenantMigrationTest.assertCommitted(tenantMigrationTest.waitForMigrationToComplete(migrationOpts)); + +assert.commandWorked(tenantMigrationTest.forgetMigration(migrationOpts.migrationIdString)); + +tenantMigrationTest.stop(); +})();
\ No newline at end of file diff --git a/src/mongo/db/repl/storage_interface.h b/src/mongo/db/repl/storage_interface.h index 3e7ac3059ab..6ae980e490c 100644 --- a/src/mongo/db/repl/storage_interface.h +++ b/src/mongo/db/repl/storage_interface.h @@ -169,7 +169,9 @@ public: */ virtual Status createCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options) = 0; + const CollectionOptions& options, + const bool createIdIndex = true, + const BSONObj& idIndexSpec = BSONObj()) = 0; /** * Creates all the specified non-_id indexes on a given collection, which must be empty. diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp index 352f2799ecf..7f99a956cbf 100644 --- a/src/mongo/db/repl/storage_interface_impl.cpp +++ b/src/mongo/db/repl/storage_interface_impl.cpp @@ -469,7 +469,9 @@ StatusWith<size_t> StorageInterfaceImpl::getOplogMaxSize(OperationContext* opCtx Status StorageInterfaceImpl::createCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options) { + const CollectionOptions& options, + const bool createIdIndex, + const BSONObj& idIndexSpec) { return writeConflictRetry(opCtx, "StorageInterfaceImpl::createCollection", nss.ns(), [&] { AutoGetDb databaseWriteGuard(opCtx, nss.db(), MODE_IX); auto db = databaseWriteGuard.ensureDbExists(); @@ -481,7 +483,7 @@ Status StorageInterfaceImpl::createCollection(OperationContext* opCtx, Lock::CollectionLock lk(opCtx, nss, MODE_IX); WriteUnitOfWork wuow(opCtx); try { - auto coll = db->createCollection(opCtx, nss, options); + auto coll = db->createCollection(opCtx, nss, options, createIdIndex, idIndexSpec); invariant(coll); } catch (const AssertionException& ex) { return ex.toStatus(); diff --git a/src/mongo/db/repl/storage_interface_impl.h b/src/mongo/db/repl/storage_interface_impl.h index 409ae9ea99b..fbb5c90c57a 100644 --- a/src/mongo/db/repl/storage_interface_impl.h +++ b/src/mongo/db/repl/storage_interface_impl.h @@ -81,7 +81,9 @@ public: Status createCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options) override; + const CollectionOptions& options, + const bool createIdIndex = true, + const BSONObj& idIndexSpec = BSONObj()) override; Status createIndexesOnEmptyCollection(OperationContext* opCtx, const NamespaceString& nss, diff --git a/src/mongo/db/repl/storage_interface_mock.h b/src/mongo/db/repl/storage_interface_mock.h index ae8c396fe04..8c913443f0e 100644 --- a/src/mongo/db/repl/storage_interface_mock.h +++ b/src/mongo/db/repl/storage_interface_mock.h @@ -170,7 +170,9 @@ public: Status createCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options) override { + const CollectionOptions& options, + const bool createIdIndex = true, + const BSONObj& idIndexSpec = BSONObj()) override { return createCollFn(opCtx, nss, options); } diff --git a/src/mongo/db/repl/tenant_collection_cloner.cpp b/src/mongo/db/repl/tenant_collection_cloner.cpp index 087e0da1261..7dc2a965097 100644 --- a/src/mongo/db/repl/tenant_collection_cloner.cpp +++ b/src/mongo/db/repl/tenant_collection_cloner.cpp @@ -387,7 +387,11 @@ BaseCloner::AfterStageBehavior TenantCollectionCloner::createCollectionStage() { // means that we have a collection with the same namespace but a different UUID, in which // case we should also fail the migration. auto status = - getStorageInterface()->createCollection(opCtx.get(), _sourceNss, _collectionOptions); + getStorageInterface()->createCollection(opCtx.get(), + _sourceNss, + _collectionOptions, + !_idIndexSpec.isEmpty() /* createIdIndex */, + _idIndexSpec); uassertStatusOKWithContext(status, "Tenant collection cloner: create collection"); } |