text: // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  #pragma once
  
  #include <string>
  #include <unordered_set>
  
  #include "kudu/consensus/metadata.pb.h"
  #include "kudu/util/status.h"
  
  namespace kudu {
  namespace consensus {
  
  enum RaftConfigState {
    PENDING_CONFIG,
    COMMITTED_CONFIG,
    ACTIVE_CONFIG,
  };
  
  bool IsRaftConfigMember(const std::string& uuid, const RaftConfigPB& config);
  bool IsRaftConfigVoter(const std::string& uuid, const RaftConfigPB& config);
  
  // Whether the specified Raft role is attributed to a peer which can participate
  // in leader elections.
  bool IsVoterRole(RaftPeerPB::Role role);
  
  // Get the specified member of the config.
  // Returns Status::NotFound if a member with the specified uuid could not be
  // found in the config.
  Status GetRaftConfigMember(RaftConfigPB* config,
                             const std::string& uuid,
                             RaftPeerPB** peer_pb);
  
  // Get the leader of the consensus configuration.
  // Returns Status::NotFound() if the leader RaftPeerPB could not be found in
  // the config, or if there is no leader defined.
  Status GetRaftConfigLeader(ConsensusStatePB* cstate, RaftPeerPB** peer_pb);
  
  // Modifies 'configuration' remove the peer with the specified 'uuid'.
  // Returns false if the server with 'uuid' is not found in the configuration.
  // Returns true on success.
  bool RemoveFromRaftConfig(RaftConfigPB* config, const std::string& uuid);
  
  // Returns true iff the two peers have equivalent replica types and associated
  // options.
  bool ReplicaTypesEqual(const RaftPeerPB& peer1, const RaftPeerPB& peer2);
  
  // Counts the number of voters in the configuration.
  int CountVoters(const RaftConfigPB& config);
  
  // Calculates size of a configuration majority based on # of voters.
  int MajoritySize(int num_voters);
  
  // Determines the role that the peer with uuid 'peer_uuid' plays in the
  // cluster. If 'peer_uuid' is empty or is not a member of the configuration,
  // this function will return NON_PARTICIPANT, regardless of whether it is
  // specified as the leader in 'leader_uuid'. Likewise, if 'peer_uuid' is a
  // NON_VOTER in the config, this function will return LEARNER, regardless of
  // whether it is specified as the leader in 'leader_uuid' (although that
  // situation is illegal in practice).
  RaftPeerPB::Role GetConsensusRole(const std::string& peer_uuid,
                                    const std::string& leader_uuid,
                                    const RaftConfigPB& config);
  
  // Same as above, but uses the leader and active role from the given
  // ConsensusStatePB.
  RaftPeerPB::Role GetConsensusRole(const std::string& peer_uuid,
                                    const ConsensusStatePB& cstate);
  
  // Same as above, but requires that the given 'peer' is a participant
  // in the committed configuration in specified consensus state.
  // If not, it will return incorrect results.
  RaftPeerPB::Role GetParticipantRole(const RaftPeerPB& peer,
                                      const ConsensusStatePB& cstate);
  
  // Verifies that the provided configuration is well formed.
  Status VerifyRaftConfig(const RaftConfigPB& config);
  
  // Superset of checks performed by VerifyRaftConfig. Also ensures that the
  // leader is a configuration voter, if it is set, and that a valid term is set.
  Status VerifyConsensusState(const ConsensusStatePB& cstate);
  
  // Provide a textual description of the difference between two consensus states,
  // suitable for logging.
  std::string DiffConsensusStates(const ConsensusStatePB& old_state,
                                  const ConsensusStatePB& new_state);
  
  // Same as the above, but just the RaftConfigPB portion of the configuration.
  std::string DiffRaftConfigs(const RaftConfigPB& old_config,
                              const RaftConfigPB& new_config);
  
  // Return 'true' iff there is a quorum and the specified tablet configuration
  // is under-replicated given the 'replication_factor', ignoring failures of
  // the UUIDs in 'uuids_ignored_for_underreplication'.
  //
  // The decision is based on the health information provided by the Raft
  // configuration in the 'config' parameter.
  bool ShouldAddReplica(const RaftConfigPB& config,
                        int replication_factor,
                        const std::unordered_set<std::string>& uuids_ignored_for_underreplication =
                            std::unordered_set<std::string>());
  
  // Check if the given Raft configuration contains at least one extra replica
  // which should (and can) be removed in accordance with the specified
  // replication factor and current Raft leader. If so, and if a healthy majority
  // exists, then return 'true' and set the UUID of the best candidate for
  // eviction into the 'uuid_to_evict' out parameter. Otherwise, return 'false'.
  bool ShouldEvictReplica(const RaftConfigPB& config,
                          const std::string& leader_uuid,
                          int replication_factor,
                          std::string* uuid_to_evict = nullptr);
  
  }  // namespace consensus
  }  // namespace kudu
  
  