diff --git a/weed-fs/src/cmd/weed/command.go b/weed-fs/src/cmd/weed/command.go index aa59459bd..77adcac66 100644 --- a/weed-fs/src/cmd/weed/command.go +++ b/weed-fs/src/cmd/weed/command.go @@ -10,7 +10,7 @@ import ( type Command struct { // Run runs the command. // The args are the arguments after the command name. - Run func(cmd *Command, args []string) + Run func(cmd *Command, args []string) bool // UsageLine is the one-line usage message. // The first word in the line is taken to be the command name. @@ -25,9 +25,6 @@ type Command struct { // Flag is a set of flags specific to this command. Flag flag.FlagSet - // CustomFlags indicates that the command will do its own - // flag parsing. - CustomFlags bool } // Name returns the command's name: the first word in the usage line. @@ -41,8 +38,8 @@ func (c *Command) Name() string { } func (c *Command) Usage() { - fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine) - fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long)) + fmt.Fprintf(os.Stderr, "Usage: %s\n", c.UsageLine) + fmt.Fprintf(os.Stderr, " %s\n", strings.TrimSpace(c.Long)) os.Exit(2) } diff --git a/weed-fs/src/cmd/weed/fix.go b/weed-fs/src/cmd/weed/fix.go new file mode 100644 index 000000000..e1d5da02d --- /dev/null +++ b/weed-fs/src/cmd/weed/fix.go @@ -0,0 +1,69 @@ +package main + +import ( + "pkg/storage" + "log" + "os" + "path" + "strconv" +) + +func init() { + cmdFix.Run = runFix // break init cycle +} + +var cmdFix = &Command{ + UsageLine: "fix -dir=/tmp -volumeId=234 -debug=1", + Short: "run weed tool fix on data file if corrupted", + Long: `Fix runs the WeedFS fix command on the .dat volume file. + + `, +} + +var ( + dir = cmdFix.Flag.String("dir", "/tmp", "data directory to store files") + volumeId = cmdFix.Flag.Int("volumeId", -1, "a non-negative volume id. The volume should already exist in the dir. The volume index file should not exist.") + IsDebug = cmdFix.Flag.Bool("debug", false, "enable debug mode") + + store *storage.Store +) + +func runFix(cmd *Command, args []string) bool { + + if *volumeId == -1 { + return false + } + + fileName := strconv.Itoa(*volumeId) + dataFile, e := os.OpenFile(path.Join(*dir, fileName+".dat"), os.O_RDONLY, 0644) + if e != nil { + log.Fatalf("Read Volume [ERROR] %s\n", e) + } + defer dataFile.Close() + indexFile, ie := os.OpenFile(path.Join(*dir, fileName+".idx"), os.O_WRONLY|os.O_CREATE, 0644) + if ie != nil { + log.Fatalf("Create Volume Index [ERROR] %s\n", ie) + } + defer indexFile.Close() + + //skip the volume super block + dataFile.Seek(storage.SuperBlockSize, 0) + + n, length := storage.ReadNeedle(dataFile) + nm := storage.NewNeedleMap(indexFile) + offset := uint32(storage.SuperBlockSize) + for n != nil { + if *IsDebug { + log.Println("key", n.Key, "volume offset", offset, "data_size", n.Size, "length", length) + } + if n.Size > 0 { + count, pe := nm.Put(n.Key, offset/8, n.Size) + if *IsDebug { + log.Println("saved", count, "with error", pe) + } + } + offset += length + n, length = storage.ReadNeedle(dataFile) + } + return true +} diff --git a/weed-fs/src/cmd/weed/version.go b/weed-fs/src/cmd/weed/version.go index a04dd79f4..61b66835f 100644 --- a/weed-fs/src/cmd/weed/version.go +++ b/weed-fs/src/cmd/weed/version.go @@ -1,7 +1,3 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - package main import ( @@ -16,10 +12,11 @@ var cmdVersion = &Command{ Long: `Version prints the Weed File System version`, } -func runVersion(cmd *Command, args []string) { +func runVersion(cmd *Command, args []string) bool{ if len(args) != 0 { cmd.Usage() } fmt.Printf("version 0.15 %s %s\n",runtime.GOOS, runtime.GOARCH) + return true } diff --git a/weed-fs/src/cmd/weed/weed.go b/weed-fs/src/cmd/weed/weed.go index 06668f448..b9122d8e6 100644 --- a/weed-fs/src/cmd/weed/weed.go +++ b/weed-fs/src/cmd/weed/weed.go @@ -14,6 +14,7 @@ import ( ) var commands = []*Command{ + cmdFix, cmdVersion, } @@ -46,13 +47,14 @@ func main() { for _, cmd := range commands { if cmd.Name() == args[0] && cmd.Run != nil { cmd.Flag.Usage = func() { cmd.Usage() } - if cmd.CustomFlags { - args = args[1:] - } else { - cmd.Flag.Parse(args[1:]) - args = cmd.Flag.Args() + cmd.Flag.Parse(args[1:]) + args = cmd.Flag.Args() + if !cmd.Run(cmd, args) { + fmt.Fprintf(os.Stderr, "Default Parameters:\n") + cmd.Flag.PrintDefaults() + fmt.Fprintf(os.Stderr, "\n") + cmd.Flag.Usage() } - cmd.Run(cmd, args) exit() return } @@ -63,7 +65,7 @@ func main() { exit() } -var usageTemplate = `Go is a tool for managing Go source code. +var usageTemplate = `WeedFS is a software to store billions of files and serve them fast! Usage: @@ -83,9 +85,9 @@ Use "weed help [topic]" for more information about that topic. ` -var helpTemplate = `{{if .Runnable}}usage: weed {{.UsageLine}} - -{{end}}{{.Long | trim}} +var helpTemplate = `{{if .Runnable}}Usage: weed {{.UsageLine}} +{{end}} + {{.Long}} ` // tmpl executes the given template text on data, writing the result to w. @@ -154,16 +156,6 @@ func exit() { os.Exit(exitStatus) } -func fatalf(format string, args ...interface{}) { - errorf(format, args...) - exit() -} - -func errorf(format string, args ...interface{}) { - log.Printf(format, args...) - setExitStatus(1) -} - var logf = log.Printf func exitIfErrors() { @@ -171,20 +163,3 @@ func exitIfErrors() { exit() } } - -// stringList's arguments should be a sequence of string or []string values. -// stringList flattens them into a single []string. -func stringList(args ...interface{}) []string { - var x []string - for _, arg := range args { - switch arg := arg.(type) { - case []string: - x = append(x, arg...) - case string: - x = append(x, arg) - default: - panic("stringList: invalid argument") - } - } - return x -}