/** * 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; }