blob: 6cdeb3fa3a4b2172b0814a21d8fcbf243a8c7697 [file] [log] [blame]
Scott Baker2d897982019-09-24 11:50:08 -07001// Copyright 2018 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package balancer
16
17import "google.golang.org/grpc/connectivity"
18
19// connectivityStateEvaluator gets updated by addrConns when their
20// states transition, based on which it evaluates the state of
21// ClientConn.
22type connectivityStateEvaluator struct {
23 numReady uint64 // Number of addrConns in ready state.
24 numConnecting uint64 // Number of addrConns in connecting state.
25 numTransientFailure uint64 // Number of addrConns in transientFailure.
26}
27
28// recordTransition records state change happening in every subConn and based on
29// that it evaluates what aggregated state should be.
30// It can only transition between Ready, Connecting and TransientFailure. Other states,
31// Idle and Shutdown are transitioned into by ClientConn; in the beginning of the connection
32// before any subConn is created ClientConn is in idle state. In the end when ClientConn
33// closes it is in Shutdown state.
34//
35// recordTransition should only be called synchronously from the same goroutine.
36func (cse *connectivityStateEvaluator) recordTransition(oldState, newState connectivity.State) connectivity.State {
37 // Update counters.
38 for idx, state := range []connectivity.State{oldState, newState} {
39 updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
40 switch state {
41 case connectivity.Ready:
42 cse.numReady += updateVal
43 case connectivity.Connecting:
44 cse.numConnecting += updateVal
45 case connectivity.TransientFailure:
46 cse.numTransientFailure += updateVal
47 }
48 }
49
50 // Evaluate.
51 if cse.numReady > 0 {
52 return connectivity.Ready
53 }
54 if cse.numConnecting > 0 {
55 return connectivity.Connecting
56 }
57 return connectivity.TransientFailure
58}