func NewRaftNode(name string, c *raft.Config, storage *raft.MemoryStorage, lookup NodeLookup, tr Transporter) *raftNode { var peers []raft.Peer node := raft.StartNode(c, peers) var mu sync.Mutex removed := make(map[uint64]bool) h := Jesteress([]byte(name)) return &raftNode{ index: 0, term: 0, lead: 0, hash: h, lt: time.Now(), Node: node, cfg: *c, mu: mu, lookup: lookup, removed: removed, idgen: idutil.NewGenerator(uint8(h), time.Now()), w: wait.New(), ticker: time.Tick(500 * time.Millisecond), raftStorage: storage, storage: &NoopStorage{}, transport: tr, applyc: make(chan apply), stopped: make(chan struct{}), done: make(chan struct{}), } }
// TestApplyMultiConfChangeShouldStop ensures that apply will return shouldStop // if the local member is removed along with other conf updates. func TestApplyMultiConfChangeShouldStop(t *testing.T) { cl := membership.NewCluster("") cl.SetStore(store.New()) for i := 1; i <= 5; i++ { cl.AddMember(&membership.Member{ID: types.ID(i)}) } srv := &EtcdServer{ id: 2, r: raftNode{ Node: newNodeNop(), transport: rafthttp.NewNopTransporter(), }, cluster: cl, w: wait.New(), } ents := []raftpb.Entry{} for i := 1; i <= 4; i++ { ent := raftpb.Entry{ Term: 1, Index: uint64(i), Type: raftpb.EntryConfChange, Data: pbutil.MustMarshal( &raftpb.ConfChange{ Type: raftpb.ConfChangeRemoveNode, NodeID: uint64(i)}), } ents = append(ents, ent) } _, shouldStop := srv.apply(ents, &raftpb.ConfState{}) if !shouldStop { t.Errorf("shouldStop = %t, want %t", shouldStop, true) } }
// start prepares and starts server in a new goroutine. It is no longer safe to // modify a server's fields after it has been sent to Start. // This function is just used for testing. func (s *EtcdServer) start() { if s.r.snapCount == 0 { log.Printf("etcdserver: set snapshot count to default %d", DefaultSnapCount) s.r.snapCount = DefaultSnapCount } s.w = wait.New() s.done = make(chan struct{}) s.stop = make(chan struct{}) // TODO: if this is an empty log, writes all peer infos // into the first entry go s.run() }
// start prepares and starts server in a new goroutine. It is no longer safe to // modify a server's fields after it has been sent to Start. // This function is just used for testing. func (s *EtcdServer) start() { if s.snapCount == 0 { plog.Infof("set snapshot count to default %d", DefaultSnapCount) s.snapCount = DefaultSnapCount } s.w = wait.New() s.done = make(chan struct{}) s.stop = make(chan struct{}) if s.ClusterVersion() != nil { plog.Infof("starting server... [version: %v, cluster version: %v]", version.Version, version.Cluster(s.ClusterVersion().String())) } else { plog.Infof("starting server... [version: %v, cluster version: to_be_decided]", version.Version) } // TODO: if this is an empty log, writes all peer infos // into the first entry go s.run() }