cmd: add stat-obj
This commit is contained in:
parent
61802b9d42
commit
7628a64a55
@ -43,6 +43,7 @@ type FullNode interface {
|
|||||||
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
|
ChainStatObj(context.Context, cid.Cid, cid.Cid) (ObjStat, error)
|
||||||
ChainSetHead(context.Context, types.TipSetKey) error
|
ChainSetHead(context.Context, types.TipSetKey) error
|
||||||
ChainGetGenesis(context.Context) (*types.TipSet, error)
|
ChainGetGenesis(context.Context) (*types.TipSet, error)
|
||||||
ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error)
|
ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error)
|
||||||
|
@ -60,6 +60,7 @@ type FullNodeStruct struct {
|
|||||||
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||||
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
|
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
|
||||||
|
ChainStatObj func(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) `perm:"read"`
|
||||||
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
|
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
|
||||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||||
ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
@ -380,6 +381,10 @@ func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, erro
|
|||||||
return c.Internal.ChainHasObj(ctx, o)
|
return c.Internal.ChainHasObj(ctx, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) ChainStatObj(ctx context.Context, obj, base cid.Cid) (api.ObjStat, error) {
|
||||||
|
return c.Internal.ChainStatObj(ctx, obj, base)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
|
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
|
||||||
return c.Internal.ChainSetHead(ctx, tsk)
|
return c.Internal.ChainSetHead(ctx, tsk)
|
||||||
}
|
}
|
||||||
|
@ -27,3 +27,8 @@ func (m *MultiaddrSlice) UnmarshalJSON(raw []byte) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _ json.Unmarshaler = new(MultiaddrSlice)
|
var _ json.Unmarshaler = new(MultiaddrSlice)
|
||||||
|
|
||||||
|
type ObjStat struct {
|
||||||
|
Size uint64
|
||||||
|
Links uint64
|
||||||
|
}
|
||||||
|
46
cli/chain.go
46
cli/chain.go
@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/go-units"
|
||||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
@ -31,6 +32,7 @@ var chainCmd = &cli.Command{
|
|||||||
chainHeadCmd,
|
chainHeadCmd,
|
||||||
chainGetBlock,
|
chainGetBlock,
|
||||||
chainReadObjCmd,
|
chainReadObjCmd,
|
||||||
|
chainStatObjCmd,
|
||||||
chainGetMsgCmd,
|
chainGetMsgCmd,
|
||||||
chainSetHeadCmd,
|
chainSetHeadCmd,
|
||||||
chainListCmd,
|
chainListCmd,
|
||||||
@ -182,6 +184,50 @@ var chainReadObjCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var chainStatObjCmd = &cli.Command{
|
||||||
|
Name: "stat-obj",
|
||||||
|
Usage: "Collect size and ipld link counts for objs",
|
||||||
|
ArgsUsage: "[cid]",
|
||||||
|
Description: `Collect object size and ipld link count for an object.
|
||||||
|
|
||||||
|
When a base is provided it will be walked first, and all links visisted
|
||||||
|
will be ignored when the passed in object is walked.
|
||||||
|
`,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "base",
|
||||||
|
Usage: "ignore links found in this obj",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
obj, err := cid.Decode(cctx.Args().First())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse cid input: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
base := cid.Undef
|
||||||
|
if cctx.IsSet("base") {
|
||||||
|
base, err = cid.Decode(cctx.String("base"))
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, err := api.ChainStatObj(ctx, obj, base)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Links: %d\n", stats.Links)
|
||||||
|
fmt.Printf("Size: %s (%d)\n", units.BytesSize(float64(stats.Size)), stats.Size)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var chainGetMsgCmd = &cli.Command{
|
var chainGetMsgCmd = &cli.Command{
|
||||||
Name: "getmessage",
|
Name: "getmessage",
|
||||||
Usage: "Get and print a message by its cid",
|
Usage: "Get and print a message by its cid",
|
||||||
|
@ -6,8 +6,10 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||||
|
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||||
"github.com/ipfs/go-blockservice"
|
"github.com/ipfs/go-blockservice"
|
||||||
@ -185,6 +187,54 @@ func (a *ChainAPI) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) {
|
|||||||
return a.Chain.Blockstore().Has(obj)
|
return a.Chain.Blockstore().Has(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ChainAPI) ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (api.ObjStat, error) {
|
||||||
|
bs := a.Chain.Blockstore()
|
||||||
|
bsvc := blockservice.New(bs, offline.Exchange(bs))
|
||||||
|
|
||||||
|
dag := merkledag.NewDAGService(bsvc)
|
||||||
|
|
||||||
|
seen := cid.NewSet()
|
||||||
|
|
||||||
|
var statslk sync.Mutex
|
||||||
|
var stats api.ObjStat
|
||||||
|
var collect = true
|
||||||
|
|
||||||
|
walker := func(ctx context.Context, c cid.Cid) ([]*ipld.Link, error) {
|
||||||
|
if c.Prefix().MhType == uint64(commcid.FC_SEALED_V1) || c.Prefix().MhType == uint64(commcid.FC_UNSEALED_V1) {
|
||||||
|
return []*ipld.Link{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nd, err := dag.Get(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if collect {
|
||||||
|
s := uint64(len(nd.RawData()))
|
||||||
|
statslk.Lock()
|
||||||
|
stats.Size = stats.Size + s
|
||||||
|
stats.Links = stats.Links + 1
|
||||||
|
statslk.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nd.Links(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if base != cid.Undef {
|
||||||
|
collect = false
|
||||||
|
if err := merkledag.Walk(ctx, walker, base, seen.Visit, merkledag.Concurrent()); err != nil {
|
||||||
|
return api.ObjStat{}, err
|
||||||
|
}
|
||||||
|
collect = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := merkledag.Walk(ctx, walker, obj, seen.Visit, merkledag.Concurrent()); err != nil {
|
||||||
|
return api.ObjStat{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ChainAPI) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
|
func (a *ChainAPI) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user