diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index b18c1cce74e..c73d4776985 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -2064,7 +2064,6 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con // TODO: non-blocking snapshot func (s *EtcdServer) snapshot(snapi uint64, confState raftpb.ConfState) { - clone := s.v2store.Clone() // commit kv to write metadata (for example: consistent index) to disk. // // This guarantees that Backend's consistent_index is >= index of last snapshot. @@ -2075,16 +2074,12 @@ func (s *EtcdServer) snapshot(snapi uint64, confState raftpb.ConfState) { // So KV().Commit() cannot run in parallel with toApply. It has to be called outside // the go routine created below. s.KV().Commit() + d := GetMembershipInfoInV2Format(s.Logger(), s.cluster) s.GoAttach(func() { lg := s.Logger() - d, err := clone.SaveNoCopy() - // TODO: current store will never fail to do a snapshot - // what should we do if the store might fail? - if err != nil { - lg.Panic("failed to save v2 store", zap.Error(err)) - } + // For backward compatibility, generate v2 snapshot from v3 state. snap, err := s.r.raftStorage.CreateSnapshot(snapi, &confState, d) if err != nil { // the snapshot was done asynchronously with the progress of raft. diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go index 54879285132..c6f68b97909 100644 --- a/server/etcdserver/server_test.go +++ b/server/etcdserver/server_test.go @@ -1047,7 +1047,10 @@ func TestSnapshot(t *testing.T) { srv.kv = mvcc.New(zaptest.NewLogger(t), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) srv.be = be - ch := make(chan struct{}, 2) + cl := membership.NewCluster(zaptest.NewLogger(t)) + srv.cluster = cl + + ch := make(chan struct{}, 1) go func() { gaction, _ := p.Wait(2) @@ -1066,24 +1069,11 @@ func TestSnapshot(t *testing.T) { } }() - go func() { - gaction, _ := st.Wait(2) - defer func() { ch <- struct{}{} }() - - if len(gaction) != 2 { - t.Errorf("len(action) = %d, want 2", len(gaction)) - } - if !reflect.DeepEqual(gaction[0], testutil.Action{Name: "Clone"}) { - t.Errorf("action = %s, want Clone", gaction[0]) - } - if !reflect.DeepEqual(gaction[1], testutil.Action{Name: "SaveNoCopy"}) { - t.Errorf("action = %s, want SaveNoCopy", gaction[1]) - } - }() - srv.snapshot(1, raftpb.ConfState{Voters: []uint64{1}}) <-ch - <-ch + if len(st.Action()) != 0 { + t.Errorf("no action expected on v2store. Got %d actions", len(st.Action())) + } } // TestSnapshotOrdering ensures raft persists snapshot onto disk before @@ -1098,7 +1088,8 @@ func TestSnapshotOrdering(t *testing.T) { n := newNopReadyNode() st := v2store.New() cl := membership.NewCluster(lg) - cl.SetStore(st) + be, _ := betesting.NewDefaultTmpBackend(t) + cl.SetBackend(schema.NewMembershipBackend(lg, be)) testdir := t.TempDir() @@ -1118,7 +1109,6 @@ func TestSnapshotOrdering(t *testing.T) { storage: p, raftStorage: rs, }) - be, _ := betesting.NewDefaultTmpBackend(t) ci := cindex.NewConsistentIndex(be) s := &EtcdServer{ lgMu: new(sync.RWMutex), @@ -1211,6 +1201,9 @@ func TestTriggerSnap(t *testing.T) { srv.kv = mvcc.New(zaptest.NewLogger(t), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) srv.be = be + cl := membership.NewCluster(zaptest.NewLogger(t)) + srv.cluster = cl + srv.start() donec := make(chan struct{}) diff --git a/server/etcdserver/snapshot_merge.go b/server/etcdserver/snapshot_merge.go index 963ead5a7e2..5afbc626c18 100644 --- a/server/etcdserver/snapshot_merge.go +++ b/server/etcdserver/snapshot_merge.go @@ -31,11 +31,7 @@ import ( func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapt, snapi uint64, confState raftpb.ConfState) snap.Message { lg := s.Logger() // get a snapshot of v2 store as []byte - clone := s.v2store.Clone() - d, err := clone.SaveNoCopy() - if err != nil { - lg.Panic("failed to save v2 store data", zap.Error(err)) - } + d := GetMembershipInfoInV2Format(lg, s.cluster) // commit kv to write metadata(for example: consistent index). s.KV().Commit()