Просмотр исходного кода

wal: backup broken wal before repairing

Xiang Li 10 лет назад
Родитель
Сommit
684ebd95ae
2 измененных файлов с 34 добавлено и 5 удалено
  1. 24 4
      wal/repair.go
  2. 10 1
      wal/util.go

+ 24 - 4
wal/repair.go

@@ -16,6 +16,7 @@ package wal
 
 
 import (
 import (
 	"io"
 	"io"
+	"log"
 	"os"
 	"os"
 	"path"
 	"path"
 
 
@@ -30,6 +31,7 @@ func Repair(dirpath string) bool {
 	if err != nil {
 	if err != nil {
 		return false
 		return false
 	}
 	}
+	defer f.Close()
 
 
 	n := 0
 	n := 0
 	rec := &walpb.Record{}
 	rec := &walpb.Record{}
@@ -45,12 +47,30 @@ func Repair(dirpath string) bool {
 		case io.EOF:
 		case io.EOF:
 			return true
 			return true
 		case io.ErrUnexpectedEOF:
 		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
 				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 false
 			}
 			}
 			return true
 			return true

+ 10 - 1
wal/util.go

@@ -15,12 +15,18 @@
 package wal
 package wal
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"log"
 	"log"
+	"strings"
 
 
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/fileutil"
 )
 )
 
 
+var (
+	badWalName = errors.New("bad wal name")
+)
+
 func Exist(dirpath string) bool {
 func Exist(dirpath string) bool {
 	names, err := fileutil.ReadDir(dirpath)
 	names, err := fileutil.ReadDir(dirpath)
 	if err != nil {
 	if err != nil {
@@ -76,8 +82,11 @@ func checkWalNames(names []string) []string {
 }
 }
 
 
 func parseWalName(str string) (seq, index uint64, err error) {
 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)
 	_, err = fmt.Sscanf(str, "%016x-%016x.wal", &seq, &index)
-	return
+	return seq, index, err
 }
 }
 
 
 func walName(seq, index uint64) string {
 func walName(seq, index uint64) string {