Esempio n. 1
0
func TestFindNewerCommitIndex_Figure8_CaseEextended(t *testing.T) {
	ci, err := config.NewClusterInfo([]ServerId{"s1", "s2", "s3", "s4", "s5"}, "s1")
	if err != nil {
		t.Fatal(err)
	}

	// Figure 8, case (e) extended with extra term 4 entry at index 4
	terms := []TermNo{1, 2, 4, 4} // leader line for the case
	imle := log.TestUtil_NewInMemoryLog_WithTerms(terms)
	lvs, err := consensus_state.NewLeaderVolatileState(ci, LogIndex(len(terms)))
	if err != nil {
		t.Fatal(err)
	}

	_findNewerCommitIndex := func(currentTerm TermNo, commitIndex LogIndex) LogIndex {
		nci, err := consensus_state.FindNewerCommitIndex(ci, lvs, imle, currentTerm, commitIndex)
		if err != nil {
			t.Fatal(err)
		}
		return nci
	}

	// match peers
	err = lvs.SetMatchIndexAndNextIndex("s2", 4)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s3", 4)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s4", 1)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s5", 1)
	if err != nil {
		t.Fatal(err)
	}

	// currentTerm = 4 has a solution
	// the highest match is returned
	if _findNewerCommitIndex(4, 0) != 4 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 1) != 4 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 2) != 4 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 3) != 4 {
		t.Fatal()
	}

	// returns 0 if current commitIndex is the highest match
	if _findNewerCommitIndex(4, 4) != 0 {
		t.Fatal()
	}
}
Esempio n. 2
0
func TestFindNewerCommitIndex_SOLO(t *testing.T) {
	ci, err := config.NewClusterInfo([]ServerId{"s1"}, "s1")
	if err != nil {
		t.Fatal(err)
	}

	terms := []TermNo{1, 2, 2, 2, 3, 3}
	imle := log.TestUtil_NewInMemoryLog_WithTerms(terms)
	lvs, err := consensus_state.NewLeaderVolatileState(ci, LogIndex(len(terms)))
	if err != nil {
		t.Fatal(err)
	}

	_findNewerCommitIndex := func(currentTerm TermNo, commitIndex LogIndex) LogIndex {
		nci, err := consensus_state.FindNewerCommitIndex(ci, lvs, imle, currentTerm, commitIndex)
		if err != nil {
			t.Fatal(err)
		}
		return nci
	}

	if nci := _findNewerCommitIndex(1, 0); nci != 1 {
		t.Fatal(nci)
	}
	if nci := _findNewerCommitIndex(1, 1); nci != 0 {
		t.Fatal(nci)
	}

	// the highest match is returned
	if nci := _findNewerCommitIndex(2, 0); nci != 4 {
		t.Fatal(nci)
	}
	if nci := _findNewerCommitIndex(2, 3); nci != 4 {
		t.Fatal(nci)
	}
	if nci := _findNewerCommitIndex(3, 1); nci != 6 {
		t.Fatal(nci)
	}

	// returns 0 if current commitIndex is the highest match
	if nci := _findNewerCommitIndex(2, 4); nci != 0 {
		t.Fatal(nci)
	}

}
Esempio n. 3
0
// #RFS-L4: If there exists an N such that N > commitIndex, a majority
// of matchIndex[i] >= N, and log[N].term == currentTerm:
// set commitIndex = N (#5.3, #5.4)
func (cm *PassiveConsensusModule) advanceCommitIndexIfPossible() error {
	newerCommitIndex, err := consensus_state.FindNewerCommitIndex(
		cm.ClusterInfo,
		cm.LeaderVolatileState,
		cm.LogRO,
		cm.RaftPersistentState.GetCurrentTerm(),
		cm.GetCommitIndex(),
	)
	if err != nil {
		return err
	}
	if newerCommitIndex != 0 && newerCommitIndex > cm.GetCommitIndex() {
		err = cm.setCommitIndex(newerCommitIndex)
		if err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 4
0
func TestFindNewerCommitIndex_Figure8_CaseCAndE(t *testing.T) {
	ci, err := config.NewClusterInfo([]ServerId{"s1", "s2", "s3", "s4", "s5"}, "s1")
	if err != nil {
		t.Fatal(err)
	}

	// Figure 8, case (c)
	terms := []TermNo{1, 2, 4} // leader line for the case
	imle := log.TestUtil_NewInMemoryLog_WithTerms(terms)
	lvs, err := consensus_state.NewLeaderVolatileState(ci, LogIndex(len(terms)))
	if err != nil {
		t.Fatal(err)
	}

	_findNewerCommitIndex := func(currentTerm TermNo, commitIndex LogIndex) LogIndex {
		nci, err := consensus_state.FindNewerCommitIndex(ci, lvs, imle, currentTerm, commitIndex)
		if err != nil {
			t.Fatal(err)
		}
		return nci
	}

	// With matchIndex stuck at 0, there is no solution for any currentTerm
	if _findNewerCommitIndex(1, 0) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(2, 0) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(3, 0) != 0 {
		t.Fatal()
	}

	// match peers for Figure 8, case (c)
	err = lvs.SetMatchIndexAndNextIndex("s2", 2)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s3", 2)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s4", 1)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s5", 1)
	if err != nil {
		t.Fatal(err)
	}

	// While we cannot be at currentTerm=1, it has solutions
	if _findNewerCommitIndex(1, 0) != 1 {
		t.Fatal()
	}
	if _findNewerCommitIndex(1, 1) != 0 {
		t.Fatal()
	}
	// While we cannot be at currentTerm=2, it has solutions
	if _findNewerCommitIndex(2, 0) != 2 {
		t.Fatal()
	}
	if _findNewerCommitIndex(2, 1) != 2 {
		t.Fatal()
	}
	// While we cannot be at currentTerm=3, it has no solution
	if _findNewerCommitIndex(3, 0) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(3, 1) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(3, 2) != 0 {
		t.Fatal()
	}
	// No solution for currentTerm >= 4
	if _findNewerCommitIndex(4, 0) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 1) != 0 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 2) != 0 {
		t.Fatal()
	}

	// match peers for Figure 8, case (e)
	err = lvs.SetMatchIndexAndNextIndex("s2", 3)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s3", 3)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s4", 1)
	if err != nil {
		t.Fatal(err)
	}
	err = lvs.SetMatchIndexAndNextIndex("s5", 1)
	if err != nil {
		t.Fatal(err)
	}

	// Now currentTerm = 4 has a solution
	if _findNewerCommitIndex(4, 0) != 3 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 1) != 3 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 2) != 3 {
		t.Fatal()
	}
	if _findNewerCommitIndex(4, 3) != 0 {
		t.Fatal()
	}
}