示例#1
0
/**
 * Returns true if the operation can continue.
 */
bool handleError(OperationContext* txn,
                 const DBException& ex,
                 const ParsedWriteOp& wholeOp,
                 WriteResult* out) {
    LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg);
    auto& curOp = *CurOp::get(txn);
    curOp.debug().exceptionInfo = ex.getInfo();

    if (ErrorCodes::isInterruption(ErrorCodes::Error(ex.getCode()))) {
        throw;  // These have always failed the whole batch.
    }

    if (ErrorCodes::isStaleShardingError(ErrorCodes::Error(ex.getCode()))) {
        auto staleConfigException = dynamic_cast<const SendStaleConfigException*>(&ex);
        if (!staleConfigException) {
            // We need to get extra info off of the SCE, but some common patterns can result in the
            // exception being converted to a Status then rethrown as a UserException, losing the
            // info we need. It would be a bug if this happens so we want to detect it in testing,
            // but it isn't severe enough that we should bring down the server if it happens in
            // production.
            dassert(staleConfigException);
            msgassertedNoTrace(35475,
                               str::stream()
                                   << "Got a StaleConfig error but exception was the wrong type: "
                                   << demangleName(typeid(ex)));
        }

        ShardingState::get(txn)
            ->onStaleShardVersion(txn, wholeOp.ns, staleConfigException->getVersionReceived());
        out->staleConfigException =
            stdx::make_unique<SendStaleConfigException>(*staleConfigException);
        return false;
    }

    out->results.emplace_back(ex.toStatus());
    return wholeOp.continueOnError;
}