summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMindaugas Malinauskas <mindaugas.malinauskas@mongodb.com>2020-07-01 15:12:52 +0300
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-08 13:14:41 +0000
commitc610e2627beeb3c8a6f95a2e7071a06e4ea1b1c0 (patch)
treeb82f27f2a285272cad90465268f3e33ff9e4bb6b /src/mongo
parentd4c7887dfae2d861cd4bb3118d576aee3c4f353f (diff)
downloadmongo-c610e2627beeb3c8a6f95a2e7071a06e4ea1b1c0.tar.gz
SERVER-46661 Use the IDL to parse a killCursors command
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/client/dbclient_base.cpp4
-rw-r--r--src/mongo/client/dbclient_connection.cpp2
-rw-r--r--src/mongo/db/commands/killcursors_cmd.cpp2
-rw-r--r--src/mongo/db/commands/killcursors_common.cpp25
-rw-r--r--src/mongo/db/query/SConscript2
-rw-r--r--src/mongo/db/query/kill_cursors.idl55
-rw-r--r--src/mongo/db/query/killcursors_request.cpp106
-rw-r--r--src/mongo/db/query/killcursors_request.h56
-rw-r--r--src/mongo/db/query/killcursors_request_test.cpp129
-rw-r--r--src/mongo/db/query/killcursors_response_test.cpp29
-rw-r--r--src/mongo/executor/task_executor_cursor.cpp4
-rw-r--r--src/mongo/s/query/async_results_merger.cpp5
-rw-r--r--src/mongo/s/query/establish_cursors.cpp5
13 files changed, 161 insertions, 263 deletions
diff --git a/src/mongo/client/dbclient_base.cpp b/src/mongo/client/dbclient_base.cpp
index 87947613ad6..f3112fb7a59 100644
--- a/src/mongo/client/dbclient_base.cpp
+++ b/src/mongo/client/dbclient_base.cpp
@@ -51,7 +51,7 @@
#include "mongo/db/commands.h"
#include "mongo/db/json.h"
#include "mongo/db/namespace_string.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/db/wire_version.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/executor/remote_command_response.h"
@@ -906,7 +906,7 @@ void DBClientBase::update(const string& ns,
void DBClientBase::killCursor(const NamespaceString& ns, long long cursorId) {
runFireAndForgetCommand(
- OpMsgRequest::fromDBAndBody(ns.db(), KillCursorsRequest(ns, {cursorId}).toBSON()));
+ OpMsgRequest::fromDBAndBody(ns.db(), KillCursorsRequest(ns, {cursorId}).toBSON(BSONObj{})));
}
namespace {
diff --git a/src/mongo/client/dbclient_connection.cpp b/src/mongo/client/dbclient_connection.cpp
index 297ae2b1c3f..8a3eeadc8f9 100644
--- a/src/mongo/client/dbclient_connection.cpp
+++ b/src/mongo/client/dbclient_connection.cpp
@@ -60,7 +60,7 @@
#include "mongo/db/commands/test_commands_enabled.h"
#include "mongo/db/json.h"
#include "mongo/db/namespace_string.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/db/server_options.h"
#include "mongo/db/wire_version.h"
#include "mongo/executor/remote_command_request.h"
diff --git a/src/mongo/db/commands/killcursors_cmd.cpp b/src/mongo/db/commands/killcursors_cmd.cpp
index 065cc40d0c9..4604a83cfa2 100644
--- a/src/mongo/db/commands/killcursors_cmd.cpp
+++ b/src/mongo/db/commands/killcursors_cmd.cpp
@@ -35,7 +35,7 @@
#include "mongo/db/curop.h"
#include "mongo/db/cursor_manager.h"
#include "mongo/db/db_raii.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/db/stats/top.h"
#include "mongo/util/scopeguard.h"
diff --git a/src/mongo/db/commands/killcursors_common.cpp b/src/mongo/db/commands/killcursors_common.cpp
index 3489948d103..4d7042070fb 100644
--- a/src/mongo/db/commands/killcursors_common.cpp
+++ b/src/mongo/db/commands/killcursors_common.cpp
@@ -35,7 +35,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/client.h"
#include "mongo/db/operation_context.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/db/query/killcursors_response.h"
namespace mongo {
@@ -43,14 +43,12 @@ namespace mongo {
Status KillCursorsCmdBase::checkAuthForCommand(Client* client,
const std::string& dbname,
const BSONObj& cmdObj) const {
- const auto statusWithRequest = KillCursorsRequest::parseFromBSON(dbname, cmdObj);
- if (!statusWithRequest.isOK()) {
- return statusWithRequest.getStatus();
- }
- const auto killCursorsRequest = statusWithRequest.getValue();
- const auto& nss = killCursorsRequest.nss;
- for (CursorId id : killCursorsRequest.cursorIds) {
+ const auto killCursorsRequest =
+ KillCursorsRequest::parse(IDLParserErrorContext("killCursors"), cmdObj);
+
+ const auto& nss = killCursorsRequest.getNamespace();
+ for (CursorId id : killCursorsRequest.getCursorIds()) {
const auto status = _checkAuth(client, nss, id);
if (!status.isOK()) {
if (status.code() == ErrorCodes::CursorNotFound) {
@@ -70,17 +68,16 @@ bool KillCursorsCmdBase::runImpl(OperationContext* opCtx,
const std::string& dbname,
const BSONObj& cmdObj,
BSONObjBuilder& result) {
- auto statusWithRequest = KillCursorsRequest::parseFromBSON(dbname, cmdObj);
- uassertStatusOK(statusWithRequest.getStatus());
- auto killCursorsRequest = std::move(statusWithRequest.getValue());
+ auto killCursorsRequest =
+ KillCursorsRequest::parse(IDLParserErrorContext("killCursors"), cmdObj);
std::vector<CursorId> cursorsKilled;
std::vector<CursorId> cursorsNotFound;
std::vector<CursorId> cursorsAlive;
std::vector<CursorId> cursorsUnknown;
- for (CursorId id : killCursorsRequest.cursorIds) {
- Status status = _killCursor(opCtx, killCursorsRequest.nss, id);
+ for (CursorId id : killCursorsRequest.getCursorIds()) {
+ Status status = _killCursor(opCtx, killCursorsRequest.getNamespace(), id);
if (status.isOK()) {
cursorsKilled.push_back(id);
} else if (status.code() == ErrorCodes::CursorNotFound) {
@@ -90,7 +87,7 @@ bool KillCursorsCmdBase::runImpl(OperationContext* opCtx,
}
audit::logKillCursorsAuthzCheck(
- opCtx->getClient(), killCursorsRequest.nss, id, status.code());
+ opCtx->getClient(), killCursorsRequest.getNamespace(), id, status.code());
}
KillCursorsResponse killCursorsResponse(
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index 4525a35a990..0bf8401eb40 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -138,10 +138,10 @@ env.Library(
'cursor_response.cpp',
'find_and_modify_request.cpp',
'getmore_request.cpp',
- 'killcursors_request.cpp',
'killcursors_response.cpp',
'view_response_formatter.cpp',
env.Idlc('count_command.idl')[0],
+ env.Idlc('kill_cursors.idl')[0],
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
diff --git a/src/mongo/db/query/kill_cursors.idl b/src/mongo/db/query/kill_cursors.idl
new file mode 100644
index 00000000000..d517ccdd477
--- /dev/null
+++ b/src/mongo/db/query/kill_cursors.idl
@@ -0,0 +1,55 @@
+# Copyright (C) 2020-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/cursor_id.h"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+types:
+ cursorId:
+ bson_serialization_type: long
+ description: "Uniquely identifies a single cursor on a particular mongoS or mongoD."
+ cpp_type: mongo::CursorId
+ deserializer: "mongo::BSONElement::_numberLong"
+
+commands:
+ killCursors:
+ description: "Kills a specified set of cursors by ID."
+ cpp_name: KillCursorsRequest
+ strict: true
+ namespace: concatenate_with_db
+ fields:
+ cursors:
+ description: "An array of cursor IDs to be killed."
+ type: array<cursorId>
+ cpp_name: cursorIds
+ optional: false \ No newline at end of file
diff --git a/src/mongo/db/query/killcursors_request.cpp b/src/mongo/db/query/killcursors_request.cpp
deleted file mode 100644
index b1ea82ce524..00000000000
--- a/src/mongo/db/query/killcursors_request.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/query/killcursors_request.h"
-
-namespace mongo {
-
-namespace {
-
-constexpr StringData kCmdName = "killCursors"_sd;
-const char kCursorsField[] = "cursors";
-
-} // namespace
-
-KillCursorsRequest::KillCursorsRequest(const NamespaceString& nsString,
- const std::vector<CursorId>& ids)
- : nss(nsString), cursorIds(ids) {}
-
-StatusWith<KillCursorsRequest> KillCursorsRequest::parseFromBSON(const std::string& dbname,
- const BSONObj& cmdObj) {
- if (cmdObj.firstElement().fieldNameStringData() != kCmdName) {
- return {ErrorCodes::FailedToParse,
- str::stream() << "First field name must be '" << kCmdName << "' in: " << cmdObj};
- }
-
- if (cmdObj.firstElement().type() != BSONType::String) {
- return {ErrorCodes::FailedToParse,
- str::stream() << "First parameter must be a string in: " << cmdObj};
- }
-
- std::string collName = cmdObj.firstElement().String();
- const NamespaceString nss(dbname, collName);
- if (!nss.isValid()) {
- return {ErrorCodes::InvalidNamespace,
- str::stream() << "Invalid collection name: " << nss.ns()};
- }
-
- if (cmdObj[kCursorsField].type() != BSONType::Array) {
- return {ErrorCodes::FailedToParse,
- str::stream() << "Field '" << kCursorsField
- << "' must be of type array in: " << cmdObj};
- }
-
- std::vector<CursorId> cursorIds;
- for (BSONElement cursorEl : cmdObj[kCursorsField].Obj()) {
- if (cursorEl.type() != BSONType::NumberLong) {
- return {ErrorCodes::FailedToParse,
- str::stream() << "Field '" << kCursorsField
- << "' contains an element that is not of type long: "
- << cursorEl};
- }
- cursorIds.push_back(cursorEl.numberLong());
- }
-
- if (cursorIds.empty()) {
- return {ErrorCodes::BadValue,
- str::stream() << "Must specify at least one cursor id in: " << cmdObj};
- }
-
- return KillCursorsRequest(nss, cursorIds);
-}
-
-BSONObj KillCursorsRequest::toBSON() const {
- BSONObjBuilder builder;
-
- builder.append(kCmdName, nss.coll());
- BSONArrayBuilder idsBuilder(builder.subarrayStart(kCursorsField));
- for (CursorId id : cursorIds) {
- idsBuilder.append(id);
- }
- idsBuilder.doneFast();
-
- return builder.obj();
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/query/killcursors_request.h b/src/mongo/db/query/killcursors_request.h
deleted file mode 100644
index 228c6c535e5..00000000000
--- a/src/mongo/db/query/killcursors_request.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <vector>
-
-#include "mongo/base/status_with.h"
-#include "mongo/bson/bsonobj.h"
-#include "mongo/db/clientcursor.h"
-#include "mongo/db/namespace_string.h"
-
-namespace mongo {
-
-struct KillCursorsRequest {
- /**
- * Constructs from a namespace and a list of cursors ids.
- */
- KillCursorsRequest(const NamespaceString& nsString, const std::vector<CursorId>& ids);
-
- static StatusWith<KillCursorsRequest> parseFromBSON(const std::string& dbname,
- const BSONObj& cmdObj);
-
- BSONObj toBSON() const;
-
- const NamespaceString nss;
- const std::vector<CursorId> cursorIds;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/query/killcursors_request_test.cpp b/src/mongo/db/query/killcursors_request_test.cpp
index d1cdb1f4650..2a63ba50769 100644
--- a/src/mongo/db/query/killcursors_request_test.cpp
+++ b/src/mongo/db/query/killcursors_request_test.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2018-present MongoDB, Inc.
+ * Copyright (C) 2020-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
@@ -29,7 +29,7 @@
#include "mongo/platform/basic.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/db/clientcursor.h"
#include "mongo/unittest/unittest.h"
@@ -38,100 +38,79 @@ namespace mongo {
namespace {
-TEST(KillCursorsRequestTest, parseFromBSONSuccess) {
- StatusWith<KillCursorsRequest> result =
- KillCursorsRequest::parseFromBSON("db",
- BSON("killCursors"
- << "coll"
- << "cursors"
- << BSON_ARRAY(CursorId(123) << CursorId(456))));
- ASSERT_OK(result.getStatus());
- KillCursorsRequest request = result.getValue();
- ASSERT_EQ(request.nss.ns(), "db.coll");
- ASSERT_EQ(request.cursorIds.size(), 2U);
- ASSERT_EQ(request.cursorIds[0], CursorId(123));
- ASSERT_EQ(request.cursorIds[1], CursorId(456));
+const IDLParserErrorContext ctxt("killCursors");
+
+TEST(KillCursorsRequestTest, parseSuccess) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "cursors" << BSON_ARRAY(CursorId(123) << CursorId(456)) << "$db"
+ << "db");
+ KillCursorsRequest request = KillCursorsRequest::parse(ctxt, bsonObj);
+ ASSERT_EQ(request.getNamespace().ns(), "db.coll");
+ ASSERT_EQ(request.getCursorIds().size(), 2U);
+ ASSERT_EQ(request.getCursorIds()[0], CursorId(123));
+ ASSERT_EQ(request.getCursorIds()[1], CursorId(456));
}
-TEST(KillCursorsRequestTest, parseFromBSONFirstFieldNotKillCursors) {
- StatusWith<KillCursorsRequest> result =
- KillCursorsRequest::parseFromBSON("db",
- BSON("foobar"
- << "coll"
- << "cursors"
- << BSON_ARRAY(CursorId(123) << CursorId(456))));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
+TEST(KillCursorsRequestTest, parseCursorsFieldEmptyArray) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "cursors" << BSONArray() << "$db"
+ << "db");
+ KillCursorsRequest request = KillCursorsRequest::parse(ctxt, bsonObj);
+ ASSERT_EQ(request.getCursorIds().size(), 0U);
}
-TEST(KillCursorsRequestTest, parseFromBSONFirstFieldNotString) {
- StatusWith<KillCursorsRequest> result = KillCursorsRequest::parseFromBSON(
- "db", BSON("killCursors" << 99 << "cursors" << BSON_ARRAY(CursorId(123) << CursorId(456))));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
+TEST(KillCursorsRequestTest, parseFirstFieldNotString) {
+ auto bsonObj =
+ BSON("killCursors" << 99 << "cursors" << BSON_ARRAY(CursorId(123) << CursorId(456)) << "$db"
+ << "db");
+ ASSERT_THROWS_CODE(
+ KillCursorsRequest::parse(ctxt, bsonObj), AssertionException, ErrorCodes::BadValue);
}
-TEST(KillCursorsRequestTest, parseFromBSONInvalidNamespace) {
- StatusWith<KillCursorsRequest> result =
- KillCursorsRequest::parseFromBSON("",
- BSON("killCursors"
- << "coll"
- << "cursors"
- << BSON_ARRAY(CursorId(123) << CursorId(456))));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::InvalidNamespace);
+TEST(KillCursorsRequestTest, parseInvalidNamespace) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "cursors" << BSON_ARRAY(CursorId(123) << CursorId(456)));
+ ASSERT_THROWS_CODE(KillCursorsRequest::parse(ctxt, bsonObj), AssertionException, 40414);
}
-TEST(KillCursorsRequestTest, parseFromBSONCursorFieldMissing) {
- StatusWith<KillCursorsRequest> result = KillCursorsRequest::parseFromBSON("db",
- BSON("killCursors"
- << "coll"));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
+TEST(KillCursorsRequestTest, parseCursorsFieldMissing) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "$db"
+ << "db");
+ ASSERT_THROWS_CODE(KillCursorsRequest::parse(ctxt, bsonObj), AssertionException, 40414);
}
-TEST(KillCursorsRequestTest, parseFromBSONCursorFieldNotArray) {
- StatusWith<KillCursorsRequest> result =
- KillCursorsRequest::parseFromBSON("db",
- BSON("killCursors"
- << "coll"
- << "cursors" << CursorId(123)));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
+TEST(KillCursorsRequestTest, parseCursorFieldNotArray) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "cursors" << CursorId(123) << "$db"
+ << "db");
+ ASSERT_THROWS_CODE(KillCursorsRequest::parse(ctxt, bsonObj), AssertionException, 10065);
}
-TEST(KillCursorsRequestTest, parseFromBSONCursorFieldEmptyArray) {
- StatusWith<KillCursorsRequest> result =
- KillCursorsRequest::parseFromBSON("db",
- BSON("killCursors"
- << "coll"
- << "cursors" << BSONArrayBuilder().arr()));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
-}
-
-
-TEST(KillCursorsRequestTest, parseFromBSONCursorFieldContainsEltOfWrongType) {
- StatusWith<KillCursorsRequest> result = KillCursorsRequest::parseFromBSON(
- "db",
- BSON("killCursors"
- << "coll"
- << "cursors" << BSON_ARRAY(CursorId(123) << "foo" << CursorId(456))));
- ASSERT_NOT_OK(result.getStatus());
- ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
+TEST(KillCursorsRequestTest, parseCursorFieldArrayWithNonCursorIdValue) {
+ auto bsonObj = BSON("killCursors"
+ << "coll"
+ << "cursors" << BSON_ARRAY(CursorId(123) << "String value") << "$db"
+ << "db");
+ ASSERT_THROWS_CODE(
+ KillCursorsRequest::parse(ctxt, bsonObj), AssertionException, ErrorCodes::TypeMismatch);
}
TEST(KillCursorsRequestTest, toBSON) {
const NamespaceString nss("db.coll");
- std::vector<CursorId> cursorIds = {CursorId(123), CursorId(456)};
+ std::vector<CursorId> cursorIds = {CursorId(123)};
KillCursorsRequest request(nss, cursorIds);
- BSONObj requestObj = request.toBSON();
+ BSONObj requestObj = request.toBSON(BSONObj{});
BSONObj expectedObj = BSON("killCursors"
<< "coll"
- << "cursors" << BSON_ARRAY(CursorId(123) << CursorId(456)));
+ << "cursors" << BSON_ARRAY(CursorId(123)));
ASSERT_BSONOBJ_EQ(requestObj, expectedObj);
}
} // namespace
-
} // namespace mongo
diff --git a/src/mongo/db/query/killcursors_response_test.cpp b/src/mongo/db/query/killcursors_response_test.cpp
index 8f091635bb4..33cf41f3a11 100644
--- a/src/mongo/db/query/killcursors_response_test.cpp
+++ b/src/mongo/db/query/killcursors_response_test.cpp
@@ -95,6 +95,19 @@ TEST(KillCursorsResponseTest, parseFromBSONArrayContainsInvalidElement) {
ASSERT_EQ(result.getStatus().code(), ErrorCodes::FailedToParse);
}
+TEST(KillCursorsResponseTest, parseFromBSONEmptyArrays) {
+ // Verifies that a kill cursors response with empty cursor ID arrays is accepted.
+ StatusWith<KillCursorsResponse> result = KillCursorsResponse::parseFromBSON(
+ BSON("cursorsKilled" << BSONArray() << "cursorsNotFound" << BSONArray() << "cursorsAlive"
+ << BSONArray() << "cursorsUnknown" << BSONArray() << "ok" << 1.0));
+ ASSERT_OK(result.getStatus());
+ KillCursorsResponse response = result.getValue();
+ ASSERT_EQ(response.cursorsKilled.size(), 0U);
+ ASSERT_EQ(response.cursorsNotFound.size(), 0U);
+ ASSERT_EQ(response.cursorsAlive.size(), 0U);
+ ASSERT_EQ(response.cursorsUnknown.size(), 0U);
+}
+
TEST(KillCursorsResponseTest, toBSON) {
std::vector<CursorId> killed = {CursorId(123)};
std::vector<CursorId> notFound = {CursorId(456), CursorId(6)};
@@ -110,6 +123,20 @@ TEST(KillCursorsResponseTest, toBSON) {
ASSERT_BSONOBJ_EQ(responseObj, expectedResponse);
}
-} // namespace
+TEST(KillCursorsResponseTest, toBSONWithZeroKilledNotFoundAliveUnknownCursors) {
+ std::vector<CursorId> killed;
+ std::vector<CursorId> notFound;
+ std::vector<CursorId> alive;
+ std::vector<CursorId> unknown;
+ // Verifies that a kill cursors response with empty cursor ID arrays can be created and is
+ // correctly serialized to a BSON object.
+ KillCursorsResponse response(killed, notFound, alive, unknown);
+ BSONObj responseObj = response.toBSON();
+ BSONObj expectedResponse =
+ BSON("cursorsKilled" << BSONArray() << "cursorsNotFound" << BSONArray() << "cursorsAlive"
+ << BSONArray() << "cursorsUnknown" << BSONArray() << "ok" << 1.0);
+ ASSERT_BSONOBJ_EQ(responseObj, expectedResponse);
+}
+} // namespace
} // namespace mongo
diff --git a/src/mongo/executor/task_executor_cursor.cpp b/src/mongo/executor/task_executor_cursor.cpp
index ac2c8dc2423..8af39f80a09 100644
--- a/src/mongo/executor/task_executor_cursor.cpp
+++ b/src/mongo/executor/task_executor_cursor.cpp
@@ -36,7 +36,7 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/getmore_request.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/util/scopeguard.h"
#include "mongo/util/time_support.h"
@@ -69,7 +69,7 @@ TaskExecutorCursor::~TaskExecutorCursor() {
// timeout if an lsid is used.
_executor
->scheduleRemoteCommand(
- _createRequest(nullptr, KillCursorsRequest(_ns, {_cursorId}).toBSON()),
+ _createRequest(nullptr, KillCursorsRequest(_ns, {_cursorId}).toBSON(BSONObj{})),
[](const auto&) {})
.isOK();
}
diff --git a/src/mongo/s/query/async_results_merger.cpp b/src/mongo/s/query/async_results_merger.cpp
index e7571307efd..635730c82ab 100644
--- a/src/mongo/s/query/async_results_merger.cpp
+++ b/src/mongo/s/query/async_results_merger.cpp
@@ -38,7 +38,7 @@
#include "mongo/db/pipeline/change_stream_constants.h"
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/getmore_request.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/executor/remote_command_response.h"
#include "mongo/s/catalog/type_shard.h"
@@ -819,7 +819,8 @@ void AsyncResultsMerger::_scheduleKillCursors(WithLock, OperationContext* opCtx)
for (const auto& remote : _remotes) {
if (remote.status.isOK() && remote.cursorId && !remote.exhausted()) {
- BSONObj cmdObj = KillCursorsRequest(_params.getNss(), {remote.cursorId}).toBSON();
+ BSONObj cmdObj =
+ KillCursorsRequest(_params.getNss(), {remote.cursorId}).toBSON(BSONObj{});
executor::RemoteCommandRequest request(
remote.getTargetHost(), _params.getNss().db().toString(), cmdObj, opCtx);
diff --git a/src/mongo/s/query/establish_cursors.cpp b/src/mongo/s/query/establish_cursors.cpp
index 07e98f29b5b..376bee65f0c 100644
--- a/src/mongo/s/query/establish_cursors.cpp
+++ b/src/mongo/s/query/establish_cursors.cpp
@@ -38,7 +38,7 @@
#include "mongo/client/remote_command_targeter.h"
#include "mongo/db/cursor_id.h"
#include "mongo/db/query/cursor_response.h"
-#include "mongo/db/query/killcursors_request.h"
+#include "mongo/db/query/kill_cursors_gen.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/executor/remote_command_response.h"
#include "mongo/logv2/log.h"
@@ -264,7 +264,8 @@ void killRemoteCursor(OperationContext* opCtx,
executor::TaskExecutor* executor,
RemoteCursor&& cursor,
const NamespaceString& nss) {
- BSONObj cmdObj = KillCursorsRequest(nss, {cursor.getCursorResponse().getCursorId()}).toBSON();
+ BSONObj cmdObj =
+ KillCursorsRequest(nss, {cursor.getCursorResponse().getCursorId()}).toBSON(BSONObj{});
executor::RemoteCommandRequest request(
cursor.getHostAndPort(), nss.db().toString(), cmdObj, opCtx);