SEBA-902 single-olt tests;
Pin protoc-gen-go to 1.3.2 to resolve compatibility issue;
Run go mod tidy / go mod vendor on importer;
Add Go Module support to demotest
Change-Id: Ifde824fc9a6317b0adc1e12bea54ee1f9b788906
diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go
index d952f09..80559b8 100644
--- a/vendor/google.golang.org/grpc/balancer/base/balancer.go
+++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go
@@ -21,6 +21,7 @@
import (
"context"
"errors"
+ "fmt"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity"
@@ -76,6 +77,9 @@
picker balancer.Picker
v2Picker balancer.V2Picker
config Config
+
+ resolverErr error // the last error reported by the resolver; cleared on successful resolution
+ connErr error // the last connection error; cleared upon leaving TransientFailure
}
func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
@@ -83,13 +87,23 @@
}
func (b *baseBalancer) ResolverError(err error) {
- switch b.state {
- case connectivity.TransientFailure, connectivity.Idle, connectivity.Connecting:
- if b.picker != nil {
- b.picker = NewErrPicker(err)
- } else {
- b.v2Picker = NewErrPickerV2(err)
- }
+ b.resolverErr = err
+ if len(b.subConns) == 0 {
+ b.state = connectivity.TransientFailure
+ }
+ if b.state != connectivity.TransientFailure {
+ // The picker will not change since the balancer does not currently
+ // report an error.
+ return
+ }
+ b.regeneratePicker()
+ if b.picker != nil {
+ b.cc.UpdateBalancerState(b.state, b.picker)
+ } else {
+ b.cc.UpdateState(balancer.State{
+ ConnectivityState: b.state,
+ Picker: b.v2Picker,
+ })
}
}
@@ -99,6 +113,8 @@
if grpclog.V(2) {
grpclog.Infoln("base.baseBalancer: got new ClientConn state: ", s)
}
+ // Successful resolution; clear resolver error and ensure we return nil.
+ b.resolverErr = nil
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
addrsSet := make(map[resolver.Address]struct{})
for _, a := range s.ResolverState.Addresses {
@@ -124,27 +140,41 @@
// The entry will be deleted in HandleSubConnStateChange.
}
}
+ // If resolver state contains no addresses, return an error so ClientConn
+ // will trigger re-resolve. Also records this as an resolver error, so when
+ // the overall state turns transient failure, the error message will have
+ // the zero address information.
+ if len(s.ResolverState.Addresses) == 0 {
+ b.ResolverError(errors.New("produced zero addresses"))
+ return balancer.ErrBadResolverState
+ }
return nil
}
+// mergeErrors builds an error from the last connection error and the last
+// resolver error. Must only be called if b.state is TransientFailure.
+func (b *baseBalancer) mergeErrors() error {
+ // connErr must always be non-nil unless there are no SubConns, in which
+ // case resolverErr must be non-nil.
+ if b.connErr == nil {
+ return fmt.Errorf("last resolver error: %v", b.resolverErr)
+ }
+ if b.resolverErr == nil {
+ return fmt.Errorf("last connection error: %v", b.connErr)
+ }
+ return fmt.Errorf("last connection error: %v; last resolver error: %v", b.connErr, b.resolverErr)
+}
+
// regeneratePicker takes a snapshot of the balancer, and generates a picker
// from it. The picker is
-// - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
+// - errPicker if the balancer is in TransientFailure,
// - built by the pickerBuilder with all READY SubConns otherwise.
-func (b *baseBalancer) regeneratePicker(err error) {
+func (b *baseBalancer) regeneratePicker() {
if b.state == connectivity.TransientFailure {
if b.pickerBuilder != nil {
b.picker = NewErrPicker(balancer.ErrTransientFailure)
} else {
- if err != nil {
- b.v2Picker = NewErrPickerV2(balancer.TransientFailureError(err))
- } else {
- // This means the last subchannel transition was not to
- // TransientFailure (otherwise err must be set), but the
- // aggregate state of the balancer is TransientFailure, meaning
- // there are no other addresses.
- b.v2Picker = NewErrPickerV2(balancer.TransientFailureError(errors.New("resolver returned no addresses")))
- }
+ b.v2Picker = NewErrPickerV2(balancer.TransientFailureError(b.mergeErrors()))
}
return
}
@@ -187,6 +217,12 @@
}
return
}
+ if oldS == connectivity.TransientFailure && s == connectivity.Connecting {
+ // Once a subconn enters TRANSIENT_FAILURE, ignore subsequent
+ // CONNECTING transitions to prevent the aggregated state from being
+ // always CONNECTING when many backends exist but are all down.
+ return
+ }
b.scStates[sc] = s
switch s {
case connectivity.Idle:
@@ -195,19 +231,20 @@
// When an address was removed by resolver, b called RemoveSubConn but
// kept the sc's state in scStates. Remove state for this sc here.
delete(b.scStates, sc)
+ case connectivity.TransientFailure:
+ // Save error to be reported via picker.
+ b.connErr = state.ConnectionError
}
- oldAggrState := b.state
b.state = b.csEvltr.RecordTransition(oldS, s)
// Regenerate picker when one of the following happens:
- // - this sc became ready from not-ready
- // - this sc became not-ready from ready
- // - the aggregated state of balancer became TransientFailure from non-TransientFailure
- // - the aggregated state of balancer became non-TransientFailure from TransientFailure
+ // - this sc entered or left ready
+ // - the aggregated state of balancer is TransientFailure
+ // (may need to update error message)
if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
- (b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
- b.regeneratePicker(state.ConnectionError)
+ b.state == connectivity.TransientFailure {
+ b.regeneratePicker()
}
if b.picker != nil {