Example #1
0
StatusWith<Shard::CommandResponse> ShardRemote::_runCommand(OperationContext* txn,
                                                            const ReadPreferenceSetting& readPref,
                                                            const string& dbName,
                                                            const BSONObj& cmdObj) {
    const BSONObj cmdWithMaxTimeMS = (isConfig() ? appendMaxTimeToCmdObj(txn, cmdObj) : cmdObj);

    const auto host =
        _targeter->findHost(readPref, RemoteCommandTargeter::selectFindHostMaxWaitTime(txn));
    if (!host.isOK()) {
        return host.getStatus();
    }

    RemoteCommandRequest request(host.getValue(),
                                 dbName,
                                 cmdWithMaxTimeMS,
                                 _getMetadataForCommand(readPref),
                                 isConfig() ? kConfigCommandTimeout
                                            : executor::RemoteCommandRequest::kNoTimeout);
    StatusWith<RemoteCommandResponse> swResponse =
        Status(ErrorCodes::InternalError, "Internal error running command");

    TaskExecutor* executor = Grid::get(txn)->getExecutorPool()->getFixedExecutor();
    auto callStatus = executor->scheduleRemoteCommand(
        request,
        [&swResponse](const RemoteCommandCallbackArgs& args) { swResponse = args.response; });
    if (!callStatus.isOK()) {
        return callStatus.getStatus();
    }

    // Block until the command is carried out
    executor->wait(callStatus.getValue());

    updateReplSetMonitor(host.getValue(), swResponse.getStatus());

    if (!swResponse.isOK()) {
        if (swResponse.getStatus().compareCode(ErrorCodes::ExceededTimeLimit)) {
            LOG(0) << "Operation timed out with status " << swResponse.getStatus();
        }
        return swResponse.getStatus();
    }

    BSONObj responseObj = swResponse.getValue().data.getOwned();
    BSONObj responseMetadata = swResponse.getValue().metadata.getOwned();
    Status commandStatus = getStatusFromCommandResult(responseObj);
    Status writeConcernStatus = getWriteConcernStatusFromCommandResult(responseObj);
    updateReplSetMonitor(host.getValue(), commandStatus);

    return CommandResponse(std::move(responseObj),
                           std::move(responseMetadata),
                           std::move(commandStatus),
                           std::move(writeConcernStatus));
}
Example #2
0
Shard::HostWithResponse ShardRemote::_runCommand(OperationContext* txn,
                                                 const ReadPreferenceSetting& readPref,
                                                 const string& dbName,
                                                 Milliseconds maxTimeMSOverride,
                                                 const BSONObj& cmdObj) {

    ReadPreferenceSetting readPrefWithMinOpTime(readPref);
    if (getId() == "config") {
        readPrefWithMinOpTime.minOpTime = grid.configOpTime();
    }
    const auto host = _targeter->findHost(txn, readPrefWithMinOpTime);
    if (!host.isOK()) {
        return Shard::HostWithResponse(boost::none, host.getStatus());
    }

    const Milliseconds requestTimeout =
        std::min(txn->getRemainingMaxTimeMillis(), maxTimeMSOverride);

    const RemoteCommandRequest request(
        host.getValue(),
        dbName,
        appendMaxTimeToCmdObj(maxTimeMSOverride, cmdObj),
        _appendMetadataForCommand(txn, readPrefWithMinOpTime),
        txn,
        requestTimeout < Milliseconds::max() ? requestTimeout : RemoteCommandRequest::kNoTimeout);

    RemoteCommandResponse swResponse =
        Status(ErrorCodes::InternalError, "Internal error running command");

    TaskExecutor* executor = Grid::get(txn)->getExecutorPool()->getFixedExecutor();
    auto callStatus = executor->scheduleRemoteCommand(
        request,
        [&swResponse](const RemoteCommandCallbackArgs& args) { swResponse = args.response; });
    if (!callStatus.isOK()) {
        return Shard::HostWithResponse(host.getValue(), callStatus.getStatus());
    }

    // Block until the command is carried out
    executor->wait(callStatus.getValue());

    updateReplSetMonitor(host.getValue(), swResponse.status);

    if (!swResponse.isOK()) {
        if (swResponse.status.compareCode(ErrorCodes::ExceededTimeLimit)) {
            LOG(0) << "Operation timed out with status " << redact(swResponse.status);
        }
        return Shard::HostWithResponse(host.getValue(), swResponse.status);
    }

    BSONObj responseObj = swResponse.data.getOwned();
    BSONObj responseMetadata = swResponse.metadata.getOwned();
    Status commandStatus = getStatusFromCommandResult(responseObj);
    Status writeConcernStatus = getWriteConcernStatusFromCommandResult(responseObj);

    // Tell the replica set monitor of any errors
    updateReplSetMonitor(host.getValue(), commandStatus);
    updateReplSetMonitor(host.getValue(), writeConcernStatus);

    return Shard::HostWithResponse(host.getValue(),
                                   CommandResponse(std::move(responseObj),
                                                   std::move(responseMetadata),
                                                   std::move(commandStatus),
                                                   std::move(writeConcernStatus)));
}