1// Copyright 2015 The etcd Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package rafthttp 16 17import ( 18 "errors" 19 "fmt" 20 "sync" 21 "time" 22 23 "go.etcd.io/etcd/pkg/types" 24 25 "go.uber.org/zap" 26) 27 28type failureType struct { 29 source string 30 action string 31} 32 33type peerStatus struct { 34 lg *zap.Logger 35 local types.ID 36 id types.ID 37 mu sync.Mutex // protect variables below 38 active bool 39 since time.Time 40} 41 42func newPeerStatus(lg *zap.Logger, local, id types.ID) *peerStatus { 43 if lg == nil { 44 lg = zap.NewNop() 45 } 46 return &peerStatus{lg: lg, local: local, id: id} 47} 48 49func (s *peerStatus) activate() { 50 s.mu.Lock() 51 defer s.mu.Unlock() 52 if !s.active { 53 s.lg.Info("peer became active", zap.String("peer-id", s.id.String())) 54 s.active = true 55 s.since = time.Now() 56 57 activePeers.WithLabelValues(s.local.String(), s.id.String()).Inc() 58 } 59} 60 61func (s *peerStatus) deactivate(failure failureType, reason string) { 62 s.mu.Lock() 63 defer s.mu.Unlock() 64 msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason) 65 if s.active { 66 s.lg.Warn("peer became inactive (message send to peer failed)", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg))) 67 s.active = false 68 s.since = time.Time{} 69 70 activePeers.WithLabelValues(s.local.String(), s.id.String()).Dec() 71 disconnectedPeers.WithLabelValues(s.local.String(), s.id.String()).Inc() 72 return 73 } 74 75 if s.lg != nil { 76 s.lg.Debug("peer deactivated again", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg))) 77 } 78} 79 80func (s *peerStatus) isActive() bool { 81 s.mu.Lock() 82 defer s.mu.Unlock() 83 return s.active 84} 85 86func (s *peerStatus) activeSince() time.Time { 87 s.mu.Lock() 88 defer s.mu.Unlock() 89 return s.since 90} 91