func (this *Paxos) doSaveConfiguration(config *thispb.Configuration) { config.MajoritySize = proto.Int32(this.majoritySize) config.ProposerList = append([]string{}, this.proposerList...) config.AcceptorList = append([]string{}, this.acceptorList...) config.LearnerList = append([]string{}, this.learnerList...) if this.IsProposer() { config.IsProposer = proto.Bool(true) config.ProposerIndex = proto.Int32(int32(this.proposerIndex)) } if this.IsAcceptor() { config.IsAcceptor = proto.Bool(true) } if this.IsLearner() { config.IsLearner = proto.Bool(true) } }
// Configure initializes the paxos agent configuration. Since classic paxos // doesn't support reconfiguration, this operation can be performed only // once. Also, local object can be used as a client if it doesn't take any // role. // // proposerList: List of proposer messenger names. // // acceptorList: List of acceptor messenger names. // // learnerList: List of learner messenger names. // // Returns nil on success. func (this *Paxos) Configure(proposerList, acceptorList, learnerList []string) error { lock, errLock := this.ctlr.LockAll() if errLock != nil { return errLock } defer lock.Unlock() if this.majoritySize > 0 { this.Errorf("paxos instance is already configured") return errs.ErrExist } // TODO: Check for duplicates. learners := make([]string, len(learnerList)) copy(learners, learnerList) sort.Sort(sort.StringSlice(learners)) acceptors := make([]string, len(acceptorList)) copy(acceptors, acceptorList) sort.Sort(sort.StringSlice(acceptors)) majoritySize := len(acceptors)/2 + 1 proposers := make([]string, len(proposerList)) copy(proposers, proposerList) sort.Sort(sort.StringSlice(proposers)) self := this.msn.UID() isLearner := false for _, learner := range learners { if learner == self { isLearner = true break } } isAcceptor := false for _, acceptor := range acceptors { if acceptor == self { isAcceptor = true break } } isProposer := false proposerIndex := -1 for ii, proposer := range proposers { if proposer == self { isProposer = true proposerIndex = ii break } } // Save configuration in the wal. config := thispb.Configuration{} config.LearnerList = learners config.ProposerList = proposers config.AcceptorList = acceptors config.MajoritySize = proto.Int32(int32(majoritySize)) if isLearner { config.IsLearner = proto.Bool(true) } if isAcceptor { config.IsAcceptor = proto.Bool(true) } if isProposer { config.IsProposer = proto.Bool(true) config.ProposerIndex = proto.Int32(int32(proposerIndex)) } return this.doUpdateConfig(&config) }
func (this *Paxos) doRestoreConfig(config *thispb.Configuration) { this.learnerList = config.GetLearnerList() this.proposerList = config.GetProposerList() this.acceptorList = config.GetAcceptorList() if config.IsLearner != nil && config.GetIsLearner() { atomic.StoreInt32(&this.isLearner, 1) } if config.IsAcceptor != nil && config.GetIsAcceptor() { atomic.StoreInt32(&this.isAcceptor, 1) } if config.IsProposer != nil && config.GetIsProposer() { atomic.StoreInt32(&this.isProposer, 1) this.proposerIndex = int(config.GetProposerIndex()) } if config.MajoritySize != nil { atomic.StoreInt32(&this.majoritySize, config.GetMajoritySize()) } }