github.com/kaituanwang/hyperledger@v2.0.1+incompatible/orderer/consensus/etcdraft/tracker.go (about) 1 /* 2 Copyright IBM Corp All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package etcdraft 8 9 import ( 10 "sync/atomic" 11 12 "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 13 "github.com/hyperledger/fabric/common/flogging" 14 "github.com/hyperledger/fabric/common/metrics" 15 "github.com/hyperledger/fabric/protoutil" 16 "go.etcd.io/etcd/raft" 17 ) 18 19 // Tracker periodically poll Raft Status, and update disseminator 20 // so that status is populated to followers. 21 type Tracker struct { 22 id uint64 23 sender *Disseminator 24 gauge metrics.Gauge 25 active *atomic.Value 26 27 counter int 28 29 logger *flogging.FabricLogger 30 } 31 32 func (t *Tracker) Check(status *raft.Status) { 33 // leaderless 34 if status.Lead == raft.None { 35 t.gauge.Set(0) 36 t.active.Store([]uint64{}) 37 return 38 } 39 40 // follower 41 if status.RaftState == raft.StateFollower { 42 return 43 } 44 45 // leader 46 current := []uint64{t.id} 47 for id, progress := range status.Progress { 48 49 if id == t.id { 50 // `RecentActive` for leader's Progress is expected to be false in current implementation of etcd/raft, 51 // but because not marking the leader recently active might be considered a bug and fixed in the future, 52 // we explicitly defend against adding the leader, to avoid potential duplicate 53 continue 54 } 55 56 if progress.RecentActive { 57 current = append(current, id) 58 } 59 } 60 61 last := t.active.Load().([]uint64) 62 t.active.Store(current) 63 64 if len(current) != len(last) { 65 t.counter = 0 66 return 67 } 68 69 // consider active nodes to be stable if it holds for 3 iterations, to avoid glitch 70 // in this value when the recent status is reset on leader election intervals 71 if t.counter < 3 { 72 t.counter++ 73 return 74 } 75 76 t.counter = 0 77 t.logger.Debugf("Current active nodes in cluster are: %+v", current) 78 79 t.gauge.Set(float64(len(current))) 80 metadata := protoutil.MarshalOrPanic(&etcdraft.ClusterMetadata{ActiveNodes: current}) 81 t.sender.UpdateMetadata(metadata) 82 }