syncElection.c 3.3 KB
Newer Older
M
Minghao Li 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

S
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
M
Minghao Li 已提交
17
#include "syncElection.h"
18
#include "syncMessage.h"
M
Minghao Li 已提交
19
#include "syncRaftCfg.h"
M
Minghao Li 已提交
20
#include "syncRaftStore.h"
S
Shengliang Guan 已提交
21
#include "syncUtil.h"
22
#include "syncVoteMgr.h"
M
Minghao Li 已提交
23

M
Minghao Li 已提交
24 25 26 27 28 29 30 31 32 33 34
// TLA+ Spec
// RequestVote(i, j) ==
//    /\ state[i] = Candidate
//    /\ j \notin votesResponded[i]
//    /\ Send([mtype         |-> RequestVoteRequest,
//             mterm         |-> currentTerm[i],
//             mlastLogTerm  |-> LastTerm(log[i]),
//             mlastLogIndex |-> Len(log[i]),
//             msource       |-> i,
//             mdest         |-> j])
//    /\ UNCHANGED <<serverVars, candidateVars, leaderVars, logVars>>
M
Minghao Li 已提交
35

S
Shengliang Guan 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static int32_t syncNodeRequestVotePeers(SSyncNode* pNode) {
  if (pNode->state != TAOS_SYNC_STATE_CANDIDATE) {
    sNTrace(pNode, "not candidate, stop elect");
    return 0;
  }

  int32_t ret = 0;
  for (int i = 0; i < pNode->peersNum; ++i) {
    SRpcMsg rpcMsg = {0};
    ret = syncBuildRequestVote(&rpcMsg, pNode->vgId);
    ASSERT(ret == 0);

    SyncRequestVote* pMsg = rpcMsg.pCont;
    pMsg->srcId = pNode->myRaftId;
    pMsg->destId = pNode->peersId[i];
    pMsg->term = pNode->pRaftStore->currentTerm;

    ret = syncNodeGetLastIndexTerm(pNode, &pMsg->lastLogIndex, &pMsg->lastLogTerm);
    ASSERT(ret == 0);

    ret = syncNodeSendMsgById(&pNode->peersId[i], pNode, &rpcMsg);
    ASSERT(ret == 0);
  }

  return ret;
}

M
Minghao Li 已提交
63
int32_t syncNodeElect(SSyncNode* pSyncNode) {
S
Shengliang Guan 已提交
64
  sNTrace(pSyncNode, "begin election");
M
Minghao Li 已提交
65

M
Minghao Li 已提交
66
  int32_t ret = 0;
M
Minghao Li 已提交
67 68 69
  if (pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER) {
    syncNodeFollower2Candidate(pSyncNode);
  }
M
Minghao Li 已提交
70 71

  if (pSyncNode->state != TAOS_SYNC_STATE_CANDIDATE) {
S
Shengliang Guan 已提交
72
    sNError(pSyncNode, "not candidate, can not elect");
M
Minghao Li 已提交
73 74
    return -1;
  }
M
Minghao Li 已提交
75

M
Minghao Li 已提交
76
  // start election
M
Minghao Li 已提交
77 78 79 80 81 82
  raftStoreNextTerm(pSyncNode->pRaftStore);
  raftStoreClearVote(pSyncNode->pRaftStore);
  voteGrantedReset(pSyncNode->pVotesGranted, pSyncNode->pRaftStore->currentTerm);
  votesRespondReset(pSyncNode->pVotesRespond, pSyncNode->pRaftStore->currentTerm);

  syncNodeVoteForSelf(pSyncNode);
M
Minghao Li 已提交
83 84
  if (voteGrantedMajority(pSyncNode->pVotesGranted)) {
    // only myself, to leader
M
Minghao Li 已提交
85
    ASSERT(!pSyncNode->pVotesGranted->toLeader);
M
Minghao Li 已提交
86 87 88
    syncNodeCandidate2Leader(pSyncNode);
    pSyncNode->pVotesGranted->toLeader = true;
    return ret;
89 90 91 92 93 94 95 96 97 98 99 100 101
  } 

  if (pSyncNode->replicaNum == 1) {
    // only myself, to leader
    voteGrantedUpdate(pSyncNode->pVotesGranted, pSyncNode);
    votesRespondUpdate(pSyncNode->pVotesRespond, pSyncNode);

    pSyncNode->quorum = syncUtilQuorum(pSyncNode->pRaftCfg->cfg.replicaNum);

    syncNodeCandidate2Leader(pSyncNode);
    pSyncNode->pVotesGranted->toLeader = true;
    return ret;

M
Minghao Li 已提交
102 103
  }

M
Minghao Li 已提交
104
  ret = syncNodeRequestVotePeers(pSyncNode);
M
Minghao Li 已提交
105
  ASSERT(ret == 0);
M
Minghao Li 已提交
106

M
Minghao Li 已提交
107
  syncNodeResetElectTimer(pSyncNode);
M
Minghao Li 已提交
108

M
Minghao Li 已提交
109
  return ret;
M
Minghao Li 已提交
110
}