| 878 | } |
| 879 | |
| 880 | void ImpalaServer::GetOperationStatus(TGetOperationStatusResp& return_val, |
| 881 | const TGetOperationStatusReq& request) { |
| 882 | if (request.operationHandle.operationId.guid.size() == 0) { |
| 883 | // An empty operation handle identifier means no execution and no result for this |
| 884 | // query (USE <database>). |
| 885 | VLOG_ROW << "GetOperationStatus(): guid size 0"; |
| 886 | return_val.operationState = TOperationState::FINISHED_STATE; |
| 887 | return_val.status.__set_statusCode(thrift::TStatusCode::SUCCESS_STATUS); |
| 888 | return; |
| 889 | } |
| 890 | |
| 891 | // Secret is inherited from session. |
| 892 | TUniqueId query_id; |
| 893 | TUniqueId op_secret; |
| 894 | Status status = THandleIdentifierToTUniqueId( |
| 895 | request.operationHandle.operationId, &query_id, &op_secret); |
| 896 | if (!status.ok()) { |
| 897 | return_val.__set_operationState(TOperationState::ERROR_STATE); |
| 898 | HS2_RETURN_ERROR(return_val, status.GetDetail(), SQLSTATE_GENERAL_ERROR); |
| 899 | } |
| 900 | VLOG_ROW << "GetOperationStatus(): query_id=" << PrintId(query_id); |
| 901 | |
| 902 | // Make query id available to the following HS2_RETURN_ERROR(). |
| 903 | ScopedThreadContext scoped_tdi(GetThreadDebugInfo(), query_id); |
| 904 | |
| 905 | QueryHandle query_handle; |
| 906 | status = GetActiveQueryHandle(query_id, &query_handle); |
| 907 | if (!status.ok()) { |
| 908 | return_val.__set_operationState(TOperationState::ERROR_STATE); |
| 909 | HS2_RETURN_ERROR(return_val, status.GetDetail(), SQLSTATE_GENERAL_ERROR); |
| 910 | } |
| 911 | |
| 912 | ScopedSessionState session_handle(this); |
| 913 | const TUniqueId session_id = query_handle->session_id(); |
| 914 | shared_ptr<SessionState> session; |
| 915 | status = session_handle.WithSession( |
| 916 | session_id, SecretArg::Operation(op_secret, query_id), &session); |
| 917 | if (!status.ok()) { |
| 918 | return_val.__set_operationState(TOperationState::ERROR_STATE); |
| 919 | HS2_RETURN_ERROR(return_val, status.GetDetail(), SQLSTATE_GENERAL_ERROR); |
| 920 | } |
| 921 | |
| 922 | // When using long polling, this waits up to long_polling_time_ms milliseconds for |
| 923 | // query completion.polling |
| 924 | query_handle->WaitForCompletionExecState(); |
| 925 | |
| 926 | { |
| 927 | lock_guard<mutex> l(*query_handle->lock()); |
| 928 | TOperationState::type operation_state = query_handle->TOperationState(); |
| 929 | return_val.__set_operationState(operation_state); |
| 930 | if (operation_state == TOperationState::ERROR_STATE) { |
| 931 | DCHECK(!query_handle->query_status().ok()); |
| 932 | return_val.__set_errorMessage(Substitute(QUERY_ERROR_FORMAT, |
| 933 | PrintId(query_id), query_handle->query_status().GetDetail())); |
| 934 | return_val.__set_sqlState(SQLSTATE_GENERAL_ERROR); |
| 935 | } else { |
| 936 | ClientRequestState::RetryState retry_state = query_handle->retry_state(); |
| 937 | if (retry_state != ClientRequestState::RetryState::RETRYING |