Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI tools for the DAGStore inverted index #7361

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion api/api_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,13 @@ type StorageMiner interface {

// IndexerAnnounceDeal informs indexer nodes that a new deal was received,
// so they can download its index
IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error
IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error //perm:admin

// DagstorePieceIndexSize returns the size of the piece index.
DagstorePieceIndexSize(ctx context.Context) (int64, error) //perm:admin

// DagstoreLookupPieces returns information about shards that contain the given CID.
DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]DagstoreShardInfo, error) //perm:admin

// RuntimeSubsystems returns the subsystems that are enabled
// in this instance.
Expand Down
28 changes: 27 additions & 1 deletion api/proxy_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified build/openrpc/full.json.gz
Binary file not shown.
Binary file modified build/openrpc/miner.json.gz
Binary file not shown.
Binary file modified build/openrpc/worker.json.gz
Binary file not shown.
148 changes: 116 additions & 32 deletions cmd/lotus-miner/dagstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"
"os"

"github.com/dustin/go-humanize"
"github.com/fatih/color"
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"

"github.com/filecoin-project/lotus/api"
Expand All @@ -21,6 +23,8 @@ var dagstoreCmd = &cli.Command{
dagstoreRecoverShardCmd,
dagstoreInitializeAllCmd,
dagstoreGcCmd,
dagstorePieceIndexSizeCmd,
dagstoreLookupPiecesCmd,
},
}

Expand Down Expand Up @@ -52,38 +56,7 @@ var dagstoreListShardsCmd = &cli.Command{
return err
}

if len(shards) == 0 {
return nil
}

tw := tablewriter.New(
tablewriter.Col("Key"),
tablewriter.Col("State"),
tablewriter.Col("Error"),
)

colors := map[string]color.Attribute{
"ShardStateAvailable": color.FgGreen,
"ShardStateServing": color.FgBlue,
"ShardStateErrored": color.FgRed,
"ShardStateNew": color.FgYellow,
}

for _, s := range shards {
m := map[string]interface{}{
"Key": s.Key,
"State": func() string {
if c, ok := colors[s.State]; ok {
return color.New(c).Sprint(s.State)
}
return s.State
}(),
"Error": s.Error,
}
tw.Write(m)
}

return tw.Flush(os.Stdout)
return printTableShards(shards)
},
}

Expand Down Expand Up @@ -265,3 +238,114 @@ var dagstoreGcCmd = &cli.Command{
return nil
},
}

func printTableShards(shards []api.DagstoreShardInfo) error {
if len(shards) == 0 {
return nil
}

tw := tablewriter.New(
tablewriter.Col("Key"),
tablewriter.Col("State"),
tablewriter.Col("Error"),
)

colors := map[string]color.Attribute{
"ShardStateAvailable": color.FgGreen,
"ShardStateServing": color.FgBlue,
"ShardStateErrored": color.FgRed,
"ShardStateNew": color.FgYellow,
}

for _, s := range shards {
m := map[string]interface{}{
"Key": s.Key,
"State": func() string {
if c, ok := colors[s.State]; ok {
return color.New(c).Sprint(s.State)
}
return s.State
}(),
"Error": s.Error,
}
tw.Write(m)
}
return tw.Flush(os.Stdout)
}

var dagstorePieceIndexSizeCmd = &cli.Command{
Name: "piece-index-size",
Usage: "Inspect the dagstore piece index size",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}

marketsApi, closer, err := lcli.GetMarketsAPI(cctx)
if err != nil {
return err
}
defer closer()

ctx := lcli.ReqContext(cctx)

size, err := marketsApi.DagstorePieceIndexSize(ctx)
if err != nil {
return err
}

fmt.Println(humanize.Bytes(uint64(size)))

return nil
},
}

var dagstoreLookupPiecesCmd = &cli.Command{
Name: "lookup-pieces",
Usage: "Lookup pieces that a given CID belongs to",
ArgsUsage: "<cid>",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}

if cctx.NArg() != 1 {
return fmt.Errorf("must provide a CID")
}

cidStr := cctx.Args().First()
cid, err := cid.Parse(cidStr)
if err != nil {
return fmt.Errorf("invalid CID: %w", err)
}

marketsApi, closer, err := lcli.GetMarketsAPI(cctx)
if err != nil {
return err
}
defer closer()

ctx := lcli.ReqContext(cctx)

