summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/killcursors_response.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/killcursors_response.cpp')
-rw-r--r--src/mongo/db/query/killcursors_response.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/mongo/db/query/killcursors_response.cpp b/src/mongo/db/query/killcursors_response.cpp
new file mode 100644
index 00000000000..4117e4dafe0
--- /dev/null
+++ b/src/mongo/db/query/killcursors_response.cpp
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kQuery
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/query/killcursors_response.h"
+
+#include "mongo/rpc/get_status_from_command_result.h"
+
+namespace mongo {
+
+namespace {
+
+const char kKilledField[] = "cursorsKilled";
+const char kNotFoundField[] = "cursorsNotFound";
+const char kAliveField[] = "cursorsAlive";
+
+Status fillOutCursorArray(const BSONObj& cmdResponse,
+ StringData fieldName,
+ std::vector<CursorId>* cursorIds) {
+ BSONElement elt = cmdResponse[fieldName];
+ if (elt.eoo()) {
+ return Status::OK();
+ }
+
+ if (elt.type() != BSONType::Array) {
+ return {ErrorCodes::FailedToParse,
+ str::stream() << "Field '" << fieldName
+ << "' must be of type array in: " << cmdResponse};
+ }
+
+ for (BSONElement cursorElt : elt.Obj()) {
+ if (cursorElt.type() != BSONType::NumberLong) {
+ return {ErrorCodes::FailedToParse,
+ str::stream() << "Field '" << fieldName
+ << "' contains an element that is not of type long: "
+ << cursorElt};
+ }
+ cursorIds->push_back(cursorElt.numberLong());
+ }
+
+ if (cursorIds->empty()) {
+ return {ErrorCodes::BadValue,
+ str::stream() << "Must specify at least one cursor id for field '" << fieldName
+ << "' in: " << cmdResponse};
+ }
+
+ return Status::OK();
+}
+
+void addCursorArrayToBSON(const std::vector<CursorId>& cursorIds,
+ StringData fieldName,
+ BSONObjBuilder* builder) {
+ BSONArrayBuilder idsBuilder(builder->subarrayStart(fieldName));
+ for (CursorId id : cursorIds) {
+ idsBuilder.append(id);
+ }
+ idsBuilder.doneFast();
+}
+
+} // namespace
+
+KillCursorsResponse::KillCursorsResponse() {}
+
+KillCursorsResponse::KillCursorsResponse(const std::vector<CursorId>& killed,
+ const std::vector<CursorId>& notFound,
+ const std::vector<CursorId>& alive)
+ : cursorsKilled(killed), cursorsNotFound(notFound), cursorsAlive(alive) {}
+
+StatusWith<KillCursorsResponse> KillCursorsResponse::parseFromBSON(const BSONObj& cmdResponse) {
+ Status cmdStatus = getStatusFromCommandResult(cmdResponse);
+ if (!cmdStatus.isOK()) {
+ return cmdStatus;
+ }
+
+ std::vector<CursorId> cursorsKilled;
+ Status killedStatus = fillOutCursorArray(cmdResponse, kKilledField, &cursorsKilled);
+ if (!killedStatus.isOK()) {
+ return killedStatus;
+ }
+
+ std::vector<CursorId> cursorsNotFound;
+ Status notFoundStatus = fillOutCursorArray(cmdResponse, kNotFoundField, &cursorsNotFound);
+ if (!notFoundStatus.isOK()) {
+ return notFoundStatus;
+ }
+
+ std::vector<CursorId> cursorsAlive;
+ Status aliveStatus = fillOutCursorArray(cmdResponse, kAliveField, &cursorsAlive);
+ if (!aliveStatus.isOK()) {
+ return aliveStatus;
+ }
+
+ return KillCursorsResponse(cursorsKilled, cursorsNotFound, cursorsAlive);
+}
+
+BSONObj KillCursorsResponse::toBSON() const {
+ BSONObjBuilder builder;
+ addToBSON(&builder);
+ builder.append("ok", 1.0);
+ return builder.obj();
+}
+
+void KillCursorsResponse::addToBSON(BSONObjBuilder* builder) const {
+ addCursorArrayToBSON(cursorsKilled, kKilledField, builder);
+ addCursorArrayToBSON(cursorsNotFound, kNotFoundField, builder);
+ addCursorArrayToBSON(cursorsAlive, kAliveField, builder);
+}
+
+} // namespace mongo