Пример #1
0
func livetestlibConflictedCommands(total int) (res []message.Commands) {
	res = make([]message.Commands, total)
	for i := range res {
		res[i] = message.Commands{
			message.Command("c"),
			message.Command(strconv.Itoa(i)),
		}
	}
	return
}
Пример #2
0
// test the correctness of the propose id without batching
func TestProposeIdNoBatch(t *testing.T) {
	N := 5000

	param := &Param{
		ReplicaId:      0,
		Size:           5,
		StateMachine:   new(test.DummySM),
		EnableBatching: false,
		Transporter:    transporter.NewDummyTR(0, 5),
		PersistentPath: tempfile(),
	}
	r, _ := New(param)

	// only start the propose
	go r.proposeLoop()
	go r.eventLoop()
	defer close(r.stop)

	resultIDs := make([]chan uint64, N)
	expectIDs := make([]uint64, N)

	j := uint64(0)
	for i := 0; i < N; i++ {
		if r.IsCheckpoint(j) {
			j++
		}
		resultIDs[i] = r.Propose(message.Command("hello"))
		expectIDs[i] = j
		j++
	}

	for i := 0; i < N; i++ {
		assert.Equal(t, <-resultIDs[i], expectIDs[i])
	}
}
Пример #3
0
// This func tests if executeList() will return error when there is
// an error returned by the state machine
func TestExecuteListWithError(t *testing.T) {
	r := commonTestlibExampleReplica()
	r.StateMachine = test.NewDummySM()
	makeCommitedInstances(r)

	// create an error
	r.InstanceMatrix[0][6].cmds = message.Commands{
		message.Command("error"),
	}

	// resolve conflicts
	assert.True(t, r.resolveConflicts(r.InstanceMatrix[0][6]))

	// should return an error
	assert.Equal(t, r.executeList(), epaxos.ErrStateMachineExecution)

	// construct executionLog
	expectLogStr := "["
	expectLogStr += "[0][2] [0][2] "
	expectLogStr += "[0][4] [0][4] "
	expectLogStr += "[1][3] [1][3] "
	expectLogStr += "[1][5] [1][5] "
	for i := 2; i < int(r.Size); i++ {
		expectLogStr += fmt.Sprintf("[%d][%d] [%d][%d] ", i, i+2, i, i+2)
		expectLogStr += fmt.Sprintf("[%d][%d] [%d][%d] ", i, i+4, i, i+4)
	}
	expectLogStr = expectLogStr[:len(expectLogStr)-1]
	expectLogStr += "]"

	// test the exection result
	executionLogStr := fmt.Sprint(r.StateMachine.(*test.DummySM).ExecutionLog)
	assert.Equal(t, executionLogStr, expectLogStr)
}
Пример #4
0
func (d *DummySM) Execute(c []message.Command) ([]interface{}, error) {
	result := make([]interface{}, 0)
	for i := range c {
		if bytes.Compare(c[i], message.Command("error")) == 0 {
			return nil, epaxos.ErrStateMachineExecution
		}
		result = append(result, string(c[i]))
		d.ExecutionLog = append(d.ExecutionLog, string(c[i]))
	}
	return result, nil
}
Пример #5
0
// test the correctness of the propose id with batching
func TestProposeIdWithBatch(t *testing.T) {
	N := 5000
	B := 100

	param := &Param{
		ReplicaId:      0,
		Size:           5,
		StateMachine:   new(test.DummySM),
		EnableBatching: true,
		BatchInterval:  time.Millisecond * 50,
		Transporter:    transporter.NewDummyTR(0, 5),
		PersistentPath: tempfile(),
	}
	r, _ := New(param)

	// only start the propose
	go r.proposeLoop()
	go r.eventLoop()
	defer close(r.stop)

	resultIDs := make([]chan uint64, N)
	expectIDs := make([]uint64, N)

	// let's batch 100 commands in a group
	exp := uint64(0)
	for i := 0; i < N/B; i++ {
		for j := 0; j < B; j++ {
			if r.IsCheckpoint(exp) {
				exp++
			}
			resultIDs[i*B+j] = r.Propose(message.Command("hello"))
			expectIDs[i*B+j] = exp
		}
		time.Sleep(param.BatchInterval * 2)
		exp++
	}

	for i := 0; i < N; i++ {
		assert.Equal(t, <-resultIDs[i], expectIDs[i])
	}
}
Пример #6
0
func livetestlibExampleCommands(i int) message.Commands {
	return message.Commands{
		message.Command(strconv.Itoa(i)),
	}
}
Пример #7
0
// a helper to make committed instances, containing scc, no un-committed, nor executed instances
func makeCommitedInstances(r *Replica) {
	r.InstanceMatrix[0][6] = NewInstance(r, 0, 6)
	r.InstanceMatrix[0][6].cmds = message.Commands{
		message.Command("[0][6]"),
		message.Command("[0][6]"),
	}
	r.InstanceMatrix[0][6].status = committed
	r.InstanceMatrix[0][6].deps = message.Dependencies{4, 5, 6, 7, 8}

	// create 1st level deps (4, 5, 6, 7, 8)
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][i+4] = NewInstance(r, uint8(i), uint64(i+4))
		r.InstanceMatrix[i][i+4].status = committed
	}
	r.InstanceMatrix[0][4].deps = message.Dependencies{2, 0, 0, 0, 0}
	r.InstanceMatrix[0][4].cmds = message.Commands{
		message.Command("[0][4]"),
		message.Command("[0][4]"),
	}

	r.InstanceMatrix[1][5].deps = message.Dependencies{0, 3, 0, 0, 0}
	r.InstanceMatrix[1][5].cmds = message.Commands{
		message.Command("[1][5]"),
		message.Command("[1][5]"),
	}

	r.InstanceMatrix[2][6].deps = message.Dependencies{0, 0, 4, 0, 0}
	r.InstanceMatrix[2][6].cmds = message.Commands{
		message.Command("[2][6]"),
		message.Command("[2][6]"),
	}

	r.InstanceMatrix[3][7].deps = message.Dependencies{0, 0, 0, 5, 0}
	r.InstanceMatrix[3][7].cmds = message.Commands{
		message.Command("[3][7]"),
		message.Command("[3][7]"),
	}

	r.InstanceMatrix[4][8].deps = message.Dependencies{0, 0, 0, 0, 6}
	r.InstanceMatrix[4][8].cmds = message.Commands{
		message.Command("[4][8]"),
		message.Command("[4][8]"),
	}

	// create 2nd level deps (2, 3, 4, 5, 6)
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][i+2] = NewInstance(r, uint8(i), uint64(i+2))
		r.InstanceMatrix[i][i+2].status = committed
		r.InstanceMatrix[i][i+2].cmds = message.Commands{
			message.Command(fmt.Sprintf("[%d][%d]", i, i+2)),
			message.Command(fmt.Sprintf("[%d][%d]", i, i+2)),
		}
	}

	// create a scc (2->4, 2->5, 3->4, 3->5)
	r.InstanceMatrix[0][2].deps = message.Dependencies{4, 5, 0, 0, 0}
	r.InstanceMatrix[1][3].deps = message.Dependencies{4, 5, 0, 0, 0}
}
Пример #8
0
func main() {
	var id int
	var restore bool

	flag.IntVar(&id, "id", -1, "id of the server")
	flag.BoolVar(&restore, "restore", false, "if recover")

	flag.Parse()

	if id < 0 {
		fmt.Println("id is required!")
		flag.PrintDefaults()
		return
	}

	addrs := []string{
		":9000", ":9001", ":9002",
		//":9003", ":9004",
	}

	tr, err := transporter.NewUDPTransporter(addrs, uint8(id), len(addrs))
	if err != nil {
		panic(err)
	}
	param := &replica.Param{
		Addrs:            addrs,
		ReplicaId:        uint8(id),
		Size:             uint8(len(addrs)),
		StateMachine:     new(Voter),
		Transporter:      tr,
		EnablePersistent: true,
		Restore:          restore,
		TimeoutInterval:  time.Second,
		//ExecuteInterval:  time.Second,
	}
	if restore {
		fmt.Fprintln(os.Stderr, "===restore===")
	}

	fmt.Println("====== Spawn new replica ======")
	r, err := replica.New(param)
	if err != nil {
		glog.Fatal(err)
	}

	fmt.Println("Done!")
	fmt.Printf("Wait %d seconds to start\n", prepareInterval)
	time.Sleep(prepareInterval * time.Second)
	err = r.Start()
	if err != nil {
		glog.Fatal(err)
	}
	fmt.Println("====== start ======")

	rand.Seed(time.Now().UTC().UnixNano())
	counter := 1
	for {
		time.Sleep(time.Millisecond * 500)
		c := "From: " + strconv.Itoa(id) + ", Command: " + strconv.Itoa(id) + ":" + strconv.Itoa(counter) + ", " + time.Now().String()
		counter++

		cmds := make([]message.Command, 0)
		cmds = append(cmds, message.Command(c))
		r.Propose(cmds...)
	}
}