Example #1
0
// 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())
}
Example #2
0
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))
		}
	}
}