Browse Source

raft: use ConfChangeSingle internally

Tobias Schottdorf 6 years ago
parent
commit
88f5561733
4 changed files with 24 additions and 21 deletions
  1. 7 7
      raft/confchange/confchange.go
  2. 2 2
      raft/confchange/datadriven_test.go
  3. 11 11
      raft/confchange/quick_test.go
  4. 4 1
      raft/raft.go

+ 7 - 7
raft/confchange/confchange.go

@@ -41,12 +41,12 @@ type Changer struct {
 // to
 // to
 //     (1 2 3)&&(1 2 3).
 //     (1 2 3)&&(1 2 3).
 //
 //
-// The supplied ConfChanges are then applied to the incoming majority config,
+// The supplied changes are then applied to the incoming majority config,
 // resulting in a joint configuration that in terms of the Raft thesis[1]
 // resulting in a joint configuration that in terms of the Raft thesis[1]
 // (Section 4.3) corresponds to `C_{new,old}`.
 // (Section 4.3) corresponds to `C_{new,old}`.
 //
 //
 // [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
 // [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
-func (c Changer) EnterJoint(ccs ...pb.ConfChange) (tracker.Config, tracker.ProgressMap, error) {
+func (c Changer) EnterJoint(ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) {
 	cfg, prs, err := c.checkAndCopy()
 	cfg, prs, err := c.checkAndCopy()
 	if err != nil {
 	if err != nil {
 		return c.err(err)
 		return c.err(err)
@@ -129,7 +129,7 @@ func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) {
 // will return an error if that is not the case, if the resulting quorum is
 // will return an error if that is not the case, if the resulting quorum is
 // zero, or if the configuration is in a joint state (i.e. if there is an
 // zero, or if the configuration is in a joint state (i.e. if there is an
 // outgoing configuration).
 // outgoing configuration).
-func (c Changer) Simple(ccs ...pb.ConfChange) (tracker.Config, tracker.ProgressMap, error) {
+func (c Changer) Simple(ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) {
 	cfg, prs, err := c.checkAndCopy()
 	cfg, prs, err := c.checkAndCopy()
 	if err != nil {
 	if err != nil {
 		return c.err(err)
 		return c.err(err)
@@ -151,14 +151,14 @@ func (c Changer) Simple(ccs ...pb.ConfChange) (tracker.Config, tracker.ProgressM
 	return checkAndReturn(cfg, prs)
 	return checkAndReturn(cfg, prs)
 }
 }
 
 
-// apply a ConfChange to the configuration. By convention, changes to voters are
+// apply a change to the configuration. By convention, changes to voters are
 // always made to the incoming majority config Voters[0]. Voters[1] is either
 // always made to the incoming majority config Voters[0]. Voters[1] is either
 // empty or preserves the outgoing majority configuration while in a joint state.
 // empty or preserves the outgoing majority configuration while in a joint state.
-func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.ConfChange) error {
+func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.ConfChangeSingle) error {
 	for _, cc := range ccs {
 	for _, cc := range ccs {
 		if cc.NodeID == 0 {
 		if cc.NodeID == 0 {
 			// etcd replaces the NodeID with zero if it decides (downstream of
 			// etcd replaces the NodeID with zero if it decides (downstream of
-			// raft) to not apply a ConfChange, so we have to have explicit code
+			// raft) to not apply a change, so we have to have explicit code
 			// here to ignore these.
 			// here to ignore these.
 			continue
 			continue
 		}
 		}
@@ -408,7 +408,7 @@ func outgoingPtr(voters *quorum.JointConfig) *quorum.MajorityConfig { return &vo
 
 
 // Describe prints the type and NodeID of the configuration changes as a
 // Describe prints the type and NodeID of the configuration changes as a
 // space-delimited string.
 // space-delimited string.
-func Describe(ccs ...pb.ConfChange) string {
+func Describe(ccs ...pb.ConfChangeSingle) string {
 	var buf strings.Builder
 	var buf strings.Builder
 	for _, cc := range ccs {
 	for _, cc := range ccs {
 		if buf.Len() > 0 {
 		if buf.Len() > 0 {

+ 2 - 2
raft/confchange/datadriven_test.go

@@ -48,7 +48,7 @@ func TestConfChangeDataDriven(t *testing.T) {
 			defer func() {
 			defer func() {
 				c.LastIndex++
 				c.LastIndex++
 			}()
 			}()
-			var ccs []pb.ConfChange
+			var ccs []pb.ConfChangeSingle
 			toks := strings.Split(strings.TrimSpace(d.Input), " ")
 			toks := strings.Split(strings.TrimSpace(d.Input), " ")
 			if toks[0] == "" {
 			if toks[0] == "" {
 				toks = nil
 				toks = nil
@@ -57,7 +57,7 @@ func TestConfChangeDataDriven(t *testing.T) {
 				if len(tok) < 2 {
 				if len(tok) < 2 {
 					return fmt.Sprintf("unknown token %s", tok)
 					return fmt.Sprintf("unknown token %s", tok)
 				}
 				}
-				var cc pb.ConfChange
+				var cc pb.ConfChangeSingle
 				switch tok[0] {
 				switch tok[0] {
 				case 'v':
 				case 'v':
 					cc.Type = pb.ConfChangeAddNode
 					cc.Type = pb.ConfChangeAddNode

+ 11 - 11
raft/confchange/quick_test.go

@@ -35,7 +35,7 @@ func TestConfChangeQuick(t *testing.T) {
 	// as intended.
 	// as intended.
 	const infoCount = 5
 	const infoCount = 5
 
 
-	runWithJoint := func(c *Changer, ccs []pb.ConfChange) error {
+	runWithJoint := func(c *Changer, ccs []pb.ConfChangeSingle) error {
 		cfg, prs, err := c.EnterJoint(ccs...)
 		cfg, prs, err := c.EnterJoint(ccs...)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
@@ -51,7 +51,7 @@ func TestConfChangeQuick(t *testing.T) {
 		return nil
 		return nil
 	}
 	}
 
 
-	runWithSimple := func(c *Changer, ccs []pb.ConfChange) error {
+	runWithSimple := func(c *Changer, ccs []pb.ConfChangeSingle) error {
 		for _, cc := range ccs {
 		for _, cc := range ccs {
 			cfg, prs, err := c.Simple(cc)
 			cfg, prs, err := c.Simple(cc)
 			if err != nil {
 			if err != nil {
@@ -62,7 +62,7 @@ func TestConfChangeQuick(t *testing.T) {
 		return nil
 		return nil
 	}
 	}
 
 
-	type testFunc func(*Changer, []pb.ConfChange) error
+	type testFunc func(*Changer, []pb.ConfChangeSingle) error
 
 
 	wrapper := func(invoke testFunc) func(setup initialChanges, ccs confChanges) (*Changer, error) {
 	wrapper := func(invoke testFunc) func(setup initialChanges, ccs confChanges) (*Changer, error) {
 		return func(setup initialChanges, ccs confChanges) (*Changer, error) {
 		return func(setup initialChanges, ccs confChanges) (*Changer, error) {
@@ -112,8 +112,8 @@ func TestConfChangeQuick(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	t.Error("setup:", Describe(cErr.In[0].([]pb.ConfChange)...))
-	t.Error("ccs:", Describe(cErr.In[1].([]pb.ConfChange)...))
+	t.Error("setup:", Describe(cErr.In[0].([]pb.ConfChangeSingle)...))
+	t.Error("ccs:", Describe(cErr.In[1].([]pb.ConfChangeSingle)...))
 	t.Errorf("out1: %+v\nout2: %+v", cErr.Out1, cErr.Out2)
 	t.Errorf("out1: %+v\nout2: %+v", cErr.Out1, cErr.Out2)
 }
 }
 
 
@@ -123,13 +123,13 @@ func (confChangeTyp) Generate(rand *rand.Rand, _ int) reflect.Value {
 	return reflect.ValueOf(confChangeTyp(rand.Intn(4)))
 	return reflect.ValueOf(confChangeTyp(rand.Intn(4)))
 }
 }
 
 
-type confChanges []pb.ConfChange
+type confChanges []pb.ConfChangeSingle
 
 
-func genCC(num func() int, id func() uint64, typ func() pb.ConfChangeType) []pb.ConfChange {
-	var ccs []pb.ConfChange
+func genCC(num func() int, id func() uint64, typ func() pb.ConfChangeType) []pb.ConfChangeSingle {
+	var ccs []pb.ConfChangeSingle
 	n := num()
 	n := num()
 	for i := 0; i < n; i++ {
 	for i := 0; i < n; i++ {
-		ccs = append(ccs, pb.ConfChange{Type: typ(), NodeID: id()})
+		ccs = append(ccs, pb.ConfChangeSingle{Type: typ(), NodeID: id()})
 	}
 	}
 	return ccs
 	return ccs
 }
 }
@@ -150,7 +150,7 @@ func (confChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
 	return reflect.ValueOf(genCC(num, id, typ))
 	return reflect.ValueOf(genCC(num, id, typ))
 }
 }
 
 
-type initialChanges []pb.ConfChange
+type initialChanges []pb.ConfChangeSingle
 
 
 func (initialChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
 func (initialChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
 	num := func() int {
 	num := func() int {
@@ -163,6 +163,6 @@ func (initialChanges) Generate(rand *rand.Rand, _ int) reflect.Value {
 	// NodeID one is special - it's in the initial config and will be a voter
 	// NodeID one is special - it's in the initial config and will be a voter
 	// always (this is to avoid uninteresting edge cases where the simple conf
 	// always (this is to avoid uninteresting edge cases where the simple conf
 	// changes can't easily make progress).
 	// changes can't easily make progress).
-	ccs := append([]pb.ConfChange{{Type: pb.ConfChangeAddNode, NodeID: 1}}, genCC(num, id, typ)...)
+	ccs := append([]pb.ConfChangeSingle{{Type: pb.ConfChangeAddNode, NodeID: 1}}, genCC(num, id, typ)...)
 	return reflect.ValueOf(ccs)
 	return reflect.ValueOf(ccs)
 }
 }

+ 4 - 1
raft/raft.go

@@ -1401,7 +1401,10 @@ func (r *raft) applyConfChange(cc pb.ConfChange) pb.ConfState {
 	cfg, prs, err := confchange.Changer{
 	cfg, prs, err := confchange.Changer{
 		Tracker:   r.prs,
 		Tracker:   r.prs,
 		LastIndex: r.raftLog.lastIndex(),
 		LastIndex: r.raftLog.lastIndex(),
-	}.Simple(cc)
+	}.Simple(pb.ConfChangeSingle{
+		Type:   cc.Type,
+		NodeID: cc.NodeID,
+	})
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}