/* * * Copyright 2017 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package grpc import ( "sync" "google.golang.org/grpc/balancer" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/resolver" ) // TODO(bar) move ClientConn methods to clientConn file. func (cc *ClientConn) updatePicker(p balancer.Picker) { // TODO(bar) add a goroutine and sync it. // TODO(bar) implement blocking behavior and unblock the previous pick. cc.pmu.Lock() cc.picker = p cc.pmu.Unlock() } // ccBalancerWrapper is a wrapper on top of cc for balancers. // It implements balancer.ClientConn interface. type ccBalancerWrapper struct { cc *ClientConn } func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) { grpclog.Infof("ccBalancerWrapper: new subconn: %v", addrs) ac, err := ccb.cc.newAddrConn(addrs) if err != nil { return nil, err } acbw := &acBalancerWrapper{ac: ac} ac.acbw = acbw return acbw, nil } func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) { grpclog.Infof("ccBalancerWrapper: removing subconn") acbw, ok := sc.(*acBalancerWrapper) if !ok { return } ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain) } func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) { // TODO(bar) update cc connectivity state. ccb.cc.updatePicker(p) } func (ccb *ccBalancerWrapper) Target() string { return ccb.cc.target } // acBalancerWrapper is a wrapper on top of ac for balancers. // It implements balancer.SubConn interface. type acBalancerWrapper struct { mu sync.Mutex ac *addrConn } func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { grpclog.Infof("acBalancerWrapper: UpdateAddresses called with %v", addrs) acbw.mu.Lock() defer acbw.mu.Unlock() // TODO(bar) update the addresses or tearDown and create a new ac. if !acbw.ac.tryUpdateAddrs(addrs) { cc := acbw.ac.cc acbw.ac.mu.Lock() // Set old ac.acbw to nil so the states update will be ignored by balancer. acbw.ac.acbw = nil acbw.ac.mu.Unlock() acState := acbw.ac.getState() acbw.ac.tearDown(errConnDrain) if acState == connectivity.Shutdown { return } ac, err := cc.newAddrConn(addrs) if err != nil { grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err) return } acbw.ac = ac ac.acbw = acbw if acState != connectivity.Idle { ac.connect(false) } } } func (acbw *acBalancerWrapper) Connect() { acbw.mu.Lock() defer acbw.mu.Unlock() acbw.ac.connect(false) } func (acbw *acBalancerWrapper) getAddrConn() *addrConn { acbw.mu.Lock() defer acbw.mu.Unlock() return acbw.ac }