chain export should work now

This commit is contained in:
whyrusleeping 2020-01-20 15:51:02 -08:00
parent 62f05d4c14
commit 57812fc61d
4 changed files with 71 additions and 2 deletions

View File

@ -38,6 +38,7 @@ type FullNode interface {
ChainGetNode(ctx context.Context, p string) (interface{}, error)
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error)
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error)
ChainExport(context.Context, *types.TipSet) (<-chan []byte, error)
// syncer
SyncState(context.Context) (*SyncState, error)

View File

@ -56,6 +56,7 @@ type FullNodeStruct struct {
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, *types.TipSet) (<-chan []byte, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
@ -361,6 +362,10 @@ func (c *FullNodeStruct) ChainGetPath(ctx context.Context, from types.TipSetKey,
return c.Internal.ChainGetPath(ctx, from, to)
}
func (c *FullNodeStruct) ChainExport(ctx context.Context, ts *types.TipSet) (<-chan []byte, error) {
return c.Internal.ChainExport(ctx, ts)
}
func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) {
return c.Internal.SyncState(ctx)
}

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"time"
@ -26,6 +27,7 @@ var chainCmd = &cli.Command{
chainSetHeadCmd,
chainListCmd,
chainGetCmd,
chainExportCmd,
},
}
@ -386,8 +388,8 @@ func printTipSet(format string, ts *types.TipSet) {
fmt.Println(format)
}
func chainExportCmd = &cli.Command{
Name: "export",
var chainExportCmd = &cli.Command{
Name: "export",
Usage: "export chain to a car file",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@ -397,5 +399,33 @@ func chainExportCmd = &cli.Command{
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify filename to export chain to")
}
ts, err := parseTipSet(api, ctx, cctx.Args().Slice())
if err != nil {
return err
}
fi, err := os.Create(cctx.Args().First())
if err != nil {
return err
}
defer fi.Close()
stream, err := api.ChainExport(ctx, ts)
if err != nil {
return err
}
for b := range stream {
_, err := fi.Write(b)
if err != nil {
return err
}
}
return nil
},
}

View File

@ -3,6 +3,7 @@ package full
import (
"context"
"fmt"
"io"
"strconv"
"strings"
@ -18,6 +19,7 @@ import (
"github.com/ipfs/go-path"
"github.com/ipfs/go-path/resolver"
mh "github.com/multiformats/go-multihash"
"github.com/prometheus/common/log"
"go.uber.org/fx"
"golang.org/x/xerrors"
@ -312,3 +314,34 @@ func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Mess
return cm.VMMessage(), nil
}
func (a *ChainAPI) ChainExport(ctx context.Context, ts *types.TipSet) (<-chan []byte, error) {
r, w := io.Pipe()
out := make(chan []byte)
go func() {
defer close(out)
if err := a.Chain.Export(ctx, ts, w); err != nil {
log.Errorf("chain export call failed: %s", err)
return
}
}()
go func() {
defer r.Close()
for {
buf := make([]byte, 4096)
n, err := r.Read(buf)
if err != nil {
log.Errorf("chain export pipe read failed: %s", err)
return
}
select {
case out <- buf[:n]:
case <-ctx.Done():
log.Warnf("export writer failed: %s", ctx.Done())
}
}
}()
return out, nil
}