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  }