3 * Copyright 2017 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 "google.golang.org/grpc/balancer"
25 "google.golang.org/grpc/connectivity"
26 "google.golang.org/grpc/grpclog"
27 "google.golang.org/grpc/resolver"
30 // PickFirstBalancerName is the name of the pick_first balancer.
31 const PickFirstBalancerName = "pick_first"
33 func newPickfirstBuilder() balancer.Builder {
34 return &pickfirstBuilder{}
37 type pickfirstBuilder struct{}
39 func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
40 return &pickfirstBalancer{cc: cc}
43 func (*pickfirstBuilder) Name() string {
44 return PickFirstBalancerName
47 type pickfirstBalancer struct {
48 cc balancer.ClientConn
52 func (b *pickfirstBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
54 grpclog.Infof("pickfirstBalancer: HandleResolvedAddrs called with error %v", err)
58 b.sc, err = b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{})
60 //TODO(yuxuanli): why not change the cc state to Idle?
61 grpclog.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
64 b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc})
67 b.sc.UpdateAddresses(addrs)
72 func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
73 grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s)
75 grpclog.Infof("pickfirstBalancer: ignored state change because sc is not recognized")
78 if s == connectivity.Shutdown {
84 case connectivity.Ready, connectivity.Idle:
85 b.cc.UpdateBalancerState(s, &picker{sc: sc})
86 case connectivity.Connecting:
87 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrNoSubConnAvailable})
88 case connectivity.TransientFailure:
89 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrTransientFailure})
93 func (b *pickfirstBalancer) Close() {
101 func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
103 return nil, nil, p.err
105 return p.sc, nil, nil
109 balancer.Register(newPickfirstBuilder())