syncRequestVote.c 5.1 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 "syncRequestVote.h"
18
#include "syncMessage.h"
M
Minghao Li 已提交
19
#include "syncRaftCfg.h"
M
Minghao Li 已提交
20 21 22
#include "syncRaftStore.h"
#include "syncUtil.h"
#include "syncVoteMgr.h"
M
Minghao Li 已提交
23

M
Minghao Li 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// TLA+ Spec
// HandleRequestVoteRequest(i, j, m) ==
//    LET logOk == \/ m.mlastLogTerm > LastTerm(log[i])
//                 \/ /\ m.mlastLogTerm = LastTerm(log[i])
//                    /\ m.mlastLogIndex >= Len(log[i])
//        grant == /\ m.mterm = currentTerm[i]
//                 /\ logOk
//                 /\ votedFor[i] \in {Nil, j}
//    IN /\ m.mterm <= currentTerm[i]
//       /\ \/ grant  /\ votedFor' = [votedFor EXCEPT ![i] = j]
//          \/ ~grant /\ UNCHANGED votedFor
//       /\ Reply([mtype        |-> RequestVoteResponse,
//                 mterm        |-> currentTerm[i],
//                 mvoteGranted |-> grant,
//                 \* mlog is used just for the `elections' history variable for
//                 \* the proof. It would not exist in a real implementation.
//                 mlog         |-> log[i],
//                 msource      |-> i,
//                 mdest        |-> j],
//                 m)
//       /\ UNCHANGED <<state, currentTerm, candidateVars, leaderVars, logVars>>
M
Minghao Li 已提交
45
//
M
Minghao Li 已提交
46

S
Shengliang Guan 已提交
47 48 49
static bool syncNodeOnRequestVoteLogOK(SSyncNode* ths, SyncRequestVote* pMsg) {
  SyncTerm  myLastTerm = syncNodeGetLastTerm(ths);
  SyncIndex myLastIndex = syncNodeGetLastIndex(ths);
50

51
  if (myLastTerm == SYNC_TERM_INVALID) {
S
Shengliang Guan 已提交
52
    sNTrace(ths,
S
Shengliang Guan 已提交
53 54 55
            "logok:0, {my-lterm:%" PRIu64 ", my-lindex:%" PRId64 ", recv-lterm:%" PRIu64 ", recv-lindex:%" PRId64
            ", recv-term:%" PRIu64 "}",
            myLastTerm, myLastIndex, pMsg->lastLogTerm, pMsg->lastLogIndex, pMsg->term);
56 57
    return false;
  }
M
Minghao Li 已提交
58

59
  if (pMsg->lastLogTerm > myLastTerm) {
S
Shengliang Guan 已提交
60
    sNTrace(ths,
S
Shengliang Guan 已提交
61 62 63
            "logok:1, {my-lterm:%" PRIu64 ", my-lindex:%" PRId64 ", recv-lterm:%" PRIu64 ", recv-lindex:%" PRId64
            ", recv-term:%" PRIu64 "}",
            myLastTerm, myLastIndex, pMsg->lastLogTerm, pMsg->lastLogIndex, pMsg->term);
64

65 66
    if (pMsg->lastLogIndex < ths->commitIndex) {
      sNWarn(ths,
67 68 69 70
             "logok:1, commit rollback required. {my-lterm:%" PRIu64 ", my-lindex:%" PRId64 ", recv-lterm:%" PRIu64
             ", recv-lindex:%" PRId64 ", recv-term:%" PRIu64 "}",
             myLastTerm, myLastIndex, pMsg->lastLogTerm, pMsg->lastLogIndex, pMsg->term);
    }
71 72
    return true;
  }
M
Minghao Li 已提交
73

74
  if (pMsg->lastLogTerm == myLastTerm && pMsg->lastLogIndex >= myLastIndex) {
S
Shengliang Guan 已提交
75
    sNTrace(ths,
S
Shengliang Guan 已提交
76 77 78
            "logok:1, {my-lterm:%" PRIu64 ", my-lindex:%" PRId64 ", recv-lterm:%" PRIu64 ", recv-lindex:%" PRId64
            ", recv-term:%" PRIu64 "}",
            myLastTerm, myLastIndex, pMsg->lastLogTerm, pMsg->lastLogIndex, pMsg->term);
79 80 81
    return true;
  }

S
Shengliang Guan 已提交
82
  sNTrace(ths,
S
Shengliang Guan 已提交
83 84 85
          "logok:0, {my-lterm:%" PRIu64 ", my-lindex:%" PRId64 ", recv-lterm:%" PRIu64 ", recv-lindex:%" PRId64
          ", recv-term:%" PRIu64 "}",
          myLastTerm, myLastIndex, pMsg->lastLogTerm, pMsg->lastLogIndex, pMsg->term);
86 87 88
  return false;
}

