github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/raft/api.go (about) 1 package raft 2 3 import ( 4 "errors" 5 6 "github.com/coreos/etcd/pkg/types" 7 ) 8 9 type RaftNodeInfo struct { 10 ClusterSize int `json:"clusterSize"` 11 Role string `json:"role"` 12 Address *Address `json:"address"` 13 PeerAddresses []*Address `json:"peerAddresses"` 14 RemovedPeerIds []uint16 `json:"removedPeerIds"` 15 AppliedIndex uint64 `json:"appliedIndex"` 16 SnapshotIndex uint64 `json:"snapshotIndex"` 17 } 18 19 type PublicRaftAPI struct { 20 raftService *RaftService 21 } 22 23 func NewPublicRaftAPI(raftService *RaftService) *PublicRaftAPI { 24 return &PublicRaftAPI{raftService} 25 } 26 27 func (s *PublicRaftAPI) Role() string { 28 if err := s.checkIfNodeInCluster(); err != nil { 29 return "" 30 } 31 _, err := s.raftService.raftProtocolManager.LeaderAddress() 32 if err != nil { 33 return "" 34 } 35 return s.raftService.raftProtocolManager.NodeInfo().Role 36 } 37 38 // helper function to check if self node is part of cluster 39 func (s *PublicRaftAPI) checkIfNodeInCluster() error { 40 if s.raftService.raftProtocolManager.IsIDRemoved(uint64(s.raftService.raftProtocolManager.raftId)) { 41 return errors.New("node not part of raft cluster. operations not allowed") 42 } 43 return nil 44 } 45 46 func (s *PublicRaftAPI) AddPeer(enodeId string) (uint16, error) { 47 if err := s.checkIfNodeInCluster(); err != nil { 48 return 0, err 49 } 50 return s.raftService.raftProtocolManager.ProposeNewPeer(enodeId, false) 51 } 52 53 func (s *PublicRaftAPI) AddLearner(enodeId string) (uint16, error) { 54 if err := s.checkIfNodeInCluster(); err != nil { 55 return 0, err 56 } 57 return s.raftService.raftProtocolManager.ProposeNewPeer(enodeId, true) 58 } 59 60 func (s *PublicRaftAPI) PromoteToPeer(raftId uint16) (bool, error) { 61 if err := s.checkIfNodeInCluster(); err != nil { 62 return false, err 63 } 64 return s.raftService.raftProtocolManager.PromoteToPeer(raftId) 65 } 66 67 func (s *PublicRaftAPI) RemovePeer(raftId uint16) error { 68 if err := s.checkIfNodeInCluster(); err != nil { 69 return err 70 } 71 return s.raftService.raftProtocolManager.ProposePeerRemoval(raftId) 72 } 73 74 func (s *PublicRaftAPI) Leader() (string, error) { 75 76 addr, err := s.raftService.raftProtocolManager.LeaderAddress() 77 if err != nil { 78 return "", err 79 } 80 return addr.NodeId.String(), nil 81 } 82 83 func (s *PublicRaftAPI) Cluster() ([]ClusterInfo, error) { 84 // check if the node has already been removed from cluster 85 // if yes return nil 86 if err := s.checkIfNodeInCluster(); err != nil { 87 return []ClusterInfo{}, nil 88 } 89 90 nodeInfo := s.raftService.raftProtocolManager.NodeInfo() 91 if nodeInfo.Role == "" { 92 return []ClusterInfo{}, nil 93 } 94 95 noLeader := false 96 leaderAddr, err := s.raftService.raftProtocolManager.LeaderAddress() 97 if err != nil { 98 noLeader = true 99 if s.raftService.raftProtocolManager.NodeInfo().Role == "" { 100 return []ClusterInfo{}, nil 101 } 102 } 103 104 peerAddresses := append(nodeInfo.PeerAddresses, nodeInfo.Address) 105 clustInfo := make([]ClusterInfo, len(peerAddresses)) 106 for i, a := range peerAddresses { 107 role := "" 108 if !noLeader { 109 if a.RaftId == leaderAddr.RaftId { 110 role = "minter" 111 } else if s.raftService.raftProtocolManager.isLearner(a.RaftId) { 112 role = "learner" 113 } else if s.raftService.raftProtocolManager.isVerifier(a.RaftId) { 114 role = "verifier" 115 } 116 } 117 clustInfo[i] = ClusterInfo{*a, role, s.checkIfNodeIsActive(a.RaftId)} 118 } 119 return clustInfo, nil 120 } 121 122 // checkIfNodeIsActive checks if the raft node is active 123 // if the raft node is active ActiveSince returns non-zero time 124 func (s *PublicRaftAPI) checkIfNodeIsActive(raftId uint16) bool { 125 if raftId == s.raftService.raftProtocolManager.raftId { 126 return true 127 } 128 activeSince := s.raftService.raftProtocolManager.transport.ActiveSince(types.ID(raftId)) 129 return !activeSince.IsZero() 130 } 131 132 func (s *PublicRaftAPI) GetRaftId(enodeId string) (uint16, error) { 133 return s.raftService.raftProtocolManager.FetchRaftId(enodeId) 134 }