Message CommandReplyBuilder::done() { invariant(_state == State::kOutputDocs); MsgData::View msg = _builder.buf(); msg.setLen(_builder.len()); msg.setOperation(dbCommandReply); _builder.decouple(); // release ownership from BufBuilder _message.setData(msg.view2ptr(), true); // transfer ownership to Message _state = State::kDone; return std::move(_message); }
Message opCommandRequestFromOpMsgRequest(const OpMsgRequest& request) { const auto commandName = request.getCommandName(); BufBuilder builder; builder.skip(mongo::MsgData::MsgDataHeaderSize); // Leave room for message header. builder.appendStr(request.getDatabase()); builder.appendStr(commandName); // OP_COMMAND is only used when communicating with 3.4 nodes and they serialize their metadata // fields differently. In addition to field-level differences, some generic arguments are pulled // out to a metadata object, separate from the body. We do all down-conversion here so that the // rest of the code only has to deal with the current format. BSONObjBuilder metadataBuilder; // Will be appended to the message after we finish the body. { BSONObjBuilder bodyBuilder(builder); for (auto elem : request.body) { const auto fieldName = elem.fieldNameStringData(); if (fieldName == "$configServerState") { metadataBuilder.appendAs(elem, "configsvr"); } else if (fieldName == "$readPreference") { BSONObjBuilder ssmBuilder(metadataBuilder.subobjStart("$ssm")); ssmBuilder.append(elem); ssmBuilder.append("$secondaryOk", uassertStatusOK(ReadPreferenceSetting::fromInnerBSON(elem)) .canRunOnSecondary()); } else if (fieldName == "$db") { // skip } else if (fieldGoesInMetadata(commandName, fieldName)) { metadataBuilder.append(elem); } else { bodyBuilder.append(elem); } } for (auto&& seq : request.sequences) { invariant(seq.name.find('.') == std::string::npos); // Only support top-level for now. dassert(!bodyBuilder.asTempObj().hasField(seq.name)); bodyBuilder.append(seq.name, seq.objs); } } metadataBuilder.obj().appendSelfToBufBuilder(builder); MsgData::View msg = builder.buf(); msg.setLen(builder.len()); msg.setOperation(dbCommand); return Message(builder.release()); }
DbResponse ServiceEntryPointMock::handleRequest(OperationContext* opCtx, const Message& request, const HostAndPort& client) { // Need to set up our { ok : 1 } response. BufBuilder b{}; // Leave room for the message header b.skip(mongo::MsgData::MsgDataHeaderSize); // Add our response auto okObj = BSON("ok" << 1.0); okObj.appendSelfToBufBuilder(b); // Add some metadata auto metadata = BSONObj(); metadata.appendSelfToBufBuilder(b); // Set Message header fields MsgData::View msg = b.buf(); msg.setLen(b.len()); msg.setOperation(dbCommandReply); return {Message(b.release()), ""}; }