blob: ed05b02ed96e0873d122fe33e501b73877b86b58 [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
David K. Bainbridgec415efe2021-08-19 13:05:21 +000022 "context"
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070023
24 "google.golang.org/grpc/balancer"
25 "google.golang.org/grpc/connectivity"
26 "google.golang.org/grpc/grpclog"
27 "google.golang.org/grpc/resolver"
28)
29
30// PickFirstBalancerName is the name of the pick_first balancer.
31const PickFirstBalancerName = "pick_first"
32
33func newPickfirstBuilder() balancer.Builder {
34 return &pickfirstBuilder{}
35}
36
37type pickfirstBuilder struct{}
38
39func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
40 return &pickfirstBalancer{cc: cc}
41}
42
43func (*pickfirstBuilder) Name() string {
44 return PickFirstBalancerName
45}
46
47type pickfirstBalancer struct {
David K. Bainbridgec415efe2021-08-19 13:05:21 +000048 cc balancer.ClientConn
49 sc balancer.SubConn
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070050}
51
52func (b *pickfirstBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
53 if err != nil {
David K. Bainbridgec415efe2021-08-19 13:05:21 +000054 if grpclog.V(2) {
55 grpclog.Infof("pickfirstBalancer: HandleResolvedAddrs called with error %v", err)
56 }
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070057 return
58 }
Arjun E K57a7fcb2020-01-30 06:44:45 +000059 if b.sc == nil {
David K. Bainbridgec415efe2021-08-19 13:05:21 +000060 b.sc, err = b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{})
Arjun E K57a7fcb2020-01-30 06:44:45 +000061 if err != nil {
David K. Bainbridgec415efe2021-08-19 13:05:21 +000062 //TODO(yuxuanli): why not change the cc state to Idle?
Arjun E K57a7fcb2020-01-30 06:44:45 +000063 if grpclog.V(2) {
64 grpclog.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
65 }
David K. Bainbridgec415efe2021-08-19 13:05:21 +000066 return
Arjun E K57a7fcb2020-01-30 06:44:45 +000067 }
David K. Bainbridgec415efe2021-08-19 13:05:21 +000068 b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc})
Arjun E K57a7fcb2020-01-30 06:44:45 +000069 b.sc.Connect()
70 } else {
David K. Bainbridgec415efe2021-08-19 13:05:21 +000071 b.sc.UpdateAddresses(addrs)
Arjun E K57a7fcb2020-01-30 06:44:45 +000072 b.sc.Connect()
73 }
Arjun E K57a7fcb2020-01-30 06:44:45 +000074}
75
David K. Bainbridgec415efe2021-08-19 13:05:21 +000076func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
Arjun E K57a7fcb2020-01-30 06:44:45 +000077 if grpclog.V(2) {
78 grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s)
79 }
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070080 if b.sc != sc {
Arjun E K57a7fcb2020-01-30 06:44:45 +000081 if grpclog.V(2) {
82 grpclog.Infof("pickfirstBalancer: ignored state change because sc is not recognized")
83 }
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070084 return
85 }
David K. Bainbridgec415efe2021-08-19 13:05:21 +000086 if s == connectivity.Shutdown {
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070087 b.sc = nil
88 return
89 }
90
David K. Bainbridgec415efe2021-08-19 13:05:21 +000091 switch s {
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070092 case connectivity.Ready, connectivity.Idle:
David K. Bainbridgec415efe2021-08-19 13:05:21 +000093 b.cc.UpdateBalancerState(s, &picker{sc: sc})
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070094 case connectivity.Connecting:
David K. Bainbridgec415efe2021-08-19 13:05:21 +000095 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrNoSubConnAvailable})
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070096 case connectivity.TransientFailure:
David K. Bainbridgec415efe2021-08-19 13:05:21 +000097 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrTransientFailure})
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070098 }
99}
100
101func (b *pickfirstBalancer) Close() {
102}
103
104type picker struct {
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000105 err error
106 sc balancer.SubConn
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700107}
108
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000109func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
110 if p.err != nil {
111 return nil, nil, p.err
112 }
113 return p.sc, nil, nil
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700114}
115
116func init() {
117 balancer.Register(newPickfirstBuilder())
118}