summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugh Tong <hugh.tong@mongodb.com>2023-05-12 00:12:49 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-05-12 02:20:31 +0000
commit7a494b24bf306a620794069d3b3ea3d794209978 (patch)
tree461257e637de6aedabedd75e9afed41bdb69be35
parent91d9967910ed5d2257074dfe3362b0b317a26cff (diff)
downloadmongo-7a494b24bf306a620794069d3b3ea3d794209978.tar.gz
SERVER-76582 Pass correct SerializationContext objs into command replies
-rw-r--r--src/mongo/db/commands/current_op.cpp6
-rw-r--r--src/mongo/db/commands/dbcommands.cpp15
-rw-r--r--src/mongo/db/commands/find_cmd.cpp8
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp11
-rw-r--r--src/mongo/db/commands/list_collections.cpp27
-rw-r--r--src/mongo/db/commands/list_databases.cpp4
-rw-r--r--src/mongo/db/commands/list_indexes.cpp21
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp3
-rw-r--r--src/mongo/db/pipeline/document_source_coll_stats.cpp7
-rw-r--r--src/mongo/db/pipeline/document_source_out.cpp3
-rw-r--r--src/mongo/db/pipeline/document_source_out_test.cpp2
-rw-r--r--src/mongo/db/query/query_request_helper.cpp10
-rw-r--r--src/mongo/db/query/query_request_helper.h4
-rw-r--r--src/mongo/db/query/query_request_test.cpp16
-rw-r--r--src/mongo/util/serialization_context.h7
15 files changed, 110 insertions, 34 deletions
diff --git a/src/mongo/db/commands/current_op.cpp b/src/mongo/db/commands/current_op.cpp
index 8ba08e6c37b..dd888b36db8 100644
--- a/src/mongo/db/commands/current_op.cpp
+++ b/src/mongo/db/commands/current_op.cpp
@@ -96,8 +96,12 @@ public:
CommandHelpers::appendSimpleCommandStatus(bodyBuilder, true);
bodyBuilder.doneFast();
+ // We need to copy the serialization context from the request to the reply object
return CursorResponse::parseFromBSON(
- replyBuilder.releaseBody(), nullptr, request.getNamespace().tenantId());
+ replyBuilder.releaseBody(),
+ nullptr,
+ request.getNamespace().tenantId(),
+ SerializationContext::stateCommandReply(request.getSerializationContext()));
}
virtual void appendToResponse(BSONObjBuilder* result) const final {
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 147df508a9c..ba74cea6106 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -220,7 +220,9 @@ public:
!storageEngine->supportsRecoveryTimestamp());
}
- Reply reply;
+ // We need to copy the serialization context from the request to the reply object
+ Reply reply(
+ SerializationContext::stateCommandReply(request().getSerializationContext()));
uassertStatusOK(
dropCollection(opCtx,
request().getNamespace(),
@@ -457,7 +459,13 @@ public:
uassert(ErrorCodes::OperationFailed, "No collection name specified", !nss.coll().empty());
- result.append("ns", NamespaceStringUtil::serialize(nss));
+ // We need to use the serialization context from the request when calling
+ // NamespaceStringUtil to build the reply
+ result.append(
+ "ns",
+ NamespaceStringUtil::serialize(
+ nss, SerializationContext::stateCommandReply(cmd.getSerializationContext())));
+
auto spec = StorageStatsSpec::parse(IDLParserContext("collStats"), cmdObj);
Status status = appendCollectionStorageStats(opCtx, nss, spec, &result);
if (!status.isOK() && (status.code() != ErrorCodes::NamespaceNotFound)) {
@@ -640,7 +648,8 @@ public:
AutoGetDb autoDb(opCtx, dbname, MODE_IS);
Database* db = autoDb.getDb();
- Reply reply;
+ // We need to copy the serialization context from the request to the reply object
+ Reply reply(SerializationContext::stateCommandReply(cmd.getSerializationContext()));
reply.setDB(dbname.db());
if (!db) {
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 2b6d5cb9dc8..2c261b751b2 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -571,6 +571,10 @@ public:
}
}
+ // We need to copy the serialization context from the request to the reply object before
+ // the request object goes out of scope
+ const auto serializationContext = cq->getFindCommandRequest().getSerializationContext();
+
// Get the execution plan for the query.
bool permitYield = true;
auto exec =
@@ -726,8 +730,8 @@ public:
// documents.
auto& metricsCollector = ResourceConsumption::MetricsCollector::get(opCtx);
metricsCollector.incrementDocUnitsReturned(nss.ns(), docUnitsReturned);
- query_request_helper::validateCursorResponse(result->getBodyBuilder().asTempObj(),
- nss.tenantId());
+ query_request_helper::validateCursorResponse(
+ result->getBodyBuilder().asTempObj(), nss.tenantId(), serializationContext);
}
void appendMirrorableRequest(BSONObjBuilder* bob) const override {
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 28a3d8fb43b..8f91862d002 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -797,9 +797,14 @@ public:
void validateResult(rpc::ReplyBuilderInterface* reply, boost::optional<TenantId> tenantId) {
auto ret = reply->getBodyBuilder().asTempObj();
- CursorGetMoreReply::parse(
- IDLParserContext{"CursorGetMoreReply", false /* apiStrict */, tenantId},
- ret.removeField("ok"));
+
+ // We need to copy the serialization context from the request to the reply object
+ CursorGetMoreReply::parse(IDLParserContext("CursorGetMoreReply",
+ false /* apiStrict */,
+ tenantId,
+ SerializationContext::stateCommandReply(
+ _cmd.getSerializationContext())),
+ ret.removeField("ok"));
}
const GetMoreCommandRequest _cmd;
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index 571c3156786..f332d975201 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -255,9 +255,14 @@ BSONObj buildCollectionBson(OperationContext* opCtx,
ListCollectionsReply createListCollectionsCursorReply(
CursorId cursorId,
const NamespaceString& cursorNss,
+ const SerializationContext& serializationContext,
std::vector<mongo::ListCollectionsReplyItem>&& firstBatch) {
return ListCollectionsReply(
- ListCollectionsReplyCursor(cursorId, cursorNss, std::move(firstBatch)));
+ ListCollectionsReplyCursor(cursorId,
+ cursorNss,
+ std::move(firstBatch),
+ SerializationContext::stateCommandReply(serializationContext)),
+ SerializationContext::stateCommandReply(serializationContext));
}
class CmdListCollections : public ListCollectionsCmdVersion1Gen<CmdListCollections> {
@@ -316,6 +321,9 @@ public:
const bool nameOnly = listCollRequest.getNameOnly();
const bool authorizedCollections = listCollRequest.getAuthorizedCollections();
+ // We need to copy the serialization context from the request to the reply object
+ const auto serializationContext = listCollRequest.getSerializationContext();
+
// The collator is null because collection objects are compared using binary comparison.
auto expCtx = make_intrusive<ExpressionContext>(
opCtx, std::unique_ptr<CollatorInterface>(nullptr), ns());
@@ -520,10 +528,11 @@ public:
try {
firstBatch.push_back(ListCollectionsReplyItem::parse(
- IDLParserContext("ListCollectionsReplyItem",
- false /* apiStrict*/,
- cursorNss.tenantId(),
- SerializationContext::stateCommandReply()),
+ IDLParserContext(
+ "ListCollectionsReplyItem",
+ false /* apiStrict*/,
+ cursorNss.tenantId(),
+ SerializationContext::stateCommandReply(serializationContext)),
nextDoc));
} catch (const DBException& exc) {
LOGV2_ERROR(
@@ -537,7 +546,7 @@ public:
}
if (exec->isEOF()) {
return createListCollectionsCursorReply(
- 0 /* cursorId */, cursorNss, std::move(firstBatch));
+ 0 /* cursorId */, cursorNss, serializationContext, std::move(firstBatch));
}
exec->saveState();
exec->detachFromOperationContext();
@@ -560,8 +569,10 @@ public:
pinnedCursor->incNBatches();
pinnedCursor->incNReturnedSoFar(firstBatch.size());
- return createListCollectionsCursorReply(
- pinnedCursor.getCursor()->cursorid(), cursorNss, std::move(firstBatch));
+ return createListCollectionsCursorReply(pinnedCursor.getCursor()->cursorid(),
+ cursorNss,
+ serializationContext,
+ std::move(firstBatch));
}
};
} cmdListCollections;
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp
index 3ad19b1d236..2f07229b1cd 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -135,7 +135,9 @@ public:
false /* setTenantId */,
authorizedDatabases);
- ListDatabasesReply reply(items);
+ // We need to copy the serialization context from the request to the reply object
+ ListDatabasesReply reply(
+ items, SerializationContext::stateCommandReply(cmd.getSerializationContext()));
if (!nameOnly) {
reply.setTotalSize(totalSize);
reply.setTotalSizeMb(totalSize / (1024 * 1024));
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index 951d1f6e4a4..848fbb896c8 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -285,6 +285,9 @@ public:
const NamespaceString& nss) {
auto& cmd = request();
+ // We need to copy the serialization context from the request to the reply object
+ const auto serializationContext = cmd.getSerializationContext();
+
long long batchSize = std::numeric_limits<long long>::max();
if (cmd.getCursor() && cmd.getCursor()->getBatchSize()) {
batchSize = *cmd.getCursor()->getBatchSize();
@@ -335,7 +338,12 @@ public:
try {
firstBatch.push_back(ListIndexesReplyItem::parse(
- IDLParserContext("ListIndexesReplyItem"), nextDoc));
+ IDLParserContext(
+ "ListIndexesReplyItem",
+ false /* apiStrict */,
+ nss.tenantId(),
+ SerializationContext::stateCommandReply(serializationContext)),
+ nextDoc));
} catch (const DBException& exc) {
LOGV2_ERROR(5254500,
"Could not parse catalog entry while replying to listIndexes",
@@ -351,7 +359,11 @@ public:
}
if (exec->isEOF()) {
- return ListIndexesReplyCursor(0 /* cursorId */, nss, std::move(firstBatch));
+ return ListIndexesReplyCursor(
+ 0 /* cursorId */,
+ nss,
+ std::move(firstBatch),
+ SerializationContext::stateCommandReply(serializationContext));
}
exec->saveState();
@@ -374,7 +386,10 @@ public:
pinnedCursor->incNReturnedSoFar(firstBatch.size());
return ListIndexesReplyCursor(
- pinnedCursor.getCursor()->cursorid(), nss, std::move(firstBatch));
+ pinnedCursor.getCursor()->cursorid(),
+ nss,
+ std::move(firstBatch),
+ SerializationContext::stateCommandReply(serializationContext));
}
};
} cmdListIndexes;
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index 337c3e5b067..20eab15b603 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -230,7 +230,8 @@ public:
if (!_aggregationRequest.getExplain() && !_aggregationRequest.getExchange()) {
query_request_helper::validateCursorResponse(
reply->getBodyBuilder().asTempObj(),
- _aggregationRequest.getNamespace().tenantId());
+ _aggregationRequest.getNamespace().tenantId(),
+ _aggregationRequest.getSerializationContext());
}
}
diff --git a/src/mongo/db/pipeline/document_source_coll_stats.cpp b/src/mongo/db/pipeline/document_source_coll_stats.cpp
index 0facc2283ef..1df5e681484 100644
--- a/src/mongo/db/pipeline/document_source_coll_stats.cpp
+++ b/src/mongo/db/pipeline/document_source_coll_stats.cpp
@@ -78,7 +78,12 @@ BSONObj DocumentSourceCollStats::makeStatsForNs(
const boost::optional<BSONObj>& filterObj) {
BSONObjBuilder builder;
- builder.append("ns", NamespaceStringUtil::serialize(nss));
+ // We need to use the serialization context from the request when calling
+ // NamespaceStringUtil to build the reply
+ builder.append(
+ "ns",
+ NamespaceStringUtil::serialize(
+ nss, SerializationContext::stateCommandReply(spec.getSerializationContext())));
auto shardName = expCtx->mongoProcessInterface->getShardName(expCtx->opCtx);
diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp
index e45933d4f73..bd7e20902ba 100644
--- a/src/mongo/db/pipeline/document_source_out.cpp
+++ b/src/mongo/db/pipeline/document_source_out.cpp
@@ -96,8 +96,10 @@ DocumentSourceOutSpec DocumentSourceOut::parseOutSpecAndResolveTargetNamespace(
DocumentSourceOutSpec outSpec;
if (spec.type() == BSONType::String) {
outSpec.setColl(spec.valueStringData());
+ // TODO SERVER-77000: access a SerializationContext object to serialize properly
outSpec.setDb(defaultDB.db());
} else if (spec.type() == BSONType::Object) {
+ // TODO SERVER-77000: access a SerializationContext object to pass into the IDLParserContext
outSpec = mongo::DocumentSourceOutSpec::parse(IDLParserContext(kStageName),
spec.embeddedObject());
} else {
@@ -325,6 +327,7 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson(
Value DocumentSourceOut::serialize(SerializationOptions opts) const {
BSONObjBuilder bob;
DocumentSourceOutSpec spec;
+ // TODO SERVER-74284: use SerializatonContext from expCtx and DatabaseNameUtil to serialize
spec.setDb(_outputNs.dbName().db());
spec.setColl(_outputNs.coll());
spec.setTimeseries(_timeseries);
diff --git a/src/mongo/db/pipeline/document_source_out_test.cpp b/src/mongo/db/pipeline/document_source_out_test.cpp
index bae50841f0a..324d681c221 100644
--- a/src/mongo/db/pipeline/document_source_out_test.cpp
+++ b/src/mongo/db/pipeline/document_source_out_test.cpp
@@ -216,6 +216,8 @@ TEST_F(DocumentSourceOutServerlessTest, CreateFromBSONContainsExpectedNamespaces
ASSERT_EQ(outSource->getOutputNs(),
NamespaceString::createNamespaceString_forTest(defaultDb, targetColl));
+ // TODO SERVER-74284: update this test once the serialize function has been updated to use
+ // DatabaseNameUtil::serialize() instead
// Assert the tenantId is not included in the serialized namespace.
auto serialized = outSource->serialize().getDocument();
auto expectedDoc = Document{{"coll", targetColl}, {"db", expCtx->ns.dbName().db()}};
diff --git a/src/mongo/db/query/query_request_helper.cpp b/src/mongo/db/query/query_request_helper.cpp
index 16d95be8c87..477ab4d4834 100644
--- a/src/mongo/db/query/query_request_helper.cpp
+++ b/src/mongo/db/query/query_request_helper.cpp
@@ -231,10 +231,16 @@ TailableModeEnum getTailableMode(const FindCommandRequest& findCommand) {
tailableModeFromBools(findCommand.getTailable(), findCommand.getAwaitData()));
}
-void validateCursorResponse(const BSONObj& outputAsBson, boost::optional<TenantId> tenantId) {
+void validateCursorResponse(const BSONObj& outputAsBson,
+ boost::optional<TenantId> tenantId,
+ const SerializationContext& serializationContext) {
if (getTestCommandsEnabled()) {
CursorInitialReply::parse(
- IDLParserContext("CursorInitialReply", false /* apiStrict */, tenantId), outputAsBson);
+ IDLParserContext("CursorInitialReply",
+ false /* apiStrict */,
+ tenantId,
+ SerializationContext::stateCommandReply(serializationContext)),
+ outputAsBson);
}
}
diff --git a/src/mongo/db/query/query_request_helper.h b/src/mongo/db/query/query_request_helper.h
index 3f73d188578..4f60e34ebb6 100644
--- a/src/mongo/db/query/query_request_helper.h
+++ b/src/mongo/db/query/query_request_helper.h
@@ -139,7 +139,9 @@ TailableModeEnum getTailableMode(const FindCommandRequest& findCommand);
/**
* Asserts whether the cursor response adhere to the format defined in IDL.
*/
-void validateCursorResponse(const BSONObj& outputAsBson, boost::optional<TenantId> tenantId);
+void validateCursorResponse(const BSONObj& outputAsBson,
+ boost::optional<TenantId> tenantId,
+ const SerializationContext& serializationContext);
/**
* Updates the projection object with a $meta projection for the showRecordId option.
diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp
index 15827a9be2f..7ae44a202fb 100644
--- a/src/mongo/db/query/query_request_test.cpp
+++ b/src/mongo/db/query/query_request_test.cpp
@@ -1524,19 +1524,19 @@ TEST(QueryRequestTest, ConvertToFindWithAllowDiskUseFalseSucceeds) {
TEST(QueryRequestHelperTest, ValidateResponseMissingFields) {
BSONObjBuilder builder;
- ASSERT_THROWS_CODE(
- query_request_helper::validateCursorResponse(builder.asTempObj(), boost::none),
- DBException,
- 6253507);
+ ASSERT_THROWS_CODE(query_request_helper::validateCursorResponse(
+ builder.asTempObj(), boost::none, SerializationContext()),
+ DBException,
+ 6253507);
}
TEST(QueryRequestHelperTest, ValidateResponseWrongDataType) {
BSONObjBuilder builder;
builder.append("cursor", 1);
- ASSERT_THROWS_CODE(
- query_request_helper::validateCursorResponse(builder.asTempObj(), boost::none),
- DBException,
- ErrorCodes::TypeMismatch);
+ ASSERT_THROWS_CODE(query_request_helper::validateCursorResponse(
+ builder.asTempObj(), boost::none, SerializationContext()),
+ DBException,
+ ErrorCodes::TypeMismatch);
}
TEST(QueryRequestHelperTest, ParsedCursorRemainsValidAfterBSONDestroyed) {
diff --git a/src/mongo/util/serialization_context.h b/src/mongo/util/serialization_context.h
index 356cc3e9c8c..62fc4f59f39 100644
--- a/src/mongo/util/serialization_context.h
+++ b/src/mongo/util/serialization_context.h
@@ -97,6 +97,13 @@ struct SerializationContext {
return *stateCommandReply;
}
+ static SerializationContext stateCommandReply(const SerializationContext& requestCtxt) {
+ return SerializationContext(Source::Command,
+ CallerType::Reply,
+ requestCtxt._prefixState,
+ requestCtxt._nonPrefixedTenantId);
+ }
+
static const SerializationContext& stateCommandRequest() {
static StaticImmortal<SerializationContext> stateCommandRequest{Source::Command,
CallerType::Request};