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

feat: dag import --stats (#8237) #8237

Merged
merged 10 commits into from
Sep 23, 2021
36 changes: 31 additions & 5 deletions core/commands/dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import (
)

const (
pinRootsOptionName = "pin-roots"
progressOptionName = "progress"
silentOptionName = "silent"
pinRootsOptionName = "pin-roots"
statsOptionName = "stats"
)

// DagCmd provides a subset of commands for interacting with ipld dag objects
Expand Down Expand Up @@ -53,9 +54,15 @@ type ResolveOutput struct {
RemPath string
}

type CarImportStats struct {
BlockCount uint64
BlockBytesCount uint64
}

// CarImportOutput is the output type of the 'dag import' commands
type CarImportOutput struct {
Root RootMeta
Root *RootMeta `json:",omitempty"`
Stats *CarImportStats `json:",omitempty"`
}

// RootMeta is the metadata for a root pinning response
Expand Down Expand Up @@ -160,8 +167,10 @@ var DagResolveCmd = &cmds.Command{
}

type importResult struct {
roots map[cid.Cid]struct{}
err error
blockCount uint64
blockBytesCount uint64
roots map[cid.Cid]struct{}
err error
}

// DagImportCmd is a command for importing a car to ipfs
Expand Down Expand Up @@ -193,8 +202,9 @@ Maximum supported CAR version: 1
cmds.FileArg("path", true, true, "The path of a .car file.").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption(silentOptionName, "No output."),
cmds.BoolOption(pinRootsOptionName, "Pin optional roots listed in the .car headers after importing.").WithDefault(true),
cmds.BoolOption(silentOptionName, "No output."),
cmds.BoolOption(statsOptionName, "Output stats."),
},
Type: CarImportOutput{},
Run: dagImport,
Expand All @@ -206,6 +216,22 @@ Maximum supported CAR version: 1
return nil
}

// event should have only one of `Root` or `Stats` set, not both
if event.Root == nil {
if event.Stats == nil {
return fmt.Errorf("Unexpected message from DAG import")
}
stats, _ := req.Options[statsOptionName].(bool)
if stats {
fmt.Fprintf(w, "Imported %d blocks (%d bytes)\n", event.Stats.BlockCount, event.Stats.BlockBytesCount)
}
return nil
}

if event.Stats != nil {
return fmt.Errorf("Unexpected message from DAG import")
}

enc, err := cmdenv.GetLowLevelCidEncoder(req)
if err != nil {
return err
Expand Down
23 changes: 21 additions & 2 deletions core/commands/dag/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
failedPins++
}

if err := res.Emit(&CarImportOutput{Root: ret}); err != nil {
if err := res.Emit(&CarImportOutput{Root: &ret}); err != nil {
return err
}
}
Expand All @@ -115,6 +115,19 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
}
}

stats, _ := req.Options[statsOptionName].(bool)
if stats {
err = res.Emit(&CarImportOutput{
Stats: &CarImportStats{
BlockCount: done.blockCount,
BlockBytesCount: done.blockBytesCount,
},
})
if err != nil {
return err
}
}

return nil
}

Expand All @@ -126,6 +139,7 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI,
batch := ipld.NewBatch(req.Context, api.Dag())

roots := make(map[cid.Cid]struct{})
var blockCount, blockBytesCount uint64

it := req.Files.Entries()
for it.Next() {
Expand Down Expand Up @@ -176,6 +190,8 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI,
if err := batch.Add(req.Context, nd); err != nil {
return err
}
blockCount++
lidel marked this conversation as resolved.
Show resolved Hide resolved
blockBytesCount += uint64(len(block.RawData()))
}

return nil
Expand All @@ -197,5 +213,8 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI,
return
}

