// Don't call this multiple times concurrently func (s *raftStorage) save(state raftpb.HardState, entries []raftpb.Entry) error { wb := s.db.NewBatch() if !raft.IsEmptyHardState(state) { stateBytes, err := state.Marshal() if err != nil { return err } wb.Put(s.hardStateKey, stateBytes) } if len(entries) > 0 { lastIndex, err := s.LastIndex() if err != nil { return err } if entries[0].Index > lastIndex+1 { panic(fmt.Errorf("missing log entries [last: %d, append at: %d]", lastIndex, entries[0].Index)) } // clear all old entries past the new index, if any for ix := entries[0].Index; ix <= lastIndex; ix++ { wb.Delete(s.getEntryKey(ix)) } // append the new entries for _, entry := range entries { entryBytes, err := entry.Marshal() if err != nil { return err } wb.Put(s.getEntryKey(entry.Index), entryBytes) } } err := s.db.Write(wb) return err }
func (w *WAL) SaveState(s *raftpb.HardState) error { if raft.IsEmptyHardState(*s) { return nil } b, err := s.Marshal() if err != nil { panic(err) } rec := &walpb.Record{Type: stateType, Data: b} return w.encoder.encode(rec) }
func (w *WAL) SaveState(s *raftpb.HardState) error { if raft.IsEmptyHardState(*s) { return nil } log.Printf("path=%s wal.saveState state=\"%+v\"", w.f.Name(), s) b, err := s.Marshal() if err != nil { panic(err) } rec := &walpb.Record{Type: stateType, Data: b} return w.encoder.encode(rec) }
// 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") }