diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/catalog/rename_collection.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/catalog/rename_collection.h | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/rename_collection_test.cpp | 77 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 3 |
4 files changed, 46 insertions, 58 deletions
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp index 96cdde914fa..e9f851bbb62 100644 --- a/src/mongo/db/catalog/rename_collection.cpp +++ b/src/mongo/db/catalog/rename_collection.cpp @@ -909,6 +909,7 @@ Status renameCollection(OperationContext* opCtx, Status renameCollectionForApplyOps(OperationContext* opCtx, const boost::optional<UUID>& uuidToRename, + const boost::optional<TenantId>& tid, const BSONObj& cmd, const repl::OpTime& renameOpTime) { @@ -919,29 +920,11 @@ Status renameCollectionForApplyOps(OperationContext* opCtx, "renameCollection() cannot accept a rename optime when writes are replicated."); } - const auto tenantIdElt = cmd["tid"]; const auto sourceNsElt = cmd["renameCollection"]; const auto targetNsElt = cmd["to"]; - if (!tenantIdElt.eoo()) - uassert(ErrorCodes::TypeMismatch, - "'tid' must be of type OID", - tenantIdElt.type() == BSONType::jstOID); - uassert(ErrorCodes::TypeMismatch, - "'renameCollection' must be of type String", - sourceNsElt.type() == BSONType::String); - uassert(ErrorCodes::TypeMismatch, - "'to' must be of type String", - targetNsElt.type() == BSONType::String); - - boost::optional<TenantId> tenantId = tenantIdElt.eoo() - ? boost::none - : boost::optional<TenantId>{TenantId::parseFromBSON(tenantIdElt)}; - - NamespaceString sourceNss{ - NamespaceStringUtil::deserialize(tenantId, sourceNsElt.valueStringData())}; - NamespaceString targetNss{ - NamespaceStringUtil::deserialize(tenantId, targetNsElt.valueStringData())}; + NamespaceString sourceNss{NamespaceStringUtil::deserialize(tid, sourceNsElt.valueStringData())}; + NamespaceString targetNss{NamespaceStringUtil::deserialize(tid, targetNsElt.valueStringData())}; // TODO: not needed once we are no longer parsing for prefixed tenantIds uassert(ErrorCodes::IllegalOperation, diff --git a/src/mongo/db/catalog/rename_collection.h b/src/mongo/db/catalog/rename_collection.h index 6920b130977..8697b70c2dc 100644 --- a/src/mongo/db/catalog/rename_collection.h +++ b/src/mongo/db/catalog/rename_collection.h @@ -76,6 +76,7 @@ Status renameCollection(OperationContext* opCtx, */ Status renameCollectionForApplyOps(OperationContext* opCtx, const boost::optional<UUID>& uuidToRename, + const boost::optional<TenantId>& tid, const BSONObj& cmd, const repl::OpTime& renameOpTime); diff --git a/src/mongo/db/catalog/rename_collection_test.cpp b/src/mongo/db/catalog/rename_collection_test.cpp index 8b0296b59f0..b8d37818602 100644 --- a/src/mongo/db/catalog/rename_collection_test.cpp +++ b/src/mongo/db/catalog/rename_collection_test.cpp @@ -588,7 +588,7 @@ TEST_F(RenameCollectionTest, auto cmd = BSON("renameCollection" << dropPendingNss.ns() << "to" << _targetNss.ns()); ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {})); // Source collections stays in drop-pending state. ASSERT_FALSE(_collectionExists(_opCtx.get(), _targetNss)); @@ -606,7 +606,7 @@ TEST_F( NamespaceString ignoredSourceNss(_sourceNss.dbName(), "ignored"); auto cmd = BSON("renameCollection" << ignoredSourceNss.ns() << "to" << _targetNss.ns()); ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), options.uuid, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), options.uuid, boost::none, cmd, {})); // Source collections stays in drop-pending state. ASSERT_FALSE(_collectionExists(_opCtx.get(), _targetNss)); @@ -618,7 +618,7 @@ TEST_F(RenameCollectionTest, RenameCollectionToItselfByNsForApplyOps) { auto uuid = _createCollectionWithUUID(_opCtx.get(), _sourceNss); auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _sourceNss.ns() << "dropTarget" << true); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _sourceNss)); } @@ -626,7 +626,7 @@ TEST_F(RenameCollectionTest, RenameCollectionToItselfByUUIDForApplyOps) { auto uuid = _createCollectionWithUUID(_opCtx.get(), _targetNss); auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns() << "dropTarget" << true); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _targetNss)); } @@ -635,7 +635,7 @@ TEST_F(RenameCollectionTest, RenameCollectionByUUIDRatherThanNsForApplyOps) { auto uuid = _createCollectionWithUUID(_opCtx.get(), realRenameFromNss); auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns() << "dropTarget" << true); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _targetNss)); } @@ -648,7 +648,7 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsDropTargetByUUIDTargetDo // Rename A to B, drop C, where B is not an existing collection auto cmd = BSON("renameCollection" << collA.ns() << "to" << collB.ns() << "dropTarget" << collCUUID); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, boost::none, cmd, {})); // A and C should be dropped ASSERT_FALSE(_collectionExists(_opCtx.get(), collA)); ASSERT_FALSE(_collectionExists(_opCtx.get(), collC)); @@ -671,7 +671,7 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsDropTargetByUUIDTargetEx // B should be kept but with a temporary name auto cmd = BSON("renameCollection" << collA.ns() << "to" << collB.ns() << "dropTarget" << collCUUID); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, boost::none, cmd, {})); // A and C should be dropped ASSERT_FALSE(_collectionExists(_opCtx.get(), collA)); ASSERT_FALSE(_collectionExists(_opCtx.get(), collC)); @@ -703,7 +703,7 @@ TEST_F(RenameCollectionTest, // B should be kept but with a temporary name auto cmd = BSON("renameCollection" << collA.ns() << "to" << collB.ns() << "dropTarget" << collCUUID); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, boost::none, cmd, {})); // A and C should be dropped ASSERT_FALSE(_collectionExists(_opCtx.get(), collA)); ASSERT_FALSE(_collectionExists(_opCtx.get(), collC)); @@ -729,7 +729,7 @@ TEST_F(RenameCollectionTest, // B should be kept but with a temporary name auto cmd = BSON("renameCollection" << collA.ns() << "to" << collB.ns() << "dropTarget" << collCUUID); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), collAUUID, boost::none, cmd, {})); // A and C should be dropped ASSERT_FALSE(_collectionExists(_opCtx.get(), collA)); // B (originally A) should exist @@ -773,8 +773,9 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsRejectsRenameOpTimeIfWri _createCollection(_opCtx.get(), _sourceNss); auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns()); auto renameOpTime = _opObserver->renameOpTime; - ASSERT_EQUALS(ErrorCodes::BadValue, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, renameOpTime)); + ASSERT_EQUALS( + ErrorCodes::BadValue, + renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, renameOpTime)); } DEATH_TEST_F(RenameCollectionTest, @@ -789,7 +790,8 @@ DEATH_TEST_F(RenameCollectionTest, << dropTargetUUID); repl::OpTime renameOpTime = {Timestamp(Seconds(200), 1U), 1LL}; - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, renameOpTime)); + ASSERT_OK( + renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, renameOpTime)); } TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsSourceAndTargetDoNotExist) { @@ -797,7 +799,7 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsSourceAndTargetDoNotExis auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns() << "dropTarget" << "true"); ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_FALSE(_collectionExists(_opCtx.get(), _sourceNss)); ASSERT_FALSE(_collectionExists(_opCtx.get(), _targetNss)); } @@ -809,7 +811,7 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsDropTargetEvenIfSourceDo auto cmd = BSON("renameCollection" << missingSourceNss.ns() << "to" << _targetNss.ns() << "dropTarget" << "true"); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_FALSE(_collectionExists(_opCtx.get(), _targetNss)); } @@ -821,7 +823,7 @@ TEST_F(RenameCollectionTest, RenameCollectionForApplyOpsDropTargetByUUIDEvenIfSo auto uuid = UUID::gen(); auto cmd = BSON("renameCollection" << missingSourceNss.ns() << "to" << _targetNss.ns() << "dropTarget" << dropTargetUUID); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), uuid, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _targetNss)); ASSERT_FALSE(_collectionExists(_opCtx.get(), dropTargetNss)); } @@ -928,7 +930,7 @@ void _testRenameCollectionAcrossDatabaseOplogEntries( if (forApplyOps) { auto cmd = BSON("renameCollection" << sourceNss.ns() << "to" << targetNss.ns() << "dropTarget" << true); - ASSERT_OK(renameCollectionForApplyOps(opCtx, boost::none, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(opCtx, boost::none, sourceNss.tenantId(), cmd, {})); } else { RenameCollectionOptions options; options.dropTarget = true; @@ -1082,7 +1084,7 @@ TEST_F(RenameCollectionTest, auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << invalidTargetNss.ns()); ASSERT_EQUALS(ErrorCodes::InvalidNamespace, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {})); } TEST_F(RenameCollectionTest, FailRenameCollectionFromSystemJavascript) { @@ -1164,10 +1166,10 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOps) { // unable to locate the source collection. If the targetNss tenantId doesn't match, well we're // going to rename the db/collection within the _tenantId, so this effectively ensures it isn't // possible to rename across tenantIds. - auto cmd = BSON("renameCollection" << _sourceNssTid.toString() << "to" - << targetNssTid.toString() << "tid" << _tenantId); + auto cmd = + BSON("renameCollection" << _sourceNssTid.toString() << "to" << targetNssTid.toString()); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, _tenantId, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), targetNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), _sourceNssTid)); } @@ -1180,13 +1182,14 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsCommonRandom ASSERT_NOT_EQUALS(_sourceNssTid, targetNssTid); // This test only has a single tenantId that belongs to neither source nor target. - auto cmd = BSON("renameCollection" << _sourceNssTid.toString() << "to" - << targetNssTid.toString() << "tid" << TenantId(OID::gen())); + auto cmd = + BSON("renameCollection" << _sourceNssTid.toString() << "to" << targetNssTid.toString()); // Because the tenantId doesn't belong to the source, we should see a collection not found // error. - ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + ASSERT_EQUALS( + ErrorCodes::NamespaceNotFound, + renameCollectionForApplyOps(_opCtx.get(), boost::none, TenantId(OID::gen()), cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _sourceNssTid)); } @@ -1198,9 +1201,9 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsCommonTid) { ASSERT_NOT_EQUALS(_sourceNssTid, targetNssTid); // A tid field supersedes tenantIds maintained in source or target. See above. - auto cmd = BSON("renameCollection" << _sourceNssTid.toString() << "to" - << targetNssTid.toString() << "tid" << _tenantId); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + auto cmd = + BSON("renameCollection" << _sourceNssTid.toString() << "to" << targetNssTid.toString()); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, _tenantId, cmd, {})); ASSERT_TRUE( _collectionExists(_opCtx.get(), NamespaceString(_tenantId, targetNssTid.toString()))); ASSERT_FALSE(_collectionExists(_opCtx.get(), _sourceNssTid)); @@ -1215,10 +1218,10 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsSourceExists ASSERT_NOT_EQUALS(otherSourceNssTid, targetNssTid); // A tid field supersedes tenantIds maintained in source or target. See above. - auto cmd = BSON("renameCollection" << otherSourceNssTid.toString() << "to" - << targetNssTid.toString() << "tid" << _otherTenantId); + auto cmd = + BSON("renameCollection" << otherSourceNssTid.toString() << "to" << targetNssTid.toString()); ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), boost::none, _otherTenantId, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _sourceNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), otherSourceNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), targetNssTid)); @@ -1237,7 +1240,7 @@ TEST_F(RenameCollectionTestMultitenancy, auto cmd = BSON("renameCollection" << otherSourceNssTid.toStringWithTenantId() << "to" << targetNssTid.toStringWithTenantId()); ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, - renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), _sourceNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), otherSourceNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), targetNssTid)); @@ -1252,7 +1255,7 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsRequireTenan auto cmd = BSON("renameCollection" << _sourceNssTid.toStringWithTenantId() << "to" << targetNssTid.toStringWithTenantId()); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {})); ASSERT_TRUE(_collectionExists(_opCtx.get(), targetNssTid)); ASSERT_FALSE(_collectionExists(_opCtx.get(), _sourceNssTid)); } @@ -1262,9 +1265,9 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsSameNS) { RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true); // A tid field supersedes tenantIds maintained in source or target. See above. - auto cmd = BSON("renameCollection" << _sourceNssTid.toString() << "to" - << _sourceNssTid.toString() << "tid" << _tenantId); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + auto cmd = + BSON("renameCollection" << _sourceNssTid.toString() << "to" << _sourceNssTid.toString()); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, _tenantId, cmd, {})); } TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsSameNSRequireTenantIdFalse) { @@ -1273,7 +1276,7 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsSameNSRequir auto cmd = BSON("renameCollection" << _sourceNssTid.toStringWithTenantId() << "to" << _sourceNssTid.toStringWithTenantId()); - ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {})); + ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {})); } TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsAcrossTenantIds) { @@ -1287,7 +1290,7 @@ TEST_F(RenameCollectionTestMultitenancy, RenameCollectionForApplyOpsAcrossTenant // enforced, and will prefix the tenantIds onto the ns fields. auto cmd = BSON("renameCollection" << _sourceNssTid.toStringWithTenantId() << "to" << targetNssTid.toStringWithTenantId()); - ASSERT_THROWS_CODE(renameCollectionForApplyOps(_opCtx.get(), boost::none, cmd, {}), + ASSERT_THROWS_CODE(renameCollectionForApplyOps(_opCtx.get(), boost::none, boost::none, cmd, {}), AssertionException, ErrorCodes::IllegalOperation); } diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 95ad2505eab..1b7e683174d 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -1053,7 +1053,8 @@ const StringMap<ApplyOpMetadata> kOpsMap = { if (!opCtx->writesAreReplicated()) { opTime = entry.getOpTime(); } - return renameCollectionForApplyOps(opCtx, entry.getUuid(), entry.getObject(), opTime); + return renameCollectionForApplyOps( + opCtx, entry.getUuid(), entry.getTid(), entry.getObject(), opTime); }, {ErrorCodes::NamespaceNotFound, ErrorCodes::NamespaceExists}}}, {"importCollection", |