| 305 | } |
| 306 | |
| 307 | void OnComplete() { |
| 308 | // [ Rendezvous point ] |
| 309 | // One and only one thread arrives here. |
| 310 | // all call_id of sub calls are destroyed and call_id of _cntl is |
| 311 | // still locked (because FLAGS_DESTROY_CID_IN_DONE is true); |
| 312 | |
| 313 | // Merge responses of successful calls if fail_limit is not reached. |
| 314 | // nfailed may be increased during the merging. |
| 315 | // NOTE: Don't forget to set "nfailed = _ndone" when the _cntl is set |
| 316 | // to be failed since the RPC is still considered to be successful if |
| 317 | // nfailed is less than fail_limit |
| 318 | int nfailed = _current_fail.load(butil::memory_order_relaxed); |
| 319 | if (nfailed < _fail_limit) { |
| 320 | for (int i = 0; i < _ndone; ++i) { |
| 321 | SubDone* sd = sub_done(i); |
| 322 | google::protobuf::Message* sub_res = sd->cntl._response; |
| 323 | if (!sd->cntl.FailedInline()) { // successful calls only. |
| 324 | if (sd->merger == NULL) { |
| 325 | try { |
| 326 | _cntl->_response->MergeFrom(*sub_res); |
| 327 | } catch (const std::exception& e) { |
| 328 | nfailed = _ndone; |
| 329 | _cntl->SetFailed(ERESPONSE, "%s", e.what()); |
| 330 | break; |
| 331 | } |
| 332 | } else { |
| 333 | ResponseMerger::Result res = |
| 334 | sd->merger->Merge(_cntl->_response, sub_res); |
| 335 | switch (res) { |
| 336 | case ResponseMerger::MERGED: |
| 337 | break; |
| 338 | case ResponseMerger::FAIL: |
| 339 | ++nfailed; |
| 340 | break; |
| 341 | case ResponseMerger::FAIL_ALL: |
| 342 | nfailed = _ndone; |
| 343 | _cntl->SetFailed( |
| 344 | ERESPONSE, |
| 345 | "Fail to merge response of channel[%d]", i); |
| 346 | break; |
| 347 | } |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | // Note: 1 <= _fail_limit <= _ndone. |
| 354 | if (nfailed >= _fail_limit) { |
| 355 | // If controller was already failed, don't change it. |
| 356 | if (!_cntl->FailedInline()) { |
| 357 | char buf[16]; |
| 358 | int unified_ec = ECANCELED; |
| 359 | for (int i = 0; i < _ndone; ++i) { |
| 360 | Controller* sub_cntl = &sub_done(i)->cntl; |
| 361 | const int ec = sub_cntl->ErrorCode(); |
| 362 | if (ec != 0 && ec != ECANCELED) { |
| 363 | if (unified_ec == ECANCELED) { |
| 364 | unified_ec = ec; |
no test coverage detected