| 2266 | } |
| 2267 | |
| 2268 | void ImpalaServer::CancelFromThreadPool(const CancellationWork& cancellation_work) { |
| 2269 | const TUniqueId& query_id = cancellation_work.query_id(); |
| 2270 | QueryHandle query_handle; |
| 2271 | Status status = GetQueryHandle(query_id, &query_handle); |
| 2272 | // Query was already unregistered. |
| 2273 | if (!status.ok()) { |
| 2274 | VLOG_QUERY << "CancelFromThreadPool(): query " << PrintId(query_id) |
| 2275 | << " already unregistered."; |
| 2276 | return; |
| 2277 | } |
| 2278 | |
| 2279 | DebugActionNoFail(query_handle->query_options(), "QUERY_CANCELLATION_THREAD"); |
| 2280 | Status error; |
| 2281 | switch (cancellation_work.cause()) { |
| 2282 | case CancellationWorkCause::TERMINATED_BY_SERVER: |
| 2283 | case CancellationWorkCause::GRACEFUL_SHUTDOWN: |
| 2284 | error = cancellation_work.error(); |
| 2285 | break; |
| 2286 | case CancellationWorkCause::BACKEND_FAILED: { |
| 2287 | // We only want to proceed with cancellation if the backends are still in use for |
| 2288 | // the query. |
| 2289 | vector<NetworkAddressPB> active_backends; |
| 2290 | Coordinator* coord = query_handle->GetCoordinator(); |
| 2291 | if (coord == nullptr) { |
| 2292 | // Query hasn't started yet - it still will run on all backends. |
| 2293 | active_backends = cancellation_work.failed_backends(); |
| 2294 | } else { |
| 2295 | active_backends = coord->GetActiveBackends(cancellation_work.failed_backends()); |
| 2296 | } |
| 2297 | if (active_backends.empty()) { |
| 2298 | VLOG_QUERY << "CancelFromThreadPool(): all failed backends already completed for " |
| 2299 | << "query " << PrintId(query_id); |
| 2300 | return; |
| 2301 | } |
| 2302 | stringstream msg; |
| 2303 | for (int i = 0; i < active_backends.size(); ++i) { |
| 2304 | msg << active_backends[i]; |
| 2305 | if (i + 1 != active_backends.size()) msg << ", "; |
| 2306 | } |
| 2307 | error = Status::Expected(TErrorCode::UNREACHABLE_IMPALADS, msg.str()); |
| 2308 | break; |
| 2309 | } |
| 2310 | default: |
| 2311 | DCHECK(false) << static_cast<int>(cancellation_work.cause()); |
| 2312 | } |
| 2313 | |
| 2314 | if (cancellation_work.unregister()) { |
| 2315 | UnregisterQueryDiscardResult(cancellation_work.query_id(), &error, true); |
| 2316 | } else { |
| 2317 | // Retry queries that would otherwise be cancelled due to an impalad leaving the |
| 2318 | // cluster. CancellationWorkCause::BACKEND_FAILED indicates that a backend running |
| 2319 | // the query was removed from the cluster membership due to a statestore heartbeat |
| 2320 | // timeout. Historically, this would cause the Coordinator to cancel all queries |
| 2321 | // running on that backend. Now, Impala attempts to retry the queries instead of |
| 2322 | // cancelling them. |
| 2323 | bool was_retried = false; |
| 2324 | if (cancellation_work.cause() == CancellationWorkCause::BACKEND_FAILED) { |
| 2325 | query_handle.query_driver()->TryQueryRetry(&*query_handle, &error, &was_retried); |
nothing calls this directly
no test coverage detected