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) {
64 65
  sNInfo(pSyncNode, "begin election");
  pSyncNode->electNum++;
M
Minghao Li 已提交
66

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

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

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

  syncNodeVoteForSelf(pSyncNode);
M
Minghao Li 已提交
84 85
  if (voteGrantedMajority(pSyncNode->pVotesGranted)) {
    // only myself, to leader
M
Minghao Li 已提交
86
    ASSERT(!pSyncNode->pVotesGranted->toLeader);
M
Minghao Li 已提交
87 88 89
    syncNodeCandidate2Leader(pSyncNode);
    pSyncNode->pVotesGranted->toLeader = true;
    return ret;
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
}