summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugh Tong <hugh.tong@mongodb.com>2022-09-09 20:46:33 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-09 22:07:25 +0000
commit18c39bc1e395412f1aa69d98a1ac1e39bfa48d9b (patch)
treed119a012df791d7a9f8b532a798cef6138a7fe66
parentdcee93e444e5b6a96d73ed08eb6afacc41ccda82 (diff)
downloadmongo-18c39bc1e395412f1aa69d98a1ac1e39bfa48d9b.tar.gz
SERVER-62393 Apply CRUD ops using correct tenant namespace during oplog application
-rw-r--r--src/mongo/db/dbhelpers.h1
-rw-r--r--src/mongo/db/repl/oplog.cpp8
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test.cpp195
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp22
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test_fixture.h1
-rw-r--r--src/mongo/db/repl/oplog_applier_utils.cpp5
6 files changed, 205 insertions, 27 deletions
diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h
index 047aa9f8534..c4741ffba17 100644
--- a/src/mongo/db/dbhelpers.h
+++ b/src/mongo/db/dbhelpers.h
@@ -87,6 +87,7 @@ struct Helpers {
*
* Returns true if a matching document was found.
*/
+ // TODO SERVER-69541 pass in NamespaceString object instead
static bool findById(OperationContext* opCtx,
StringData ns,
BSONObj query,
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index be4cc5863b4..03365f0db74 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -1599,8 +1599,12 @@ Status applyOperation_inlock(OperationContext* opCtx,
// document.
invariant(op.getObject2());
auto&& documentId = *op.getObject2();
- auto documentFound = Helpers::findById(
- opCtx, collection->ns().ns(), documentId, changeStreamPreImage);
+
+ // TODO SERVER-69541 pass in NamespaceString object instead
+ auto documentFound = Helpers::findById(opCtx,
+ collection->ns().toStringWithTenantId(),
+ documentId,
+ changeStreamPreImage);
invariant(documentFound);
}
diff --git a/src/mongo/db/repl/oplog_applier_impl_test.cpp b/src/mongo/db/repl/oplog_applier_impl_test.cpp
index a695eb26a2d..ff4441515d4 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test.cpp
+++ b/src/mongo/db/repl/oplog_applier_impl_test.cpp
@@ -129,10 +129,12 @@ TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentDataba
TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
applyOplogEntryOrGroupedInsertsDeleteDocumentDatabaseMissing) {
+
+ const NamespaceString nss(boost::none, "test.t");
NamespaceString otherNss("test.othername");
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, {});
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
@@ -170,7 +172,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
NamespaceString otherNss(nss.getSisterNS("othername"));
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, kUuid);
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
@@ -214,7 +216,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
// implicitly create the collection.
auto op = makeOplogEntry(OpTypeEnum::kDelete, nss, {});
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
ASSERT_FALSE(collectionExists(_opCtx.get(), nss));
auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
@@ -242,7 +244,7 @@ TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentCollec
const NamespaceString nss("test.t");
repl::createCollection(_opCtx.get(), nss, {});
auto op = makeOplogEntry(OpTypeEnum::kInsert, nss, {});
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
}
TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
@@ -251,7 +253,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
repl::createCollection(_opCtx.get(), nss, {});
auto op = makeOplogEntry(OpTypeEnum::kDelete, nss, {});
int prevDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
auto postDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
ASSERT_EQ(1, postDeleteWasEmpty - prevDeleteWasEmpty);
@@ -277,7 +279,7 @@ TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsDeleteDocumentCollec
createCollection(_opCtx.get(), nss, createRecordPreImageCollectionOptions());
ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {BSON("_id" << 0)}, 0));
auto op = makeOplogEntry(OpTypeEnum::kDelete, nss, {});
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
}
TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
@@ -287,7 +289,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {BSON("_id" << 0)}, 0));
auto op = makeOplogEntry(OpTypeEnum::kInsert, nss, uuid);
int prevInsertOnExistingDoc = replOpCounters.getInsertOnExistingDoc()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
auto postInsertOnExistingDoc = replOpCounters.getInsertOnExistingDoc()->load();
ASSERT_EQ(1, postInsertOnExistingDoc - prevInsertOnExistingDoc);
@@ -304,7 +306,7 @@ TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
auto uuid = createCollectionWithUuid(_opCtx.get(), nss);
ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {BSON("_id" << 0)}, 0));
auto op = makeOplogEntry(OpTypeEnum::kInsert, nss, uuid);
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::DuplicateKey, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::DuplicateKey, op, nss, false);
}
TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
@@ -318,7 +320,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
BSON(doc_diff::kUpdateSectionFieldName << fromjson("{a: 1}"))),
BSON("_id" << 0));
int prevUpdateOnMissingDoc = replOpCounters.getUpdateOnMissingDoc()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
auto postUpdateOnMissingDoc = replOpCounters.getUpdateOnMissingDoc()->load();
ASSERT_EQ(1, postUpdateOnMissingDoc - prevUpdateOnMissingDoc);
@@ -339,7 +341,8 @@ TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
update_oplog_entry::makeDeltaOplogEntry(
BSON(doc_diff::kUpdateSectionFieldName << fromjson("{a: 1}"))),
BSON("_id" << 0));
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::UpdateOperationFailed, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(
+ ErrorCodes::UpdateOperationFailed, op, nss, false);
}
TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentCollectionLockedByUUID) {
@@ -348,7 +351,7 @@ TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentCollec
// Test that the collection to lock is determined by the UUID and not the 'ns' field.
NamespaceString otherNss(nss.getSisterNS("othername"));
auto op = makeOplogEntry(OpTypeEnum::kInsert, otherNss, uuid);
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
}
TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
@@ -362,7 +365,7 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
NamespaceString otherNss(nss.getSisterNS("othername"));
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, options.uuid);
int prevDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, false);
auto postDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
ASSERT_EQ(1, postDeleteWasEmpty - prevDeleteWasEmpty);
@@ -399,7 +402,7 @@ TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsDeleteDocumentCollec
// Test that the collection to lock is determined by the UUID and not the 'ns' field.
NamespaceString otherNss(nss.getSisterNS("othername"));
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, options.uuid);
- _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
}
TEST_F(OplogApplierImplTest, applyOplogEntryToRecordChangeStreamPreImages) {
@@ -700,6 +703,172 @@ TEST_F(OplogApplierImplTest,
secondDerivedOp.getObject()["lastWriteOpTime"]["ts"].timestamp());
}
+TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentIncludesTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const TenantId tid(OID::gen());
+ const NamespaceString nss(tid, "test.t");
+ BSONObj doc = BSON("_id" << 0);
+
+ repl::createCollection(_opCtx.get(), nss, {});
+
+ auto op = makeOplogEntry(OpTypeEnum::kInsert, nss, boost::none, doc, boost::none);
+
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
+
+ // TODO SERVER-67423: use docExists to check that the doc actually got inserted
+}
+
+TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsInsertDocumentIncorrectTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const auto commonNss("test.t"_sd);
+ const TenantId tid1(OID::gen());
+ const TenantId tid2(OID::gen());
+ const NamespaceString nssTenant1(tid1, commonNss);
+ const NamespaceString nssTenant2(tid2, commonNss);
+ BSONObj doc = BSON("_id" << 0);
+
+ repl::createCollection(_opCtx.get(), nssTenant1, {});
+
+ auto op = makeOplogEntry(OpTypeEnum::kInsert, nssTenant2, boost::none, doc, boost::none);
+
+ ASSERT_THROWS(
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nssTenant2, false),
+ ExceptionFor<ErrorCodes::NamespaceNotFound>);
+
+ // TODO SERVER-67423: use docExists to check that the doc still exists on nssTenant1, and does
+ // not exist on nssTenant2
+}
+
+TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsDeleteDocumentIncludesTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const TenantId tid(OID::gen());
+ const NamespaceString nss(tid, "test.t");
+ BSONObj doc = BSON("_id" << 0);
+
+ // this allows us to set deleteArgs.deletedDoc needed by the onDeleteFn validation function in
+ // _testApplyOplogEntryOrGroupedInsertsCrudOperation below
+ CollectionOptions options = createRecordPreImageCollectionOptions();
+
+ repl::createCollection(_opCtx.get(), nss, options);
+ ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {doc}, 0));
+
+ auto op = makeOplogEntry(OpTypeEnum::kDelete, nss, boost::none);
+
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
+
+ // TODO SERVER-67423: use docExists to check that the doc actually got deleted
+}
+
+TEST_F(OplogApplierImplTestEnableSteadyStateConstraints, // see TODO SERVER-67423 below
+ applyOplogEntryOrGroupedInsertsDeleteDocumentIncorrectTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const auto commonNss("test.t"_sd);
+ const TenantId tid1(OID::gen());
+ const TenantId tid2(OID::gen());
+ const NamespaceString nssTenant1(tid1, commonNss);
+ const NamespaceString nssTenant2(tid2, commonNss);
+ BSONObj doc = BSON("_id" << 0);
+
+ repl::createCollection(_opCtx.get(), nssTenant1, {});
+ ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nssTenant1, {doc}, 0));
+
+ auto op = makeOplogEntry(OpTypeEnum::kDelete, nssTenant2, boost::none);
+
+ ASSERT_THROWS(
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nssTenant2, false),
+ ExceptionFor<ErrorCodes::NamespaceNotFound>);
+
+ // TODO SERVER-67423: use docExists to check that the doc still exists on nssTenant1, and does
+ // not exist on nssTenant2. Also, we are using OplogApplierImplTestEnableSteadyStateConstraints
+ // because according to OplogApplierUtils::applyOplogEntryOrGroupedInsertsCommon not enabling
+ // steady state constraints allows the delete to fail silently. While updating SERVER-67423, we
+ // can instead use docExists to check the results of the deletion rather than rely on the
+ // exception
+}
+
+// Steady state constraints are required for secondaries in order to avoid turning an insert into an
+// upsert and masking duplicateKey errors.
+TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
+ applyOplogEntryOrGroupedInsertsUuidIncludesTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const auto commonNss("test.t"_sd);
+ const TenantId tid1(OID::gen());
+ const TenantId tid2(OID::gen());
+ const NamespaceString nssTenant1(tid1, commonNss);
+ const NamespaceString nssTenant2(tid2, commonNss);
+ BSONObj doc = BSON("_id" << 0);
+
+ auto uuid1 = createCollectionWithUuid(_opCtx.get(), nssTenant1);
+ auto uuid2 = createCollectionWithUuid(_opCtx.get(), nssTenant2);
+
+ // Only insert on tenant1, such that we will cause a duplicate key error on one tenant but not
+ // the other.
+ ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nssTenant1, {doc}, 0));
+
+ auto duplicateInsertOp = makeOplogEntry(OpTypeEnum::kInsert, nssTenant1, uuid1);
+ auto successfulInsertOp = makeOplogEntry(OpTypeEnum::kInsert, nssTenant2, uuid2);
+
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(
+ ErrorCodes::DuplicateKey, duplicateInsertOp, nssTenant1, false);
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(
+ ErrorCodes::OK, successfulInsertOp, nssTenant2, true);
+}
+
+TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsUpdateDocumentIncludesTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const TenantId tid(OID::gen());
+ const NamespaceString nss(tid, "test.t");
+ BSONObj doc = BSON("_id" << 0);
+
+ createCollection(_opCtx.get(), nss, {});
+ ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {doc}, 0));
+
+ auto op = makeOplogEntry(repl::OpTypeEnum::kUpdate,
+ nss,
+ boost::none,
+ update_oplog_entry::makeDeltaOplogEntry(
+ BSON(doc_diff::kUpdateSectionFieldName << fromjson("{a: 1}"))),
+ BSON("_id" << 0));
+
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nss, true);
+
+ // TODO SERVER-67423: use docExists to check that the doc exists in its new updated form
+}
+
+TEST_F(OplogApplierImplTest, applyOplogEntryOrGroupedInsertsUpdateDocumentIncorrectTenantId) {
+ RAIIServerParameterControllerForTest multitenancyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ const auto commonNss("test.t"_sd);
+ const TenantId tid1(OID::gen());
+ const TenantId tid2(OID::gen());
+ const NamespaceString nssTenant1(tid1, commonNss);
+ const NamespaceString nssTenant2(tid2, commonNss);
+ BSONObj doc = BSON("_id" << 0);
+
+ createCollection(_opCtx.get(), nssTenant1, {});
+ ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nssTenant1, {doc}, 0));
+
+ auto op = makeOplogEntry(repl::OpTypeEnum::kUpdate,
+ nssTenant2,
+ boost::none,
+ update_oplog_entry::makeDeltaOplogEntry(
+ BSON(doc_diff::kUpdateSectionFieldName << fromjson("{a: 1}"))),
+ BSON("_id" << 0));
+
+ ASSERT_THROWS(
+ _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, nssTenant2, true),
+ ExceptionFor<ErrorCodes::NamespaceNotFound>);
+
+ // TODO SERVER-67423: use docExists to check that the original doc still exists on nssTenant1,
+ // and no doc exists on nssTenant2
+}
+
class MultiOplogEntryOplogApplierImplTest : public OplogApplierImplTest {
public:
MultiOplogEntryOplogApplierImplTest()
diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
index 1070ac64784..007d9da4e0e 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
+++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
@@ -218,17 +218,17 @@ Status OplogApplierImplTest::_applyOplogEntryOrGroupedInsertsWrapper(
}
void OplogApplierImplTest::_testApplyOplogEntryOrGroupedInsertsCrudOperation(
- ErrorCodes::Error expectedError, const OplogEntry& op, bool expectedApplyOpCalled) {
+ ErrorCodes::Error expectedError,
+ const OplogEntry& op,
+ const NamespaceString& targetNss,
+ bool expectedApplyOpCalled) {
bool applyOpCalled = false;
- auto checkOpCtx = [](OperationContext* opCtx) {
+ auto checkOpCtx = [&targetNss](OperationContext* opCtx) {
ASSERT_TRUE(opCtx);
- ASSERT_TRUE(
- opCtx->lockState()->isDbLockedForMode(DatabaseName(boost::none, "test"), MODE_IX));
- ASSERT_FALSE(
- opCtx->lockState()->isDbLockedForMode(DatabaseName(boost::none, "test"), MODE_X));
- ASSERT_TRUE(
- opCtx->lockState()->isCollectionLockedForMode(NamespaceString("test.t"), MODE_IX));
+ ASSERT_TRUE(opCtx->lockState()->isDbLockedForMode(targetNss.dbName(), MODE_IX));
+ ASSERT_FALSE(opCtx->lockState()->isDbLockedForMode(targetNss.dbName(), MODE_X));
+ ASSERT_TRUE(opCtx->lockState()->isCollectionLockedForMode(targetNss, MODE_IX));
ASSERT_FALSE(opCtx->writesAreReplicated());
ASSERT_TRUE(DocumentValidationSettings::get(opCtx).isSchemaValidationDisabled());
};
@@ -237,7 +237,7 @@ void OplogApplierImplTest::_testApplyOplogEntryOrGroupedInsertsCrudOperation(
[&](OperationContext* opCtx, const NamespaceString& nss, const std::vector<BSONObj>& docs) {
applyOpCalled = true;
checkOpCtx(opCtx);
- ASSERT_EQUALS(NamespaceString("test.t"), nss);
+ ASSERT_EQUALS(targetNss, nss);
ASSERT_EQUALS(1U, docs.size());
// For upserts we don't know the intended value of the document.
if (op.getOpType() == repl::OpTypeEnum::kInsert) {
@@ -253,7 +253,7 @@ void OplogApplierImplTest::_testApplyOplogEntryOrGroupedInsertsCrudOperation(
const OplogDeleteEntryArgs& args) {
applyOpCalled = true;
checkOpCtx(opCtx);
- ASSERT_EQUALS(NamespaceString("test.t"), nss);
+ ASSERT_EQUALS(targetNss, nss);
ASSERT(args.deletedDoc);
ASSERT_BSONOBJ_EQ(op.getObject(), *(args.deletedDoc));
return Status::OK();
@@ -262,7 +262,7 @@ void OplogApplierImplTest::_testApplyOplogEntryOrGroupedInsertsCrudOperation(
_opObserver->onUpdateFn = [&](OperationContext* opCtx, const OplogUpdateEntryArgs& args) {
applyOpCalled = true;
checkOpCtx(opCtx);
- ASSERT_EQUALS(NamespaceString("test.t"), args.nss);
+ ASSERT_EQUALS(targetNss, args.nss);
return Status::OK();
};
diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
index 7b800e5127a..e2c374e24b4 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
+++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
@@ -200,6 +200,7 @@ protected:
void _testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::Error expectedError,
const OplogEntry& op,
+ const NamespaceString& targetNss,
bool expectedApplyOpCalled);
Status _applyOplogEntryOrGroupedInsertsWrapper(OperationContext* opCtx,
diff --git a/src/mongo/db/repl/oplog_applier_utils.cpp b/src/mongo/db/repl/oplog_applier_utils.cpp
index 84cfd1b569d..451f3906257 100644
--- a/src/mongo/db/repl/oplog_applier_utils.cpp
+++ b/src/mongo/db/repl/oplog_applier_utils.cpp
@@ -187,7 +187,7 @@ NamespaceString OplogApplierUtils::parseUUIDOrNs(OperationContext* opCtx,
NamespaceStringOrUUID OplogApplierUtils::getNsOrUUID(const NamespaceString& nss,
const OplogEntry& op) {
if (auto ui = op.getUuid()) {
- return {nss.db().toString(), ui.value()};
+ return {nss.dbName(), ui.value()};
}
return nss;
}
@@ -206,6 +206,9 @@ Status OplogApplierUtils::applyOplogEntryOrGroupedInsertsCommon(
CurOp individualOp(opCtx);
const NamespaceString nss(op.getNss());
auto opType = op.getOpType();
+
+ invariant(op.getTid() == nss.tenantId());
+
if (opType == OpTypeEnum::kNoop) {
incrementOpsAppliedStats();
return Status::OK();