| 165 | } |
| 166 | |
| 167 | void QueryDriver::TryQueryRetry( |
| 168 | ClientRequestState* client_request_state, Status* error, bool* was_retried) { |
| 169 | DCHECK(error != nullptr); |
| 170 | if (was_retried != nullptr) *was_retried = false; |
| 171 | |
| 172 | // Get the most recent query attempt, and retry it. |
| 173 | const TUniqueId& query_id = client_request_state->query_id(); |
| 174 | DCHECK(client_request_state->schedule() != nullptr); |
| 175 | |
| 176 | DCHECK(exec_request_ != nullptr); |
| 177 | if (exec_request_->query_options.retry_failed_queries) { |
| 178 | lock_guard<mutex> l(*client_request_state->lock()); |
| 179 | |
| 180 | if (client_request_state->stmt_type() != TStmtType::QUERY) { |
| 181 | // Retrying DML queries would be useful but currently it is |
| 182 | // buggy / untested (see IMPALA-10585). |
| 183 | return; |
| 184 | } |
| 185 | |
| 186 | // Queries can only be retried if no rows for the query have been fetched |
| 187 | // (IMPALA-9225). |
| 188 | if (client_request_state->fetched_rows()) { |
| 189 | string err_msg = Substitute("Skipping retry of query_id=$0 because the client has " |
| 190 | "already fetched some rows", |
| 191 | PrintId(query_id)); |
| 192 | VLOG_QUERY << err_msg; |
| 193 | error->AddDetail(err_msg); |
| 194 | return; |
| 195 | } |
| 196 | |
| 197 | // If a retry for the failed query has already been scheduled, don't retry it |
| 198 | // again. |
| 199 | if (client_request_state->WasRetried()) { |
| 200 | return; |
| 201 | } |
| 202 | |
| 203 | // Queries can only be retried once (IMPALA-9200). |
| 204 | if (client_request_state->IsRetriedQuery()) { |
| 205 | VLOG_QUERY << Substitute( |
| 206 | "Skipping retry of query_id=$0 because it has already been retried", |
| 207 | PrintId(query_id)); |
| 208 | // If query retries are enabled, but the max number of retries has been hit, |
| 209 | // include the number of retries in the error message. |
| 210 | error->AddDetail("Max retry limit was hit. Query was retried 1 time(s)."); |
| 211 | return; |
| 212 | } |
| 213 | |
| 214 | const TUniqueId& query_id = client_request_state_->query_id(); |
| 215 | |
| 216 | // Triggering a retry from the INITIALIZED phase is possible: the |
| 217 | // cancellation thread pool can kill a query while it is in the INITIALIZATION phase. |
| 218 | // Triggering a retry from the FINISHED phase is also possible: the retryable failure |
| 219 | // happens after rows are available and before the client fetches any rows. |
| 220 | ClientRequestState::ExecState exec_state = client_request_state_->exec_state(); |
| 221 | DCHECK(exec_state == ClientRequestState::ExecState::INITIALIZED |
| 222 | || exec_state == ClientRequestState::ExecState::PENDING |
| 223 | || exec_state == ClientRequestState::ExecState::RUNNING |
| 224 | || exec_state == ClientRequestState::ExecState::FINISHED) |
no test coverage detected