mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
wal: save latest state into new WAL
So we could always read out state when open at valid index.
This commit is contained in:
parent
23b32a6cbe
commit
af0f34c595
11
wal/wal.go
11
wal/wal.go
@ -56,8 +56,9 @@ var (
|
|||||||
// A just opened WAL is in read mode, and ready for reading records.
|
// A just opened WAL is in read mode, and ready for reading records.
|
||||||
// The WAL will be ready for appending after reading out all the previous records.
|
// The WAL will be ready for appending after reading out all the previous records.
|
||||||
type WAL struct {
|
type WAL struct {
|
||||||
dir string // the living directory of the underlay files
|
dir string // the living directory of the underlay files
|
||||||
metadata []byte // metadata recorded at the head of each WAL
|
metadata []byte // metadata recorded at the head of each WAL
|
||||||
|
state raftpb.HardState // hardstate recorded at the head of WAL
|
||||||
|
|
||||||
ri uint64 // index of entry to start reading
|
ri uint64 // index of entry to start reading
|
||||||
decoder *decoder // decoder to decode records
|
decoder *decoder // decoder to decode records
|
||||||
@ -236,7 +237,10 @@ func (w *WAL) Cut() error {
|
|||||||
if err := w.saveCrc(prevCrc); err != nil {
|
if err := w.saveCrc(prevCrc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return w.encoder.encode(&walpb.Record{Type: metadataType, Data: w.metadata})
|
if err := w.encoder.encode(&walpb.Record{Type: metadataType, Data: w.metadata}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return w.SaveState(&w.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WAL) sync() error {
|
func (w *WAL) sync() error {
|
||||||
@ -274,6 +278,7 @@ func (w *WAL) SaveState(s *raftpb.HardState) error {
|
|||||||
if raft.IsEmptyHardState(*s) {
|
if raft.IsEmptyHardState(*s) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
w.state = *s
|
||||||
b := pbutil.MustMarshal(s)
|
b := pbutil.MustMarshal(s)
|
||||||
rec := &walpb.Record{Type: stateType, Data: b}
|
rec := &walpb.Record{Type: stateType, Data: b}
|
||||||
return w.encoder.encode(rec)
|
return w.encoder.encode(rec)
|
||||||
|
@ -142,12 +142,15 @@ func TestCut(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer w.Close()
|
|
||||||
|
|
||||||
// TODO(unihorn): remove this when cut can operate on an empty file
|
// TODO(unihorn): remove this when cut can operate on an empty file
|
||||||
if err := w.SaveEntry(&raftpb.Entry{}); err != nil {
|
if err := w.SaveEntry(&raftpb.Entry{}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
state := raftpb.HardState{Term: 1}
|
||||||
|
if err := w.SaveState(&state); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
if err := w.Cut(); err != nil {
|
if err := w.Cut(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -167,6 +170,25 @@ func TestCut(t *testing.T) {
|
|||||||
if g := path.Base(w.f.Name()); g != wname {
|
if g := path.Base(w.f.Name()); g != wname {
|
||||||
t.Errorf("name = %s, want %s", g, wname)
|
t.Errorf("name = %s, want %s", g, wname)
|
||||||
}
|
}
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
// check the state in the last WAL
|
||||||
|
f, err := os.Open(path.Join(p, wname))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
w = &WAL{
|
||||||
|
decoder: newDecoder(f),
|
||||||
|
ri: 2,
|
||||||
|
}
|
||||||
|
_, gst, _, err := w.ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(gst, state) {
|
||||||
|
t.Errorf("state = %+v, want %+v", gst, state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecover(t *testing.T) {
|
func TestRecover(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user