// createMergedSnapshotMessage creates a snapshot message that contains: raft status (term, conf), // a snapshot of v2 store inside raft.Snapshot as []byte, a snapshot of v3 KV in the top level message // as ReadCloser. func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapi uint64, confState raftpb.ConfState) snap.Message { snapt, err := s.r.raftStorage.Term(snapi) if err != nil { log.Panicf("get term should never fail: %v", err) } // get a snapshot of v2 store as []byte clone := s.store.Clone() d, err := clone.SaveNoCopy() if err != nil { plog.Panicf("store save should never fail: %v", err) } dbsnap := s.be.Snapshot() // get a snapshot of v3 KV as readCloser rc := newSnapshotReaderCloser(dbsnap) // put the []byte snapshot of store into raft snapshot and return the merged snapshot with // KV readCloser snapshot. snapshot := raftpb.Snapshot{ Metadata: raftpb.SnapshotMetadata{ Index: snapi, Term: snapt, ConfState: confState, }, Data: d, } m.Snapshot = snapshot return *snap.NewMessage(m, rc, dbsnap.Size()) }
func TestSnapshotSend(t *testing.T) { tests := []struct { m raftpb.Message rc io.ReadCloser size int64 wsent bool wfiles int }{ // sent and receive with no errors { m: raftpb.Message{Type: raftpb.MsgSnap, To: 1}, rc: strReaderCloser{strings.NewReader("hello")}, size: 5, wsent: true, wfiles: 1, }, // error when reading snapshot for send { m: raftpb.Message{Type: raftpb.MsgSnap, To: 1}, rc: &errReadCloser{fmt.Errorf("snapshot error")}, size: 1, wsent: false, wfiles: 0, }, // sends less than the given snapshot length { m: raftpb.Message{Type: raftpb.MsgSnap, To: 1}, rc: strReaderCloser{strings.NewReader("hello")}, size: 10000, wsent: false, wfiles: 0, }, // sends less than actual snapshot length { m: raftpb.Message{Type: raftpb.MsgSnap, To: 1}, rc: strReaderCloser{strings.NewReader("hello")}, size: 1, wsent: false, wfiles: 0, }, } for i, tt := range tests { sent, files := testSnapshotSend(t, snap.NewMessage(tt.m, tt.rc, tt.size)) if tt.wsent != sent { t.Errorf("#%d: snapshot expected %v, got %v", i, tt.wsent, sent) } if tt.wfiles != len(files) { t.Fatalf("#%d: expected %d files, got %d files", i, tt.wfiles, len(files)) } } }