Beispiel #1
0
 void Command::appendCommandWCStatus(BSONObjBuilder& result, const Status& status) {
     if (!status.isOK()) {
         WCErrorDetail wcError;
         wcError.setErrCode(status.code());
         wcError.setErrMessage(status.reason());
         result.append("writeConcernError", wcError.toBSON());
     }
 }
Beispiel #2
0
void Command::appendCommandWCStatus(BSONObjBuilder& result,
                                    const Status& awaitReplicationStatus,
                                    const WriteConcernResult& wcResult) {
    if (!awaitReplicationStatus.isOK() && !result.hasField("writeConcernError")) {
        WCErrorDetail wcError;
        wcError.setErrCode(awaitReplicationStatus.code());
        wcError.setErrMessage(awaitReplicationStatus.reason());
        if (wcResult.wTimedOut) {
            wcError.setErrInfo(BSON("wtimeout" << true));
        }
        result.append("writeConcernError", wcError.toBSON());
    }
}
void appendWriteConcernErrorToCmdResponse(const std::string& shardID,
                                          const BSONElement& wcErrorElem,
                                          BSONObjBuilder& responseBuilder) {
    WCErrorDetail wcError;
    std::string errMsg;
    auto wcErrorObj = wcErrorElem.Obj();
    if (!wcError.parseBSON(wcErrorObj, &errMsg)) {
        wcError.setErrMessage("Failed to parse writeConcernError: " + wcErrorObj.toString() +
                              ", Received error: " + errMsg);
    }
    wcError.setErrMessage(wcError.getErrMessage() + " at " + shardID);
    responseBuilder.append("writeConcernError", wcError.toBSON());
}
Beispiel #4
0
void BatchWriteOp::buildClientResponse(BatchedCommandResponse* batchResp) {
    dassert(isFinished());

    // Result is OK
    batchResp->setOk(true);

    // For non-verbose, it's all we need.
    if (!_clientRequest->isVerboseWC()) {
        dassert(batchResp->isValid(NULL));
        return;
    }

    //
    // Find all the errors in the batch
    //

    vector<WriteOp*> errOps;

    size_t numWriteOps = _clientRequest->sizeWriteOps();
    for (size_t i = 0; i < numWriteOps; ++i) {
        WriteOp& writeOp = _writeOps[i];

        if (writeOp.getWriteState() == WriteOpState_Error) {
            errOps.push_back(&writeOp);
        }
    }

    //
    // Build the per-item errors.
    //

    if (!errOps.empty()) {
        for (vector<WriteOp*>::iterator it = errOps.begin(); it != errOps.end(); ++it) {
            WriteOp& writeOp = **it;
            WriteErrorDetail* error = new WriteErrorDetail();
            writeOp.getOpError().cloneTo(error);
            batchResp->addToErrDetails(error);
        }
    }

    // Only return a write concern error if everything succeeded (unordered or ordered)
    // OR if something succeeded and we're unordered
    bool reportWCError = errOps.empty() ||
        (!_clientRequest->getOrdered() && errOps.size() < _clientRequest->sizeWriteOps());
    if (!_wcErrors.empty() && reportWCError) {
        WCErrorDetail* error = new WCErrorDetail;

        // Generate the multi-error message below
        stringstream msg;
        if (_wcErrors.size() > 1) {
            msg << "multiple errors reported : ";
            error->setErrCode(ErrorCodes::WriteConcernFailed);
        } else {
            error->setErrCode((*_wcErrors.begin())->error.getErrCode());
        }

        for (vector<ShardWCError*>::const_iterator it = _wcErrors.begin(); it != _wcErrors.end();
             ++it) {
            const ShardWCError* wcError = *it;
            if (it != _wcErrors.begin())
                msg << " :: and :: ";
            msg << wcError->error.getErrMessage() << " at " << wcError->endpoint.shardName;
        }

        error->setErrMessage(msg.str());
        batchResp->setWriteConcernError(error);
    }

    //
    // Append the upserted ids, if required
    //

    if (_upsertedIds.size() != 0) {
        batchResp->setUpsertDetails(_upsertedIds.vector());
    }

    // Stats
    int nValue =
        _stats->numInserted + _stats->numUpserted + _stats->numMatched + _stats->numDeleted;
    batchResp->setN(nValue);
    if (_clientRequest->getBatchType() == BatchedCommandRequest::BatchType_Update &&
        _stats->numModified >= 0) {
        batchResp->setNModified(_stats->numModified);
    }

    dassert(batchResp->isValid(NULL));
}