| 881 | } |
| 882 | |
| 883 | void Coordinator::HandleExecStateTransition( |
| 884 | const ExecState old_state, const ExecState new_state) { |
| 885 | static const unordered_map<ExecState, const char *> exec_state_to_event{ |
| 886 | {ExecState::EXECUTING, "Executing"}, |
| 887 | {ExecState::RETURNED_RESULTS, "Last row fetched"}, |
| 888 | {ExecState::CANCELLED, "Execution cancelled"}, |
| 889 | {ExecState::ERROR, "Execution error"}}; |
| 890 | if (old_state == new_state) return; |
| 891 | // Once we enter a terminal state, we stay there, guaranteeing this code runs only once. |
| 892 | DCHECK_EQ(old_state, ExecState::EXECUTING); |
| 893 | // Should never transition to the initial state. |
| 894 | DCHECK_NE(new_state, ExecState::EXECUTING); |
| 895 | // Can't transition until the exec RPCs are no longer in progress. Otherwise, a |
| 896 | // cancel RPC could be missed, and resources freed before a backend has had a chance |
| 897 | // to take a resource reference. |
| 898 | DCHECK(exec_rpcs_complete_.Load()) << "exec rpcs not completed"; |
| 899 | |
| 900 | query_events_->MarkEvent(exec_state_to_event.at(new_state)); |
| 901 | // This thread won the race to transitioning into a terminal state - terminate |
| 902 | // execution and release resources. |
| 903 | ReleaseExecResources(); |
| 904 | if (new_state == ExecState::RETURNED_RESULTS) { |
| 905 | // Cancel all backends, but wait for the final status reports to be received so that |
| 906 | // we have a complete profile for this successful query. |
| 907 | CancelBackends(/*fire_and_forget=*/ false); |
| 908 | WaitForBackends(); |
| 909 | } else { |
| 910 | CancelBackends(/*fire_and_forget=*/ true); |
| 911 | } |
| 912 | ReleaseQueryAdmissionControlResources(); |
| 913 | // Once the query has released its admission control resources, update its end time. |
| 914 | // However, for non Query statement like DML statement, we still need to update HMS |
| 915 | // after the query finishes. So the end time of non Query statement is not set here. |
| 916 | // Instead, we set it in ClientRequestState::Wait(). |
| 917 | if (stmt_type_ == TStmtType::QUERY) parent_request_state_->UpdateEndTime(); |
| 918 | // Can compute summary only after we stop accepting reports from the backends. Both |
| 919 | // WaitForBackends() and CancelBackends() ensures that. |
| 920 | // TODO: should move this off of the query execution path? |
| 921 | ComputeQuerySummary(); |
| 922 | finalized_.Set(true); |
| 923 | } |
| 924 | |
| 925 | Status Coordinator::FinalizeResultSink() { |
| 926 | // All instances must have reported their final statuses before finalization, which is a |
nothing calls this directly
no test coverage detected