summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorauto-revert-processor <dev-prod-dag@mongodb.com>2022-10-22 03:34:21 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-22 04:06:30 +0000
commite5fa2aabe4ddfe1d18d94e326d1ef3dc4ca2af26 (patch)
tree76b6db279d573582be14a2812ac8b184a97a0f74 /src/mongo/db
parent0fb4acf0e581936924c2353a6cfdb29ce5f06348 (diff)
downloadmongo-e5fa2aabe4ddfe1d18d94e326d1ef3dc4ca2af26.tar.gz
Revert "SERVER-62880 Use tid field to apply applyOps and transactions oplog entries"
This reverts commit 9a60ad4e90d5e2faccedcea26e31b1992676d395.
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/commands/oplog_application_checks.cpp22
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test.cpp216
-rw-r--r--src/mongo/db/repl/oplog_entry.cpp11
-rw-r--r--src/mongo/db/repl/transaction_oplog_application.cpp4
4 files changed, 13 insertions, 240 deletions
diff --git a/src/mongo/db/commands/oplog_application_checks.cpp b/src/mongo/db/commands/oplog_application_checks.cpp
index 816a8157403..c4f65bb478b 100644
--- a/src/mongo/db/commands/oplog_application_checks.cpp
+++ b/src/mongo/db/commands/oplog_application_checks.cpp
@@ -62,19 +62,15 @@ Status OplogApplicationChecks::checkOperationAuthorization(OperationContext* opC
BSONElement nsElem = oplogEntry["ns"];
checkBSONType(BSONType::String, nsElem);
- boost::optional<TenantId> tid = oplogEntry.hasElement("tid")
- ? boost::make_optional<TenantId>(TenantId::parseFromBSON(oplogEntry["tid"]))
- : boost::none;
- NamespaceString nss =
- NamespaceStringUtil::deserialize(tid, oplogEntry["ns"].checkAndGetStringData());
+ NamespaceString ns(oplogEntry["ns"].checkAndGetStringData());
if (oplogEntry.hasField("ui"_sd)) {
// ns by UUID overrides the ns specified if they are different.
auto catalog = CollectionCatalog::get(opCtx);
boost::optional<NamespaceString> uuidCollNS =
catalog->lookupNSSByUUID(opCtx, getUUIDFromOplogEntry(oplogEntry));
- if (uuidCollNS && *uuidCollNS != nss)
- nss = *uuidCollNS;
+ if (uuidCollNS && *uuidCollNS != ns)
+ ns = *uuidCollNS;
}
BSONElement oElem = oplogEntry["o"];
@@ -88,19 +84,19 @@ Status OplogApplicationChecks::checkOperationAuthorization(OperationContext* opC
return Status(ErrorCodes::FailedToParse, "Unrecognized command in op");
}
- auto dbNameForAuthCheck = nss.dbName();
+ std::string dbNameForAuthCheck = ns.db().toString();
if (commandName == "renameCollection") {
// renameCollection commands must be run on the 'admin' database. Its arguments are
// fully qualified namespaces. Catalog internals don't know the op produced by running
// renameCollection was originally run on 'admin', so we must restore this.
- dbNameForAuthCheck = DatabaseName(nss.tenantId(), "admin");
+ dbNameForAuthCheck = "admin";
}
// TODO reuse the parse result for when we run() later. Note that when running,
// we must use a potentially different dbname.
return [&] {
try {
- auto request = OpMsgRequestBuilder::create(nss.dbName(), o);
+ auto request = OpMsgRequest::fromDBAndBody(dbNameForAuthCheck, o);
commandInOplogEntry->parse(opCtx, request)->checkAuthorization(opCtx, request);
return Status::OK();
} catch (const DBException& e) {
@@ -110,7 +106,7 @@ Status OplogApplicationChecks::checkOperationAuthorization(OperationContext* opC
}
if (opType == "i"_sd) {
- return auth::checkAuthForInsert(authSession, opCtx, nss);
+ return auth::checkAuthForInsert(authSession, opCtx, ns);
} else if (opType == "u"_sd) {
BSONElement o2Elem = oplogEntry["o2"];
checkBSONType(BSONType::Object, o2Elem);
@@ -126,14 +122,14 @@ Status OplogApplicationChecks::checkOperationAuthorization(OperationContext* opC
return auth::checkAuthForUpdate(authSession,
opCtx,
- nss,
+ ns,
o2,
write_ops::UpdateModification::parseFromOplogEntry(
o, write_ops::UpdateModification::DiffOptions{}),
upsert);
} else if (opType == "d"_sd) {
- return auth::checkAuthForDelete(authSession, opCtx, nss, o);
+ return auth::checkAuthForDelete(authSession, opCtx, ns, o);
} else if (opType == "db"_sd) {
// It seems that 'db' isn't used anymore. Require all actions to prevent casual use.
ActionSet allActions;
diff --git a/src/mongo/db/repl/oplog_applier_impl_test.cpp b/src/mongo/db/repl/oplog_applier_impl_test.cpp
index 3ded20a0e83..07dbe78a257 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test.cpp
+++ b/src/mongo/db/repl/oplog_applier_impl_test.cpp
@@ -1559,222 +1559,6 @@ TEST_F(MultiOplogEntryOplogApplierImplTest, MultiApplyTwoTransactionsOneBatch) {
ASSERT_BSONOBJ_EQ(BSON("_id" << 4), *(nss1It++));
}
-class MultiOplogEntryOplogApplierImplTestMultitenant : public OplogApplierImplTest {
-public:
- MultiOplogEntryOplogApplierImplTestMultitenant()
- : _tenantId(OID::gen()),
- _nss(_tenantId, "test.preptxn"),
- _cmdNss(_tenantId, "admin", "$cmd"),
- _txnNum(1) {}
-
-protected:
- void setUp() override {
- OplogApplierImplTest::setUp();
-
- createCollectionWithUuid(_opCtx.get(), NamespaceString::kSessionTransactionsTableNamespace);
-
- _uuid = UUID::gen();
- _lsid = makeLogicalSessionId(_opCtx.get());
-
- _opObserver->onCreateCollectionFn = [&](OperationContext* opCtx,
- const CollectionPtr&,
- const NamespaceString& collNss,
- const CollectionOptions&,
- const BSONObj&) {
- stdx::lock_guard<Latch> lock(_mutex);
- if (collNss.isOplog()) {
- _oplogDocs.insert(_oplogDocs.end(), BSON("create" << collNss.coll()));
- } else if (collNss == _nss ||
- collNss == NamespaceString::kSessionTransactionsTableNamespace) {
- // Storing the documents in a sorted data structure to make checking for valid
- // results easier. The inserts will be performed by different threads and
- // there's no guarantee of the order.
- (_docs[collNss]).push_back(BSON("create" << collNss.coll()));
- } else
- FAIL("Unexpected create") << " on " << collNss;
- };
-
- _opObserver->onInsertsFn = [&](OperationContext*,
- const NamespaceString& nss,
- const std::vector<BSONObj>& docs) {
- stdx::lock_guard<Latch> lock(_mutex);
- if (nss.isOplog()) {
- _oplogDocs.insert(_oplogDocs.end(), docs.begin(), docs.end());
- } else if (nss == _nss || nss == NamespaceString::kSessionTransactionsTableNamespace) {
- // Storing the inserted documents in a sorted data structure to make checking
- // for valid results easier. The inserts will be performed by different threads
- // and there's no guarantee of the order.
- (_docs[nss]).insert(_docs[nss].end(), docs.begin(), docs.end());
- } else
- FAIL("Unexpected insert") << " into " << nss << " first doc: " << docs.front();
- };
-
- _writerPool = makeReplWriterPool();
- }
-
- void tearDown() override {
- OplogApplierImplTest::tearDown();
- }
-
- std::vector<BSONObj>& oplogDocs() {
- return _oplogDocs;
- }
-
-protected:
- TenantId _tenantId;
- NamespaceString _nss;
- NamespaceString _cmdNss;
- boost::optional<UUID> _uuid;
- LogicalSessionId _lsid;
- TxnNumber _txnNum;
- boost::optional<OplogEntry> _commitOp;
- std::map<NamespaceString, std::vector<BSONObj>> _docs;
- std::vector<BSONObj> _oplogDocs;
- std::unique_ptr<ThreadPool> _writerPool;
-
-private:
- Mutex _mutex = MONGO_MAKE_LATCH("MultiOplogEntryOplogApplierImplTest::_mutex");
-};
-
-TEST_F(MultiOplogEntryOplogApplierImplTestMultitenant,
- MultiApplyUnpreparedTransactionTwoBatchesFeatureFlagOn) {
- RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
- RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
- // Tests an unprepared transaction with ops both in the batch with the commit and prior
- // batches. Populate transaction with 2 linked entries - a create collection and an insert.
- std::vector<OplogEntry> ops;
- ops.push_back(makeCommandOplogEntryWithSessionInfoAndStmtIds(
- {Timestamp(Seconds(1), 1), 1LL},
- _cmdNss,
- BSON("applyOps" << BSON_ARRAY(BSON("op"
- << "c"
- << "tid" << _tenantId << "ns" << _nss.ns() << "ui"
- << *_uuid << "o" << BSON("create" << _nss.coll())))
- << "partialTxn" << true),
- _lsid,
- _txnNum,
- {StmtId(0)},
- OpTime()));
-
- ops.push_back(makeCommandOplogEntryWithSessionInfoAndStmtIds(
- {Timestamp(Seconds(1), 2), 1LL},
- _cmdNss,
- BSON("applyOps" << BSON_ARRAY(BSON("op"
- << "i"
- << "tid" << _tenantId << "ns" << _nss.ns() << "ui"
- << *_uuid << "o" << BSON("_id" << 1)))
- << "partialTxn" << true),
- _lsid,
- _txnNum,
- {StmtId(1)},
- ops.back().getOpTime()));
-
- auto commitOp = makeCommandOplogEntryWithSessionInfoAndStmtIds({Timestamp(Seconds(1), 3), 1LL},
- _cmdNss,
- BSON("applyOps" << BSONArray()),
- _lsid,
- _txnNum,
- {StmtId(2)},
- ops.back().getOpTime());
-
- NoopOplogApplierObserver observer;
- OplogApplierImpl oplogApplier(
- nullptr, // executor
- nullptr, // oplogBuffer
- &observer,
- ReplicationCoordinator::get(_opCtx.get()),
- getConsistencyMarkers(),
- getStorageInterface(),
- repl::OplogApplier::Options(repl::OplogApplication::Mode::kSecondary),
- _writerPool.get());
-
- // Insert the first entry in its own batch. This should result in the oplog entry being written
- // but the entry should not be applied as it is part of a pending transaction.
- ASSERT_OK(oplogApplier.applyOplogBatch(_opCtx.get(), {ops[0]}));
- ASSERT_EQ(1U, oplogDocs().size());
- ASSERT_EQ(0U, _docs[_nss].size());
-
- // Insert the rest of the entries, including the commit. These entries should be added to the
- // oplog, and all the entries including the first should be applied.
- ASSERT_OK(oplogApplier.applyOplogBatch(_opCtx.get(), {ops[1], commitOp}));
- ASSERT_EQ(3U, oplogDocs().size());
- ASSERT_EQ(2U, _docs[_nss].size());
-
- // Check that we applied the expected documents
- auto nssIt = _docs[_nss].begin();
- ASSERT_BSONOBJ_EQ(BSON("create" << _nss.coll()), *nssIt);
- ASSERT_BSONOBJ_EQ(BSON("_id" << 1), *(++nssIt));
-}
-
-TEST_F(MultiOplogEntryOplogApplierImplTestMultitenant,
- MultiApplyUnpreparedTransactionTwoBatchesFeatureFlagOff) {
- RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
- RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", false);
- // Tests an unprepared transaction with ops both in the batch with the commit and prior
- // batches. Populate transaction with 2 linked entries - a create collection and an insert.
- std::vector<OplogEntry> ops;
- ops.push_back(makeCommandOplogEntryWithSessionInfoAndStmtIds(
- {Timestamp(Seconds(1), 1), 1LL},
- _cmdNss,
- BSON("applyOps" << BSON_ARRAY(BSON("op"
- << "c"
- << "ns" << _nss.toStringWithTenantId() << "ui" << *_uuid
- << "o" << BSON("create" << _nss.coll())))
- << "partialTxn" << true),
- _lsid,
- _txnNum,
- {StmtId(0)},
- OpTime()));
-
- ops.push_back(makeCommandOplogEntryWithSessionInfoAndStmtIds(
- {Timestamp(Seconds(1), 2), 1LL},
- _cmdNss,
- BSON("applyOps" << BSON_ARRAY(BSON("op"
- << "i"
- << "ns" << _nss.toStringWithTenantId() << "ui" << *_uuid
- << "o" << BSON("_id" << 1)))
- << "partialTxn" << true),
- _lsid,
- _txnNum,
- {StmtId(1)},
- ops.back().getOpTime()));
-
- auto commitOp = makeCommandOplogEntryWithSessionInfoAndStmtIds({Timestamp(Seconds(1), 3), 1LL},
- _cmdNss,
- BSON("applyOps" << BSONArray()),
- _lsid,
- _txnNum,
- {StmtId(2)},
- ops.back().getOpTime());
-
- NoopOplogApplierObserver observer;
- OplogApplierImpl oplogApplier(
- nullptr, // executor
- nullptr, // oplogBuffer
- &observer,
- ReplicationCoordinator::get(_opCtx.get()),
- getConsistencyMarkers(),
- getStorageInterface(),
- repl::OplogApplier::Options(repl::OplogApplication::Mode::kSecondary),
- _writerPool.get());
-
- // Insert the first entry in its own batch. This should result in the oplog entry being written
- // but the entry should not be applied as it is part of a pending transaction.
- ASSERT_OK(oplogApplier.applyOplogBatch(_opCtx.get(), {ops[0]}));
- ASSERT_EQ(1U, oplogDocs().size());
- ASSERT_EQ(0U, _docs[_nss].size());
-
- // Insert the rest of the entries, including the commit. These entries should be added to the
- // oplog, and all the entries including the first should be applied.
- ASSERT_OK(oplogApplier.applyOplogBatch(_opCtx.get(), {ops[1], commitOp}));
- ASSERT_EQ(3U, oplogDocs().size());
- ASSERT_EQ(2U, _docs[_nss].size());
-
- // Check that we applied the expected documents
- auto nssIt = _docs[_nss].begin();
- ASSERT_BSONOBJ_EQ(BSON("create" << _nss.coll()), *nssIt);
- ASSERT_BSONOBJ_EQ(BSON("_id" << 1), *(++nssIt));
-}
class MultiOplogEntryPreparedTransactionTest : public MultiOplogEntryOplogApplierImplTest {
protected:
diff --git a/src/mongo/db/repl/oplog_entry.cpp b/src/mongo/db/repl/oplog_entry.cpp
index 4f394c573a5..1bbcc9027be 100644
--- a/src/mongo/db/repl/oplog_entry.cpp
+++ b/src/mongo/db/repl/oplog_entry.cpp
@@ -508,15 +508,8 @@ bool DurableOplogEntry::isSingleOplogEntryTransactionWithCommand() const {
// entries with commands at the beginning.
for (BSONElement e : applyOps.Array()) {
auto ns = e.Obj().getField("ns");
- if (!ns.eoo()) {
- auto tid = e.Obj().getField("tid");
- auto tenantId = tid.eoo()
- ? boost::none
- : boost::make_optional<TenantId>(TenantId::parseFromBSON(tid));
-
- if (NamespaceStringUtil::deserialize(tenantId, ns.String()).isCommand()) {
- return true;
- }
+ if (!ns.eoo() && NamespaceString(ns.String()).isCommand()) {
+ return true;
}
}
return false;
diff --git a/src/mongo/db/repl/transaction_oplog_application.cpp b/src/mongo/db/repl/transaction_oplog_application.cpp
index 5ea9efb3731..2c77e473588 100644
--- a/src/mongo/db/repl/transaction_oplog_application.cpp
+++ b/src/mongo/db/repl/transaction_oplog_application.cpp
@@ -136,10 +136,10 @@ Status _applyTransactionFromOplogChain(OperationContext* opCtx,
auto ops = readTransactionOperationsFromOplogChain(opCtx, entry, {});
- const auto dbName = entry.getNss().dbName();
+ const auto dbName = entry.getNss().db().toString();
Status status = Status::OK();
- writeConflictRetry(opCtx, "replaying prepared transaction", dbName.db(), [&] {
+ writeConflictRetry(opCtx, "replaying prepared transaction", dbName, [&] {
WriteUnitOfWork wunit(opCtx);
// we might replay a prepared transaction behind oldest timestamp.