提交 13f617d1 作者: Kevin Atkinson

filestore util: allow listing/verifying of individual blocks.

License: MIT
Signed-off-by: 's avatarKevin Atkinson <k@kevina.org>
上级 4bf43047
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/filestore" "github.com/ipfs/go-ipfs/filestore"
u "gx/ipfs/QmZuY8aV7zbNXVy6DyN9SmnuH3o9nG852F4aTiSBpts8d1/go-ipfs-util" u "gx/ipfs/QmZuY8aV7zbNXVy6DyN9SmnuH3o9nG852F4aTiSBpts8d1/go-ipfs-util"
cid "gx/ipfs/QmV5gPoRsjN1Gid3LMdNZTyfCtP2DsvqEbMAmz82RmmiGk/go-cid"
) )
var FileStoreCmd = &cmds.Command{ var FileStoreCmd = &cmds.Command{
...@@ -24,19 +25,30 @@ var lsFileStore = &cmds.Command{ ...@@ -24,19 +25,30 @@ var lsFileStore = &cmds.Command{
Helptext: cmds.HelpText{ Helptext: cmds.HelpText{
Tagline: "List objects in filestore.", Tagline: "List objects in filestore.",
}, },
Arguments: []cmds.Argument{
cmds.StringArg("obj", false, true, "Cid of objects to list."),
},
Run: func(req cmds.Request, res cmds.Response) { Run: func(req cmds.Request, res cmds.Response) {
_, fs, err := getFilestore(req) _, fs, err := getFilestore(req)
if err != nil { if err != nil {
res.SetError(err, cmds.ErrNormal) res.SetError(err, cmds.ErrNormal)
return return
} }
next, err := filestore.ListAll(fs) args := req.Arguments()
if err != nil { if len(args) > 0 {
res.SetError(err, cmds.ErrNormal) out := perKeyActionToChan(args, func(c *cid.Cid) *filestore.ListRes {
return return filestore.List(fs, c)
}, req.Context())
res.SetOutput(out)
} else {
next, err := filestore.ListAll(fs)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
out := listResToChan(next, req.Context())
res.SetOutput(out)
} }
out := listResAsChan(next, req.Context())
res.SetOutput(out)
}, },
PostRun: func(req cmds.Request, res cmds.Response) { PostRun: func(req cmds.Request, res cmds.Response) {
if res.Error() != nil { if res.Error() != nil {
...@@ -52,6 +64,7 @@ var lsFileStore = &cmds.Command{ ...@@ -52,6 +64,7 @@ var lsFileStore = &cmds.Command{
for r0 := range outChan { for r0 := range outChan {
r := r0.(*filestore.ListRes) r := r0.(*filestore.ListRes)
if r.ErrorMsg != "" { if r.ErrorMsg != "" {
errors = true
fmt.Fprintf(res.Stderr(), "%s\n", r.ErrorMsg) fmt.Fprintf(res.Stderr(), "%s\n", r.ErrorMsg)
} else { } else {
fmt.Fprintf(res.Stdout(), "%s\n", r.FormatLong()) fmt.Fprintf(res.Stdout(), "%s\n", r.FormatLong())
...@@ -68,19 +81,30 @@ var verifyFileStore = &cmds.Command{ ...@@ -68,19 +81,30 @@ var verifyFileStore = &cmds.Command{
Helptext: cmds.HelpText{ Helptext: cmds.HelpText{
Tagline: "Verify objects in filestore.", Tagline: "Verify objects in filestore.",
}, },
Arguments: []cmds.Argument{
cmds.StringArg("obj", false, true, "Cid of objects to verify."),
},
Run: func(req cmds.Request, res cmds.Response) { Run: func(req cmds.Request, res cmds.Response) {
_, fs, err := getFilestore(req) _, fs, err := getFilestore(req)
if err != nil { if err != nil {
res.SetError(err, cmds.ErrNormal) res.SetError(err, cmds.ErrNormal)
return return
} }
next, err := filestore.VerifyAll(fs) args := req.Arguments()
if err != nil { if len(args) > 0 {
res.SetError(err, cmds.ErrNormal) out := perKeyActionToChan(args, func(c *cid.Cid) *filestore.ListRes {
return return filestore.Verify(fs, c)
}, req.Context())
res.SetOutput(out)
} else {
next, err := filestore.VerifyAll(fs)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
out := listResToChan(next, req.Context())
res.SetOutput(out)
} }
out := listResAsChan(next, req.Context())
res.SetOutput(out)
}, },
PostRun: func(req cmds.Request, res cmds.Response) { PostRun: func(req cmds.Request, res cmds.Response) {
if res.Error() != nil { if res.Error() != nil {
...@@ -94,6 +118,9 @@ var verifyFileStore = &cmds.Command{ ...@@ -94,6 +118,9 @@ var verifyFileStore = &cmds.Command{
res.SetOutput(nil) res.SetOutput(nil)
for r0 := range outChan { for r0 := range outChan {
r := r0.(*filestore.ListRes) r := r0.(*filestore.ListRes)
if r.Status == filestore.StatusOtherError {
fmt.Fprintf(res.Stderr(), "%s\n", r.ErrorMsg)
}
fmt.Fprintf(res.Stdout(), "%s %s\n", r.Status.Format(), r.FormatLong()) fmt.Fprintf(res.Stdout(), "%s %s\n", r.Status.Format(), r.FormatLong())
} }
}, },
...@@ -112,7 +139,7 @@ func getFilestore(req cmds.Request) (*core.IpfsNode, *filestore.Filestore, error ...@@ -112,7 +139,7 @@ func getFilestore(req cmds.Request) (*core.IpfsNode, *filestore.Filestore, error
return n, fs, err return n, fs, err
} }
func listResAsChan(next func() *filestore.ListRes, ctx context.Context) <-chan interface{} { func listResToChan(next func() *filestore.ListRes, ctx context.Context) <-chan interface{} {
out := make(chan interface{}, 128) out := make(chan interface{}, 128)
go func() { go func() {
defer close(out) defer close(out)
...@@ -130,3 +157,27 @@ func listResAsChan(next func() *filestore.ListRes, ctx context.Context) <-chan i ...@@ -130,3 +157,27 @@ func listResAsChan(next func() *filestore.ListRes, ctx context.Context) <-chan i
}() }()
return out return out
} }
func perKeyActionToChan(args []string, action func(*cid.Cid) *filestore.ListRes, ctx context.Context) <-chan interface{} {
out := make(chan interface{}, 128)
go func() {
defer close(out)
for _, arg := range args {
c, err := cid.Decode(arg)
if err != nil {
out <- &filestore.ListRes{
Status: filestore.StatusOtherError,
ErrorMsg: fmt.Sprintf("%s: %v", arg, err),
}
continue
}
r := action(c)
select {
case out <- r:
case <-ctx.Done():
return
}
}
}()
return out
}
...@@ -3,6 +3,7 @@ package filestore ...@@ -3,6 +3,7 @@ package filestore
import ( import (
"fmt" "fmt"
"github.com/ipfs/go-ipfs/blocks/blockstore"
pb "github.com/ipfs/go-ipfs/filestore/pb" pb "github.com/ipfs/go-ipfs/filestore/pb"
dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help" dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help"
...@@ -19,7 +20,8 @@ const ( ...@@ -19,7 +20,8 @@ const (
StatusFileError Status = 10 // Backing File Error StatusFileError Status = 10 // Backing File Error
//StatusFileNotFound Status = 11 // Backing File Not Found //StatusFileNotFound Status = 11 // Backing File Not Found
//StatusFileChanged Status = 12 // Contents of the file changed //StatusFileChanged Status = 12 // Contents of the file changed
StatusOtherError Status = 20 // Internal Error, likely corrupt entry StatusOtherError Status = 20 // Internal Error, likely corrupt entry
StatusKeyNotFound Status = 30
) )
func (s Status) String() string { func (s Status) String() string {
...@@ -30,13 +32,15 @@ func (s Status) String() string { ...@@ -30,13 +32,15 @@ func (s Status) String() string {
return "error" return "error"
case StatusOtherError: case StatusOtherError:
return "ERROR" return "ERROR"
case StatusKeyNotFound:
return "missing"
default: default:
return "???" return "???"
} }
} }
func (s Status) Format() string { func (s Status) Format() string {
return fmt.Sprintf("%-5s", s.String()) return fmt.Sprintf("%-7s", s.String())
} }
type ListRes struct { type ListRes struct {
...@@ -52,19 +56,40 @@ func (r *ListRes) FormatLong() string { ...@@ -52,19 +56,40 @@ func (r *ListRes) FormatLong() string {
switch { switch {
case r.Key == nil: case r.Key == nil:
return "?????????????????????????????????????????????????" return "?????????????????????????????????????????????????"
case r.FilePath == "":
return r.Key.String()
default: default:
return fmt.Sprintf("%-50s %6d %s %d", r.Key, r.Size, r.FilePath, r.Offset) return fmt.Sprintf("%-50s %6d %s %d", r.Key, r.Size, r.FilePath, r.Offset)
} }
} }
func List(fs *Filestore, key *cid.Cid) *ListRes {
return list(fs, false, key)
}
func ListAll(fs *Filestore) (func() *ListRes, error) { func ListAll(fs *Filestore) (func() *ListRes, error) {
return listAll(fs, false) return listAll(fs, false)
} }
func Verify(fs *Filestore, key *cid.Cid) *ListRes {
return list(fs, true, key)
}
func VerifyAll(fs *Filestore) (func() *ListRes, error) { func VerifyAll(fs *Filestore) (func() *ListRes, error) {
return listAll(fs, true) return listAll(fs, true)
} }
func list(fs *Filestore, verify bool, key *cid.Cid) *ListRes {
dobj, err := fs.fm.getDataObj(key)
if err != nil {
return mkListRes(key, nil, err)
}
if verify {
_, err = fs.fm.readDataObj(key, dobj)
}
return mkListRes(key, dobj, err)
}
func listAll(fs *Filestore, verify bool) (func() *ListRes, error) { func listAll(fs *Filestore, verify bool) (func() *ListRes, error) {
q := dsq.Query{} q := dsq.Query{}
qr, err := fs.fm.ds.Query(q) qr, err := fs.fm.ds.Query(q)
...@@ -112,7 +137,9 @@ func mkListRes(c *cid.Cid, d *pb.DataObj, err error) *ListRes { ...@@ -112,7 +137,9 @@ func mkListRes(c *cid.Cid, d *pb.DataObj, err error) *ListRes {
status := StatusOk status := StatusOk
errorMsg := "" errorMsg := ""
if err != nil { if err != nil {
if _, ok := err.(*CorruptReferenceError); ok { if err == ds.ErrNotFound || err == blockstore.ErrNotFound {
status = StatusKeyNotFound
} else if _, ok := err.(*CorruptReferenceError); ok {
status = StatusFileError status = StatusFileError
} else { } else {
status = StatusOtherError status = StatusOtherError
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论