Пример #1
0
// ElectLeader performs a leader election for the next round.
func (this *Election) ElectLeader(timeout time.Duration) (
	string, int64, error) {

	lock := this.ctlr.ReadLockAll()
	target := this.msn.UID()
	if !this.InCommittee() {
		target = this.committee[rand.Intn(len(this.committee))]
	}
	lock.Unlock()

	request := thispb.ElectRequest{}
	request.ElectionRound = proto.Int64(this.CurrentRound() + 1)
	message := thispb.ElectionMessage{}
	message.ElectRequest = &request

	reqHeader := this.msn.NewRequest(this.namespace, this.uid, "Election.Elect",
		timeout)
	defer this.msn.CloseMessage(reqHeader)

	if err := msg.SendProto(this.msn, target, reqHeader, &message); err != nil {
		this.Errorf("could not send elect request to %s: %v", target, err)
		return "", -1, err
	}

	message.Reset()
	_, errRecv := msg.ReceiveProto(this.msn, reqHeader, &message)
	if errRecv != nil {
		this.Errorf("could not receive elect response from %s: %v", target,
			errRecv)
		return "", -1, errRecv
	}

	if message.ElectResponse == nil {
		this.Errorf("elect response from %s is empty", target)
		return "", -1, errs.ErrCorrupt
	}
	response := message.GetElectResponse()

	change := thispb.ElectionChange{}
	change.ElectionRound = response.ElectionRound
	change.ElectionWinner = response.ElectionWinner
	if err := this.UpdateElection(&change); err != nil {
		this.Errorf("could not update to new election round: %v", err)
		return "", -1, err
	}

	newRound := response.GetElectionRound()
	newLeader := response.GetElectionWinner()
	return newLeader, newRound, nil
}
Пример #2
0
// Propose proposes given value for a consensus.
//
// value: The value to propose for consensus.
//
// timeout: Maximum time duration for the propose operation.
//
// Returns the chosen value on success.
func (this *Paxos) Propose(value []byte, timeout time.Duration) (
	[]byte, error) {

	// If local instance is not a proposer, find a random proposer.
	proposer := this.msn.UID()
	if !this.IsProposer() {
		proposer = this.proposerList[rand.Intn(len(this.proposerList))]
		this.Infof("using %s as the proposer", proposer)
	}

	// Send the propose request.
	request := thispb.ProposeRequest{}
	request.ProposedValue = value
	message := thispb.PaxosMessage{}
	message.ProposeRequest = &request
	reqHeader := this.msn.NewRequest(this.namespace, this.uid,
		"ClassicPaxos.Propose", timeout)
	errSend := msg.SendProto(this.msn, proposer, reqHeader, &message)
	if errSend != nil {
		this.Errorf("could not send propose request to %s: %v", proposer, errSend)
		return nil, errSend
	}

	// Wait for the response.
	_, errRecv := msg.ReceiveProto(this.msn, reqHeader, &message)
	if errRecv != nil {
		this.Errorf("could not receive propose response from %s: %v", proposer,
			errRecv)
		return nil, errRecv
	}

	if message.ProposeResponse == nil {
		this.Errorf("propose response from %s is empty", proposer)
		return nil, errs.ErrCorrupt
	}

	response := message.GetProposeResponse()
	return response.GetChosenValue(), nil
}