diff options
author | jannaerin <golden.janna@gmail.com> | 2022-04-07 16:53:58 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-25 16:33:52 +0000 |
commit | 5ef801809526ad8a8d5732d2689391e241ddf09e (patch) | |
tree | fec685dd70d1d620621e1072349c2637e628c6cc | |
parent | 33e3835fe308932345eec777f5201f7df762b428 (diff) | |
download | mongo-5ef801809526ad8a8d5732d2689391e241ddf09e.tar.gz |
SERVER-64608 Add tenantId to NamespaceString
20 files changed, 289 insertions, 123 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index e028a244889..61d3585d772 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -84,7 +84,6 @@ env.Library( target='multitenancy', source=[ 'multitenancy.cpp', - 'tenant_database_name.cpp', ], LIBDEPS=[ 'multitenancy_params', @@ -94,7 +93,6 @@ env.Library( '$BUILD_DIR/mongo/db/auth/auth', '$BUILD_DIR/mongo/db/auth/security_token', '$BUILD_DIR/mongo/idl/feature_flag', - 'namespace_string', 'server_feature_flags', ] ) @@ -247,10 +245,12 @@ env.Library( target='namespace_string', source=[ 'namespace_string.cpp', + 'tenant_database_name.cpp', ], LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/repl/optime', + 'multitenancy_params', ], LIBDEPS_PRIVATE=[ 'server_options_core', diff --git a/src/mongo/db/commands/current_op_common.cpp b/src/mongo/db/commands/current_op_common.cpp index 6b816a79057..7e82a137c92 100644 --- a/src/mongo/db/commands/current_op_common.cpp +++ b/src/mongo/db/commands/current_op_common.cpp @@ -110,8 +110,9 @@ bool CurrentOpCommandBase::run(OperationContext* opCtx, pipeline.push_back(groupBuilder.obj()); // Pipeline is complete; create an AggregateCommandRequest for $currentOp. - AggregateCommandRequest request(NamespaceString::makeCollectionlessAggregateNSS("admin"), - std::move(pipeline)); + AggregateCommandRequest request( + NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "admin")), + std::move(pipeline)); // Run the pipeline and obtain a CursorResponse. auto aggResults = uassertStatusOK(runAggregation(opCtx, request)); diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp index b0d94e170ec..3a0b72f6bc8 100644 --- a/src/mongo/db/db_raii.cpp +++ b/src/mongo/db/db_raii.cpp @@ -876,6 +876,7 @@ AutoGetCollectionForReadCommandLockFree::AutoGetCollectionForReadCommandLockFree OldClientContext::OldClientContext(OperationContext* opCtx, const std::string& ns, bool doVersion) : _opCtx(opCtx) { + // TODO SERVER-65488 Grab the TenantDatabaseName from the NamespaceString passed in const auto dbName = nsToDatabaseSubstring(ns); const TenantDatabaseName tenantDbName(boost::none, dbName); _db = DatabaseHolder::get(opCtx)->getDb(opCtx, tenantDbName); diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp index d6bc8ced42f..f3099235fca 100644 --- a/src/mongo/db/namespace_string.cpp +++ b/src/mongo/db/namespace_string.cpp @@ -35,6 +35,7 @@ #include "mongo/base/parse_number.h" #include "mongo/base/status.h" +#include "mongo/db/multitenancy_gen.h" #include "mongo/db/server_options.h" #include "mongo/util/str.h" @@ -165,6 +166,23 @@ const NamespaceString NamespaceString::kCompactStructuredEncryptionCoordinatorNa const NamespaceString NamespaceString::kClusterParametersNamespace(NamespaceString::kConfigDb, "clusterParameters"); +NamespaceString NamespaceString::parseFromStringExpectTenantIdInMultitenancyMode(StringData ns) { + if (!gMultitenancySupport) { + return NamespaceString(ns, boost::none); + } + + auto tenantDelim = ns.find('_'); + auto collDelim = ns.find('.'); + // If the first '_' is after the '.' that separates the db and coll names, the '_' is part + // of the coll name and is not a db prefix. + if (tenantDelim == std::string::npos || collDelim < tenantDelim) { + return NamespaceString(ns, boost::none); + } + + const TenantId tenantId(OID(ns.substr(0, tenantDelim))); + return NamespaceString(ns.substr(tenantDelim + 1, ns.size() - 1 - tenantDelim), tenantId); +} + bool NamespaceString::isListCollectionsCursorNS() const { return coll() == listCollectionsCursorCol; } @@ -242,15 +260,15 @@ bool NamespaceString::mustBeAppliedInOwnOplogBatch() const { _ns == kTenantMigrationRecipientsNamespace.ns(); } -NamespaceString NamespaceString::makeListCollectionsNSS(StringData dbName) { +NamespaceString NamespaceString::makeListCollectionsNSS(const TenantDatabaseName& dbName) { NamespaceString nss(dbName, listCollectionsCursorCol); dassert(nss.isValid()); dassert(nss.isListCollectionsCursorNS()); return nss; } -NamespaceString NamespaceString::makeCollectionlessAggregateNSS(StringData dbname) { - NamespaceString nss(dbname, collectionlessAggregateCursorCol); +NamespaceString NamespaceString::makeCollectionlessAggregateNSS(const TenantDatabaseName& dbName) { + NamespaceString nss(dbName, collectionlessAggregateCursorCol); dassert(nss.isValid()); dassert(nss.isCollectionlessAggregateNS()); return nss; diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h index c4bbc52fcbd..5dfcac951e3 100644 --- a/src/mongo/db/namespace_string.h +++ b/src/mongo/db/namespace_string.h @@ -39,6 +39,8 @@ #include "mongo/bson/util/builder.h" #include "mongo/db/repl/optime.h" #include "mongo/db/server_options.h" +#include "mongo/db/tenant_database_name.h" +#include "mongo/db/tenant_id.h" #include "mongo/logv2/log_attr.h" #include "mongo/util/assert_util.h" #include "mongo/util/uuid.h" @@ -222,37 +224,48 @@ public: /** * Constructs an empty NamespaceString. */ - NamespaceString() : _ns(), _dotIndex(std::string::npos) {} + NamespaceString() : _ns(), _dotIndex(std::string::npos), _dbName() {} /** - * Constructs a NamespaceString from the fully qualified namespace named in "ns". + * Constructs a NamespaceString from the fully qualified namespace named in "ns" and the + * tenantId. "ns" is NOT expected to contain the tenantId. */ - explicit NamespaceString(StringData ns) { - _ns = ns.toString(); // copy to our buffer + explicit NamespaceString(boost::optional<TenantId> tenantId, StringData ns) { + _ns = tenantId ? tenantId->toString() + "_" + ns.toString() + : ns.toString(); // copy to our buffer _dotIndex = _ns.find('.'); uassert(ErrorCodes::InvalidNamespace, "namespaces cannot have embedded null characters", _ns.find('\0') == std::string::npos); + + auto db = _dotIndex == std::string::npos ? ns : ns.substr(0, _dotIndex); + _dbName = TenantDatabaseName(tenantId, db); } + // TODO SERVER-65920 Remove this constructor once all constructor call sites have been updated + // to pass tenantId explicitly + explicit NamespaceString(StringData ns, boost::optional<TenantId> tenantId = boost::none) + : NamespaceString(tenantId, ns) {} + /** * Constructs a NamespaceString for the given database and collection names. * "dbName" must not contain a ".", and "collectionName" must not start with one. */ - NamespaceString(StringData dbName, StringData collectionName) - : _ns(dbName.size() + collectionName.size() + 1, '\0') { + NamespaceString(TenantDatabaseName dbName, StringData collectionName) + : _ns(dbName.fullName().size() + collectionName.size() + 1, '\0') { uassert(ErrorCodes::InvalidNamespace, - "'.' is an invalid character in the database name: " + dbName, - dbName.find('.') == std::string::npos); + "'.' is an invalid character in the database name: " + dbName.dbName(), + dbName.dbName().find('.') == std::string::npos); uassert(ErrorCodes::InvalidNamespace, "Collection names cannot start with '.': " + collectionName, collectionName.empty() || collectionName[0] != '.'); - std::string::iterator it = std::copy(dbName.begin(), dbName.end(), _ns.begin()); + auto db = dbName.fullName(); + std::string::iterator it = std::copy(db.begin(), db.end(), _ns.begin()); *it = '.'; ++it; it = std::copy(collectionName.begin(), collectionName.end(), it); - _dotIndex = dbName.size(); + _dotIndex = db.size(); dassert(it == _ns.end()); dassert(_ns[_dotIndex] == '.'); @@ -260,19 +273,42 @@ public: uassert(ErrorCodes::InvalidNamespace, "namespaces cannot have embedded null characters", _ns.find('\0') == std::string::npos); + + _dbName = std::move(dbName); } /** + * Constructs a NamespaceString for the given db name, collection name, and tenantId. + * "db" must not contain a ".", and "collectionName" must not start with one. "dbName" is + * NOT expected to contain a tenantId. + */ + NamespaceString(boost::optional<TenantId> tenantId, StringData db, StringData collectionName) + : NamespaceString(TenantDatabaseName(tenantId, db), collectionName) {} + + // TODO SERVER-65920 Remove this constructor once all constructor call sites have been updated + // to pass tenantId explicitly + NamespaceString(StringData db, + StringData collectionName, + boost::optional<TenantId> tenantId = boost::none) + : NamespaceString(TenantDatabaseName(tenantId, db), collectionName) {} + + /** + * Constructs a NamespaceString from the string 'ns'. Should only be used when reading a + * namespace from disk. 'ns' is expected to contain a tenantId when running in Serverless mode. + */ + static NamespaceString parseFromStringExpectTenantIdInMultitenancyMode(StringData ns); + + /** * Constructs the namespace '<dbName>.$cmd.aggregate', which we use as the namespace for * aggregation commands with the format {aggregate: 1}. */ - static NamespaceString makeCollectionlessAggregateNSS(StringData dbName); + static NamespaceString makeCollectionlessAggregateNSS(const TenantDatabaseName& dbName); /** * Constructs a NamespaceString representing a listCollections namespace. The format for this * namespace is "<dbName>.$cmd.listCollections". */ - static NamespaceString makeListCollectionsNSS(StringData dbName); + static NamespaceString makeListCollectionsNSS(const TenantDatabaseName& dbName); /** * NOTE: DollarInDbNameBehavior::allow is deprecated. @@ -285,8 +321,17 @@ public: Allow, // Deprecated }; + boost::optional<TenantId> tenantId() const { + return _dbName.tenantId(); + } + StringData db() const { - return _dotIndex == std::string::npos ? _ns : StringData(_ns.data(), _dotIndex); + // TODO SERVER-65456 Remove this function. + return StringData(_dbName.fullName()); + } + + TenantDatabaseName dbName() const { + return _dbName; } StringData coll() const { @@ -541,7 +586,7 @@ public: * contain a $ should be checked explicitly. * @return if db is an allowed database name */ - static bool validDBName(StringData db, + static bool validDBName(StringData dbString, DollarInDbNameBehavior behavior = DollarInDbNameBehavior::Disallow); /** @@ -603,6 +648,7 @@ public: private: std::string _ns; size_t _dotIndex = 0; + TenantDatabaseName _dbName; }; /** @@ -612,8 +658,15 @@ private: class NamespaceStringOrUUID { public: NamespaceStringOrUUID(NamespaceString nss) : _nss(std::move(nss)) {} - NamespaceStringOrUUID(std::string dbname, UUID uuid) + NamespaceStringOrUUID(TenantDatabaseName dbname, UUID uuid) : _uuid(std::move(uuid)), _dbname(std::move(dbname)) {} + NamespaceStringOrUUID(boost::optional<TenantId> tenantId, std::string db, UUID uuid) + : _uuid(std::move(uuid)), _dbname(TenantDatabaseName(std::move(tenantId), std::move(db))) {} + // TODO SERVER-65920 Remove once all call sites have been changed to take tenantId explicitly + NamespaceStringOrUUID(std::string db, + UUID uuid, + boost::optional<TenantId> tenantId = boost::none) + : _uuid(std::move(uuid)), _dbname(TenantDatabaseName(std::move(tenantId), std::move(db))) {} const boost::optional<NamespaceString>& nss() const { return _nss; @@ -630,7 +683,11 @@ public: /** * Returns database name if this object was initialized with a UUID. */ - const std::string& dbname() const { + std::string dbname() const { + return _dbname ? _dbname->dbName() : ""; + } + + const boost::optional<TenantDatabaseName>& dbnameWithTenant() const { return _dbname; } @@ -642,7 +699,7 @@ public: * Returns database name derived from either '_nss' or '_dbname'. */ StringData db() const { - return _nss ? _nss->db() : StringData(_dbname); + return _nss ? _nss->db() : StringData(_dbname->dbName()); } /** @@ -663,10 +720,10 @@ private: // When seralizing, if both '_nss' and '_uuid' are present, use '_nss'. bool _preferNssForSerialization = false; - // Empty string when '_nss' is non-none, and contains the database name when '_uuid' is + // Empty when '_nss' is non-none, and contains the database name when '_uuid' is // non-none. Although the UUID specifies a collection uniquely, we must later verify that the // collection belongs to the database named here. - std::string _dbname; + boost::optional<TenantDatabaseName> _dbname; }; std::ostream& operator<<(std::ostream& stream, const NamespaceString& nss); diff --git a/src/mongo/db/namespace_string_test.cpp b/src/mongo/db/namespace_string_test.cpp index 1a81e856e5f..6fc57751e1e 100644 --- a/src/mongo/db/namespace_string_test.cpp +++ b/src/mongo/db/namespace_string_test.cpp @@ -27,8 +27,11 @@ * it in the license file. */ +#include <boost/optional.hpp> + #include "mongo/platform/basic.h" +#include "mongo/db/multitenancy_gen.h" #include "mongo/db/namespace_string.h" #include "mongo/db/repl/optime.h" #include "mongo/unittest/unittest.h" @@ -277,7 +280,8 @@ TEST(NamespaceStringTest, NamespaceStringParse5) { } TEST(NamespaceStringTest, makeListCollectionsNSIsCorrect) { - NamespaceString ns = NamespaceString::makeListCollectionsNSS("DB"); + NamespaceString ns = + NamespaceString::makeListCollectionsNSS(TenantDatabaseName(boost::none, "DB")); ASSERT_EQUALS("DB", ns.db()); ASSERT_EQUALS("$cmd.listCollections", ns.coll()); ASSERT(ns.isValid()); @@ -296,5 +300,83 @@ TEST(NamespaceStringTest, EmptyNSStringReturnsEmptyDb) { ASSERT_EQ(nss.db(), StringData{}); } +TEST(NamespaceStringTest, NSSWithTenantId) { + TenantId tenantId(OID::gen()); + std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar"; + + NamespaceString nss("foo.bar", tenantId); + ASSERT_EQ(nss.ns(), tenantNsStr); + ASSERT_EQ(nss.toString(), tenantNsStr); + ASSERT(nss.tenantId()); + ASSERT_EQ(*nss.tenantId(), tenantId); + + TenantDatabaseName dbName(tenantId, "foo"); + NamespaceString nss2(dbName, "bar"); + ASSERT_EQ(nss2.ns(), tenantNsStr); + ASSERT_EQ(nss2.toString(), tenantNsStr); + ASSERT(nss2.tenantId()); + ASSERT_EQ(*nss2.tenantId(), tenantId); + + NamespaceString nss3("foo", "bar", tenantId); + ASSERT_EQ(nss3.ns(), tenantNsStr); + ASSERT_EQ(nss3.toString(), tenantNsStr); + ASSERT(nss3.tenantId()); + ASSERT_EQ(*nss3.tenantId(), tenantId); +} + +TEST(NamespaceStringTest, NSSNoCollectionWithTenantId) { + TenantId tenantId(OID::gen()); + std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo"; + + NamespaceString nss("foo", tenantId); + ASSERT_EQ(nss.ns(), tenantNsStr); + ASSERT_EQ(nss.toString(), tenantNsStr); + ASSERT(nss.tenantId()); + ASSERT_EQ(*nss.tenantId(), tenantId); + + TenantDatabaseName dbName(tenantId, "foo"); + NamespaceString nss2(dbName, ""); + ASSERT(nss2.tenantId()); + ASSERT_EQ(*nss2.tenantId(), tenantId); + + NamespaceString nss3("foo", "", tenantId); + ASSERT(nss3.tenantId()); + ASSERT_EQ(*nss3.tenantId(), tenantId); +} + +TEST(NamespaceStringTest, ParseNSSWithTenantId) { + gMultitenancySupport = true; + + TenantId tenantId(OID::gen()); + std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar"; + + NamespaceString nss = + NamespaceString::parseFromStringExpectTenantIdInMultitenancyMode(tenantNsStr); + ASSERT_EQ(nss.ns(), tenantNsStr); + ASSERT(nss.tenantId()); + ASSERT_EQ(*nss.tenantId(), tenantId); +} + +TEST(NamespaceStringTest, CompareNSSWithTenantId) { + TenantId tenantIdMin(OID("000000000000000000000000")); + TenantId tenantIdMax(OID::max()); + + ASSERT(NamespaceString(tenantIdMin, "foo.bar") == NamespaceString(tenantIdMin, "foo.bar")); + + ASSERT(NamespaceString(tenantIdMin, "foo.bar") != NamespaceString(tenantIdMax, "foo.bar")); + ASSERT(NamespaceString(tenantIdMin, "foo.bar") != NamespaceString(tenantIdMin, "zoo.bar")); + + ASSERT(NamespaceString(tenantIdMin, "foo.bar") < NamespaceString(tenantIdMax, "foo.bar")); + ASSERT(NamespaceString(tenantIdMin, "foo.bar") < NamespaceString(tenantIdMin, "zoo.bar")); + ASSERT(NamespaceString(tenantIdMin, "zoo.bar") < NamespaceString(tenantIdMax, "foo.bar")); + + ASSERT(NamespaceString(tenantIdMax, "foo.bar") > NamespaceString(tenantIdMin, "foo.bar")); + ASSERT(NamespaceString(tenantIdMin, "zoo.bar") > NamespaceString(tenantIdMin, "foo.bar")); + ASSERT(NamespaceString(tenantIdMax, "foo.bar") > NamespaceString(tenantIdMin, "zoo.bar")); + + ASSERT(NamespaceString(tenantIdMin, "foo.bar") <= NamespaceString(tenantIdMin, "foo.bar")); + ASSERT(NamespaceString(tenantIdMin, "foo.bar") >= NamespaceString(tenantIdMin, "foo.bar")); +} + } // namespace } // namespace mongo diff --git a/src/mongo/db/pipeline/aggregation_request_helper.cpp b/src/mongo/db/pipeline/aggregation_request_helper.cpp index 04fcc4023e3..e73a814e0c8 100644 --- a/src/mongo/db/pipeline/aggregation_request_helper.cpp +++ b/src/mongo/db/pipeline/aggregation_request_helper.cpp @@ -127,7 +127,8 @@ NamespaceString parseNs(const std::string& dbname, const BSONObj& cmdObj) { << firstElement.fieldNameStringData() << "' field must specify a collection name or 1", firstElement.number() == 1); - return NamespaceString::makeCollectionlessAggregateNSS(dbname); + return NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, dbname)); } else { uassert(ErrorCodes::TypeMismatch, str::stream() << "collection name has invalid type: " diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp index 947764892b7..4038b32dfd8 100644 --- a/src/mongo/db/pipeline/aggregation_request_test.cpp +++ b/src/mongo/db/pipeline/aggregation_request_test.cpp @@ -253,7 +253,8 @@ TEST(AggregationRequestTest, ShouldSerializeBatchSizeIfSetAndExplainFalse) { } TEST(AggregationRequestTest, ShouldSerialiseAggregateFieldToOneIfCollectionIsAggregateOneNSS) { - NamespaceString nss = NamespaceString::makeCollectionlessAggregateNSS("a"); + NamespaceString nss = + NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "a")); AggregateCommandRequest request(nss, {}); auto expectedSerialization = diff --git a/src/mongo/db/pipeline/change_stream_event_transform_test.cpp b/src/mongo/db/pipeline/change_stream_event_transform_test.cpp index 5554f3d4203..2f4271e097f 100644 --- a/src/mongo/db/pipeline/change_stream_event_transform_test.cpp +++ b/src/mongo/db/pipeline/change_stream_event_transform_test.cpp @@ -123,9 +123,10 @@ TEST(ChangeStreamEventTransformTest, TestCreateViewTransform) { Document{{"db", viewNss.db()}, {"coll", viewNss.coll()}}}, {DocumentSourceChangeStream::kOperationDescriptionField, opDescription}}; - ASSERT_DOCUMENT_EQ( - applyTransformation(oplogEntry, NamespaceString::makeCollectionlessAggregateNSS("viewDB")), - expectedDoc); + ASSERT_DOCUMENT_EQ(applyTransformation(oplogEntry, + NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, "viewDB"))), + expectedDoc); } TEST(ChangeStreamEventTransformTest, TestCreateViewOnSingleCollection) { diff --git a/src/mongo/db/pipeline/document_source_change_stream_add_post_image_test.cpp b/src/mongo/db/pipeline/document_source_change_stream_add_post_image_test.cpp index 25ca17bbbfa..0d4f8778b14 100644 --- a/src/mongo/db/pipeline/document_source_change_stream_add_post_image_test.cpp +++ b/src/mongo/db/pipeline/document_source_change_stream_add_post_image_test.cpp @@ -239,7 +239,8 @@ TEST_F(DocumentSourceChangeStreamAddPostImageTest, ShouldErrorIfDatabaseMismatchOnCollectionlessNss) { auto expCtx = getExpCtx(); - expCtx->ns = NamespaceString::makeCollectionlessAggregateNSS("test"); + expCtx->ns = + NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "test")); // Set up the lookup change post image stage. auto lookupChangeStage = DocumentSourceChangeStreamAddPostImage::create(expCtx, getSpec()); @@ -264,7 +265,8 @@ TEST_F(DocumentSourceChangeStreamAddPostImageTest, TEST_F(DocumentSourceChangeStreamAddPostImageTest, ShouldPassIfDatabaseMatchesOnCollectionlessNss) { auto expCtx = getExpCtx(); - expCtx->ns = NamespaceString::makeCollectionlessAggregateNSS("test"); + expCtx->ns = + NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "test")); // Set up the lookup change post image stage. auto lookupChangeStage = DocumentSourceChangeStreamAddPostImage::create(expCtx, getSpec()); diff --git a/src/mongo/db/pipeline/document_source_change_stream_test.cpp b/src/mongo/db/pipeline/document_source_change_stream_test.cpp index 0d7c31b293c..cc559e218a5 100644 --- a/src/mongo/db/pipeline/document_source_change_stream_test.cpp +++ b/src/mongo/db/pipeline/document_source_change_stream_test.cpp @@ -2811,7 +2811,8 @@ TEST_F(ChangeStreamStageTest, UsesResumeTokenAsSortKeyIfNeedsMergeIsFalse) { class ChangeStreamStageDBTest : public ChangeStreamStageTest { public: ChangeStreamStageDBTest() - : ChangeStreamStageTest(NamespaceString::makeCollectionlessAggregateNSS(nss.db())) {} + : ChangeStreamStageTest(NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, nss.db()))) {} }; TEST_F(ChangeStreamStageDBTest, TransformInsert) { @@ -4468,7 +4469,8 @@ TEST_F(MultiTokenFormatVersionTest, CanResumeFromV2HighWaterMark) { ResumeTokenData resumeToken = ResumeToken::makeHighWaterMarkToken(resumeTs, 2).getData(); resumeToken.version = 2; auto expCtx = getExpCtxRaw(); - expCtx->ns = NamespaceString::makeCollectionlessAggregateNSS("unittests"); + expCtx->ns = NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, "unittests")); // Create a change stream spec that resumes after 'resumeToken'. const auto spec = diff --git a/src/mongo/db/pipeline/document_source_current_op_test.cpp b/src/mongo/db/pipeline/document_source_current_op_test.cpp index 260bfbf0829..34daaa921ba 100644 --- a/src/mongo/db/pipeline/document_source_current_op_test.cpp +++ b/src/mongo/db/pipeline/document_source_current_op_test.cpp @@ -53,7 +53,8 @@ const std::string kMockShardName = "testshard"; class DocumentSourceCurrentOpTest : public AggregationContextFixture { public: DocumentSourceCurrentOpTest() - : AggregationContextFixture(NamespaceString::makeCollectionlessAggregateNSS("admin")) {} + : AggregationContextFixture(NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, "admin"))) {} }; /** @@ -98,7 +99,8 @@ TEST_F(DocumentSourceCurrentOpTest, ShouldFailToParseIfSpecIsNotObject) { TEST_F(DocumentSourceCurrentOpTest, ShouldFailToParseIfNotRunOnAdmin) { const auto specObj = fromjson("{$currentOp:{}}"); - getExpCtx()->ns = NamespaceString::makeCollectionlessAggregateNSS("foo"); + getExpCtx()->ns = + NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "foo")); ASSERT_THROWS_CODE(DocumentSourceCurrentOp::createFromBson(specObj.firstElement(), getExpCtx()), AssertionException, ErrorCodes::InvalidNamespace); diff --git a/src/mongo/db/pipeline/document_source_facet_test.cpp b/src/mongo/db/pipeline/document_source_facet_test.cpp index 44e3d9668e9..01bded3cc1e 100644 --- a/src/mongo/db/pipeline/document_source_facet_test.cpp +++ b/src/mongo/db/pipeline/document_source_facet_test.cpp @@ -116,7 +116,8 @@ TEST_F(DocumentSourceFacetTest, ShouldSucceedWhenNamespaceIsCollectionless) { auto ctx = getExpCtx(); auto spec = fromjson("{$facet: {a: [{$match: {}}]}}"); - ctx->ns = NamespaceString::makeCollectionlessAggregateNSS("unittests"); + ctx->ns = NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, "unittests")); ASSERT_TRUE(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx).get()); } diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 99eef08c31c..1842b77713a 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -4206,7 +4206,7 @@ TEST_F(PipelineValidateTest, AggregateOneNSNotValidForEmptyPipeline) { const std::vector<BSONObj> rawPipeline = {}; auto ctx = getExpCtx(); - ctx->ns = NamespaceString::makeCollectionlessAggregateNSS("a"); + ctx->ns = NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "a")); ASSERT_THROWS_CODE( Pipeline::parse(rawPipeline, ctx), AssertionException, ErrorCodes::InvalidNamespace); @@ -4216,7 +4216,7 @@ TEST_F(PipelineValidateTest, AggregateOneNSNotValidIfInitialStageRequiresCollect const std::vector<BSONObj> rawPipeline = {fromjson("{$match: {}}")}; auto ctx = getExpCtx(); - ctx->ns = NamespaceString::makeCollectionlessAggregateNSS("a"); + ctx->ns = NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "a")); ASSERT_THROWS_CODE( Pipeline::parse(rawPipeline, ctx), AssertionException, ErrorCodes::InvalidNamespace); @@ -4226,7 +4226,7 @@ TEST_F(PipelineValidateTest, AggregateOneNSValidIfInitialStageIsCollectionless) auto ctx = getExpCtx(); auto collectionlessSource = DocumentSourceCollectionlessMock::create(ctx); - ctx->ns = NamespaceString::makeCollectionlessAggregateNSS("a"); + ctx->ns = NamespaceString::makeCollectionlessAggregateNSS(TenantDatabaseName(boost::none, "a")); Pipeline::create({collectionlessSource}, ctx); } @@ -4247,7 +4247,8 @@ TEST_F(PipelineValidateTest, AggregateOneNSValidForFacetPipelineRegardlessOfInit const std::vector<BSONObj> rawPipeline = {fromjson("{$facet: {subPipe: [{$match: {}}]}}")}; auto ctx = getExpCtx(); - ctx->ns = NamespaceString::makeCollectionlessAggregateNSS("unittests"); + ctx->ns = NamespaceString::makeCollectionlessAggregateNSS( + TenantDatabaseName(boost::none, "unittests")); ASSERT_THROWS_CODE( Pipeline::parse(rawPipeline, ctx), AssertionException, ErrorCodes::InvalidNamespace); 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 de2abb00078..567ac101a75 100644 --- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp +++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp @@ -462,9 +462,11 @@ void createCollection(OperationContext* opCtx, writeConflictRetry(opCtx, "createCollection", nss.ns(), [&] { Lock::DBLock dbLk(opCtx, nss.db(), MODE_IX); Lock::CollectionLock collLk(opCtx, nss, MODE_X); + OldClientContext ctx(opCtx, nss.ns()); auto db = ctx.db(); ASSERT_TRUE(db); + mongo::WriteUnitOfWork wuow(opCtx); auto coll = db->createCollection(opCtx, nss, options); ASSERT_TRUE(coll); diff --git a/src/mongo/db/repl/tenant_oplog_applier_test.cpp b/src/mongo/db/repl/tenant_oplog_applier_test.cpp index 17860543896..460865c8ed4 100644 --- a/src/mongo/db/repl/tenant_oplog_applier_test.cpp +++ b/src/mongo/db/repl/tenant_oplog_applier_test.cpp @@ -50,6 +50,7 @@ #include "mongo/db/repl/tenant_oplog_batcher.h" #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/service_context_test_fixture.h" +#include "mongo/db/tenant_id.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/logv2/log.h" #include "mongo/unittest/log_test.h" @@ -114,8 +115,6 @@ private: std::vector<MutableOplogEntry> _entries; }; -constexpr auto dbName = "tenant_test"_sd; - class TenantOplogApplierTest : public ServiceContextMongoDTest { public: void setUp() override { @@ -185,7 +184,8 @@ protected: OplogBufferMock _oplogBuffer; executor::NetworkInterfaceMock* _net; std::shared_ptr<executor::ThreadPoolTaskExecutor> _executor; - std::string _tenantId = "tenant"; + std::string _tenantId = OID::gen().toString(); + TenantDatabaseName _dbName = TenantDatabaseName(TenantId(OID(_tenantId)), "test"); UUID _migrationUuid = UUID::gen(); ServiceContext::UniqueOperationContext _opCtx; TenantOplogApplierTestOpObserver* _opObserver; // Owned by service context opObserverRegistry @@ -199,8 +199,8 @@ private: TEST_F(TenantOplogApplierTest, NoOpsForSingleBatch) { std::vector<OplogEntry> srcOps; - srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(dbName, "foo"), UUID::gen())); - srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(dbName, "bar"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(_dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(_dbName, "bar"), UUID::gen())); pushOps(srcOps); auto writerPool = makeTenantMigrationWriterPool(); @@ -225,7 +225,7 @@ TEST_F(TenantOplogApplierTest, NoOpsForLargeBatch) { std::vector<OplogEntry> srcOps; // This should be big enough to use several threads to do the writing for (int i = 0; i < 64; i++) { - srcOps.push_back(makeInsertOplogEntry(i + 1, NamespaceString(dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(i + 1, NamespaceString(_dbName, "foo"), UUID::gen())); } pushOps(srcOps); @@ -250,10 +250,10 @@ TEST_F(TenantOplogApplierTest, NoOpsForLargeBatch) { TEST_F(TenantOplogApplierTest, NoOpsForMultipleBatches) { std::vector<OplogEntry> srcOps; - srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(dbName, "foo"), UUID::gen())); - srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(dbName, "bar"), UUID::gen())); - srcOps.push_back(makeInsertOplogEntry(3, NamespaceString(dbName, "baz"), UUID::gen())); - srcOps.push_back(makeInsertOplogEntry(4, NamespaceString(dbName, "bif"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(_dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(_dbName, "bar"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(3, NamespaceString(_dbName, "baz"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(4, NamespaceString(_dbName, "bif"), UUID::gen())); auto writerPool = makeTenantMigrationWriterPool(); @@ -283,18 +283,18 @@ TEST_F(TenantOplogApplierTest, NoOpsForMultipleBatches) { TEST_F(TenantOplogApplierTest, NoOpsForLargeTransaction) { std::vector<OplogEntry> innerOps1; - innerOps1.push_back(makeInsertOplogEntry(11, NamespaceString(dbName, "bar"), UUID::gen())); - innerOps1.push_back(makeInsertOplogEntry(12, NamespaceString(dbName, "bar"), UUID::gen())); + innerOps1.push_back(makeInsertOplogEntry(11, NamespaceString(_dbName, "bar"), UUID::gen())); + innerOps1.push_back(makeInsertOplogEntry(12, NamespaceString(_dbName, "bar"), UUID::gen())); std::vector<OplogEntry> innerOps2; - innerOps2.push_back(makeInsertOplogEntry(21, NamespaceString(dbName, "bar"), UUID::gen())); - innerOps2.push_back(makeInsertOplogEntry(22, NamespaceString(dbName, "bar"), UUID::gen())); + innerOps2.push_back(makeInsertOplogEntry(21, NamespaceString(_dbName, "bar"), UUID::gen())); + innerOps2.push_back(makeInsertOplogEntry(22, NamespaceString(_dbName, "bar"), UUID::gen())); std::vector<OplogEntry> innerOps3; - innerOps3.push_back(makeInsertOplogEntry(31, NamespaceString(dbName, "bar"), UUID::gen())); - innerOps3.push_back(makeInsertOplogEntry(32, NamespaceString(dbName, "bar"), UUID::gen())); + innerOps3.push_back(makeInsertOplogEntry(31, NamespaceString(_dbName, "bar"), UUID::gen())); + innerOps3.push_back(makeInsertOplogEntry(32, NamespaceString(_dbName, "bar"), UUID::gen())); // Makes entries with ts from range [2, 5). std::vector<OplogEntry> srcOps = makeMultiEntryTransactionOplogEntries( - 2, dbName, /* prepared */ false, {innerOps1, innerOps2, innerOps3}); + 2, _dbName.dbName(), /* prepared */ false, {innerOps1, innerOps2, innerOps3}); pushOps(srcOps); auto writerPool = makeTenantMigrationWriterPool(); @@ -320,7 +320,7 @@ TEST_F(TenantOplogApplierTest, NoOpsForLargeTransaction) { TEST_F(TenantOplogApplierTest, CommitUnpreparedTransaction_DataPartiallyApplied) { createCollectionWithUuid(_opCtx.get(), NamespaceString::kSessionTransactionsTableNamespace); - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto lsid = makeLogicalSessionId(_opCtx.get()); TxnNumber txnNum(0); @@ -372,7 +372,7 @@ TEST_F(TenantOplogApplierTest, CommitUnpreparedTransaction_DataPartiallyApplied) } TEST_F(TenantOplogApplierTest, ApplyInsert_DatabaseMissing) { - auto entry = makeInsertOplogEntry(1, NamespaceString(dbName, "bar"), UUID::gen()); + auto entry = makeInsertOplogEntry(1, NamespaceString(_dbName, "bar"), UUID::gen()); bool onInsertsCalled = false; _opObserver->onInsertsFn = [&](OperationContext* opCtx, const NamespaceString&, @@ -393,8 +393,8 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_DatabaseMissing) { } TEST_F(TenantOplogApplierTest, ApplyInsert_CollectionMissing) { - createDatabase(_opCtx.get(), dbName); - auto entry = makeInsertOplogEntry(1, NamespaceString(dbName, "bar"), UUID::gen()); + createDatabase(_opCtx.get(), _dbName.fullName()); + auto entry = makeInsertOplogEntry(1, NamespaceString(_dbName, "bar"), UUID::gen()); bool onInsertsCalled = false; _opObserver->onInsertsFn = [&](OperationContext* opCtx, const NamespaceString&, @@ -415,7 +415,7 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_CollectionMissing) { } TEST_F(TenantOplogApplierTest, ApplyInsert_InsertExisting) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, @@ -433,7 +433,6 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_InsertExisting) { }; pushOps({entry}); auto writerPool = makeTenantMigrationWriterPool(); - auto applier = std::make_shared<TenantOplogApplier>( _migrationUuid, _tenantId, OpTime(), &_oplogBuffer, _executor, writerPool.get()); ASSERT_OK(applier->startup()); @@ -448,7 +447,7 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_InsertExisting) { } TEST_F(TenantOplogApplierTest, ApplyInsert_UniqueKey_InsertExisting) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); // Create unique key index on the collection. @@ -483,7 +482,7 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_UniqueKey_InsertExisting) { } TEST_F(TenantOplogApplierTest, ApplyInsert_Success) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto entry = makeInsertOplogEntry(1, nss, uuid); bool onInsertsCalled = false; @@ -491,7 +490,7 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_Success) { [&](OperationContext* opCtx, const NamespaceString& nss, const std::vector<BSONObj>& docs) { ASSERT_FALSE(onInsertsCalled); onInsertsCalled = true; - ASSERT_EQUALS(nss.db(), dbName); + ASSERT_EQUALS(nss.db(), _dbName.fullName()); ASSERT_EQUALS(nss.coll(), "bar"); ASSERT_EQUALS(1, docs.size()); ASSERT_BSONOBJ_EQ(docs[0], entry.getObject()); @@ -513,9 +512,9 @@ TEST_F(TenantOplogApplierTest, ApplyInsert_Success) { TEST_F(TenantOplogApplierTest, ApplyInserts_Grouped) { // TODO(SERVER-50256): remove nss_workaround, which is used to work around a bug where // the first operation assigned to a worker cannot be grouped. - NamespaceString nss_workaround(dbName, "a"); - NamespaceString nss1(dbName, "bar"); - NamespaceString nss2(dbName, "baz"); + NamespaceString nss_workaround(_dbName, "a"); + NamespaceString nss1(_dbName, "bar"); + NamespaceString nss2(_dbName, "baz"); auto uuid1 = createCollectionWithUuid(_opCtx.get(), nss1); auto uuid2 = createCollectionWithUuid(_opCtx.get(), nss2); std::vector<OplogEntry> entries; @@ -567,7 +566,7 @@ TEST_F(TenantOplogApplierTest, ApplyInserts_Grouped) { } TEST_F(TenantOplogApplierTest, ApplyUpdate_MissingDocument) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto entry = makeOplogEntry( repl::OpTypeEnum::kUpdate, nss, uuid, BSON("$set" << BSON("a" << 1)), BSON("_id" << 0)); @@ -596,7 +595,7 @@ TEST_F(TenantOplogApplierTest, ApplyUpdate_MissingDocument) { } TEST_F(TenantOplogApplierTest, ApplyUpdate_Success) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {BSON("_id" << 0)}, 0)); auto entry = makeOplogEntry( @@ -622,7 +621,7 @@ TEST_F(TenantOplogApplierTest, ApplyUpdate_Success) { } TEST_F(TenantOplogApplierTest, ApplyDelete_DatabaseMissing) { - auto entry = makeOplogEntry(OpTypeEnum::kDelete, NamespaceString(dbName, "bar"), UUID::gen()); + auto entry = makeOplogEntry(OpTypeEnum::kDelete, NamespaceString(_dbName, "bar"), UUID::gen()); bool onDeleteCalled = false; _opObserver->onDeleteFn = [&](OperationContext* opCtx, const NamespaceString&, @@ -645,8 +644,8 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_DatabaseMissing) { } TEST_F(TenantOplogApplierTest, ApplyDelete_CollectionMissing) { - createDatabase(_opCtx.get(), dbName); - auto entry = makeOplogEntry(OpTypeEnum::kDelete, NamespaceString(dbName, "bar"), UUID::gen()); + createDatabase(_opCtx.get(), _dbName.fullName()); + auto entry = makeOplogEntry(OpTypeEnum::kDelete, NamespaceString(_dbName, "bar"), UUID::gen()); bool onDeleteCalled = false; _opObserver->onDeleteFn = [&](OperationContext* opCtx, const NamespaceString&, @@ -669,7 +668,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_CollectionMissing) { } TEST_F(TenantOplogApplierTest, ApplyDelete_DocumentMissing) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto entry = makeOplogEntry(OpTypeEnum::kDelete, nss, uuid, BSON("_id" << 0)); bool onDeleteCalled = false; @@ -694,7 +693,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_DocumentMissing) { } TEST_F(TenantOplogApplierTest, ApplyDelete_Success) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); ASSERT_OK(getStorageInterface()->insertDocument(_opCtx.get(), nss, {BSON("_id" << 0)}, 0)); auto entry = makeOplogEntry(OpTypeEnum::kDelete, nss, uuid, BSON("_id" << 0)); @@ -710,7 +709,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_Success) { ASSERT_TRUE(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_IX)); ASSERT_TRUE(opCtx->writesAreReplicated()); ASSERT_FALSE(args.fromMigrate); - ASSERT_EQUALS(nss.db(), dbName); + ASSERT_EQUALS(nss.db(), _dbName.fullName()); ASSERT_EQUALS(nss.coll(), "bar"); ASSERT_EQUALS(uuid, observer_uuid); }; @@ -729,7 +728,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_Success) { } TEST_F(TenantOplogApplierTest, ApplyCreateCollCommand_CollExisting) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto op = BSON("op" << "c" @@ -758,8 +757,8 @@ TEST_F(TenantOplogApplierTest, ApplyCreateCollCommand_CollExisting) { } TEST_F(TenantOplogApplierTest, ApplyRenameCollCommand_CollExisting) { - NamespaceString nss1(dbName, "foo"); - NamespaceString nss2(dbName, "bar"); + NamespaceString nss1(_dbName, "foo"); + NamespaceString nss2(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss2); auto op = BSON("op" @@ -792,7 +791,7 @@ TEST_F(TenantOplogApplierTest, ApplyRenameCollCommand_CollExisting) { } TEST_F(TenantOplogApplierTest, ApplyCreateCollCommand_Success) { - NamespaceString nss(dbName, "t"); + NamespaceString nss(_dbName, "t"); auto op = BSON("op" << "c" @@ -826,7 +825,7 @@ TEST_F(TenantOplogApplierTest, ApplyCreateCollCommand_Success) { } TEST_F(TenantOplogApplierTest, ApplyCreateIndexesCommand_Success) { - NamespaceString nss(dbName, "t"); + NamespaceString nss(_dbName, "t"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto op = BSON("op" @@ -867,7 +866,7 @@ TEST_F(TenantOplogApplierTest, ApplyCreateIndexesCommand_Success) { } TEST_F(TenantOplogApplierTest, ApplyStartIndexBuildCommand_Failure) { - NamespaceString nss(dbName, "t"); + NamespaceString nss(_dbName, "t"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto op = BSON("op" << "c" @@ -920,7 +919,7 @@ TEST_F(TenantOplogApplierTest, ApplyCreateCollCommand_WrongNSS) { } TEST_F(TenantOplogApplierTest, ApplyDropIndexesCommand_IndexNotFound) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto op = BSON("op" << "c" @@ -952,7 +951,7 @@ TEST_F(TenantOplogApplierTest, ApplyDropIndexesCommand_IndexNotFound) { } TEST_F(TenantOplogApplierTest, ApplyCollModCommand_IndexNotFound) { - NamespaceString nss(dbName, "bar"); + NamespaceString nss(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto op = BSON("op" << "c" @@ -989,8 +988,8 @@ TEST_F(TenantOplogApplierTest, ApplyCollModCommand_IndexNotFound) { } TEST_F(TenantOplogApplierTest, ApplyCollModCommand_CollectionMissing) { - createDatabase(_opCtx.get(), dbName); - NamespaceString nss(dbName, "bar"); + createDatabase(_opCtx.get(), _dbName.fullName()); + NamespaceString nss(_dbName, "bar"); UUID uuid(UUID::gen()); auto op = BSON("op" << "c" @@ -1053,7 +1052,7 @@ TEST_F(TenantOplogApplierTest, ApplyCRUD_WrongUUID) { // Should not be able to apply a CRUD operation to a namespace not belonging to us, even if // we claim it does in the nss field. NamespaceString nss("notmytenant", "bar"); - NamespaceString nss_to_apply(dbName, "bar"); + NamespaceString nss_to_apply(_dbName, "bar"); auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto entry = makeInsertOplogEntry(1, nss_to_apply, uuid); bool onInsertsCalled = false; @@ -1124,7 +1123,7 @@ TEST_F(TenantOplogApplierTest, ApplyResumeTokenNoop_Success) { TEST_F(TenantOplogApplierTest, ApplyInsertThenResumeTokenNoopInDifferentBatch_Success) { std::vector<OplogEntry> srcOps; - srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(_dbName, "foo"), UUID::gen())); srcOps.push_back(makeNoopOplogEntry(2, TenantMigrationRecipientService::kNoopMsg)); pushOps(srcOps); auto writerPool = makeTenantMigrationWriterPool(); @@ -1155,7 +1154,7 @@ TEST_F(TenantOplogApplierTest, ApplyInsertThenResumeTokenNoopInDifferentBatch_Su TEST_F(TenantOplogApplierTest, ApplyResumeTokenNoopThenInsertInSameBatch_Success) { std::vector<OplogEntry> srcOps; srcOps.push_back(makeNoopOplogEntry(1, TenantMigrationRecipientService::kNoopMsg)); - srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(2, NamespaceString(_dbName, "foo"), UUID::gen())); pushOps(srcOps); auto writerPool = makeTenantMigrationWriterPool(); @@ -1180,7 +1179,7 @@ TEST_F(TenantOplogApplierTest, ApplyResumeTokenNoopThenInsertInSameBatch_Success TEST_F(TenantOplogApplierTest, ApplyResumeTokenInsertThenNoopSameTimestamp_Success) { std::vector<OplogEntry> srcOps; - srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(_dbName, "foo"), UUID::gen())); srcOps.push_back(makeNoopOplogEntry(1, TenantMigrationRecipientService::kNoopMsg)); pushOps(srcOps); ASSERT_EQ(srcOps[0].getOpTime(), srcOps[1].getOpTime()); @@ -1207,7 +1206,7 @@ TEST_F(TenantOplogApplierTest, ApplyResumeTokenInsertThenNoopSameTimestamp_Succe TEST_F(TenantOplogApplierTest, ApplyResumeTokenInsertThenNoop_Success) { std::vector<OplogEntry> srcOps; - srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(dbName, "foo"), UUID::gen())); + srcOps.push_back(makeInsertOplogEntry(1, NamespaceString(_dbName, "foo"), UUID::gen())); srcOps.push_back(makeNoopOplogEntry(2, TenantMigrationRecipientService::kNoopMsg)); pushOps(srcOps); auto writerPool = makeTenantMigrationWriterPool(); @@ -1233,8 +1232,8 @@ TEST_F(TenantOplogApplierTest, ApplyResumeTokenInsertThenNoop_Success) { TEST_F(TenantOplogApplierTest, ApplyInsert_MultiKeyIndex) { createCollectionWithUuid(_opCtx.get(), NamespaceString::kSessionTransactionsTableNamespace); - NamespaceString indexedNss(dbName, "indexedColl"); - NamespaceString nonIndexedNss(dbName, "nonIndexedColl"); + NamespaceString indexedNss(_dbName, "indexedColl"); + NamespaceString nonIndexedNss(_dbName, "nonIndexedColl"); auto indexedCollUUID = createCollectionWithUuid(_opCtx.get(), indexedNss); createCollection(_opCtx.get(), nonIndexedNss, CollectionOptions()); diff --git a/src/mongo/db/tenant_database_name.cpp b/src/mongo/db/tenant_database_name.cpp index 457763d206b..f1c8fb0eb9e 100644 --- a/src/mongo/db/tenant_database_name.cpp +++ b/src/mongo/db/tenant_database_name.cpp @@ -29,29 +29,10 @@ #include "mongo/db/tenant_database_name.h" -#include "mongo/db/multitenancy_gen.h" -#include "mongo/db/server_feature_flags_gen.h" - namespace mongo { -TenantDatabaseName::TenantDatabaseName(boost::optional<TenantId> tenantId, StringData dbName) { - // TODO SERVER-62114 Check instead if gMultitenancySupport is enabled. - if (gFeatureFlagRequireTenantID.isEnabledAndIgnoreFCV()) - invariant(tenantId); - - _tenantId = tenantId; - _dbName = dbName.toString(); - - _tenantDbName = - _tenantId ? boost::make_optional(_tenantId->toString() + "_" + _dbName) : boost::none; -} - TenantDatabaseName TenantDatabaseName::createSystemTenantDbName(StringData dbName) { - // TODO SERVER-62114 Check instead if gMultitenancySupport is enabled. - if (gFeatureFlagRequireTenantID.isEnabledAndIgnoreFCV()) { - return TenantDatabaseName(TenantId::kSystemTenantId, dbName); - } - + // TODO SERVER-62491 Use kSystemTenantId return TenantDatabaseName(boost::none, dbName); } diff --git a/src/mongo/db/tenant_database_name.h b/src/mongo/db/tenant_database_name.h index bf013d7fd4a..4ae9e6a6cf1 100644 --- a/src/mongo/db/tenant_database_name.h +++ b/src/mongo/db/tenant_database_name.h @@ -55,10 +55,21 @@ public: * Constructs a TenantDatabaseName from the given tenantId and database name. * "dbName" is expected only consist of a db name. It is the caller's responsibility to ensure * the dbName is a valid db name. - * - * If featureFlagRequireTenantID is set, tenantId is required. */ - TenantDatabaseName(boost::optional<TenantId> tenantId, StringData dbName); + TenantDatabaseName(boost::optional<TenantId> tenantId, StringData dbName) { + _tenantId = tenantId; + _dbName = dbName.toString(); + + _tenantDbName = + _tenantId ? boost::make_optional(_tenantId->toString() + "_" + _dbName) : boost::none; + } + + /** + * Prefer to use the constructor above. + * TODO SERVER-65456 Remove this constructor. + */ + TenantDatabaseName(StringData dbName, boost::optional<TenantId> tenantId = boost::none) + : TenantDatabaseName(tenantId, dbName) {} static TenantDatabaseName createSystemTenantDbName(StringData dbName); diff --git a/src/mongo/db/tenant_database_name_test.cpp b/src/mongo/db/tenant_database_name_test.cpp index 75d9550afef..dcf967402e0 100644 --- a/src/mongo/db/tenant_database_name_test.cpp +++ b/src/mongo/db/tenant_database_name_test.cpp @@ -68,10 +68,11 @@ TEST(TenantDatabaseNameTest, MultitenancySupportEnabledTenantIDNotRequired) { ASSERT_EQUALS(std::string(tenantId.toString() + "_a"), tdnWithTenant.fullName()); } +/* +// TODO SERVER-65457 Re-enable these tests + DEATH_TEST(TenantDatabaseNameTest, TenantIDRequiredNoTenantIdAssigned, "invariant") { RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true); - // TODO SERVER-62114 Remove enabling this feature flag. - RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true); TenantDatabaseName tdnWithoutTenant(boost::none, "a"); } @@ -88,6 +89,7 @@ TEST(TenantDatabaseNameTest, TenantIDRequiredBasic) { ASSERT_EQUALS(std::string("a"), tdn.dbName()); ASSERT_EQUALS(std::string(tenantId.toString() + "_a"), tdn.fullName()); } +*/ TEST(TenantDatabaseNameTest, VerifyEqualsOperator) { TenantId tenantId(OID::gen()); diff --git a/src/mongo/s/commands/cluster_list_collections_cmd.cpp b/src/mongo/s/commands/cluster_list_collections_cmd.cpp index a279d772a8c..cb2b2a98813 100644 --- a/src/mongo/s/commands/cluster_list_collections_cmd.cpp +++ b/src/mongo/s/commands/cluster_list_collections_cmd.cpp @@ -222,7 +222,8 @@ public: BSONObjBuilder& output) final { CommandHelpers::handleMarkKillOnClientDisconnect(opCtx); - const auto nss(NamespaceString::makeListCollectionsNSS(dbName)); + const auto nss( + NamespaceString::makeListCollectionsNSS(TenantDatabaseName(boost::none, dbName))); BSONObj newCmd = cmdObj; |