| 522 | } |
| 523 | |
| 524 | Status QueryDriver::Unregister(ImpalaServer::QueryDriverMap* query_driver_map) { |
| 525 | DCHECK(finalized_.Load()); |
| 526 | // Wait until retry_query_thread_ finishes, otherwise the resources for this thread |
| 527 | // may not be released. |
| 528 | if (retry_query_thread_.get() != nullptr) { |
| 529 | retry_query_thread_->Join(); |
| 530 | retry_query_thread_.reset(); |
| 531 | } |
| 532 | DCHECK(retry_query_thread_.get() == nullptr); |
| 533 | const TUniqueId* query_id = nullptr; |
| 534 | const TUniqueId* retry_query_id = nullptr; |
| 535 | { |
| 536 | // In order to preserve a consistent lock ordering, client_request_state_lock_ is |
| 537 | // released before QueryDriverMap::Delete() is called, as Delete() requires taking |
| 538 | // a ScopedShardedMapRef (a sharded map lock). Methods in ImpalaServer (such as |
| 539 | // UnresponsiveBackendThread) require taking a ScopedShardedMapRef and then calling |
| 540 | // Get*ClientRequestState methods. So in order to define a consistent lock ordering |
| 541 | // (e.g. acquire ScopedShardedMapRef before client_request_state_lock_) |
| 542 | // client_request_state_lock_ is released before calling Delete(). |
| 543 | lock_guard<SpinLock> l(client_request_state_lock_); |
| 544 | query_id = &client_request_state_->query_id(); |
| 545 | if (retried_client_request_state_ != nullptr) { |
| 546 | retry_query_id = &retried_client_request_state_->query_id(); |
| 547 | } else if (registered_retry_query_id_ != ZERO_UNIQUE_ID) { |
| 548 | retry_query_id = ®istered_retry_query_id_; |
| 549 | } |
| 550 | } |
| 551 | RETURN_IF_ERROR(query_driver_map->Delete(*query_id)); |
| 552 | if (retry_query_id != nullptr) { |
| 553 | RETURN_IF_ERROR(query_driver_map->Delete(*retry_query_id)); |
| 554 | } |
| 555 | return Status::OK(); |
| 556 | } |
| 557 | |
| 558 | void QueryDriver::Abandon() { |
| 559 | finalized_.Store(true); |