Beispiel #1
0
func (rn *RaftNode) Append(data []byte) {
	rn.smRequestChan <- raftsm.CreateEvent("Append", "data", data)
}
Beispiel #2
0
func CreateRaftNode(conf Config) (*RaftNode, error) {
	rn := new(RaftNode)
	rn.id = conf.Id
	//rn.leaderId = 0    //? 0 is invalid
	rn.commitIndex = 0 //?verify
	rnlog, err := log.Open(conf.LogDir)
	if err != nil {
		return nil, err
	}
	rn.rnlog = rnlog
	rn.rnlog.RegisterSampleEntry(raftsm.LogEntry{})

	if rn.rnlog.GetLastIndex() == -1 {
		rn.rnlog.Append(raftsm.LogEntry{0, nil, false})
	}

	rn.server, err = GetServer(int(conf.Id), conf.Cluster)
	if err != nil {
		return nil, err
	}

	//--Init State Machine ---
	peerIds := make([]uint64, 0)
	for _, e := range conf.Cluster {
		if e.Id != conf.Id {
			peerIds = append(peerIds, e.Id)
		}
	}
	rn.majority = uint64(math.Ceil(float64(len(conf.Cluster)) / 2.0)) //? Assumes len is always odd
	rn.statefile = conf.LogDir + "/TermVotedFor"                      //? change required
	data, err := ioutil.ReadFile(rn.statefile)
	if err != nil {
		tvf := TermVotedFor{0, 0}
		data, err := json.Marshal(tvf)
		if err != nil {
			return nil, err
		}
		err = ioutil.WriteFile(rn.statefile, data, 0777)
		if err != nil {
			return nil, err
		}

		rn.currentTerm = 0
		rn.votedFor = 0
	} else {
		var tvf TermVotedFor
		err = json.Unmarshal(data, &tvf)
		if err != nil {
			return nil, err
		}
		rn.currentTerm = tvf.CurrentTerm
		rn.votedFor = tvf.VotedFor
	}

	rn.logIndex = uint64(rn.rnlog.GetLastIndex()) + 1

	rn.sm = raftsm.InitStateMachine(conf.Id, peerIds, rn.majority, time.Duration(conf.ElectionTimeout)*time.Millisecond, time.Duration(conf.HeartbeatTimeout)*time.Millisecond, rn.currentTerm, rn.votedFor /*//?*/, rn.rnlog)

	rn.smAlarmChan = *rn.sm.GetAlarmChannel()
	rn.smCommitChan = *rn.sm.GetCommitChannel()
	rn.smSaveChan = *rn.sm.GetSaveChannel()
	rn.smSendChan = *rn.sm.GetSendChannel()

	rn.smTimeoutChan = *rn.sm.GetTimeoutChannel()
	rn.smResponseChan = *rn.sm.GetResponseChannel()
	rn.smRequestChan = *rn.sm.GetRequestChannel()

	rn.commitChan = make(chan CommitInfo, 1000)
	rn.stopChan = make(chan int, 2)

	rn.timer = time.AfterFunc(100000*time.Second, func() {
		//fmt.Println(rn.id,": timeout at:",time.Now())
		rn.smTimeoutChan <- raftsm.CreateEvent("Timeout")
	})
	rn.timer.Stop()
	gob.Register(raftsm.Event{})
	return rn, nil
}