From 684ebd95ae46b7d11dbe4b52dd175a556d906978 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Sun, 29 Mar 2015 15:42:59 -0700 Subject: [PATCH] wal: backup broken wal before repairing --- wal/repair.go | 28 ++++++++++++++++++++++++---- wal/util.go | 11 ++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/wal/repair.go b/wal/repair.go index 846bb0127..0f2c70216 100644 --- a/wal/repair.go +++ b/wal/repair.go @@ -16,6 +16,7 @@ package wal import ( "io" + "log" "os" "path" @@ -30,6 +31,7 @@ func Repair(dirpath string) bool { if err != nil { return false } + defer f.Close() n := 0 rec := &walpb.Record{} @@ -45,12 +47,30 @@ func Repair(dirpath string) bool { case io.EOF: return true case io.ErrUnexpectedEOF: - err = f.Truncate(int64(n)) - if err != nil { + log.Printf("wal: repairing %v", f.Name()) + bf, bferr := os.Create(f.Name() + ".broken") + if bferr != nil { + log.Printf("wal: could not repair %v, failed to create backup file", f.Name()) return false } - err = f.Sync() - if err != nil { + defer bf.Close() + + if _, err = f.Seek(0, os.SEEK_SET); err != nil { + log.Printf("wal: could not repair %v, failed to read file", f.Name()) + return false + } + + if _, err = io.Copy(bf, f); err != nil { + log.Printf("wal: could not repair %v, failed to copy file", f.Name()) + return false + } + + if err = f.Truncate(int64(n)); err != nil { + log.Printf("wal: could not repair %v, failed to truncate file", f.Name()) + return false + } + if err = f.Sync(); err != nil { + log.Printf("wal: could not repair %v, failed to sync file", f.Name()) return false } return true diff --git a/wal/util.go b/wal/util.go index c80fbdef2..b8b292fe7 100644 --- a/wal/util.go +++ b/wal/util.go @@ -15,12 +15,18 @@ package wal import ( + "errors" "fmt" "log" + "strings" "github.com/coreos/etcd/pkg/fileutil" ) +var ( + badWalName = errors.New("bad wal name") +) + func Exist(dirpath string) bool { names, err := fileutil.ReadDir(dirpath) if err != nil { @@ -76,8 +82,11 @@ func checkWalNames(names []string) []string { } func parseWalName(str string) (seq, index uint64, err error) { + if !strings.HasSuffix(str, ".wal") { + return 0, 0, badWalName + } _, err = fmt.Sscanf(str, "%016x-%016x.wal", &seq, &index) - return + return seq, index, err } func walName(seq, index uint64) string {