func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error { start := time.Now() fname := fmt.Sprintf("%016x-%016x%s", snapshot.Metadata.Term, snapshot.Metadata.Index, snapSuffix) b := pbutil.MustMarshal(snapshot) crc := crc32.Update(0, crcTable, b) snap := snappb.Snapshot{Crc: crc, Data: b} d, err := snap.Marshal() if err != nil { return err } else { marshallingDurations.Observe(float64(time.Since(start).Nanoseconds() / int64(time.Microsecond))) } err = ioutil.WriteFile(path.Join(s.dir, fname), d, 0666) if err == nil { saveDurations.Observe(float64(time.Since(start).Nanoseconds() / int64(time.Microsecond))) } return err }
// Read reads the snapshot named by snapname and returns the snapshot. func Read(snapname string) (*raftpb.Snapshot, error) { b, err := ioutil.ReadFile(snapname) if err != nil { plog.Errorf("cannot read file %v: %v", snapname, err) return nil, err } if len(b) == 0 { plog.Errorf("unexpected empty snapshot") return nil, ErrEmptySnapshot } var serializedSnap snappb.Snapshot if err = serializedSnap.Unmarshal(b); err != nil { plog.Errorf("corrupted snapshot file %v: %v", snapname, err) return nil, err } if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 { plog.Errorf("unexpected empty snapshot") return nil, ErrEmptySnapshot } crc := crc32.Update(0, crcTable, serializedSnap.Data) if crc != serializedSnap.Crc { plog.Errorf("corrupted snapshot file %v: crc mismatch", snapname) return nil, ErrCRCMismatch } var snap raftpb.Snapshot if err = snap.Unmarshal(serializedSnap.Data); err != nil { plog.Errorf("corrupted snapshot file %v: %v", snapname, err) return nil, err } return &snap, nil }