void Proposer :: OnPrepareReply(const PaxosMsg & oPaxosMsg) { PLGHead("START Msg.ProposalID %lu State.ProposalID %lu Msg.from_nodeid %lu RejectByPromiseID %lu", oPaxosMsg.proposalid(), m_oProposerState.GetProposalID(), oPaxosMsg.nodeid(), oPaxosMsg.rejectbypromiseid()); BP->GetProposerBP()->OnPrepareReply(); if (!m_bIsPreparing) { BP->GetProposerBP()->OnPrepareReplyButNotPreparing(); //PLGErr("Not preparing, skip this msg"); return; } if (oPaxosMsg.proposalid() != m_oProposerState.GetProposalID()) { BP->GetProposerBP()->OnPrepareReplyNotSameProposalIDMsg(); //PLGErr("ProposalID not same, skip this msg"); return; } m_oMsgCounter.AddReceive(oPaxosMsg.nodeid()); if (oPaxosMsg.rejectbypromiseid() == 0) { BallotNumber oBallot(oPaxosMsg.preacceptid(), oPaxosMsg.preacceptnodeid()); PLGDebug("[Promise] PreAcceptedID %lu PreAcceptedNodeID %lu ValueSize %zu", oPaxosMsg.preacceptid(), oPaxosMsg.preacceptnodeid(), oPaxosMsg.value().size()); m_oMsgCounter.AddPromiseOrAccept(oPaxosMsg.nodeid()); m_oProposerState.AddPreAcceptValue(oBallot, oPaxosMsg.value()); } else { PLGDebug("[Reject] RejectByPromiseID %lu", oPaxosMsg.rejectbypromiseid()); m_oMsgCounter.AddReject(oPaxosMsg.nodeid()); m_bWasRejectBySomeone = true; m_oProposerState.SetOtherProposalID(oPaxosMsg.rejectbypromiseid()); } if (m_oMsgCounter.IsPassedOnThisRound()) { int iUseTimeMs = m_oTimeStat.Point(); BP->GetProposerBP()->PreparePass(iUseTimeMs); PLGImp("[Pass] start accept, usetime %dms", iUseTimeMs); m_bCanSkipPrepare = true; Accept(); } else if (m_oMsgCounter.IsRejectedOnThisRound() || m_oMsgCounter.IsAllReceiveOnThisRound()) { BP->GetProposerBP()->PrepareNotPass(); PLGImp("[Not Pass] wait 30ms and restart prepare"); AddPrepareTimer(OtherUtils::FastRand() % 30 + 10); } PLGHead("END"); }
void Proposer :: OnAcceptReply(const PaxosMsg & oPaxosMsg) { PLGHead("START Msg.ProposalID %lu State.ProposalID %lu Msg.from_nodeid %lu RejectByPromiseID %lu", oPaxosMsg.proposalid(), m_oProposerState.GetProposalID(), oPaxosMsg.nodeid(), oPaxosMsg.rejectbypromiseid()); BP->GetProposerBP()->OnAcceptReply(); if (!m_bIsAccepting) { //PLGErr("Not proposing, skip this msg"); BP->GetProposerBP()->OnAcceptReplyButNotAccepting(); return; } if (oPaxosMsg.proposalid() != m_oProposerState.GetProposalID()) { //PLGErr("ProposalID not same, skip this msg"); BP->GetProposerBP()->OnAcceptReplyNotSameProposalIDMsg(); return; } m_oMsgCounter.AddReceive(oPaxosMsg.nodeid()); if (oPaxosMsg.rejectbypromiseid() == 0) { PLGDebug("[Accept]"); m_oMsgCounter.AddPromiseOrAccept(oPaxosMsg.nodeid()); } else { PLGDebug("[Reject]"); m_oMsgCounter.AddReject(oPaxosMsg.nodeid()); m_bWasRejectBySomeone = true; m_oProposerState.SetOtherProposalID(oPaxosMsg.rejectbypromiseid()); } if (m_oMsgCounter.IsPassedOnThisRound()) { int iUseTimeMs = m_oTimeStat.Point(); BP->GetProposerBP()->AcceptPass(iUseTimeMs); PLGImp("[Pass] Start send learn, usetime %dms", iUseTimeMs); ExitAccept(); m_poLearner->ProposerSendSuccess(GetInstanceID(), m_oProposerState.GetProposalID()); } else if (m_oMsgCounter.IsRejectedOnThisRound() || m_oMsgCounter.IsAllReceiveOnThisRound()) { BP->GetProposerBP()->AcceptNotPass(); PLGImp("[Not pass] wait 30ms and Restart prepare"); AddAcceptTimer(OtherUtils::FastRand() % 30 + 10); } PLGHead("END"); }
void Learner :: OnProposerSendSuccess(const PaxosMsg & oPaxosMsg) { BP->GetLearnerBP()->OnProposerSendSuccess(); PLGHead("START Msg.InstanceID %lu Now.InstanceID %lu Msg.ProposalID %lu State.AcceptedID %lu " "State.AcceptedNodeID %lu, Msg.from_nodeid %lu", oPaxosMsg.instanceid(), GetInstanceID(), oPaxosMsg.proposalid(), m_poAcceptor->GetAcceptorState()->GetAcceptedBallot().m_llProposalID, m_poAcceptor->GetAcceptorState()->GetAcceptedBallot().m_llNodeID, oPaxosMsg.nodeid()); if (oPaxosMsg.instanceid() != GetInstanceID()) { //Instance id not same, that means not in the same instance, ignord. PLGDebug("InstanceID not same, skip msg"); return; } if (m_poAcceptor->GetAcceptorState()->GetAcceptedBallot().isnull()) { //Not accept any yet. BP->GetLearnerBP()->OnProposerSendSuccessNotAcceptYet(); PLGDebug("I haven't accpeted any proposal"); return; } BallotNumber oBallot(oPaxosMsg.proposalid(), oPaxosMsg.nodeid()); if (m_poAcceptor->GetAcceptorState()->GetAcceptedBallot() != oBallot) { //Proposalid not same, this accept value maybe not chosen value. PLGDebug("ProposalBallot not same to AcceptedBallot"); BP->GetLearnerBP()->OnProposerSendSuccessBallotNotSame(); return; } //learn value. m_oLearnerState.LearnValueWithoutWrite( oPaxosMsg.instanceid(), m_poAcceptor->GetAcceptorState()->GetAcceptedValue(), m_poAcceptor->GetAcceptorState()->GetChecksum()); BP->GetLearnerBP()->OnProposerSendSuccessSuccessLearn(); PLGHead("END Learn value OK, value %zu", m_poAcceptor->GetAcceptorState()->GetAcceptedValue().size()); TransmitToFollower(); }
void Proposer :: OnExpiredAcceptReply(const PaxosMsg & oPaxosMsg) { if (oPaxosMsg.rejectbypromiseid() != 0) { PLGDebug("[Expired Accept Reply Reject] RejectByPromiseID %lu", oPaxosMsg.rejectbypromiseid()); m_bWasRejectBySomeone = true; m_oProposerState.SetOtherProposalID(oPaxosMsg.rejectbypromiseid()); } }
void IOLoop :: DealWithRetry() { if (m_oRetryQueue.empty()) { return; } bool bHaveRetryOne = false; while (!m_oRetryQueue.empty()) { PaxosMsg & oPaxosMsg = m_oRetryQueue.front(); if (oPaxosMsg.instanceid() > m_poInstance->GetNowInstanceID() + 1) { break; } else if (oPaxosMsg.instanceid() == m_poInstance->GetNowInstanceID() + 1) { //only after retry i == now_i, than we can retry i + 1. if (bHaveRetryOne) { BP->GetIOLoopBP()->DealWithRetryMsg(); PLGDebug("retry msg (i+1). instanceid %lu", oPaxosMsg.instanceid()); m_poInstance->OnReceivePaxosMsg(oPaxosMsg, true); } else { break; } } else if (oPaxosMsg.instanceid() == m_poInstance->GetNowInstanceID()) { BP->GetIOLoopBP()->DealWithRetryMsg(); PLGDebug("retry msg. instanceid %lu", oPaxosMsg.instanceid()); m_poInstance->OnReceivePaxosMsg(oPaxosMsg); // 3.29 : 这里需要先处理完当前 instanceID 的实例再处理下一个,所以这里 // 这里使用了一个标志位作为判断。 bHaveRetryOne = true; } m_oRetryQueue.pop(); } }
void Learner :: OnSendLearnValue(const PaxosMsg & oPaxosMsg) { BP->GetLearnerBP()->OnSendLearnValue(); PLGHead("START Msg.InstanceID %lu Now.InstanceID %lu Msg.ballot_proposalid %lu Msg.ballot_nodeid %lu Msg.ValueSize %zu", oPaxosMsg.instanceid(), GetInstanceID(), oPaxosMsg.proposalid(), oPaxosMsg.nodeid(), oPaxosMsg.value().size()); if (oPaxosMsg.instanceid() > GetInstanceID()) { PLGDebug("[Latest Msg] i can't learn"); return; } else if (oPaxosMsg.instanceid() < GetInstanceID()) { PLGDebug("[Lag Msg] no need to learn"); return; } //learn value BallotNumber oBallot(oPaxosMsg.proposalid(), oPaxosMsg.proposalnodeid()); int ret = m_oLearnerState.LearnValue(oPaxosMsg.instanceid(), oBallot, oPaxosMsg.value(), GetLastChecksum()); if (ret != 0) { PLGErr("LearnState.LearnValue fail, ret %d", ret); return; } PLGHead("END LearnValue OK, proposalid %lu proposalid_nodeid %lu valueLen %zu", oPaxosMsg.proposalid(), oPaxosMsg.nodeid(), oPaxosMsg.value().size()); if (oPaxosMsg.flag() == PaxosMsgFlagType_SendLearnValue_NeedAck) { //every time' when receive valid need ack learn value, reset noop timeout. Reset_AskforLearn_Noop(); SendLearnValue_Ack(oPaxosMsg.nodeid()); } }
void ProposerState :: AddPreAcceptValue( const BallotNumber & oOtherPreAcceptBallot, const std::string & sOtherPreAcceptValue) { PLGDebug("OtherPreAcceptID %lu OtherPreAcceptNodeID %lu HighestOtherPreAcceptID %lu " "HighestOtherPreAcceptNodeID %lu OtherPreAcceptValue %zu", oOtherPreAcceptBallot.m_llProposalID, oOtherPreAcceptBallot.m_llNodeID, m_oHighestOtherPreAcceptBallot.m_llProposalID, m_oHighestOtherPreAcceptBallot.m_llNodeID, sOtherPreAcceptValue.size()); if (oOtherPreAcceptBallot.isnull()) { return; } if (oOtherPreAcceptBallot > m_oHighestOtherPreAcceptBallot) { m_oHighestOtherPreAcceptBallot = oOtherPreAcceptBallot; m_sValue = sOtherPreAcceptValue; } }
int LearnerState :: LearnValue(const uint64_t llInstanceID, const BallotNumber & oLearnedBallot, const std::string & sValue, const uint32_t iLastChecksum) { if (llInstanceID > 0 && iLastChecksum == 0) { m_iNewChecksum = 0; } else if (sValue.size() > 0) { m_iNewChecksum = crc32(iLastChecksum, (const uint8_t *)sValue.data(), sValue.size(), CRC32SKIP); } AcceptorStateData oState; oState.set_instanceid(llInstanceID); oState.set_acceptedvalue(sValue); oState.set_promiseid(oLearnedBallot.m_llProposalID); oState.set_promisenodeid(oLearnedBallot.m_llNodeID); oState.set_acceptedid(oLearnedBallot.m_llProposalID); oState.set_acceptednodeid(oLearnedBallot.m_llNodeID); oState.set_checksum(m_iNewChecksum); WriteOptions oWriteOptions; oWriteOptions.bSync = false; int ret = m_oPaxosLog.WriteState(oWriteOptions, m_poConfig->GetMyGroupIdx(), llInstanceID, oState); if (ret != 0) { PLGErr("LogStorage.WriteLog fail, InstanceID %lu ValueLen %zu ret %d", llInstanceID, sValue.size(), ret); return ret; } LearnValueWithoutWrite(llInstanceID, sValue, m_iNewChecksum); PLGDebug("OK, InstanceID %lu ValueLen %zu checksum %u", llInstanceID, sValue.size(), m_iNewChecksum); return 0; }