func()

in grpcgcp/gcp_balancer.go [457:549]


func (gb *gcpBalancer) UpdateSubConnState(sc balancer.SubConn, scs balancer.SubConnState) {
	gb.mu.Lock()
	defer gb.mu.Unlock()
	s := scs.ConnectivityState

	if scRef, found := gb.refreshingScRefs[sc]; found {
		if gb.log.V(FINE) {
			gb.log.Infof("handle replacement SubConn state change: %p, %v", sc, s)
		}
		if s != connectivity.Ready {
			// Ignore the replacement sc until it's ready.
			return
		}

		// Replace SubConn of the scRef with the fresh SubConn (sc) concluding
		// the refresh process initiated by refresh(*subConnRef).
		oldSc := scRef.subConn
		gb.scStates[sc] = gb.scStates[oldSc]
		delete(gb.refreshingScRefs, sc)
		delete(gb.scRefs, oldSc)
		delete(gb.scStates, oldSc)
		gb.scRefs[sc] = scRef
		scRef.subConn = sc
		scRef.deCalls = 0
		scRef.lastResp = time.Now()
		scRef.refreshing = false
		scRef.refreshCnt++
		gb.cc.RemoveSubConn(oldSc)
	}

	if gb.log.V(FINE) {
		gb.log.Infof("handle SubConn state change: %p, %v", sc, s)
	}

	oldS, ok := gb.scStates[sc]
	if !ok {
		if gb.log.V(FINE) {
			gb.log.Infof(
				"got state changes for an unknown/replaced SubConn: %p, %v",
				sc,
				s,
			)
		}
		return
	}
	gb.scStates[sc] = s
	switch s {
	case connectivity.Idle:
		sc.Connect()
	case connectivity.Shutdown:
		delete(gb.scRefs, sc)
		delete(gb.scStates, sc)
	}
	if oldS == connectivity.Ready && s != oldS {
		// Subconn is broken. Remove fallback mapping to this subconn.
		for k, v := range gb.fallbackMap {
			if v == sc {
				delete(gb.fallbackMap, k)
			}
		}
	}
	if oldS != connectivity.Ready && s == connectivity.Ready {
		// Remove fallback mapping for the keys of recovered subconn.
		for k := range gb.fallbackMap {
			if gb.affinityMap[k] == sc {
				delete(gb.fallbackMap, k)
			}
		}
	}

	oldAggrState := gb.state
	gb.state = gb.csEvltr.recordTransition(oldS, s)

	// Regenerate picker when one of the following happens:
	//  - this sc became ready from not-ready
	//  - this sc became not-ready from ready
	//  - the aggregated state of balancer became TransientFailure from non-TransientFailure
	//  - the aggregated state of balancer became non-TransientFailure from TransientFailure
	if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
		(gb.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
		gb.regeneratePicker()
		gb.cc.UpdateState(balancer.State{
			ConnectivityState: gb.state,
			Picker:            gb.picker,
		})
	}

	if scRef := gb.scRefs[sc]; scRef != nil {
		// Inform of the state change.
		close(scRef.stateSignal)
		scRef.stateSignal = make(chan struct{})
	}
}