S
Shengliang Guan 已提交
89 90 91
int32_t syncNodeOnRequestVote(SSyncNode* ths, const SRpcMsg* pRpcMsg) {
  int32_t          ret = 0;
  SyncRequestVote* pMsg = pRpcMsg->pCont;
M
Minghao Li 已提交
92 93

  // if already drop replica, do not process
S
Shengliang Guan 已提交
94
  if (!syncNodeInRaftGroup(ths, &pMsg->srcId)) {
S
Shengliang Guan 已提交
95
    syncLogRecvRequestVote(ths, pMsg, -1, "not in my config");
M
Minghao Li 已提交
96 97 98 99 100 101
    return -1;
  }

  bool logOK = syncNodeOnRequestVoteLogOK(ths, pMsg);

  // maybe update term
S
Shengliang Guan 已提交
102
  if (pMsg->term > ths->raftStore.currentTerm) {
M
Minghao Li 已提交
103 104
    syncNodeStepDown(ths, pMsg->term);
    // syncNodeUpdateTerm(ths, pMsg->term);
M
Minghao Li 已提交
105
  }
S
Shengliang Guan 已提交
106
  ASSERT(pMsg->term <= ths->raftStore.currentTerm);
M
Minghao Li 已提交
107

S
Shengliang Guan 已提交
108 109
  bool grant = (pMsg->term == ths->raftStore.currentTerm) && logOK &&
               ((!raftStoreHasVoted(ths)) || (syncUtilSameId(&ths->raftStore.voteFor, &pMsg->srcId)));
M
Minghao Li 已提交
110 111 112
  if (grant) {
    // maybe has already voted for pMsg->srcId
    // vote again, no harm
S
Shengliang Guan 已提交
113
    raftStoreVote(ths, &(pMsg->srcId));
M
Minghao Li 已提交
114

M
Minghao Li 已提交
115
    // candidate ?
S
Shengliang Guan 已提交
116
    syncNodeStepDown(ths, ths->raftStore.currentTerm);
M
Minghao Li 已提交
117

M
Minghao Li 已提交
118 119 120 121 122
    // forbid elect for this round
    syncNodeResetElectTimer(ths);
  }

  // send msg
S
Shengliang Guan 已提交
123 124
  SRpcMsg rpcMsg = {0};
  ret = syncBuildRequestVoteReply(&rpcMsg, ths->vgId);
125
  ASSERT(ret == 0);
S
Shengliang Guan 已提交
126 127

  SyncRequestVoteReply* pReply = rpcMsg.pCont;
M
Minghao Li 已提交
128 129
  pReply->srcId = ths->myRaftId;
  pReply->destId = pMsg->srcId;
S
Shengliang Guan 已提交
130
  pReply->term = ths->raftStore.currentTerm;
M
Minghao Li 已提交
131 132 133
  pReply->voteGranted = grant;

  // trace log
S
Shengliang Guan 已提交
134 135
  syncLogRecvRequestVote(ths, pMsg, pReply->voteGranted, "");
  syncLogSendRequestVoteReply(ths, pReply, "");
M
Minghao Li 已提交
136 137
  syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
  return 0;
138
}