shards, err := marketsApi.DagstoreLookupPieces(ctx, cid)
if err != nil {
return err
}

return printTableShards(shards)
},
}
31 changes: 30 additions & 1 deletion documentation/en/api-v0-methods-miner.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* [DagstoreInitializeAll](#DagstoreInitializeAll)
* [DagstoreInitializeShard](#DagstoreInitializeShard)
* [DagstoreListShards](#DagstoreListShards)
* [DagstoreLookupPieces](#DagstoreLookupPieces)
* [DagstorePieceIndexSize](#DagstorePieceIndexSize)
* [DagstoreRecoverShard](#DagstoreRecoverShard)
* [Deals](#Deals)
* [DealsConsiderOfflineRetrievalDeals](#DealsConsiderOfflineRetrievalDeals)
Expand Down Expand Up @@ -444,6 +446,33 @@ Inputs: `null`

Response: `null`

### DagstoreLookupPieces
DagstoreLookupPieces returns information about shards that contain the given CID.


Perms: admin

Inputs:
```json
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
]
```

Response: `null`

### DagstorePieceIndexSize
DagstorePieceIndexSize returns the size of the piece index.


Perms: admin

Inputs: `null`

Response: `9`

### DagstoreRecoverShard
DagstoreRecoverShard attempts to recover a failed shard.

Expand Down Expand Up @@ -673,7 +702,7 @@ IndexerAnnounceDeal informs indexer nodes that a new deal was received,
so they can download its index


Perms:
Perms: admin

Inputs:
```json
Expand Down
30 changes: 30 additions & 0 deletions documentation/en/cli-lotus-miner.md
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,8 @@ COMMANDS:
recover-shard Attempt to recover a shard in errored state
initialize-all Initialize all uninitialized shards, streaming results as they're produced; only shards for unsealed pieces are initialized by default
gc Garbage collect the dagstore
piece-index-size Inspect the dagstore piece index size
lookup-pieces Lookup pieces that a given CID belongs to
help, h Shows a list of commands or help for one command

OPTIONS:
Expand Down Expand Up @@ -1115,6 +1117,34 @@ OPTIONS:

```

### lotus-miner dagstore piece-index-size
```
NAME:
lotus-miner dagstore piece-index-size - Inspect the dagstore piece index size

USAGE:
lotus-miner dagstore piece-index-size [command options] [arguments...]

OPTIONS:
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)

```

### lotus-miner dagstore lookup-pieces
```
NAME:
lotus-miner dagstore lookup-pieces - Lookup pieces that a given CID belongs to

USAGE:
lotus-miner dagstore lookup-pieces [command options] <cid>

OPTIONS:
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)

```

## lotus-miner index
```
NAME:
Expand Down
51 changes: 51 additions & 0 deletions node/impl/storminer.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,57 @@ func (sm *StorageMinerAPI) IndexerAnnounceDeal(ctx context.Context, proposalCid
return sm.StorageProvider.AnnounceDealToIndexer(ctx, proposalCid)
}

func (sm *StorageMinerAPI) DagstorePieceIndexSize(ctx context.Context) (int64, error) {
if sm.DAGStore == nil {
return 0, fmt.Errorf("dagstore not available on this node")
}

res, err := sm.DAGStore.TopLevelIndex.Size()
if err != nil {
return 0, fmt.Errorf("failed to get dagstore piece index size: %w", err)
}

return res, nil
}

func (sm *StorageMinerAPI) DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]api.DagstoreShardInfo, error) {
if sm.DAGStore == nil {
return nil, fmt.Errorf("dagstore not available on this node")
}

keys, err := sm.DAGStore.TopLevelIndex.GetShardsForMultihash(cid.Hash())
if err != nil {
return nil, err
}

var ret []api.DagstoreShardInfo

for _, k := range keys {
shard, err := sm.DAGStore.GetShardInfo(k)
if err != nil {
return nil, err
}

ret = append(ret, api.DagstoreShardInfo{
Key: k.String(),
State: shard.ShardState.String(),
Error: func() string {
if shard.Error == nil {
return ""
}
return shard.Error.Error()
}(),
})
}

// order by key.
sort.SliceStable(ret, func(i, j int) bool {
return ret[i].Key < ret[j].Key
})

return ret, nil
}

func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]api.MarketDeal, error) {
return sm.listDeals(ctx)
}
Expand Down