From 433b4138c5c165d55c6dcf66f34797797b73bdbb Mon Sep 17 00:00:00 2001 From: Yicheng Qin Date: Wed, 29 Oct 2014 10:42:21 -0700 Subject: [PATCH] etcdserver: panic on storage error It is a critical error to etcd, and etcd is not able to recover it now. --- etcdserver/server.go | 16 +++++++++++----- etcdserver/server_test.go | 11 ++++++----- snap/snapshotter.go | 6 +++--- wal/wal.go | 14 +++++++++----- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/etcdserver/server.go b/etcdserver/server.go index f140fd202..a1f1ec4ec 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -89,9 +89,9 @@ type Response struct { type Storage interface { // Save function saves ents and state to the underlying stable storage. // Save MUST block until st and ents are on stable storage. - Save(st raftpb.HardState, ents []raftpb.Entry) + Save(st raftpb.HardState, ents []raftpb.Entry) error // SaveSnap function saves snapshot to the underlying stable storage. - SaveSnap(snap raftpb.Snapshot) + SaveSnap(snap raftpb.Snapshot) error // TODO: WAL should be able to control cut itself. After implement self-controled cut, // remove it in this interface. @@ -315,8 +315,12 @@ func (s *EtcdServer) run() { } } - s.storage.Save(rd.HardState, rd.Entries) - s.storage.SaveSnap(rd.Snapshot) + if err := s.storage.Save(rd.HardState, rd.Entries); err != nil { + log.Panicf("etcdserver: save state and entries error: %v", err) + } + if err := s.storage.SaveSnap(rd.Snapshot); err != nil { + log.Panicf("etcdserver: create snapshot error: %v", err) + } s.send(rd.Messages) // TODO(bmizerany): do this in the background, but take @@ -673,7 +677,9 @@ func (s *EtcdServer) snapshot(snapi uint64, snapnodes []uint64) { panic("TODO: this is bad, what do we do about it?") } s.node.Compact(snapi, snapnodes, d) - s.storage.Cut() + if err := s.storage.Cut(); err != nil { + log.Panicf("etcdserver: rotate wal file error: %v", err) + } } func GetClusterFromPeers(urls []string) (*Cluster, error) { diff --git a/etcdserver/server_test.go b/etcdserver/server_test.go index 6693d4f4e..d9486e384 100644 --- a/etcdserver/server_test.go +++ b/etcdserver/server_test.go @@ -1221,18 +1221,19 @@ type storageRecorder struct { recorder } -func (p *storageRecorder) Save(st raftpb.HardState, ents []raftpb.Entry) { +func (p *storageRecorder) Save(st raftpb.HardState, ents []raftpb.Entry) error { p.record(action{name: "Save"}) + return nil } func (p *storageRecorder) Cut() error { p.record(action{name: "Cut"}) return nil } -func (p *storageRecorder) SaveSnap(st raftpb.Snapshot) { - if raft.IsEmptySnap(st) { - return +func (p *storageRecorder) SaveSnap(st raftpb.Snapshot) error { + if !raft.IsEmptySnap(st) { + p.record(action{name: "SaveSnap"}) } - p.record(action{name: "SaveSnap"}) + return nil } type readyNode struct { diff --git a/snap/snapshotter.go b/snap/snapshotter.go index 32d90a635..2aa5d4fc9 100644 --- a/snap/snapshotter.go +++ b/snap/snapshotter.go @@ -52,11 +52,11 @@ func New(dir string) *Snapshotter { } } -func (s *Snapshotter) SaveSnap(snapshot raftpb.Snapshot) { +func (s *Snapshotter) SaveSnap(snapshot raftpb.Snapshot) error { if raft.IsEmptySnap(snapshot) { - return + return nil } - s.save(&snapshot) + return s.save(&snapshot) } func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error { diff --git a/wal/wal.go b/wal/wal.go index 2655823ee..0051b8b09 100644 --- a/wal/wal.go +++ b/wal/wal.go @@ -273,13 +273,17 @@ func (w *WAL) SaveState(s *raftpb.HardState) error { return w.encoder.encode(rec) } -func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) { +func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) error { // TODO(xiangli): no more reference operator - w.SaveState(&st) - for i := range ents { - w.SaveEntry(&ents[i]) + if err := w.SaveState(&st); err != nil { + return err } - w.Sync() + for i := range ents { + if err := w.SaveEntry(&ents[i]); err != nil { + return err + } + } + return w.Sync() } func (w *WAL) saveCrc(prevCrc uint32) error {