diff options
author | Mindaugas Malinauskas <mindaugas.malinauskas@mongodb.com> | 2020-07-01 15:12:52 +0300 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-08 13:14:41 +0000 |
commit | c610e2627beeb3c8a6f95a2e7071a06e4ea1b1c0 (patch) | |
tree | b82f27f2a285272cad90465268f3e33ff9e4bb6b /src/mongo | |
parent | d4c7887dfae2d861cd4bb3118d576aee3c4f353f (diff) | |
download | mongo-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.cpp | 4 | ||||
-rw-r--r-- | src/mongo/client/dbclient_connection.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/killcursors_cmd.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/killcursors_common.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/query/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/query/kill_cursors.idl | 55 | ||||
-rw-r--r-- | src/mongo/db/query/killcursors_request.cpp | 106 | ||||
-rw-r--r-- | src/mongo/db/query/killcursors_request.h | 56 | ||||
-rw-r--r-- | src/mongo/db/query/killcursors_request_test.cpp | 129 | ||||
-rw-r--r-- | src/mongo/db/query/killcursors_response_test.cpp | 29 | ||||
-rw-r--r-- | src/mongo/executor/task_executor_cursor.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/query/async_results_merger.cpp | 5 | ||||
-rw-r--r-- | src/mongo/s/query/establish_cursors.cpp | 5 |
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); |