Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / google.golang.org / grpc / resolver_conn_wrapper.go
1 /*
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
19 package grpc
20
21 import (
22         "fmt"
23         "strings"
24
25         "google.golang.org/grpc/grpclog"
26         "google.golang.org/grpc/internal/channelz"
27         "google.golang.org/grpc/resolver"
28 )
29
30 // ccResolverWrapper is a wrapper on top of cc for resolvers.
31 // It implements resolver.ClientConnection interface.
32 type ccResolverWrapper struct {
33         cc                 *ClientConn
34         resolver           resolver.Resolver
35         addrCh             chan []resolver.Address
36         scCh               chan string
37         done               chan struct{}
38         lastAddressesCount int
39 }
40
41 // split2 returns the values from strings.SplitN(s, sep, 2).
42 // If sep is not found, it returns ("", "", false) instead.
43 func split2(s, sep string) (string, string, bool) {
44         spl := strings.SplitN(s, sep, 2)
45         if len(spl) < 2 {
46                 return "", "", false
47         }
48         return spl[0], spl[1], true
49 }
50
51 // parseTarget splits target into a struct containing scheme, authority and
52 // endpoint.
53 //
54 // If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
55 // target}.
56 func parseTarget(target string) (ret resolver.Target) {
57         var ok bool
58         ret.Scheme, ret.Endpoint, ok = split2(target, "://")
59         if !ok {
60                 return resolver.Target{Endpoint: target}
61         }
62         ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
63         if !ok {
64                 return resolver.Target{Endpoint: target}
65         }
66         return ret
67 }
68
69 // newCCResolverWrapper parses cc.target for scheme and gets the resolver
70 // builder for this scheme and builds the resolver. The monitoring goroutine
71 // for it is not started yet and can be created by calling start().
72 //
73 // If withResolverBuilder dial option is set, the specified resolver will be
74 // used instead.
75 func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) {
76         rb := cc.dopts.resolverBuilder
77         if rb == nil {
78                 return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme)
79         }
80
81         ccr := &ccResolverWrapper{
82                 cc:     cc,
83                 addrCh: make(chan []resolver.Address, 1),
84                 scCh:   make(chan string, 1),
85                 done:   make(chan struct{}),
86         }
87
88         var err error
89         ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, resolver.BuildOption{DisableServiceConfig: cc.dopts.disableServiceConfig})
90         if err != nil {
91                 return nil, err
92         }
93         return ccr, nil
94 }
95
96 func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOption) {
97         ccr.resolver.ResolveNow(o)
98 }
99
100 func (ccr *ccResolverWrapper) close() {
101         ccr.resolver.Close()
102         close(ccr.done)
103 }
104
105 // NewAddress is called by the resolver implemenetion to send addresses to gRPC.
106 func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
107         select {
108         case <-ccr.done:
109                 return
110         default:
111         }
112         grpclog.Infof("ccResolverWrapper: sending new addresses to cc: %v", addrs)
113         if channelz.IsOn() {
114                 ccr.addChannelzTraceEvent(addrs)
115         }
116         ccr.cc.handleResolvedAddrs(addrs, nil)
117 }
118
119 // NewServiceConfig is called by the resolver implemenetion to send service
120 // configs to gRPC.
121 func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
122         select {
123         case <-ccr.done:
124                 return
125         default:
126         }
127         grpclog.Infof("ccResolverWrapper: got new service config: %v", sc)
128         ccr.cc.handleServiceConfig(sc)
129 }
130
131 func (ccr *ccResolverWrapper) addChannelzTraceEvent(addrs []resolver.Address) {
132         if len(addrs) == 0 && ccr.lastAddressesCount != 0 {
133                 channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
134                         Desc:     "Resolver returns an empty address list",
135                         Severity: channelz.CtWarning,
136                 })
137         } else if len(addrs) != 0 && ccr.lastAddressesCount == 0 {
138                 var s string
139                 for i, a := range addrs {
140                         if a.ServerName != "" {
141                                 s += a.Addr + "(" + a.ServerName + ")"
142                         } else {
143                                 s += a.Addr
144                         }
145                         if i != len(addrs)-1 {
146                                 s += " "
147                         }
148                 }
149                 channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
150                         Desc:     fmt.Sprintf("Resolver returns a non-empty address list (previous one was empty) %q", s),
151                         Severity: channelz.CtINFO,
152                 })
153         }
154         ccr.lastAddressesCount = len(addrs)
155 }