diff --git a/docs/debugging/healing-bin/main.go b/docs/debugging/healing-bin/main.go new file mode 100644 index 000000000..be33071ea --- /dev/null +++ b/docs/debugging/healing-bin/main.go @@ -0,0 +1,136 @@ +// Copyright (c) 2015-2021 MinIO, Inc. +// +// This file is part of MinIO Object Storage stack +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package main + +import ( + "archive/zip" + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + + "github.com/minio/cli" + "github.com/tinylib/msgp/msgp" +) + +func main() { + app := cli.NewApp() + app.Copyright = "MinIO, Inc." + app.Usage = "healing.bin to JSON" + app.HideVersion = true + app.HideHelpCommand = true + app.CustomAppHelpTemplate = `NAME: + {{.Name}} - {{.Usage}} + +USAGE: + {{.Name}} {{if .VisibleFlags}}[FLAGS]{{end}} [HEALINGBINFILE|INSPECTZIPFILE] + +files ending in '.zip' will be searched for '.healing.bin files recursively and +printed together as a single JSON. + +FLAGS: + {{range .VisibleFlags}}{{.}} + {{end}} +` + app.Flags = []cli.Flag{} + app.Action = func(c *cli.Context) error { + if !c.Args().Present() { + cli.ShowAppHelpAndExit(c, 1) // last argument is exit code + } + + ht := make(map[string]map[string]interface{}) + file := c.Args().Get(0) + if strings.HasSuffix(file, ".zip") { + var sz int64 + f, err := os.Open(file) + if err != nil { + return err + } + if st, err := f.Stat(); err == nil { + sz = st.Size() + } + defer f.Close() + zr, err := zip.NewReader(f, sz) + if err != nil { + return err + } + for _, file := range zr.File { + if !file.FileInfo().IsDir() && strings.HasSuffix(file.Name, ".healing.bin") { + r, err := file.Open() + if err != nil { + return err + } + + b, err := ioutil.ReadAll(r) + if err != nil { + return err + } + buf := bytes.NewBuffer(nil) + if _, err = msgp.CopyToJSON(buf, bytes.NewReader(b)); err != nil { + return err + } + + dec := json.NewDecoder(buf) + // Use number to preserve integers. + dec.UseNumber() + var htr map[string]interface{} + if err = dec.Decode(&htr); err != nil { + return err + } + ht[file.Name] = htr + } + } + b, err := json.MarshalIndent(ht, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + return nil + } + b, err := ioutil.ReadFile(file) + if err != nil { + return err + } + buf := bytes.NewBuffer(nil) + if _, err = msgp.CopyToJSON(buf, bytes.NewReader(b)); err != nil { + return err + } + var htr map[string]interface{} + dec := json.NewDecoder(buf) + // Use number to preserve integers. + dec.UseNumber() + if err = dec.Decode(&htr); err != nil { + return err + } + ht[file] = htr + b, err = json.MarshalIndent(ht, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + return nil + } + + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} diff --git a/docs/debugging/xl-meta/main.go b/docs/debugging/xl-meta/main.go index 4a03cf9ff..8c5d6e8b8 100644 --- a/docs/debugging/xl-meta/main.go +++ b/docs/debugging/xl-meta/main.go @@ -46,35 +46,40 @@ func main() { USAGE: {{.Name}} {{if .VisibleFlags}}[FLAGS]{{end}} METAFILES... -Multiple files can be added. Files ending in ".zip" will be searched for 'xl.meta' files. -Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt -Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt -Double stars means full recursive. testdir/**/xl.meta will search for all xl.meta recursively. +Multiple files can be added. Files ending in '.zip' will be searched +for 'xl.meta' files. Wildcards are accepted: 'testdir/*.txt' will compress +all files in testdir ending with '.txt', directories can be wildcards +as well. 'testdir/*/*.txt' will match 'testdir/subdir/b.txt', double stars +means full recursive. 'testdir/**/xl.meta' will search for all xl.meta +recursively. -{{if .VisibleFlags}} -GLOBAL FLAGS: +FLAGS: {{range .VisibleFlags}}{{.}} - {{end}}{{end}} + {{end}} ` app.HideHelpCommand = true app.Flags = []cli.Flag{ cli.BoolFlag{ - Usage: "Print each file as a separate line without formatting", + Usage: "print each file as a separate line without formatting", Name: "ndjson", }, cli.BoolFlag{ - Usage: "Display inline data keys and sizes", + Usage: "display inline data keys and sizes", Name: "data", }, cli.BoolFlag{ - Usage: "Export inline data", + Usage: "export inline data", Name: "export", }, } app.Action = func(c *cli.Context) error { + if !c.Args().Present() { + cli.ShowAppHelpAndExit(c, 1) // last argument is exit code + } + ndjson := c.Bool("ndjson") decode := func(r io.Reader, file string) ([]byte, error) { b, err := ioutil.ReadAll(r) @@ -90,7 +95,7 @@ GLOBAL FLAGS: var data xlMetaInlineData switch minor { case 0: - _, err = msgp.CopyToJSON(buf, bytes.NewBuffer(b)) + _, err = msgp.CopyToJSON(buf, bytes.NewReader(b)) if err != nil { return nil, err } @@ -104,7 +109,7 @@ GLOBAL FLAGS: b = nbuf } - _, err = msgp.CopyToJSON(buf, bytes.NewBuffer(v)) + _, err = msgp.CopyToJSON(buf, bytes.NewReader(v)) if err != nil { return nil, err }