예제 #1
0
rpc::UniqueReply MockRemoteDBServer::runCommand(InstanceID id, const OpMsgRequest& request) {
    checkIfUp(id);
    std::string cmdName = request.getCommandName().toString();

    BSONObj reply;
    {
        scoped_spinlock lk(_lock);

        uassert(ErrorCodes::IllegalOperation,
                str::stream() << "no reply for command: " << cmdName,
                _cmdMap.count(cmdName));

        reply = _cmdMap[cmdName]->next();
    }

    if (_delayMilliSec > 0) {
        mongo::sleepmillis(_delayMilliSec);
    }

    checkIfUp(id);

    {
        scoped_spinlock lk(_lock);
        _cmdCount++;
    }

    // We need to construct a reply message - it will always be read through a view so it
    // doesn't matter whether we use OpMsgReplyBuilder or LegacyReplyBuilder
    auto message = rpc::OpMsgReplyBuilder{}.setCommandReply(reply).done();
    auto replyView = stdx::make_unique<rpc::OpMsgReply>(&message);
    return rpc::UniqueReply(std::move(message), std::move(replyView));
}
예제 #2
0
BSONObj CommandHelpers::runCommandDirectly(OperationContext* opCtx, const OpMsgRequest& request) {
    auto command = globalCommandRegistry()->findCommand(request.getCommandName());
    invariant(command);
    BSONObjBuilder out;
    try {
        bool ok = command->publicRun(opCtx, request, out);
        appendCommandStatus(out, ok);
    } catch (const StaleConfigException&) {
        // These exceptions are intended to be handled at a higher level.
        throw;
    } catch (const DBException& ex) {
        out.resetToEmpty();
        appendCommandStatus(out, ex.toStatus());
    }
    return out.obj();
}
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());
}
예제 #4
0
파일: commands.cpp 프로젝트: RyanBard/mongo
BSONObj CommandHelpers::runCommandDirectly(OperationContext* opCtx, const OpMsgRequest& request) {
    auto command = globalCommandRegistry()->findCommand(request.getCommandName());
    invariant(command);
    rpc::OpMsgReplyBuilder replyBuilder;
    std::unique_ptr<CommandInvocation> invocation;
    try {
        invocation = command->parse(opCtx, request);
        invocation->run(opCtx, &replyBuilder);
        auto body = replyBuilder.getBodyBuilder();
        CommandHelpers::extractOrAppendOk(body);
    } catch (const StaleConfigException&) {
        // These exceptions are intended to be handled at a higher level.
        throw;
    } catch (const DBException& ex) {
        if (ex.code() == ErrorCodes::Unauthorized) {
            CommandHelpers::auditLogAuthEvent(opCtx, invocation.get(), request, ex.code());
        }
        auto body = replyBuilder.getBodyBuilder();
        body.resetToEmpty();
        appendCommandStatusNoThrow(body, ex.toStatus());
    }
    return replyBuilder.releaseBody();
}