Browse Source

Merge branch 'master' of https://github.com/chrislusf/seaweedfs

pull/2579/head
chrislu 3 years ago
parent
commit
1a7d5b5b5e
  1. 99
      weed/command/fix.go

99
weed/command/fix.go

@ -2,7 +2,7 @@ package command
import ( import (
"fmt" "fmt"
"io/ioutil"
"io/fs"
"os" "os"
"path" "path"
"strconv" "strconv"
@ -22,17 +22,15 @@ func init() {
} }
var cmdFix = &Command{ var cmdFix = &Command{
UsageLine: "fix -dir=/tmp -volumeId=234",
Short: "run weed tool fix on index file if corrupted",
Long: `Fix runs the SeaweedFS fix command to re-create the index .idx file.
UsageLine: "fix [-volumeId=234] [-collection=bigData] /tmp",
Short: "run weed tool fix on files or whole folders to recreate index file(s) if corrupted",
Long: `Fix runs the SeaweedFS fix command on dat files or whole folders to re-create the index .idx file.
`, `,
} }
var ( var (
fixVolumePath = cmdFix.Flag.String("dir", ".", "data directory to store files")
fixVolumeCollection = cmdFix.Flag.String("collection", "", "the volume collection name")
fixVolumeId = cmdFix.Flag.Int("volumeId", 0, "an optional volume id.")
fixVolumeCollection = cmdFix.Flag.String("collection", "", "an optional volume collection name, if specified only it will be processed")
fixVolumeId = cmdFix.Flag.Int64("volumeId", 0, "an optional volume id, if not 0 (default) only it will be processed")
) )
type VolumeFileScanner4Fix struct { type VolumeFileScanner4Fix struct {
@ -62,63 +60,68 @@ func (scanner *VolumeFileScanner4Fix) VisitNeedle(n *needle.Needle, offset int64
} }
func runFix(cmd *Command, args []string) bool { func runFix(cmd *Command, args []string) bool {
dir := util.ResolvePath(*fixVolumePath)
if *fixVolumeId != 0 {
doFixOneVolume(dir, *fixVolumeCollection, needle.VolumeId(*fixVolumeId))
return true
}
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Println(err)
return false
}
for _, file := range files {
if !strings.HasSuffix(file.Name(), ".dat") {
continue
for _, arg := range args {
basePath, f := path.Split(util.ResolvePath(arg))
files := []fs.DirEntry{}
if f == "" {
fileInfo, err := os.ReadDir(basePath)
if err != nil {
fmt.Println(err)
return false
}
files = fileInfo
} else {
fileInfo, err := os.Stat(basePath + f)
if err != nil {
fmt.Println(err)
return false
}
files = []fs.DirEntry{fs.FileInfoToDirEntry(fileInfo)}
} }
if *fixVolumeCollection != "" {
if !strings.HasPrefix(file.Name(), *fixVolumeCollection+"_") {
for _, file := range files {
if !strings.HasSuffix(file.Name(), ".dat") {
continue continue
} }
if *fixVolumeCollection != "" {
if !strings.HasPrefix(file.Name(), *fixVolumeCollection+"_") {
continue
}
}
baseFileName := file.Name()[:len(file.Name())-4]
collection, volumeIdStr := "", baseFileName
if sepIndex := strings.LastIndex(baseFileName, "_"); sepIndex > 0 {
collection = baseFileName[:sepIndex]
volumeIdStr = baseFileName[sepIndex+1:]
}
volumeId, parseErr := strconv.ParseInt(volumeIdStr, 10, 64)
if parseErr != nil {
fmt.Printf("Failed to parse volume id from %s: %v\n", baseFileName, parseErr)
return false
}
if *fixVolumeId != 0 && *fixVolumeId != volumeId {
continue
}
doFixOneVolume(basePath, baseFileName, collection, volumeId)
} }
baseFileName := file.Name()[:len(file.Name())-4]
collection, volumeIdStr := "", baseFileName
if sepIndex := strings.LastIndex(baseFileName, "_"); sepIndex > 0 {
collection = baseFileName[:sepIndex]
volumeIdStr = baseFileName[sepIndex+1:]
}
volumeId, parseErr := strconv.ParseInt(volumeIdStr, 10, 64)
if parseErr != nil {
fmt.Printf("Failed to parse volume id from %s: %v\n", baseFileName, parseErr)
return false
}
doFixOneVolume(dir, collection, needle.VolumeId(volumeId))
} }
return true return true
} }
func doFixOneVolume(dir, collection string, volumeId needle.VolumeId) {
baseFileName := strconv.Itoa(int(volumeId))
if collection != "" {
baseFileName = collection + "_" + baseFileName
}
func doFixOneVolume(basepath string, baseFileName string, collection string, volumeId int64) {
indexFileName := path.Join(dir, baseFileName+".idx")
indexFileName := path.Join(basepath, baseFileName+".idx")
nm := needle_map.NewMemDb() nm := needle_map.NewMemDb()
defer nm.Close() defer nm.Close()
vid := needle.VolumeId(*fixVolumeId)
vid := needle.VolumeId(volumeId)
scanner := &VolumeFileScanner4Fix{ scanner := &VolumeFileScanner4Fix{
nm: nm, nm: nm,
} }
if err := storage.ScanVolumeFile(dir, collection, vid, storage.NeedleMapInMemory, scanner); err != nil {
if err := storage.ScanVolumeFile(basepath, collection, vid, storage.NeedleMapInMemory, scanner); err != nil {
glog.Fatalf("scan .dat File: %v", err) glog.Fatalf("scan .dat File: %v", err)
os.Remove(indexFileName) os.Remove(indexFileName)
} }

Loading…
Cancel
Save