ret <- importResult{roots: roots}
ret <- importResult{
blockCount: blockCount,
blockBytesCount: blockBytesCount,
roots: roots}
}
2 changes: 1 addition & 1 deletion test/sharness/lib/test-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ test_launch_ipfs_daemon() {

# wait for api file to show up
test_expect_success "api file shows up" '
test_wait_for_file 50 100ms "$IPFS_PATH/api"
test_wait_for_file 50 200ms "$IPFS_PATH/api"
'

test_set_address_vars actual_daemon
Expand Down
2 changes: 1 addition & 1 deletion test/sharness/t0041-ping.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ test_expect_success "test ping 0" '
'

test_expect_success "test ping offline" '
iptb stop 1 &&
iptb stop 1 && sleep 2 &&
! ipfsi 0 ping -n2 -- "$PEERID_1"
'

Expand Down
56 changes: 44 additions & 12 deletions test/sharness/t0054-dag-car-import-export.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,25 @@ run_online_imp_exp_tests() {
reset_blockstore 0
reset_blockstore 1

cat > basic_import_expected <<EOE
cat > basic_import_stats_expected <<EOE
Imported 1198 blocks (468513 bytes)
Pinned root${tab}bafkqaaa${tab}success
Pinned root${tab}bafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u${tab}success
Pinned root${tab}bafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy${tab}success
EOE
# output without the --stats line at the top
tail -n +2 basic_import_stats_expected > basic_import_expected

# Explainer:
# naked_root_import_json_expected output is produced by dag import of combined_naked_roots_genesis_and_128.car
# executed when roots are already present in the repo - thus the BlockCount=0
# (if blocks were not present in the repo, blockstore: block not found would be returned)
cat >naked_root_import_json_expected <<EOE
{"Root":{"Cid":{"/":"bafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u"},"PinErrorMsg":""}}
{"Root":{"Cid":{"/":"bafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy"},"PinErrorMsg":""}}
{"Stats":{"BlockCount":0,"BlockBytesCount":0}}
EOE


test_expect_success "basic import" '
do_import 0 \
../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
Expand All @@ -79,6 +86,18 @@ EOE
test_cmp_sorted basic_import_expected basic_import_actual
'

test_expect_success "basic import with --stats" '
do_import 0 --stats \
../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car \
../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car \
> basic_import_actual
'

test_expect_success "basic import output with --stats as expected" '
test_cmp_sorted basic_import_stats_expected basic_import_actual
'

test_expect_success "basic fetch+export 1" '
ipfsi 1 dag export bafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy > reexported_testnet_128.car
'
Expand All @@ -98,7 +117,7 @@ EOE
'

test_expect_success "import/pin naked roots only, relying on local blockstore having all the data" '
ipfsi 1 dag import --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
ipfsi 1 dag import --stats --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
> naked_import_result_json_actual
'

Expand All @@ -117,7 +136,7 @@ EOE
cat ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car > pipe_testnet &
cat ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car > pipe_devnet &

do_import 0 \
do_import 0 --stats \
pipe_testnet \
pipe_devnet \
../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
Expand All @@ -134,7 +153,7 @@ EOE
'

test_expect_success "fifo-import output as expected" '
test_cmp_sorted basic_import_expected basic_fifo_import_actual
test_cmp_sorted basic_import_stats_expected basic_fifo_import_actual
'
}

Expand Down Expand Up @@ -168,33 +187,46 @@ test_expect_success "correct error" '
test_cmp_sorted offline_fetch_error_expected offline_fetch_error_actual
'


cat >multiroot_import_json_expected <<EOE
cat >multiroot_import_json_stats_expected <<EOE
{"Root":{"Cid":{"/":"bafy2bzaceb55n7uxyfaelplulk3ev2xz7gnq6crncf3ahnvu46hqqmpucizcw"},"PinErrorMsg":""}}
{"Root":{"Cid":{"/":"bafy2bzacebedrc4n2ac6cqdkhs7lmj5e4xiif3gu7nmoborihajxn3fav3vdq"},"PinErrorMsg":""}}
{"Root":{"Cid":{"/":"bafy2bzacede2hsme6hparlbr4g2x6pylj43olp4uihwjq3plqdjyrdhrv7cp4"},"PinErrorMsg":""}}
{"Stats":{"BlockCount":2825,"BlockBytesCount":1339709}}
EOE
test_expect_success "multiroot import works" '
# output without --stats line
head -3 multiroot_import_json_stats_expected > multiroot_import_json_expected

test_expect_success "multiroot import works (--enc=json)" '
ipfs dag import --enc=json ../t0054-dag-car-import-export-data/lotus_testnet_export_256_multiroot.car > multiroot_import_json_actual
'
test_expect_success "multiroot import expected output" '
test_cmp_sorted multiroot_import_json_expected multiroot_import_json_actual
'

test_expect_success "multiroot import works with --stats" '
ipfs dag import --stats --enc=json ../t0054-dag-car-import-export-data/lotus_testnet_export_256_multiroot.car > multiroot_import_json_actual
'
test_expect_success "multiroot import expected output" '
test_cmp_sorted multiroot_import_json_stats_expected multiroot_import_json_actual
'


cat >pin_import_expected << EOE
{"Stats":{"BlockCount":1198,"BlockBytesCount":468513}}
EOE
test_expect_success "pin-less import works" '
ipfs dag import --enc=json --pin-roots=false \
ipfs dag import --stats --enc=json --pin-roots=false \
../t0054-dag-car-import-export-data/lotus_devnet_genesis.car \
../t0054-dag-car-import-export-data/lotus_testnet_export_128.car \
> no-pin_import_actual
'
test_expect_success "expected silence on --pin-roots=false" '
test_cmp /dev/null no-pin_import_actual
test_expect_success "expected no pins on --pin-roots=false" '
test_cmp pin_import_expected no-pin_import_actual
'


test_expect_success "naked root import works" '
ipfs dag import --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
ipfs dag import --stats --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \
> naked_root_import_json_actual
'
test_expect_success "naked root import expected output" '
Expand Down