summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorRishab Joshi <rishab.joshi@mongodb.com>2022-10-18 22:12:42 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-26 19:12:04 +0000
commit19def89272f8ce690467271cb6c27d0b1f34064c (patch)
tree39189a3be3aa071744f589118a173934980afd32 /src/mongo
parent9253cb64b199e8019d7e1066ded43d1ed706baf7 (diff)
downloadmongo-19def89272f8ce690467271cb6c27d0b1f34064c.tar.gz
SERVER-70567 Introduce multitenancy to BenchRun.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/client/dbclient_base.cpp27
-rw-r--r--src/mongo/client/dbclient_base.h35
-rw-r--r--src/mongo/shell/bench.cpp71
-rw-r--r--src/mongo/shell/bench.h2
4 files changed, 106 insertions, 29 deletions
diff --git a/src/mongo/client/dbclient_base.cpp b/src/mongo/client/dbclient_base.cpp
index d2ff6128a72..4e40dc95cfa 100644
--- a/src/mongo/client/dbclient_base.cpp
+++ b/src/mongo/client/dbclient_base.cpp
@@ -220,7 +220,6 @@ std::pair<rpc::UniqueReply, DBClientBase*> DBClientBase::runCommandWithTarget(
auto opCtx = haveClient() ? cc().getOperationContext() : nullptr;
appendMetadata(opCtx, _metadataWriter, _apiParameters, request);
auto requestMsg = request.serialize();
-
Message replyMsg;
try {
@@ -838,20 +837,26 @@ std::list<BSONObj> DBClientBase::_getIndexSpecs(const NamespaceStringOrUUID& nsO
void DBClientBase::dropIndex(const string& ns,
BSONObj keys,
- boost::optional<BSONObj> writeConcernObj) {
- dropIndex(ns, genIndexName(keys), writeConcernObj);
+ boost::optional<BSONObj> writeConcernObj,
+ boost::optional<TenantId> tenantId) {
+ dropIndex(ns, genIndexName(keys), writeConcernObj, tenantId);
}
void DBClientBase::dropIndex(const string& ns,
const string& indexName,
- boost::optional<BSONObj> writeConcernObj) {
+ boost::optional<BSONObj> writeConcernObj,
+ boost::optional<TenantId> tenantId) {
BSONObjBuilder cmdBuilder;
cmdBuilder.append("dropIndexes", nsToCollectionSubstring(ns));
cmdBuilder.append("index", indexName);
if (writeConcernObj) {
cmdBuilder.append(WriteConcernOptions::kWriteConcernField, *writeConcernObj);
}
+ if (tenantId) {
+ tenantId->serializeToBSON("$tenant"_sd, &cmdBuilder);
+ }
+
BSONObj info;
if (!runCommand(nsToDatabase(ns), cmdBuilder.obj(), info)) {
LOGV2_DEBUG(20118,
@@ -905,9 +910,14 @@ string DBClientBase::genIndexName(const BSONObj& keys) {
void DBClientBase::createIndexes(StringData ns,
const std::vector<const IndexSpec*>& descriptors,
- boost::optional<BSONObj> writeConcernObj) {
+ boost::optional<BSONObj> writeConcernObj,
+ boost::optional<TenantId> tenantId) {
BSONObjBuilder command;
command.append("createIndexes", nsToCollectionSubstring(ns));
+ if (tenantId) {
+ tenantId->serializeToBSON("$tenant", &command);
+ }
+
{
BSONArrayBuilder indexes(command.subarrayStart("indexes"));
for (const auto& desc : descriptors) {
@@ -929,9 +939,14 @@ void DBClientBase::createIndexes(StringData ns,
void DBClientBase::createIndexes(StringData ns,
const std::vector<BSONObj>& specs,
- boost::optional<BSONObj> writeConcernObj) {
+ boost::optional<BSONObj> writeConcernObj,
+ boost::optional<TenantId> tenantId) {
BSONObjBuilder command;
command.append("createIndexes", nsToCollectionSubstring(ns));
+ if (tenantId) {
+ tenantId->serializeToBSON("$tenant", &command);
+ }
+
{
BSONArrayBuilder indexes(command.subarrayStart("indexes"));
for (const auto& spec : specs) {
diff --git a/src/mongo/client/dbclient_base.h b/src/mongo/client/dbclient_base.h
index e8376b2b8ec..4de6ef59288 100644
--- a/src/mongo/client/dbclient_base.h
+++ b/src/mongo/client/dbclient_base.h
@@ -421,11 +421,14 @@ public:
* 'ns': Namespace on which to create the index
* 'keys': Document describing keys and index types. You must provide at least one field and
* its direction.
+ *
+ * SERVER-70433 Remove 'tenantId' as parameter.
*/
void createIndex(StringData ns,
const BSONObj& keys,
- boost::optional<BSONObj> writeConcernObj = boost::none) {
- return createIndex(ns, IndexSpec().addKeys(keys), writeConcernObj);
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none) {
+ return createIndex(ns, IndexSpec().addKeys(keys), writeConcernObj, tenantId);
}
/**
@@ -435,27 +438,37 @@ public:
* 'ns': Namespace on which to create the index
* 'descriptor': Configuration object describing the index to create. The descriptor must
* describe at least one key and index type.
+ *
+ * SERVER-70433 Remove 'tenantId' as parameter.
*/
virtual void createIndex(StringData ns,
const IndexSpec& descriptor,
- boost::optional<BSONObj> writeConcernObj = boost::none) {
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none) {
std::vector<const IndexSpec*> toBuild;
toBuild.push_back(&descriptor);
- createIndexes(ns, toBuild, writeConcernObj);
+ createIndexes(ns, toBuild, writeConcernObj, tenantId);
}
+ /**
+ * SERVER-70433 Remove 'tenantId' as parameter.
+ */
virtual void createIndexes(StringData ns,
const std::vector<const IndexSpec*>& descriptor,
- boost::optional<BSONObj> writeConcernObj = boost::none);
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none);
/**
* Creates indexes on the collection 'ns' as described by 'specs'.
*
* Failure to construct the indexes is reported by throwing an AssertionException.
+ *
+ * SERVER-70433 Remove 'tenantId' as parameter.
*/
virtual void createIndexes(StringData ns,
const std::vector<BSONObj>& specs,
- boost::optional<BSONObj> writeConcernObj = boost::none);
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none);
/**
* Lists indexes on the collection 'nsOrUuid'.
@@ -474,13 +487,17 @@ public:
virtual std::list<BSONObj> getIndexSpecs(const NamespaceStringOrUUID& nsOrUuid,
bool includeBuildUUIDs,
int options);
-
+ /*
+ * SERVER-70433 Remove 'tenantId' as parameter.
+ */
virtual void dropIndex(const std::string& ns,
BSONObj keys,
- boost::optional<BSONObj> writeConcernObj = boost::none);
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none);
virtual void dropIndex(const std::string& ns,
const std::string& indexName,
- boost::optional<BSONObj> writeConcernObj = boost::none);
+ boost::optional<BSONObj> writeConcernObj = boost::none,
+ boost::optional<TenantId> tenantId = boost::none);
/**
* Drops all indexes for the collection.
diff --git a/src/mongo/shell/bench.cpp b/src/mongo/shell/bench.cpp
index ff9bb11327b..cbaa79a866a 100644
--- a/src/mongo/shell/bench.cpp
+++ b/src/mongo/shell/bench.cpp
@@ -209,8 +209,11 @@ int runQueryWithReadCommands(DBClientBase* conn,
Milliseconds delayBeforeGetMore,
BSONObj readPrefObj,
BSONObj* objOut) {
- const auto dbName =
- findCommand->getNamespaceOrUUID().nss().value_or(NamespaceString()).db().toString();
+ const auto dbName = findCommand->getNamespaceOrUUID()
+ .nss()
+ .value_or(NamespaceString())
+ .dbName()
+ .toStringWithTenantId();
BSONObj findCommandResult;
BSONObj findCommandObj = findCommand->toBSON(readPrefObj);
@@ -380,7 +383,7 @@ BenchRunOp opFromBson(const BSONObj& op) {
auto name = arg.fieldNameStringData();
if (name == "batchSize") {
uassert(34377,
- str::stream() << "Field 'batchSize' should be a number, instead it's type: "
+ str::stream() << "Field 'batchSize' should be a number, instead it's of type: "
<< typeName(arg.type()),
arg.isNumber());
uassert(34378,
@@ -399,13 +402,13 @@ BenchRunOp opFromBson(const BSONObj& op) {
myOp.context = arg.Obj();
} else if (name == "cpuFactor") {
uassert(40436,
- str::stream() << "Field 'cpuFactor' should be a number, instead it's type: "
+ str::stream() << "Field 'cpuFactor' should be a number, instead it's of type: "
<< typeName(arg.type()),
arg.isNumber());
myOp.cpuFactor = arg.numberDouble();
} else if (name == "delay") {
uassert(34379,
- str::stream() << "Field 'delay' should be a number, instead it's type: "
+ str::stream() << "Field 'delay' should be a number, instead it's of type: "
<< typeName(arg.type()),
arg.isNumber());
myOp.delay = arg.numberInt();
@@ -418,14 +421,21 @@ BenchRunOp opFromBson(const BSONObj& op) {
myOp.doc = arg.Obj();
} else if (name == "expected") {
uassert(34380,
- str::stream() << "Field 'Expected' should be a number, instead it's type: "
+ str::stream() << "Field 'expected' should be a number, instead it's of type: "
<< typeName(arg.type()),
arg.isNumber());
uassert(34400,
- str::stream() << "Field 'Expected' only valid for find op type. Type is "
+ str::stream() << "Field 'expected' only valid for find op type. Type is "
<< opType,
(opType == "find") || (opType == "query"));
myOp.expected = arg.numberInt();
+ } else if (name == "expectedDoc") {
+ uassert(
+ 7056700,
+ str::stream() << "Field 'expectedDoc' should be an object, instead it's of type: "
+ << typeName(arg.type()),
+ arg.isABSONObj());
+ myOp.expectedDoc = arg.Obj();
} else if (name == "filter") {
uassert(
34401,
@@ -450,7 +460,7 @@ BenchRunOp opFromBson(const BSONObj& op) {
<< opType,
(opType == "find") || (opType == "query"));
uassert(ErrorCodes::BadValue,
- str::stream() << "Field 'limit' should be a number, instead it's type: "
+ str::stream() << "Field 'limit' should be a number, instead it's of type: "
<< typeName(arg.type()),
arg.isNumber());
myOp.limit = arg.numberInt();
@@ -463,13 +473,20 @@ BenchRunOp opFromBson(const BSONObj& op) {
myOp.multi = arg.trueValue();
} else if (name == "ns") {
uassert(34385,
- str::stream() << "Field 'ns' should be a string, instead it's type: "
+ str::stream() << "Field 'ns' should be a string, instead it's of type: "
<< typeName(arg.type()),
arg.type() == String);
myOp.ns = arg.String();
+ } else if (name == "tenantId") {
+ uassert(
+ 7056701,
+ str::stream() << "Field 'tenantId' should be an ObjectId, instead it's of type: "
+ << typeName(arg.type()),
+ arg.type() == jstOID);
+ myOp.tenantId = TenantId{arg.OID()};
} else if (name == "op") {
uassert(ErrorCodes::BadValue,
- str::stream() << "Field 'op' is not a string, instead it's type: "
+ str::stream() << "Field 'op' is not a string, instead it's of type: "
<< typeName(arg.type()),
arg.type() == String);
auto type = arg.valueStringData();
@@ -1009,6 +1026,7 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
findCommand->setLimit(1LL);
findCommand->setSingleBatch(true);
findCommand->setSort(this->sort);
+ findCommand->setDollarTenant(this->tenantId);
if (config.useSnapshotReads) {
findCommand->setReadConcern(readConcernSnapshot);
}
@@ -1029,6 +1047,16 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
readPrefObj,
&result);
LOGV2_DEBUG(22796, 5, "Result from benchRun thread [findOne]", "result"_attr = result);
+
+ if (!this->expectedDoc.isEmpty() && this->expectedDoc.woCompare(result) != 0) {
+ LOGV2_INFO(7056702,
+ "Bench 'findOne' on: {namespace} expected: {expected} got: {got}",
+ "Bench 'findOne' on namespace got different results then expected",
+ "namespace"_attr = this->ns,
+ "expected"_attr = this->expectedDoc,
+ "got"_attr = result);
+ verify(false);
+ }
} break;
case OpType::COMMAND: {
bool ok;
@@ -1094,6 +1122,8 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
if (!this->sort.isEmpty()) {
findCommand->setSort(this->sort);
}
+ findCommand->setDollarTenant(this->tenantId);
+
BSONObjBuilder readConcernBuilder;
if (config.useSnapshotReads) {
readConcernBuilder.append("level", "snapshot");
@@ -1132,8 +1162,8 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
if (this->expected >= 0 && count != this->expected) {
LOGV2_INFO(22797,
- "Bench query on: {namespace} expected: {expected} got: {got}",
- "Bench query on namespace got diffrent results then expected",
+ "Bench 'find' on: {namespace} expected: {expected} got: {got}",
+ "Bench 'find' on namespace got different results then expected",
"namespace"_attr = this->ns,
"expected"_attr = this->expected,
"got"_attr = count);
@@ -1149,6 +1179,10 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
BSONObjBuilder builder;
builder.append("update", nsToCollectionSubstring(this->ns));
+ if (this->tenantId) {
+ this->tenantId->serializeToBSON("$tenant"_sd, &builder);
+ }
+
BSONArrayBuilder updateArray(builder.subarrayStart("updates"));
{
BSONObjBuilder singleUpdate;
@@ -1215,6 +1249,10 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
BSONObj insertDoc;
BSONObjBuilder builder;
builder.append("insert", nsToCollectionSubstring(this->ns));
+ if (this->tenantId) {
+ this->tenantId->serializeToBSON("$tenant"_sd, &builder);
+ }
+
BSONArrayBuilder docBuilder(builder.subarrayStart("documents"));
if (this->isDocAnArray) {
for (const auto& element : this->doc) {
@@ -1251,6 +1289,10 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
BSONObj predicate = fixQuery(this->query, *state->bsonTemplateEvaluator);
BSONObjBuilder builder;
builder.append("delete", nsToCollectionSubstring(this->ns));
+ if (this->tenantId) {
+ this->tenantId->serializeToBSON("$tenant"_sd, &builder);
+ }
+
BSONArrayBuilder docBuilder(builder.subarrayStart("deletes"));
int limit = (this->multi == true) ? 0 : 1;
docBuilder.append(BSON("q" << predicate << "limit" << limit));
@@ -1274,10 +1316,11 @@ void BenchRunOp::executeOnce(DBClientBase* conn,
22801, 5, "Result from benchRun thread [safe remove]", "result"_attr = result);
} break;
case OpType::CREATEINDEX:
- conn->createIndex(this->ns, this->key);
+ conn->createIndex(
+ this->ns, this->key, boost::none /* writeConcernObj */, this->tenantId);
break;
case OpType::DROPINDEX:
- conn->dropIndex(this->ns, this->key);
+ conn->dropIndex(this->ns, this->key, boost::none /* writeConcernObj */, this->tenantId);
break;
case OpType::LET: {
BSONObjBuilder templateBuilder;
diff --git a/src/mongo/shell/bench.h b/src/mongo/shell/bench.h
index 053de58fd17..6badfbb346b 100644
--- a/src/mongo/shell/bench.h
+++ b/src/mongo/shell/bench.h
@@ -127,6 +127,8 @@ struct BenchRunOp {
bool useWriteCmd = false;
BSONObj writeConcern;
BSONObj value;
+ BSONObj expectedDoc;
+ boost::optional<TenantId> tenantId;
// Only used for find cmds when set greater than 0. A find operation will retrieve the latest
// cluster time from the oplog and randomly chooses a time between that timestamp and