func (cc *ClientConn) resetTransport(closeTransport bool) error { var retries int for { cc.mu.Lock() t := cc.transport ts := cc.transportSeq // Avoid wait() picking up a dying transport unnecessarily. cc.transportSeq = 0 if cc.closing { cc.mu.Unlock() return ErrClientConnClosing } cc.mu.Unlock() if closeTransport { t.Close() } newTransport, err := transport.NewClientTransport(cc.dopts.protocol, cc.target, cc.dopts.authOptions) if err != nil { // TODO(zhaoq): Record the error with glog.V. closeTransport = false time.Sleep(backoff(retries)) retries++ log.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target) continue } cc.mu.Lock() cc.transport = newTransport cc.transportSeq = ts + 1 if cc.ready != nil { close(cc.ready) cc.ready = nil } cc.mu.Unlock() return nil } }
func (ac *addrConn) resetTransport(closeTransport bool) error { var retries int for { ac.mu.Lock() ac.printf("connecting") if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() return errConnClosing } if ac.down != nil { ac.down(downErrorf(false, true, "%v", errNetworkIO)) ac.down = nil } ac.state = Connecting ac.stateCV.Broadcast() t := ac.transport ac.mu.Unlock() if closeTransport && t != nil { t.Close() } sleepTime := ac.dopts.bs.backoff(retries) ac.dopts.copts.Timeout = sleepTime if sleepTime < minConnectTimeout { ac.dopts.copts.Timeout = minConnectTimeout } connectTime := time.Now() newTransport, err := transport.NewClientTransport(ac.addr.Addr, &ac.dopts.copts) if err != nil { ac.mu.Lock() if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() return errConnClosing } ac.errorf("transient failure: %v", err) ac.state = TransientFailure ac.stateCV.Broadcast() if ac.ready != nil { close(ac.ready) ac.ready = nil } ac.mu.Unlock() sleepTime -= time.Since(connectTime) if sleepTime < 0 { sleepTime = 0 } closeTransport = false select { case <-time.After(sleepTime): case <-ac.shutdownChan: } retries++ grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) continue } ac.mu.Lock() ac.printf("ready") if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() newTransport.Close() return errConnClosing } ac.state = Ready ac.stateCV.Broadcast() ac.transport = newTransport if ac.ready != nil { close(ac.ready) ac.ready = nil } ac.down = ac.cc.balancer.Up(ac.addr) ac.mu.Unlock() return nil } }
func (cc *Conn) resetTransport(closeTransport bool) error { var retries int start := time.Now() for { cc.mu.Lock() cc.printf("connecting") if cc.state == Shutdown { cc.mu.Unlock() return ErrClientConnClosing } cc.state = Connecting cc.stateCV.Broadcast() cc.mu.Unlock() if closeTransport { cc.transport.Close() } // Adjust timeout for the current try. copts := cc.dopts.copts if copts.Timeout < 0 { cc.Close() return ErrClientConnTimeout } if copts.Timeout > 0 { copts.Timeout -= time.Since(start) if copts.Timeout <= 0 { cc.Close() return ErrClientConnTimeout } } sleepTime := backoff(retries) timeout := sleepTime if timeout < minConnectTimeout { timeout = minConnectTimeout } if copts.Timeout == 0 || copts.Timeout > timeout { copts.Timeout = timeout } connectTime := time.Now() newTransport, err := transport.NewClientTransport(cc.target, &copts) if err != nil { cc.mu.Lock() cc.errorf("transient failure: %v", err) cc.state = TransientFailure cc.stateCV.Broadcast() if cc.ready != nil { close(cc.ready) cc.ready = nil } cc.mu.Unlock() sleepTime -= time.Since(connectTime) if sleepTime < 0 { sleepTime = 0 } // Fail early before falling into sleep. if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) { cc.mu.Lock() cc.errorf("connection timeout") cc.mu.Unlock() cc.Close() return ErrClientConnTimeout } closeTransport = false time.Sleep(sleepTime) retries++ grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target) continue } cc.mu.Lock() cc.printf("ready") if cc.state == Shutdown { // cc.Close() has been invoked. cc.mu.Unlock() newTransport.Close() return ErrClientConnClosing } cc.state = Ready cc.stateCV.Broadcast() cc.transport = newTransport if cc.ready != nil { close(cc.ready) cc.ready = nil } cc.mu.Unlock() return nil } }
func (cc *ClientConn) resetTransport(closeTransport bool) error { var retries int start := time.Now() for { cc.mu.Lock() t := cc.transport ts := cc.transportSeq // Avoid wait() picking up a dying transport unnecessarily. cc.transportSeq = 0 if cc.closing { cc.mu.Unlock() return ErrClientConnClosing } cc.mu.Unlock() if closeTransport { t.Close() } // Adjust timeout for the current try. copts := cc.dopts.copts if copts.Timeout < 0 { cc.Close() return ErrClientConnTimeout } if copts.Timeout > 0 { copts.Timeout -= time.Since(start) if copts.Timeout <= 0 { cc.Close() return ErrClientConnTimeout } } newTransport, err := transport.NewClientTransport(cc.target, &copts) if err != nil { sleepTime := backoff(retries) // Fail early before falling into sleep. if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) { cc.Close() return ErrClientConnTimeout } closeTransport = false time.Sleep(sleepTime) retries++ grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target) continue } cc.mu.Lock() if cc.closing { // cc.Close() has been invoked. cc.mu.Unlock() newTransport.Close() return ErrClientConnClosing } cc.transport = newTransport cc.transportSeq = ts + 1 if cc.ready != nil { close(cc.ready) cc.ready = nil } cc.mu.Unlock() return nil } }
func (ac *addrConn) resetTransport(closeTransport bool) error { for retries := 0; ; retries++ { ac.mu.Lock() ac.printf("connecting") if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() return errConnClosing } if ac.down != nil { ac.down(downErrorf(false, true, "%v", errNetworkIO)) ac.down = nil } ac.state = Connecting ac.stateCV.Broadcast() t := ac.transport ac.mu.Unlock() if closeTransport && t != nil { t.Close() } sleepTime := ac.dopts.bs.backoff(retries) timeout := minConnectTimeout if timeout < sleepTime { timeout = sleepTime } ctx, cancel := context.WithTimeout(ac.ctx, timeout) connectTime := time.Now() newTransport, err := transport.NewClientTransport(ctx, ac.addr.Addr, ac.dopts.copts) if err != nil { cancel() if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { return err } grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) ac.mu.Lock() if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() return errConnClosing } ac.errorf("transient failure: %v", err) ac.state = TransientFailure ac.stateCV.Broadcast() if ac.ready != nil { close(ac.ready) ac.ready = nil } ac.mu.Unlock() closeTransport = false select { case <-time.After(sleepTime - time.Since(connectTime)): case <-ac.ctx.Done(): return ac.ctx.Err() } continue } ac.mu.Lock() ac.printf("ready") if ac.state == Shutdown { // ac.tearDown(...) has been invoked. ac.mu.Unlock() newTransport.Close() return errConnClosing } ac.state = Ready ac.stateCV.Broadcast() ac.transport = newTransport if ac.ready != nil { close(ac.ready) ac.ready = nil } if ac.cc.dopts.balancer != nil { ac.down = ac.cc.dopts.balancer.Up(ac.addr) } ac.mu.Unlock() return nil } }