mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
raft: use ConfChangeSingle internally
This commit is contained in:
parent
10680744b9
commit
88f5561733
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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("setup:", Describe(cErr.In[0].([]pb.ConfChangeSingle)...))
|
||||||
t.Error("ccs:", Describe(cErr.In[1].([]pb.ConfChange)...))
|
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 {
|
func genCC(num func() int, id func() uint64, typ func() pb.ConfChangeType) []pb.ConfChangeSingle {
|
||||||
var ccs []pb.ConfChange
|
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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user