requestConnectionLocked starts connecting on the subchannel corresponding to the current address. If no subchannel exists, one is created. If the current subchannel is in TransientFailure, a connection to the next address is attempted until a subchannel is found.
()
| 534 | // subchannel is in TransientFailure, a connection to the next address is |
| 535 | // attempted until a subchannel is found. |
| 536 | func (b *pickfirstBalancer) requestConnectionLocked() { |
| 537 | if !b.addressList.isValid() { |
| 538 | return |
| 539 | } |
| 540 | var lastErr error |
| 541 | for valid := true; valid; valid = b.addressList.increment() { |
| 542 | curAddr := b.addressList.currentAddress() |
| 543 | sd, ok := b.subConns.Get(curAddr) |
| 544 | if !ok { |
| 545 | var err error |
| 546 | // We want to assign the new scData to sd from the outer scope, |
| 547 | // hence we can't use := below. |
| 548 | sd, err = b.newSCData(curAddr) |
| 549 | if err != nil { |
| 550 | // This should never happen, unless the clientConn is being shut |
| 551 | // down. |
| 552 | if b.logger.V(2) { |
| 553 | b.logger.Infof("Failed to create a subConn for address %v: %v", curAddr.String(), err) |
| 554 | } |
| 555 | // Do nothing, the LB policy will be closed soon. |
| 556 | return |
| 557 | } |
| 558 | b.subConns.Set(curAddr, sd) |
| 559 | } |
| 560 | |
| 561 | switch sd.rawConnectivityState { |
| 562 | case connectivity.Idle: |
| 563 | sd.subConn.Connect() |
| 564 | b.scheduleNextConnectionLocked() |
| 565 | return |
| 566 | case connectivity.TransientFailure: |
| 567 | // The SubConn is being re-used and failed during a previous pass |
| 568 | // over the addressList. It has not completed backoff yet. |
| 569 | // Mark it as having failed and try the next address. |
| 570 | sd.connectionFailedInFirstPass = true |
| 571 | lastErr = sd.lastErr |
| 572 | continue |
| 573 | case connectivity.Connecting: |
| 574 | // Wait for the connection attempt to complete or the timer to fire |
| 575 | // before attempting the next address. |
| 576 | b.scheduleNextConnectionLocked() |
| 577 | return |
| 578 | default: |
| 579 | b.logger.Errorf("SubConn with unexpected state %v present in SubConns map.", sd.rawConnectivityState) |
| 580 | return |
| 581 | |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | // All the remaining addresses in the list are in TRANSIENT_FAILURE, end the |
| 586 | // first pass if possible. |
| 587 | b.endFirstPassIfPossibleLocked(lastErr) |
| 588 | } |
| 589 | |
| 590 | func (b *pickfirstBalancer) scheduleNextConnectionLocked() { |
| 591 | b.cancelConnectionTimer() |
no test coverage detected