// HardState contains term, vote and commit. // Snapshot contains data and snapshot metadata. func (n *node) saveToStorage(hardState raftpb.HardState, entries []raftpb.Entry, snapshot raftpb.Snapshot) { if !raft.IsEmptySnap(snapshot) { fmt.Printf("saveToStorage snapshot: %v\n", snapshot.String()) le, err := n.store.LastIndex() if err != nil { log.Fatalf("While retrieving last index: %v\n", err) } te, err := n.store.Term(le) if err != nil { log.Fatalf("While retrieving term: %v\n", err) } fmt.Printf("%d node Term for le: %v is %v\n", n.id, le, te) if snapshot.Metadata.Index <= le { fmt.Printf("%d node ignoring snapshot. Last index: %v\n", n.id, le) return } if err := n.store.ApplySnapshot(snapshot); err != nil { log.Fatalf("Applying snapshot: %v", err) } } if !raft.IsEmptyHardState(hardState) { n.store.SetHardState(hardState) } n.store.Append(entries) }
// 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 { log.Printf("snap: snapshotter cannot read file %v: %v", snapname, err) return nil, err } var serializedSnap snappb.Snapshot if err = serializedSnap.Unmarshal(b); err != nil { log.Printf("snap: corrupted snapshot file %v: %v", snapname, err) return nil, err } if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 { log.Printf("snap: unexpected empty snapshot") return nil, ErrEmptySnapshot } crc := crc32.Update(0, crcTable, serializedSnap.Data) if crc != serializedSnap.Crc { log.Printf("snap: corrupted snapshot file %v: crc mismatch", snapname) return nil, ErrCRCMismatch } var snap raftpb.Snapshot if err = snap.Unmarshal(serializedSnap.Data); err != nil { log.Printf("snap: corrupted snapshot file %v: %v", snapname, err) return nil, err } return &snap, nil }
func (s *Snapshotter) Save(snapshot *raftpb.Snapshot) error { fname := fmt.Sprintf("%016x-%016x%s", snapshot.Term, snapshot.Index, snapSuffix) b, err := snapshot.Marshal() if err != nil { panic(err) } crc := crc32.Update(0, crcTable, b) snap := snappb.Snapshot{Crc: crc, Data: b} d, err := snap.Marshal() if err != nil { return err } return ioutil.WriteFile(path.Join(s.dir, fname), d, 0666) }
// Store stores the snapshot, hardstate and entries for a given RAFT group. func (w *Wal) Store(gid uint32, s raftpb.Snapshot, h raftpb.HardState, es []raftpb.Entry) error { b := w.wals.NewWriteBatch() defer b.Destroy() if !raft.IsEmptySnap(s) { data, err := s.Marshal() if err != nil { return x.Wrapf(err, "wal.Store: While marshal snapshot") } b.Put(w.snapshotKey(gid), data) } if !raft.IsEmptyHardState(h) { data, err := h.Marshal() if err != nil { return x.Wrapf(err, "wal.Store: While marshal hardstate") } b.Put(w.hardStateKey(gid), data) } var t, i uint64 for _, e := range es { t, i = e.Term, e.Index data, err := e.Marshal() if err != nil { return x.Wrapf(err, "wal.Store: While marshal entry") } k := w.entryKey(gid, e.Term, e.Index) b.Put(k, data) } // If we get no entries, then the default value of t and i would be zero. That would // end up deleting all the previous valid raft entry logs. This check avoids that. if t > 0 || i > 0 { // Delete all keys above this index. start := w.entryKey(gid, t, i+1) prefix := w.prefix(gid) itr := w.wals.NewIterator() defer itr.Close() for itr.Seek(start); itr.ValidForPrefix(prefix); itr.Next() { b.Delete(itr.Key().Data()) } } err := w.wals.WriteBatch(b) return x.Wrapf(err, "wal.Store: While WriteBatch") }
func loadSnap(dir, name string) (*raftpb.Snapshot, error) { var err error var b []byte fpath := path.Join(dir, name) defer func() { if err != nil { renameBroken(fpath) } }() b, err = ioutil.ReadFile(fpath) if err != nil { log.Printf("snap: snapshotter cannot read file %v: %v", name, err) return nil, err } var serializedSnap snappb.Snapshot if err = serializedSnap.Unmarshal(b); err != nil { log.Printf("snap: corrupted snapshot file %v: %v", name, err) return nil, err } if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 { log.Printf("snap: unexpected empty snapshot") return nil, ErrEmptySnapshot } crc := crc32.Update(0, crcTable, serializedSnap.Data) if crc != serializedSnap.Crc { log.Printf("snap: corrupted snapshot file %v: crc mismatch", name) return nil, ErrCRCMismatch } var snap raftpb.Snapshot if err = snap.Unmarshal(serializedSnap.Data); err != nil { log.Printf("snap: corrupted snapshot file %v: %v", name, err) return nil, err } return &snap, nil }