summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/dbmessage.cpp55
-rw-r--r--src/mongo/db/dbmessage.h37
-rw-r--r--src/mongo/db/ops/write_ops.cpp64
-rw-r--r--src/mongo/db/ops/write_ops.h7
-rw-r--r--src/mongo/db/ops/write_ops_parsers.h9
-rw-r--r--src/mongo/db/ops/write_ops_parsers_test.cpp69
-rw-r--r--src/mongo/rpc/op_legacy_integration_test.cpp40
-rw-r--r--src/mongo/rpc/protocol_fuzzer.cpp15
8 files changed, 64 insertions, 232 deletions
diff --git a/src/mongo/db/dbmessage.cpp b/src/mongo/db/dbmessage.cpp
index b8d94d2f866..5a92832a108 100644
--- a/src/mongo/db/dbmessage.cpp
+++ b/src/mongo/db/dbmessage.cpp
@@ -138,21 +138,6 @@ T DbMessage::readAndAdvance() {
return t;
}
-namespace {
-template <typename Func>
-Message makeMessage(NetworkOp op, Func&& bodyBuilder) {
- BufBuilder b;
- b.skip(sizeof(MSGHEADER::Layout));
-
- bodyBuilder(b);
-
- const int size = b.len();
- auto out = Message(b.release());
- out.header().setOperation(op);
- out.header().setLen(size);
- return out;
-}
-} // namespace
Message makeDeprecatedQueryMessage(StringData ns,
BSONObj query,
@@ -186,46 +171,6 @@ Message makeDeprecatedInsertMessage(StringData ns, const BSONObj* objs, size_t c
});
}
-Message makeDeprecatedUpdateMessage(StringData ns, BSONObj query, BSONObj update, int flags) {
- return makeMessage(dbUpdate, [&](BufBuilder& b) {
- const int reservedFlags = 0;
- b.appendNum(reservedFlags);
- b.appendStr(ns);
- b.appendNum(flags);
-
- query.appendSelfToBufBuilder(b);
- update.appendSelfToBufBuilder(b);
- });
-}
-
-Message makeDeprecatedRemoveMessage(StringData ns, BSONObj query, int flags) {
- return makeMessage(dbDelete, [&](BufBuilder& b) {
- const int reservedFlags = 0;
- b.appendNum(reservedFlags);
- b.appendStr(ns);
- b.appendNum(flags);
-
- query.appendSelfToBufBuilder(b);
- });
-}
-
-Message makeDeprecatedKillCursorsMessage(long long cursorId) {
- return makeMessage(dbKillCursors, [&](BufBuilder& b) {
- b.appendNum((int)0); // reserved
- b.appendNum((int)1); // number
- b.appendNum(cursorId);
- });
-}
-
-Message makeDeprecatedGetMoreMessage(StringData ns, long long cursorId, int nToReturn, int flags) {
- return makeMessage(dbGetMore, [&](BufBuilder& b) {
- b.appendNum(flags);
- b.appendStr(ns);
- b.appendNum(nToReturn);
- b.appendNum(cursorId);
- });
-}
-
DbResponse makeErrorResponseToDeprecatedOpQuery(StringData errorMsg) {
BSONObjBuilder err;
err.append("$err", errorMsg);
diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h
index 63c78c261cb..822bb29ecee 100644
--- a/src/mongo/db/dbmessage.h
+++ b/src/mongo/db/dbmessage.h
@@ -384,6 +384,20 @@ public:
}
};
+template <typename Func>
+Message makeMessage(NetworkOp op, Func&& bodyBuilder) {
+ BufBuilder b;
+ b.skip(sizeof(MSGHEADER::Layout));
+
+ bodyBuilder(b);
+
+ const int size = b.len();
+ auto out = Message(b.release());
+ out.header().setOperation(op);
+ out.header().setLen(size);
+ return out;
+}
+
/**
* Builds a legacy OP_QUERY message.
*/
@@ -419,11 +433,6 @@ enum UpdateOptions {
UpdateOption_Broadcast = 1 << 2
};
-/**
- * Builds a legacy OP_UPDATE message.
- */
-Message makeDeprecatedUpdateMessage(StringData ns, BSONObj query, BSONObj update, int flags = 0);
-
enum RemoveOptions {
/** only delete one option */
RemoveOption_JustOne = 1 << 0,
@@ -433,24 +442,6 @@ enum RemoveOptions {
};
/**
- * Builds a legacy OP_REMOVE message.
- */
-Message makeDeprecatedRemoveMessage(StringData ns, BSONObj query, int flags = 0);
-
-/**
- * Builds a legacy OP_KILLCURSORS message.
- */
-Message makeDeprecatedKillCursorsMessage(long long cursorId);
-
-/**
- * Builds a legacy OP_GET_MORE message.
- */
-Message makeDeprecatedGetMoreMessage(StringData ns,
- long long cursorId,
- int nToReturn,
- int flags = 0);
-
-/**
* A response to a DbMessage.
*
* Order of fields makes DbResponse{funcReturningMessage()} valid.
diff --git a/src/mongo/db/ops/write_ops.cpp b/src/mongo/db/ops/write_ops.cpp
index aefe6a20a4c..5c60f26fb6c 100644
--- a/src/mongo/db/ops/write_ops.cpp
+++ b/src/mongo/db/ops/write_ops.cpp
@@ -182,37 +182,6 @@ write_ops::UpdateCommandRequest UpdateOp::parse(const OpMsgRequest& request) {
return updateOp;
}
-write_ops::UpdateCommandRequest UpdateOp::parseLegacy(const Message& msgRaw) {
- DbMessage msg(msgRaw);
-
- UpdateCommandRequest op(NamespaceString(msg.getns()));
-
- {
- write_ops::WriteCommandRequestBase writeCommandBase;
- writeCommandBase.setBypassDocumentValidation(false);
- writeCommandBase.setOrdered(true);
- op.setWriteCommandRequestBase(std::move(writeCommandBase));
- }
-
- op.setUpdates([&] {
- std::vector<write_ops::UpdateOpEntry> updates;
- updates.emplace_back();
-
- // Legacy updates only allowed one update per operation. Layout is flags, query, update.
- auto& singleUpdate = updates.back();
- const int flags = msg.pullInt();
- singleUpdate.setUpsert(flags & UpdateOption_Upsert);
- singleUpdate.setMulti(flags & UpdateOption_Multi);
- singleUpdate.setQ(msg.nextJsObj());
- singleUpdate.setU(
- write_ops::UpdateModification::parseLegacyOpUpdateFromBSON(msg.nextJsObj()));
-
- return updates;
- }());
-
- return op;
-}
-
write_ops::UpdateCommandReply UpdateOp::parseResponse(const BSONObj& obj) {
uassertStatusOK(getStatusFromCommandResult(obj));
@@ -237,34 +206,6 @@ write_ops::DeleteCommandRequest DeleteOp::parse(const OpMsgRequest& request) {
return deleteOp;
}
-write_ops::DeleteCommandRequest DeleteOp::parseLegacy(const Message& msgRaw) {
- DbMessage msg(msgRaw);
-
- DeleteCommandRequest op(NamespaceString(msg.getns()));
-
- {
- write_ops::WriteCommandRequestBase writeCommandBase;
- writeCommandBase.setBypassDocumentValidation(false);
- writeCommandBase.setOrdered(true);
- op.setWriteCommandRequestBase(std::move(writeCommandBase));
- }
-
- op.setDeletes([&] {
- std::vector<write_ops::DeleteOpEntry> deletes;
- deletes.emplace_back();
-
- // Legacy deletes only allowed one delete per operation. Layout is flags, query.
- auto& singleDelete = deletes.back();
- const int flags = msg.pullInt();
- singleDelete.setMulti(!(flags & RemoveOption_JustOne));
- singleDelete.setQ(msg.nextJsObj());
-
- return deletes;
- }());
-
- return op;
-}
-
void DeleteOp::validate(const DeleteCommandRequest& deleteOp) {
checkOpCountForCommand(deleteOp, deleteOp.getDeletes().size());
}
@@ -344,11 +285,6 @@ write_ops::UpdateModification write_ops::UpdateModification::parseFromBSON(BSONE
return UpdateModification(elem);
}
-write_ops::UpdateModification write_ops::UpdateModification::parseLegacyOpUpdateFromBSON(
- const BSONObj& obj) {
- return UpdateModification(obj, ClassicTag{});
-}
-
int write_ops::UpdateModification::objsize() const {
return stdx::visit(
visit_helper::Overloaded{
diff --git a/src/mongo/db/ops/write_ops.h b/src/mongo/db/ops/write_ops.h
index 5fa6651bad5..5dc73cc0d49 100644
--- a/src/mongo/db/ops/write_ops.h
+++ b/src/mongo/db/ops/write_ops.h
@@ -38,6 +38,11 @@ namespace mongo {
class InsertOp {
public:
static write_ops::InsertCommandRequest parse(const OpMsgRequest& request);
+ /**
+ * This is to parse OP_INSERT legacy request and deprecated and used only to parse legacy insert
+ * request to know how many documents need to be inserted for the purpose of monitoring. Do not
+ * call this method any more.
+ */
static write_ops::InsertCommandRequest parseLegacy(const Message& msg);
static void validate(const write_ops::InsertCommandRequest& insertOp);
};
@@ -45,7 +50,6 @@ public:
class UpdateOp {
public:
static write_ops::UpdateCommandRequest parse(const OpMsgRequest& request);
- static write_ops::UpdateCommandRequest parseLegacy(const Message& msg);
static write_ops::UpdateCommandReply parseResponse(const BSONObj& obj);
static void validate(const write_ops::UpdateCommandRequest& updateOp);
};
@@ -53,7 +57,6 @@ public:
class DeleteOp {
public:
static write_ops::DeleteCommandRequest parse(const OpMsgRequest& request);
- static write_ops::DeleteCommandRequest parseLegacy(const Message& msg);
static void validate(const write_ops::DeleteCommandRequest& deleteOp);
};
diff --git a/src/mongo/db/ops/write_ops_parsers.h b/src/mongo/db/ops/write_ops_parsers.h
index 22608793005..788ae259722 100644
--- a/src/mongo/db/ops/write_ops_parsers.h
+++ b/src/mongo/db/ops/write_ops_parsers.h
@@ -122,15 +122,6 @@ public:
*/
void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const;
- // When parsing from legacy OP_UPDATE messages, we receive the "u" field as an object. When an
- // array is parsed, we receive it as an object with numeric fields names and can't differentiate
- // between a user constructed object and an array. For that reason, we don't support pipeline
- // style update via OP_UPDATE and 'obj' is assumed to be a classic update.
- //
- // If a user did send a pipeline-style update via OP_UPDATE, it would fail parsing a field
- // representing an aggregation stage, due to the leading '$'' character.
- static UpdateModification parseLegacyOpUpdateFromBSON(const BSONObj& obj);
-
int objsize() const;
Type type() const;
diff --git a/src/mongo/db/ops/write_ops_parsers_test.cpp b/src/mongo/db/ops/write_ops_parsers_test.cpp
index e8abac496fd..7fd55f1ef32 100644
--- a/src/mongo/db/ops/write_ops_parsers_test.cpp
+++ b/src/mongo/db/ops/write_ops_parsers_test.cpp
@@ -444,75 +444,6 @@ TEST(LegacyWriteOpsParsers, RealMultiInsert) {
}
}
-TEST(LegacyWriteOpsParsers, UpdateCommandRequest) {
- const std::string ns = "test.foo";
- const BSONObj query = BSON("x" << 1);
- const BSONObj update = BSON("$inc" << BSON("x" << 1));
- for (bool upsert : {false, true}) {
- for (bool multi : {false, true}) {
- auto message = makeDeprecatedUpdateMessage(ns,
- query,
- update,
- (upsert ? UpdateOption_Upsert : 0) |
- (multi ? UpdateOption_Multi : 0));
- const auto op = UpdateOp::parseLegacy(message);
- ASSERT_EQ(op.getNamespace().ns(), ns);
- ASSERT(!op.getWriteCommandRequestBase().getBypassDocumentValidation());
- ASSERT_EQ(op.getWriteCommandRequestBase().getOrdered(), true);
- ASSERT_EQ(op.getUpdates().size(), 1u);
- ASSERT_BSONOBJ_EQ(op.getUpdates()[0].getQ(), query);
- ASSERT_BSONOBJ_EQ(op.getUpdates()[0].getU().getUpdateClassic(), update);
- ASSERT_EQ(op.getUpdates()[0].getUpsert(), upsert);
- ASSERT_EQ(op.getUpdates()[0].getMulti(), multi);
- }
- }
-}
-
-// When parsing from legacy OP_UPDATE messages, we receive the "u" field as an object. When an array
-// is parsed, we receive it as an object with numeric fields names and can't differentiate between a
-// user constructed object and an array. For that reason, we parse as a classic-style update rather
-// than as pipeline-style.
-TEST(LegacyWriteOpsParsers, UpdateWithArrayUpdateFieldIsParsedAsReplacementStyleUpdate) {
- const std::string ns = "test.foo";
- const BSONObj query = BSON("x" << 1);
- const BSONObj update = BSON_ARRAY(BSON("$addFields" << BSON("x" << 1)));
- for (bool upsert : {false, true}) {
- for (bool multi : {false, true}) {
- auto message = makeDeprecatedUpdateMessage(ns,
- query,
- update,
- (upsert ? UpdateOption_Upsert : 0) |
- (multi ? UpdateOption_Multi : 0));
- const auto op = UpdateOp::parseLegacy(message);
- ASSERT_EQ(op.getNamespace().ns(), ns);
- ASSERT(!op.getWriteCommandRequestBase().getBypassDocumentValidation());
- ASSERT_EQ(op.getWriteCommandRequestBase().getOrdered(), true);
- ASSERT_EQ(op.getUpdates().size(), 1u);
- ASSERT_BSONOBJ_EQ(op.getUpdates()[0].getQ(), query);
- ASSERT(op.getUpdates()[0].getU().type() ==
- write_ops::UpdateModification::Type::kClassic);
- ASSERT_BSONOBJ_EQ(op.getUpdates()[0].getU().getUpdateClassic(), update);
- ASSERT_EQ(op.getUpdates()[0].getUpsert(), upsert);
- ASSERT_EQ(op.getUpdates()[0].getMulti(), multi);
- }
- }
-}
-
-TEST(LegacyWriteOpsParsers, Remove) {
- const std::string ns = "test.foo";
- const BSONObj query = BSON("x" << 1);
- for (bool multi : {false, true}) {
- auto message = makeDeprecatedRemoveMessage(ns, query, (multi ? 0 : RemoveOption_JustOne));
- const auto op = DeleteOp::parseLegacy(message);
- ASSERT_EQ(op.getNamespace().ns(), ns);
- ASSERT(!op.getWriteCommandRequestBase().getBypassDocumentValidation());
- ASSERT_EQ(op.getWriteCommandRequestBase().getOrdered(), true);
- ASSERT_EQ(op.getDeletes().size(), 1u);
- ASSERT_BSONOBJ_EQ(op.getDeletes()[0].getQ(), query);
- ASSERT_EQ(op.getDeletes()[0].getMulti(), multi);
- }
-}
-
/**
* Test OpTime serializer and deserializer when OpTime does not have term initailized.
*/
diff --git a/src/mongo/rpc/op_legacy_integration_test.cpp b/src/mongo/rpc/op_legacy_integration_test.cpp
index 955c681ae68..ec9f64eef36 100644
--- a/src/mongo/rpc/op_legacy_integration_test.cpp
+++ b/src/mongo/rpc/op_legacy_integration_test.cpp
@@ -54,6 +54,46 @@ long getDeprecatedOpCount(BSONObj serverStatus, const char* opName) {
return deprecatedOpcounters ? deprecatedOpcounters[opName].Long() : 0;
}
+Message makeDeprecatedUpdateMessage(StringData ns, BSONObj query, BSONObj update, int flags) {
+ return makeMessage(dbUpdate, [&](BufBuilder& b) {
+ const int reservedFlags = 0;
+ b.appendNum(reservedFlags);
+ b.appendStr(ns);
+ b.appendNum(flags);
+
+ query.appendSelfToBufBuilder(b);
+ update.appendSelfToBufBuilder(b);
+ });
+}
+
+Message makeDeprecatedRemoveMessage(StringData ns, BSONObj query, int flags) {
+ return makeMessage(dbDelete, [&](BufBuilder& b) {
+ const int reservedFlags = 0;
+ b.appendNum(reservedFlags);
+ b.appendStr(ns);
+ b.appendNum(flags);
+
+ query.appendSelfToBufBuilder(b);
+ });
+}
+
+Message makeDeprecatedKillCursorsMessage(long long cursorId) {
+ return makeMessage(dbKillCursors, [&](BufBuilder& b) {
+ b.appendNum((int)0); // reserved
+ b.appendNum((int)1); // number
+ b.appendNum(cursorId);
+ });
+}
+
+Message makeDeprecatedGetMoreMessage(StringData ns, long long cursorId, int nToReturn, int flags) {
+ return makeMessage(dbGetMore, [&](BufBuilder& b) {
+ b.appendNum(flags);
+ b.appendStr(ns);
+ b.appendNum(nToReturn);
+ b.appendNum(cursorId);
+ });
+}
+
// Issue a find command request so we can use cursor id from it to test the deprecated getMore
// and killCursors ops.
int64_t getValidCursorIdFromFindCmd(DBClientBase* conn, const char* collName) {
diff --git a/src/mongo/rpc/protocol_fuzzer.cpp b/src/mongo/rpc/protocol_fuzzer.cpp
index 19876d0ef47..a9edfba382b 100644
--- a/src/mongo/rpc/protocol_fuzzer.cpp
+++ b/src/mongo/rpc/protocol_fuzzer.cpp
@@ -75,11 +75,10 @@ void doFuzzing(ConstDataRangeCursor fuzzedData) try {
msg = uassertStatusOK(compression.manager.decompressMessage(msg));
}
- DbMessage dbMsgObj(msg);
switch (msg.operation()) {
case dbMsg: {
- auto request = rpc::opMsgRequestFromAnyProtocol(msg);
+ auto request = OpMsgRequest::parseOwned(msg);
validateBSON(request.body);
for (const auto& docSeq : request.sequences) {
for (const auto& doc : docSeq.objs) {
@@ -87,22 +86,18 @@ void doFuzzing(ConstDataRangeCursor fuzzedData) try {
}
}
} break;
- case dbUpdate: {
- auto op = UpdateOp::parseLegacy(msg);
- } break;
case dbInsert: {
auto op = InsertOp::parseLegacy(msg);
} break;
- case dbDelete: {
- auto op = DeleteOp::parseLegacy(msg);
- }
case dbQuery: {
+ DbMessage dbMsgObj(msg);
QueryMessage q(dbMsgObj);
} break;
- // TODO these message types don't have discrete parsers. We should move their parsing out
- // of the ServiceEntryPointCommon so we can actually
+ // These message types don't have parsers because they are no longer supported.
case dbGetMore:
case dbKillCursors:
+ case dbDelete:
+ case dbUpdate:
break;
default:
invariant(!isSupportedRequestNetworkOp(msg.operation()));