// 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

