Example #1
0
// returns true if successful
func RunCoordinator(view int, index int, reqs []msgs.ClientRequest, io *msgs.Io, config Config, prepare bool) bool {

	entry := msgs.Entry{
		View:      view,
		Committed: false,
		Requests:  reqs}

	majority := Majority(config.N)
	// phase 1: prepare
	if prepare {
		prepare := msgs.PrepareRequest{config.ID, view, index, entry}
		glog.Info("Starting prepare phase", prepare)
		(*io).OutgoingBroadcast.Requests.Prepare <- prepare

		// collect responses
		glog.Info("Waiting for ", majority, " prepare responses")
		for i := 0; i < majority; {
			msg := <-(*io).Incoming.Responses.Prepare
			// check msg replies to the msg we just sent
			if reflect.DeepEqual(msg.Request, prepare) {
				glog.Info("Received ", msg)
				if !msg.Response.Success {
					glog.Warning("Master is stepping down")
					return false
				}
				i++
				glog.Info("Successful response received, waiting for ", majority-i, " more")
			}
		}
	}

	// phase 2: commit
	entry.Committed = true
	commit := msgs.CommitRequest{config.ID, view, index, entry}
	glog.Info("Starting commit phase", commit)
	(*io).OutgoingBroadcast.Requests.Commit <- commit
	// TODO: handle replies properly
	go func() {
		for i := 0; i < majority; {
			msg := <-(*io).Incoming.Responses.Commit
			// check msg replies to the msg we just sent
			if reflect.DeepEqual(msg.Request, commit) {
				glog.Info("Received ", msg)
			}
		}
	}()

	return true
}
Example #2
0
func TestInit(t *testing.T) {
	flag.Parse()
	defer glog.Flush()

	// create a node in system of 3 nodes
	io := msgs.MakeIo(10, 3)
	conf := Config{0, 3}
	go Init(io, conf)

	// TEST 1 - SIMPLE COMMIT

	// tell node to prepare update A 3
	request1 := msgs.ClientRequest{
		ClientID:  2,
		RequestID: 0,
		Request:   "update A 3"}

	entry1 := msgs.Entry{
		View:      0,
		Committed: false,
		Request:   request1}

	prepare1 := msgs.PrepareRequest{
		SenderID: 0,
		View:     0,
		Index:    0,
		Entry:    entry1}

	prepare1_res := msgs.PrepareResponse{
		SenderID: 0,
		Success:  true}

	(*io).Incoming.Requests.Prepare <- prepare1

	// check node replies correctly
	select {
	case reply := <-(*io).OutgoingUnicast[0].Responses.Prepare:
		if reply != prepare1_res {
			t.Error(reply)
		}
	case <-time.After(time.Second):
		t.Error("Participant not responding")
	}

	// tell node to commit update A 3
	entry1.Committed = true
	commit1 := msgs.CommitRequest{
		SenderID: 0,
		View:     0,
		Index:    0,
		Entry:    entry1}

	commit1_res := msgs.CommitResponse{
		SenderID:    0,
		Success:     true,
		CommitIndex: 0}

	(*io).Incoming.Requests.Commit <- commit1

	// check node replies correctly
	select {
	case reply := <-(*io).OutgoingUnicast[0].Responses.Commit:
		if reply != commit1_res {
			t.Error(reply)
		}
	case <-time.After(time.Second):
		t.Error("Participant not responding")
	}

	// check if update A 3 was committed to state machine

	select {
	case reply := <-(*io).OutgoingRequests:
		if reply != request1 {
			t.Error(reply)
		}
	case <-time.After(time.Second):
		t.Error("Participant not responding")
	}
}