| 695 | } |
| 696 | |
| 697 | Coordinator::BackendState::CancelResult Coordinator::BackendState::Cancel( |
| 698 | bool fire_and_forget) { |
| 699 | // Update 'result' based on the actions we take in this function and/or errors we hit. |
| 700 | CancelResult result; |
| 701 | bool notify_exec_done = false; |
| 702 | { |
| 703 | unique_lock<mutex> l(lock_); |
| 704 | |
| 705 | // Nothing to cancel if the exec rpc was not sent. |
| 706 | if (!exec_rpc_sent_) { |
| 707 | if (status_.ok()) { |
| 708 | status_ = Status::CANCELLED; |
| 709 | result.became_done = true; |
| 710 | } |
| 711 | VLogForBackend("Not sending Cancel() rpc because nothing was started."); |
| 712 | exec_done_ = true; |
| 713 | notify_exec_done = true; |
| 714 | goto done; |
| 715 | } |
| 716 | |
| 717 | // If the exec rpc was sent but the callback hasn't been executed, try to cancel the |
| 718 | // rpc and then wait for it to be done. |
| 719 | if (!exec_done_) { |
| 720 | VLogForBackend("Attempting to cancel Exec() rpc"); |
| 721 | cancel_exec_rpc_ = true; |
| 722 | exec_rpc_controller_.Cancel(); |
| 723 | if (!WaitOnExecLocked(&l, (int64_t)FLAGS_backend_client_rpc_timeout_ms)) { |
| 724 | VLogForBackend(Substitute( |
| 725 | "Exec() rpc was not responsive after waiting for $0 ms", |
| 726 | FLAGS_backend_client_rpc_timeout_ms)); |
| 727 | exec_done_ = true; |
| 728 | notify_exec_done = true; |
| 729 | } |
| 730 | } |
| 731 | |
| 732 | // Don't cancel if we're done or already sent an RPC. Note that its possible the |
| 733 | // backend is still running, eg. if the rpc layer reported that the Exec() rpc failed |
| 734 | // but it actually reached the backend. In that case, the backend will cancel itself |
| 735 | // the first time it tries to send a status report and the coordinator responds with |
| 736 | // an error. |
| 737 | if (IsDoneLocked(l)) { |
| 738 | VLogForBackend(Substitute( |
| 739 | "Not cancelling because the backend is already done: $0", status_.GetDetail())); |
| 740 | goto done; |
| 741 | } else if (sent_cancel_rpc_) { |
| 742 | DCHECK(status_.ok()); |
| 743 | // If we did a fire_and_forget=false followed by fire_and_forget=true. |
| 744 | if (fire_and_forget) { |
| 745 | status_ = Status::CANCELLED; |
| 746 | result.became_done = true; |
| 747 | } |
| 748 | VLogForBackend(Substitute( |
| 749 | "Not cancelling because cancel RPC already sent: $0", status_.GetDetail())); |
| 750 | goto done; |
| 751 | } |
| 752 | |
| 753 | // Avoid sending redundant cancel RPCs. |
| 754 | sent_cancel_rpc_ = true; |
nothing calls this directly
no test coverage detected