コード例 #1
0
ファイル: client.go プロジェクト: qinlodestar/freestore
func getInitialView() (*view.View, error) {
	hostname, err := os.Hostname()
	if err != nil {
		log.Panicln(err)
	}

	if *initialProcess == "" {
		switch {
		case strings.Contains(hostname, "node-"): // emulab.net
			updates := []view.Update{view.Update{Type: view.Join, Process: view.Process{"10.1.1.2:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"10.1.1.3:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"10.1.1.4:5000"}},
			}
			return view.NewWithUpdates(updates...), nil
		default:
			updates := []view.Update{view.Update{Type: view.Join, Process: view.Process{"[::]:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"[::]:5001"}},
				view.Update{Type: view.Join, Process: view.Process{"[::]:5002"}},
			}
			return view.NewWithUpdates(updates...), nil
		}
	} else {
		process := view.Process{*initialProcess}
		initialView, err := client.GetCurrentView(process)
		if err != nil {
			log.Fatalf("Failed to get current view from process %v: %v\n", process, err)
		}
		return initialView, nil
	}
}
コード例 #2
0
ファイル: storage_test.go プロジェクト: qinlodestar/freestore
func TestDatabaseFunctions(t *testing.T) {
	initStorage()

	updates := []view.Update{view.Update{Type: view.Join, Process: view.Process{"[::]:5000"}},
		view.Update{Type: view.Join, Process: view.Process{"[::]:5001"}},
		view.Update{Type: view.Join, Process: view.Process{"[::]:5002"}}}

	associatedView := view.NewWithUpdates(updates...)

	thisProcess := view.Process{"[::]:5001"}

	if key, value, _ := storage.First(); key != nil && value != nil {
		t.Errorf("storage is not empty or unitinialized")
	}

	if proposalNumber, err := getLastProposalNumber(associatedView.NumberOfUpdates()); proposalNumber != 0 || err == nil {
		t.Errorf("getLastProposalNumber should return proposalNumber == 0 and err != nil, got %v and %v", proposalNumber, err)
	}

	saveProposalNumberOnStorage(associatedView.NumberOfUpdates(), 1)
	if proposalNumber, err := getLastProposalNumber(associatedView.NumberOfUpdates()); proposalNumber != 1 || err != nil {
		t.Errorf("getLastProposalNumber should return proposalNumber == 1 and err == nil, got %v and %v", proposalNumber, err)
	}

	if proposalNumber := getNextProposalNumber(associatedView, thisProcess); proposalNumber != 4 {
		t.Errorf("getNextProposalNumber: expected proposalNumber == 4, got %v", proposalNumber)
	}

	if proposalNumber, err := getLastProposalNumber(associatedView.NumberOfUpdates()); proposalNumber != 4 || err != nil {
		t.Errorf("getNextProposalNumber: expted proposalNumber == 4 and err == <nil>, got %v and %v", proposalNumber, err)
	}
}
コード例 #3
0
ファイル: client_test.go プロジェクト: qinlodestar/freestore
func BenchmarkRegisterMsgGobDecode(b *testing.B) {
	updates := []view.Update{view.Update{Type: view.Join, Process: view.Process{"10.1.1.2:5000"}},
		view.Update{Type: view.Join, Process: view.Process{"10.1.1.3:5000"}},
		view.Update{Type: view.Join, Process: view.Process{"10.1.1.4:5000"}},
	}
	v1 := view.NewWithUpdates(updates...)

	msg := RegisterMsg{}
	msg.Value = createFakeData(512)
	msg.Timestamp = 1
	msg.ViewRef = view.ViewToViewRef(v1)

	buf := new(bytes.Buffer)
	var msg2 RegisterMsg

	for i := 0; i < b.N; i++ {
		b.StopTimer()
		buf.Reset()
		encoder := gob.NewEncoder(buf)
		err := encoder.Encode(msg)
		if err != nil {
			b.Errorf(err.Error())
		}
		buf2 := bytes.NewReader(buf.Bytes())
		decoder := gob.NewDecoder(buf2)
		b.StartTimer()

		err = decoder.Decode(&msg2)
		if err != nil {
			b.Errorf(err.Error())
		}
	}
}
コード例 #4
0
ファイル: client_test.go プロジェクト: qinlodestar/freestore
func TestRegisterMsgGob(t *testing.T) {
	updates := []view.Update{view.Update{Type: view.Join, Process: view.Process{"10.1.1.2:5000"}},
		view.Update{Type: view.Join, Process: view.Process{"10.1.1.3:5000"}},
		view.Update{Type: view.Join, Process: view.Process{"10.1.1.4:5000"}},
	}

	v1 := view.NewWithUpdates(updates...)

	msg := RegisterMsg{}
	msg.Value = createFakeData(512)
	msg.Timestamp = 1
	msg.ViewRef = view.ViewToViewRef(v1)

	buf := new(bytes.Buffer)
	encoder := gob.NewEncoder(buf)
	err := encoder.Encode(msg)
	if err != nil {
		t.Errorf(err.Error())
	}

	var msg2 RegisterMsg
	buf2 := bytes.NewReader(buf.Bytes())
	decoder := gob.NewDecoder(buf2)
	err = decoder.Decode(&msg2)
	if err != nil {
		t.Errorf(err.Error())
	}
}
コード例 #5
0
ファイル: server.go プロジェクト: qinlodestar/freestore
func getInitialView(bindAddr string, initialProc string) *view.View {
	hostname, err := os.Hostname()
	if err != nil {
		log.Fatalln(err)
	}

	if initialProc == "" {
		var updates []view.Update
		switch {
		case strings.Contains(hostname, "node-"): // emulab.net
			updates = []view.Update{
				view.Update{Type: view.Join, Process: view.Process{"10.1.1.2:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"10.1.1.3:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"10.1.1.4:5000"}},
			}
		default:
			updates = []view.Update{
				view.Update{Type: view.Join, Process: view.Process{"[::]:5000"}},
				view.Update{Type: view.Join, Process: view.Process{"[::]:5001"}},
				view.Update{Type: view.Join, Process: view.Process{"[::]:5002"}},
			}
		}
		hardCodedView := view.NewWithUpdates(updates...)

		// don't ask for current view if the process is in the hardCodedView
		if hardCodedView.HasMember(view.Process{bindAddr}) {
			return hardCodedView
		}

		for _, u := range updates {
			v, err := client.GetCurrentView(u.Process)
			if err != nil {
				log.Println("Failed to get current view from process %v: %v\n", u.Process, err)
				continue
			}

			if v.Equal(hardCodedView) {
				return hardCodedView
			} else {
				return v
			}
		}
		log.Fatalln("Fatal: None of the hard coded initial processes are responsive.")
		return nil
	} else {
		process := view.Process{initialProc}
		initialView, err := client.GetCurrentView(process)
		if err != nil {
			log.Fatalf("Failed to get current view from process %v: %v\n", process, err)
		}
		return initialView
	}
}
コード例 #6
0
ファイル: viewseq.go プロジェクト: qinlodestar/freestore
func (viewSeq ViewSeq) GetMostUpdatedView() *view.View {
	if len(viewSeq) == 0 {
		return view.NewWithUpdates()
	}

	mostUpdatedViewIndex := 0
	for loopIndex, loopView := range viewSeq {
		if loopView.MoreUpdatedThan(viewSeq[mostUpdatedViewIndex]) {
			mostUpdatedViewIndex = loopIndex
		}
	}

	return viewSeq[mostUpdatedViewIndex]
}
コード例 #7
0
func (s *Server) viewGeneratorWorker(vgi viewGeneratorInstance, initialSeq ViewSeq) {
	log.Printf("Starting new viewGeneratorWorker with initialSeq: %v\n", initialSeq)

	associatedView := vgi.AssociatedView
	jobChan := vgi.jobChan

	var lastProposedSeq ViewSeq
	var lastConvergedSeq ViewSeq
	var viewSeqQuorumCounter viewSeqQuorumCounterType
	var seqConvQuorumCounter seqConvQuorumCounterType

	countViewSeq := func(viewSeqMsg ViewSeqMsg) {
		if viewSeqQuorumCounter.count(&viewSeqMsg, associatedView.QuorumSize()) {
			newConvergedSeq := viewSeqMsg.ProposedSeq

			log.Printf("sending newConvergedSeq: %v\n", newConvergedSeq)
			lastConvergedSeq = newConvergedSeq

			seqConvMsg := SeqConvMsg{}
			seqConvMsg.AssociatedView = associatedView
			seqConvMsg.Seq = newConvergedSeq

			// Send seq-conv to all
			go broadcastViewSequenceConv(associatedView, seqConvMsg)
		}
	}

	if len(initialSeq) != 0 {
		// Send viewSeqMsg to all
		viewSeqMsg := ViewSeqMsg{}
		viewSeqMsg.ProposedSeq = initialSeq
		viewSeqMsg.LastConvergedSeq = nil
		viewSeqMsg.AssociatedView = associatedView
		viewSeqMsg.Sender = s.thisProcess

		go broadcastViewSequence(associatedView, viewSeqMsg)
		countViewSeq(viewSeqMsg)

		lastProposedSeq = initialSeq
	}

	for {
		job := <-jobChan
		switch jobPointer := job.(type) {
		case ViewSeqMsg:
			receivedViewSeqMsg := jobPointer
			log.Println("received ViewSeqMsg:", receivedViewSeqMsg)

			var newProposeSeq ViewSeq

			hasChanges := false
			hasConflict := false

		OuterLoop:
			for _, v := range receivedViewSeqMsg.ProposedSeq {
				if lastProposedSeq.HasView(v) {
					continue
				}

				log.Printf("New view discovered: %v\n", v)
				hasChanges = true

				// check if v conflicts with any view from lastProposedSeq
				for _, v2 := range lastProposedSeq {
					if v.LessUpdatedThan(v2) && v2.LessUpdatedThan(v) {
						log.Printf("Has conflict between %v and %v!\n", v, v2)
						hasConflict = true
						break OuterLoop
					}
				}
			}

			if hasChanges {
				if hasConflict {
					// set lastConvergedSeq to the one with the most updated view
					receivedLastConvergedSeqMostUpdatedView := receivedViewSeqMsg.LastConvergedSeq.GetMostUpdatedView()
					thisProcessLastConvergedSeqMostUpdatedView := lastConvergedSeq.GetMostUpdatedView()
					if thisProcessLastConvergedSeqMostUpdatedView.LessUpdatedThan(receivedLastConvergedSeqMostUpdatedView) {
						lastConvergedSeq = receivedViewSeqMsg.LastConvergedSeq
					}

					oldMostUpdated := lastProposedSeq.GetMostUpdatedView()
					receivedMostUpdated := receivedViewSeqMsg.ProposedSeq.GetMostUpdatedView()

					updates := append(oldMostUpdated.GetUpdates(), receivedMostUpdated.GetUpdates()...)
					auxView := view.NewWithUpdates(updates...)

					newProposeSeq = lastConvergedSeq.Append(auxView)
				} else {
					newProposeSeq = lastProposedSeq.Append(receivedViewSeqMsg.ProposedSeq...)
				}
				log.Println("sending newProposeSeq:", newProposeSeq)

				viewSeqMsg := ViewSeqMsg{}
				viewSeqMsg.Sender = s.thisProcess
				viewSeqMsg.AssociatedView = associatedView
				viewSeqMsg.ProposedSeq = newProposeSeq
				viewSeqMsg.LastConvergedSeq = lastConvergedSeq

				go broadcastViewSequence(associatedView, viewSeqMsg)
				countViewSeq(viewSeqMsg)

				lastProposedSeq = newProposeSeq
			}

			// Quorum check
			countViewSeq(receivedViewSeqMsg)

		case *SeqConv:
			receivedSeqConvMsg := jobPointer
			log.Println("received SeqConvMsg:", receivedSeqConvMsg)

			// Quorum check
			if seqConvQuorumCounter.count(receivedSeqConvMsg, associatedView.QuorumSize()) {
				s.generatedViewSeqChan <- generatedViewSeq{ViewSeq: receivedSeqConvMsg.Seq, AssociatedView: associatedView}
			}
		default:
			log.Fatalln("Something is wrong with the switch statement")
		}

	}
}