Esempio n. 1
0
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()), ""};
}