diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 58710d7d1f88de8937aacb6b153e6a1fc9f785c8..c146c2fa7a54f19f2d8e5386b47782200376020b 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -510,15 +510,17 @@ void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term) { } void syncNodeBecomeFollower(SSyncNode* pSyncNode) { + // maybe clear leader cache if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) { pSyncNode->leaderCache = EMPTY_RAFT_ID; } + // state change pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER; syncNodeStopHeartbeatTimer(pSyncNode); - int32_t electMS = syncUtilElectRandomMS(); - syncNodeRestartElectTimer(pSyncNode, electMS); + // reset elect timer + syncNodeResetElectTimer(pSyncNode); } // TLA+ Spec @@ -540,19 +542,31 @@ void syncNodeBecomeFollower(SSyncNode* pSyncNode) { // /\ UNCHANGED <> // void syncNodeBecomeLeader(SSyncNode* pSyncNode) { + // state change pSyncNode->state = TAOS_SYNC_STATE_LEADER; + + // set leader cache pSyncNode->leaderCache = pSyncNode->myRaftId; for (int i = 0; i < pSyncNode->pNextIndex->replicaNum; ++i) { + // maybe overwrite myself, no harm + // just do it! pSyncNode->pNextIndex->index[i] = pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore) + 1; } for (int i = 0; i < pSyncNode->pMatchIndex->replicaNum; ++i) { + // maybe overwrite myself, no harm + // just do it! pSyncNode->pMatchIndex->index[i] = SYNC_INDEX_INVALID; } + // stop elect timer syncNodeStopElectTimer(pSyncNode); + + // start heartbeat timer syncNodeStartHeartbeatTimer(pSyncNode); + + // start replicate right now! syncNodeReplicate(pSyncNode); } @@ -578,6 +592,9 @@ void syncNodeCandidate2Follower(SSyncNode* pSyncNode) { } // raft vote -------------- + +// just called by syncNodeVoteForSelf +// need assert void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) { assert(term == pSyncNode->pRaftStore->currentTerm); assert(!raftStoreHasVoted(pSyncNode->pRaftStore)); @@ -585,6 +602,7 @@ void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) raftStoreVote(pSyncNode->pRaftStore, pRaftId); } +// simulate get vote from outside void syncNodeVoteForSelf(SSyncNode* pSyncNode) { syncNodeVoteForTerm(pSyncNode, pSyncNode->pRaftStore->currentTerm, &(pSyncNode->myRaftId)); diff --git a/source/libs/sync/src/syncRaftStore.c b/source/libs/sync/src/syncRaftStore.c index bb0eab0fdc559a05636a076d21fa963e5f34f2c7..3f6db129ce46de97b14da2b240b56878826f5e0e 100644 --- a/source/libs/sync/src/syncRaftStore.c +++ b/source/libs/sync/src/syncRaftStore.c @@ -216,7 +216,7 @@ cJSON *raftStore2Json(SRaftStore *pRaftStore) { char *raftStore2Str(SRaftStore *pRaftStore) { cJSON *pJson = raftStore2Json(pRaftStore); - char *serialized = cJSON_Print(pJson); + char * serialized = cJSON_Print(pJson); cJSON_Delete(pJson); return serialized; } diff --git a/source/libs/sync/src/syncRequestVoteReply.c b/source/libs/sync/src/syncRequestVoteReply.c index 802d95076cccd1379ae26cc143aa3df509f27eb7..10ea53864feff623f706cbf0cb86fa2122ab875d 100644 --- a/source/libs/sync/src/syncRequestVoteReply.c +++ b/source/libs/sync/src/syncRequestVoteReply.c @@ -45,6 +45,7 @@ int32_t syncNodeOnRequestVoteReplyCb(SSyncNode* ths, SyncRequestVoteReply* pMsg) return ret; } + assert(!(pMsg->term > ths->pRaftStore->currentTerm)); // no need this code, because if I receive reply.term, then I must have sent for that term. // if (pMsg->term > ths->pRaftStore->currentTerm) { // syncNodeUpdateTerm(ths, pMsg->term); @@ -52,17 +53,29 @@ int32_t syncNodeOnRequestVoteReplyCb(SSyncNode* ths, SyncRequestVoteReply* pMsg) assert(pMsg->term == ths->pRaftStore->currentTerm); + // This tallies votes even when the current state is not Candidate, + // but they won't be looked at, so it doesn't matter. if (ths->state == TAOS_SYNC_STATE_CANDIDATE) { votesRespondAdd(ths->pVotesRespond, pMsg); if (pMsg->voteGranted) { + // add vote voteGrantedVote(ths->pVotesGranted, pMsg); + + // maybe to leader if (voteGrantedMajority(ths->pVotesGranted)) { if (!ths->pVotesGranted->toLeader) { syncNodeCandidate2Leader(ths); + + // prevent to leader again! ths->pVotesGranted->toLeader = true; } } + } else { + ; + // do nothing + // UNCHANGED <> } } + return ret; }