Wire up client import manager
This commit is contained in:
parent
8942967223
commit
47f0898ce9
@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/ipfs/go-filestore"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
@ -356,10 +355,12 @@ type MinerSectors struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Import struct {
|
type Import struct {
|
||||||
Status filestore.Status
|
Key int64
|
||||||
Key cid.Cid
|
Err error
|
||||||
|
|
||||||
|
Root *cid.Cid
|
||||||
|
Source string
|
||||||
FilePath string
|
FilePath string
|
||||||
Size uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DealInfo struct {
|
type DealInfo struct {
|
||||||
|
@ -204,7 +204,15 @@ var clientLocalCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
fmt.Printf("%s %s %s %s\n", encoder.Encode(v.Key), v.FilePath, types.SizeStr(types.NewInt(v.Size)), v.Status)
|
cidStr := "<nil>"
|
||||||
|
if v.Root != nil {
|
||||||
|
cidStr = encoder.Encode(*v.Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%d: %s @%s (%s)\n", v.Key, cidStr, v.FilePath, v.Source)
|
||||||
|
if v.Err != nil {
|
||||||
|
fmt.Printf("\terror: %s\n", v.Err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -435,8 +435,9 @@ func Repo(r repo.Repo) Option {
|
|||||||
Override(new(dtypes.MetadataDS), modules.Datastore),
|
Override(new(dtypes.MetadataDS), modules.Datastore),
|
||||||
Override(new(dtypes.ChainBlockstore), modules.ChainBlockstore),
|
Override(new(dtypes.ChainBlockstore), modules.ChainBlockstore),
|
||||||
|
|
||||||
|
Override(new(dtypes.ClientImportMgr), modules.ClientImportMgr),
|
||||||
Override(new(dtypes.ClientMultiDstore), modules.ClientMultiDatastore),
|
Override(new(dtypes.ClientMultiDstore), modules.ClientMultiDatastore),
|
||||||
Override(new(dtypes.ClientFilestore), modules.ClientFstore),
|
|
||||||
Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore),
|
Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore),
|
||||||
|
|
||||||
Override(new(ci.PrivKey), lp2p.PrivKey),
|
Override(new(ci.PrivKey), lp2p.PrivKey),
|
||||||
|
@ -2,15 +2,8 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-fil-markets/pieceio"
|
|
||||||
basicnode "github.com/ipld/go-ipld-prime/node/basic"
|
|
||||||
"github.com/ipld/go-ipld-prime/traversal/selector"
|
|
||||||
"github.com/ipld/go-ipld-prime/traversal/selector/builder"
|
|
||||||
"github.com/multiformats/go-multiaddr"
|
|
||||||
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -18,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ipfs/go-blockservice"
|
"github.com/ipfs/go-blockservice"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/ipfs/go-filestore"
|
|
||||||
chunker "github.com/ipfs/go-ipfs-chunker"
|
chunker "github.com/ipfs/go-ipfs-chunker"
|
||||||
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
||||||
files "github.com/ipfs/go-ipfs-files"
|
files "github.com/ipfs/go-ipfs-files"
|
||||||
@ -28,10 +20,15 @@ import (
|
|||||||
"github.com/ipfs/go-unixfs/importer/balanced"
|
"github.com/ipfs/go-unixfs/importer/balanced"
|
||||||
ihelper "github.com/ipfs/go-unixfs/importer/helpers"
|
ihelper "github.com/ipfs/go-unixfs/importer/helpers"
|
||||||
"github.com/ipld/go-car"
|
"github.com/ipld/go-car"
|
||||||
|
basicnode "github.com/ipld/go-ipld-prime/node/basic"
|
||||||
|
"github.com/ipld/go-ipld-prime/traversal/selector"
|
||||||
|
"github.com/ipld/go-ipld-prime/traversal/selector/builder"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
"github.com/multiformats/go-multiaddr"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/pieceio"
|
||||||
rm "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
rm "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
||||||
@ -46,6 +43,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/markets/utils"
|
"github.com/filecoin-project/lotus/markets/utils"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
"github.com/filecoin-project/lotus/node/impl/paych"
|
"github.com/filecoin-project/lotus/node/impl/paych"
|
||||||
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,7 +62,7 @@ type API struct {
|
|||||||
Retrieval rm.RetrievalClient
|
Retrieval rm.RetrievalClient
|
||||||
Chain *store.ChainStore
|
Chain *store.ChainStore
|
||||||
|
|
||||||
Imports *importmgr.Mgr
|
Imports dtypes.ClientImportMgr
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcDealExpiration(minDuration uint64, md *miner.DeadlineInfo, startEpoch abi.ChainEpoch) abi.ChainEpoch {
|
func calcDealExpiration(minDuration uint64, md *miner.DeadlineInfo, startEpoch abi.ChainEpoch) abi.ChainEpoch {
|
||||||
@ -75,6 +73,10 @@ func calcDealExpiration(minDuration uint64, md *miner.DeadlineInfo, startEpoch a
|
|||||||
return minExp + miner.WPoStProvingPeriod - (minExp % miner.WPoStProvingPeriod) + (md.PeriodStart % miner.WPoStProvingPeriod) - 1
|
return minExp + miner.WPoStProvingPeriod - (minExp % miner.WPoStProvingPeriod) + (md.PeriodStart % miner.WPoStProvingPeriod) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) imgr() *importmgr.Mgr {
|
||||||
|
return a.Imports
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) {
|
func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) {
|
||||||
exist, err := a.WalletHas(ctx, params.Wallet)
|
exist, err := a.WalletHas(ctx, params.Wallet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -193,7 +195,7 @@ func (a *API) ClientGetDealInfo(ctx context.Context, d cid.Cid) (*api.DealInfo,
|
|||||||
func (a *API) ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) {
|
func (a *API) ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) {
|
||||||
// TODO: check if we have the ENTIRE dag
|
// TODO: check if we have the ENTIRE dag
|
||||||
|
|
||||||
offExch := merkledag.NewDAGService(blockservice.New(a.Imports.Bs, offline.Exchange(a.Imports.Bs)))
|
offExch := merkledag.NewDAGService(blockservice.New(a.Imports.Blockstore, offline.Exchange(a.Imports.Blockstore)))
|
||||||
_, err := offExch.Get(ctx, root)
|
_, err := offExch.Get(ctx, root)
|
||||||
if err == ipld.ErrNotFound {
|
if err == ipld.ErrNotFound {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -258,11 +260,11 @@ func (a *API) makeRetrievalQuery(ctx context.Context, rp rm.RetrievalPeer, paylo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) ClientImport(ctx context.Context, ref api.FileRef) (cid.Cid, error) {
|
func (a *API) ClientImport(ctx context.Context, ref api.FileRef) (cid.Cid, error) {
|
||||||
id, st, err := a.Imports.NewStore()
|
id, st, err := a.imgr().NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Cid{}, err
|
return cid.Cid{}, err
|
||||||
}
|
}
|
||||||
if err := a.Imports.AddLabel(id, "source", "import"); err != nil {
|
if err := a.imgr().AddLabel(id, "source", "import"); err != nil {
|
||||||
return cid.Cid{}, err
|
return cid.Cid{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,11 +280,11 @@ func (a *API) ClientImport(ctx context.Context, ref api.FileRef) (cid.Cid, error
|
|||||||
func (a *API) ClientImportLocal(ctx context.Context, f io.Reader) (cid.Cid, error) {
|
func (a *API) ClientImportLocal(ctx context.Context, f io.Reader) (cid.Cid, error) {
|
||||||
file := files.NewReaderFile(f)
|
file := files.NewReaderFile(f)
|
||||||
|
|
||||||
id, st, err := a.Imports.NewStore()
|
id, st, err := a.imgr().NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Cid{}, err
|
return cid.Cid{}, err
|
||||||
}
|
}
|
||||||
if err := a.Imports.AddLabel(id, "source", "import-local"); err != nil {
|
if err := a.imgr().AddLabel(id, "source", "import-local"); err != nil {
|
||||||
return cid.Cid{}, err
|
return cid.Cid{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,49 +310,38 @@ func (a *API) ClientImportLocal(ctx context.Context, f io.Reader) (cid.Cid, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
||||||
if a.Filestore == nil {
|
importIDs := a.imgr().List()
|
||||||
return nil, errors.New("listing imports is not supported with in-memory dag yet")
|
|
||||||
}
|
out := make([]api.Import, len(importIDs))
|
||||||
next, err := filestore.ListAll(a.Filestore, false)
|
for i, id := range importIDs {
|
||||||
|
info, err := a.imgr().Info(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make this less very bad by tracking root cids instead of using ListAll
|
|
||||||
|
|
||||||
out := make([]api.Import, 0)
|
|
||||||
lowest := make([]uint64, 0)
|
|
||||||
for {
|
|
||||||
r := next()
|
|
||||||
if r == nil {
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
matched := false
|
|
||||||
for i := range out {
|
|
||||||
if out[i].FilePath == r.FilePath {
|
|
||||||
matched = true
|
|
||||||
if lowest[i] > r.Offset {
|
|
||||||
lowest[i] = r.Offset
|
|
||||||
out[i] = api.Import{
|
out[i] = api.Import{
|
||||||
Status: r.Status,
|
Key: id,
|
||||||
Key: r.Key,
|
Err: xerrors.Errorf("getting info: %w", err),
|
||||||
FilePath: r.FilePath,
|
}
|
||||||
Size: r.Size,
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ai := api.Import{
|
||||||
|
Key: id,
|
||||||
|
Source: info.Labels[importmgr.LSource],
|
||||||
|
FilePath: info.Labels[importmgr.LFileName],
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Labels[importmgr.LRootCid] != "" {
|
||||||
|
c, err := cid.Parse(info.Labels[importmgr.LRootCid])
|
||||||
|
if err != nil {
|
||||||
|
ai.Err = err
|
||||||
|
} else {
|
||||||
|
ai.Root = &c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
out[i] = ai
|
||||||
}
|
|
||||||
if !matched {
|
|
||||||
out = append(out, api.Import{
|
|
||||||
Status: r.Status,
|
|
||||||
Key: r.Key,
|
|
||||||
FilePath: r.FilePath,
|
|
||||||
Size: r.Size,
|
|
||||||
})
|
|
||||||
lowest = append(lowest, r.Offset)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error {
|
func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error {
|
||||||
@ -367,11 +358,11 @@ func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
|
|||||||
return xerrors.Errorf("cannot make retrieval deal for zero bytes")
|
return xerrors.Errorf("cannot make retrieval deal for zero bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
id, st, err := a.Imports.NewStore()
|
id, st, err := a.imgr().NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := a.Imports.AddLabel(id, "source", "retrieval"); err != nil {
|
if err := a.imgr().AddLabel(id, "source", "retrieval"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,11 +496,11 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string, miner address.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) ClientGenCar(ctx context.Context, ref api.FileRef, outputPath string) error {
|
func (a *API) ClientGenCar(ctx context.Context, ref api.FileRef, outputPath string) error {
|
||||||
id, st, err := a.Imports.NewStore()
|
id, st, err := a.imgr().NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := a.Imports.AddLabel(id, "source", "gen-car"); err != nil {
|
if err := a.imgr().AddLabel(id, "source", "gen-car"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,9 @@ package modules
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
"github.com/ipfs/go-merkledag"
|
|
||||||
"github.com/libp2p/go-libp2p-core/host"
|
"github.com/libp2p/go-libp2p-core/host"
|
||||||
"github.com/libp2p/go-libp2p-core/routing"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
|
||||||
graphsyncimpl "github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
graphsyncimpl "github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
||||||
@ -21,18 +18,13 @@ import (
|
|||||||
smnet "github.com/filecoin-project/go-fil-markets/storagemarket/network"
|
smnet "github.com/filecoin-project/go-fil-markets/storagemarket/network"
|
||||||
"github.com/filecoin-project/go-statestore"
|
"github.com/filecoin-project/go-statestore"
|
||||||
"github.com/filecoin-project/go-storedcounter"
|
"github.com/filecoin-project/go-storedcounter"
|
||||||
"github.com/ipfs/go-bitswap"
|
|
||||||
"github.com/ipfs/go-bitswap/network"
|
|
||||||
"github.com/ipfs/go-blockservice"
|
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
"github.com/ipfs/go-datastore/namespace"
|
"github.com/ipfs/go-datastore/namespace"
|
||||||
"github.com/ipfs/go-filestore"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/markets/retrievaladapter"
|
"github.com/filecoin-project/lotus/markets/retrievaladapter"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
payapi "github.com/filecoin-project/lotus/node/impl/paych"
|
payapi "github.com/filecoin-project/lotus/node/impl/paych"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
"github.com/filecoin-project/lotus/paychmgr"
|
"github.com/filecoin-project/lotus/paychmgr"
|
||||||
@ -53,28 +45,12 @@ func ClientMultiDatastore(lc fx.Lifecycle, r repo.LockedRepo) (dtypes.ClientMult
|
|||||||
return mds, nil
|
return mds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClientFstore(r repo.LockedRepo) (dtypes.ClientFilestore, error) {
|
func ClientImportMgr(mds dtypes.ClientMultiDstore, ds dtypes.MetadataDS) dtypes.ClientImportMgr {
|
||||||
clientds, err := r.Datastore("/client")
|
return importmgr.New(mds, namespace.Wrap(ds, datastore.NewKey("/client")))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blocks := namespace.Wrap(clientds, datastore.NewKey("blocks"))
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs(r.Path())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fm := filestore.NewFileManager(clientds, filepath.Dir(absPath))
|
|
||||||
fm.AllowFiles = true
|
|
||||||
// TODO: fm.AllowUrls (needs more code in client import)
|
|
||||||
|
|
||||||
bs := blockstore.NewBlockstore(blocks)
|
|
||||||
return filestore.NewFilestore(bs, fm), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClientBlockstore(fstore dtypes.ClientFilestore) dtypes.ClientBlockstore {
|
func ClientBlockstore(imgr dtypes.ClientImportMgr) dtypes.ClientBlockstore {
|
||||||
return blockstore.NewIdStore((*filestore.Filestore)(fstore))
|
return blockstore.NewIdStore(imgr.Blockstore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterClientValidator is an initialization hook that registers the client
|
// RegisterClientValidator is an initialization hook that registers the client
|
||||||
@ -103,24 +79,6 @@ func NewClientDatastore(ds dtypes.MetadataDS) dtypes.ClientDatastore {
|
|||||||
return namespace.Wrap(ds, datastore.NewKey("/deals/client"))
|
return namespace.Wrap(ds, datastore.NewKey("/deals/client"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientDAG is a DAGService for the ClientBlockstore
|
|
||||||
func ClientDAG(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.ClientBlockstore, rt routing.Routing, h host.Host) dtypes.ClientDAG {
|
|
||||||
bitswapNetwork := network.NewFromIpfsHost(h, rt)
|
|
||||||
bitswapOptions := []bitswap.Option{bitswap.ProvideEnabled(false)}
|
|
||||||
exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, ibs, bitswapOptions...)
|
|
||||||
|
|
||||||
bsvc := blockservice.New(ibs, exch)
|
|
||||||
dag := merkledag.NewDAGService(bsvc)
|
|
||||||
|
|
||||||
lc.Append(fx.Hook{
|
|
||||||
OnStop: func(_ context.Context) error {
|
|
||||||
return bsvc.Close()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return dag
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClientRequestValidator(deals dtypes.ClientDealStore) dtypes.ClientRequestValidator {
|
func NewClientRequestValidator(deals dtypes.ClientDealStore) dtypes.ClientRequestValidator {
|
||||||
return requestvalidation.NewUnifiedRequestValidator(nil, deals)
|
return requestvalidation.NewUnifiedRequestValidator(nil, deals)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package dtypes
|
|||||||
import (
|
import (
|
||||||
bserv "github.com/ipfs/go-blockservice"
|
bserv "github.com/ipfs/go-blockservice"
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
"github.com/ipfs/go-filestore"
|
|
||||||
"github.com/ipfs/go-graphsync"
|
"github.com/ipfs/go-graphsync"
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
exchange "github.com/ipfs/go-ipfs-exchange-interface"
|
exchange "github.com/ipfs/go-ipfs-exchange-interface"
|
||||||
@ -29,7 +28,7 @@ type ChainExchange exchange.Interface
|
|||||||
type ChainBlockService bserv.BlockService
|
type ChainBlockService bserv.BlockService
|
||||||
|
|
||||||
type ClientMultiDstore *importmgr.MultiStore
|
type ClientMultiDstore *importmgr.MultiStore
|
||||||
type ClientFilestore *filestore.Filestore
|
type ClientImportMgr *importmgr.Mgr
|
||||||
type ClientBlockstore blockstore.Blockstore
|
type ClientBlockstore blockstore.Blockstore
|
||||||
type ClientDealStore *statestore.StateStore
|
type ClientDealStore *statestore.StateStore
|
||||||
type ClientRequestValidator *requestvalidation.UnifiedRequestValidator
|
type ClientRequestValidator *requestvalidation.UnifiedRequestValidator
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/ipfs/go-filestore"
|
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
@ -18,8 +17,8 @@ import (
|
|||||||
// If ipfsMaddr is empty, a local IPFS node is assumed considering IPFS_PATH configuration.
|
// If ipfsMaddr is empty, a local IPFS node is assumed considering IPFS_PATH configuration.
|
||||||
// If ipfsMaddr is not empty, it will connect to the remote IPFS node with the provided multiaddress.
|
// If ipfsMaddr is not empty, it will connect to the remote IPFS node with the provided multiaddress.
|
||||||
// The flag useForRetrieval indicates if the IPFS node will also be used for storing retrieving deals.
|
// The flag useForRetrieval indicates if the IPFS node will also be used for storing retrieving deals.
|
||||||
func IpfsClientBlockstore(ipfsMaddr string, useForRetrieval bool) func(helpers.MetricsCtx, fx.Lifecycle, dtypes.ClientFilestore) (dtypes.ClientBlockstore, error) {
|
func IpfsClientBlockstore(ipfsMaddr string, useForRetrieval bool) func(helpers.MetricsCtx, fx.Lifecycle, dtypes.ClientImportMgr) (dtypes.ClientBlockstore, error) {
|
||||||
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, fstore dtypes.ClientFilestore) (dtypes.ClientBlockstore, error) {
|
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, localStore dtypes.ClientImportMgr) (dtypes.ClientBlockstore, error) {
|
||||||
var err error
|
var err error
|
||||||
var ipfsbs *ipfsbstore.IpfsBstore
|
var ipfsbs *ipfsbstore.IpfsBstore
|
||||||
if ipfsMaddr != "" {
|
if ipfsMaddr != "" {
|
||||||
@ -38,7 +37,7 @@ func IpfsClientBlockstore(ipfsMaddr string, useForRetrieval bool) func(helpers.M
|
|||||||
var ws blockstore.Blockstore
|
var ws blockstore.Blockstore
|
||||||
ws = ipfsbs
|
ws = ipfsbs
|
||||||
if !useForRetrieval {
|
if !useForRetrieval {
|
||||||
ws = blockstore.NewIdStore((*filestore.Filestore)(fstore))
|
ws = blockstore.NewIdStore(localStore.Blockstore)
|
||||||
}
|
}
|
||||||
return bufbstore.NewTieredBstore(ipfsbs, ws), nil
|
return bufbstore.NewTieredBstore(ipfsbs, ws), nil
|
||||||
}
|
}
|
||||||
|
@ -1 +1,96 @@
|
|||||||
package importmgr
|
package importmgr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/ipfs/go-datastore"
|
||||||
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type multiReadBs struct {
|
||||||
|
// TODO: some caching
|
||||||
|
mds *MultiStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) Has(cid cid.Cid) (bool, error) {
|
||||||
|
m.mds.lk.RLock()
|
||||||
|
defer m.mds.lk.RUnlock()
|
||||||
|
|
||||||
|
var merr error
|
||||||
|
for i, store := range m.mds.open {
|
||||||
|
has, err := store.Bstore.Has(cid)
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, xerrors.Errorf("has (ds %d): %w", i, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, merr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) Get(cid cid.Cid) (blocks.Block, error) {
|
||||||
|
m.mds.lk.RLock()
|
||||||
|
defer m.mds.lk.RUnlock()
|
||||||
|
|
||||||
|
var merr error
|
||||||
|
for i, store := range m.mds.open {
|
||||||
|
has, err := store.Bstore.Has(cid)
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, xerrors.Errorf("has (ds %d): %w", i, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := store.Bstore.Get(cid)
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, xerrors.Errorf("get (ds %d): %w", i, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if merr == nil {
|
||||||
|
return nil, datastore.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, merr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) DeleteBlock(cid cid.Cid) error {
|
||||||
|
return xerrors.Errorf("operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) GetSize(cid cid.Cid) (int, error) {
|
||||||
|
return 0, xerrors.Errorf("operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) Put(block blocks.Block) error {
|
||||||
|
return xerrors.Errorf("operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) PutMany(blocks []blocks.Block) error {
|
||||||
|
return xerrors.Errorf("operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||||
|
return nil, xerrors.Errorf("operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiReadBs) HashOnRead(enabled bool) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ blockstore.Blockstore = &multiReadBs{}
|
||||||
|
@ -3,22 +3,33 @@ package importmgr
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
"github.com/ipfs/go-datastore/namespace"
|
"github.com/ipfs/go-datastore/namespace"
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mgr struct {
|
type Mgr struct {
|
||||||
mds *MultiStore
|
mds *MultiStore
|
||||||
Bs blockstore.Blockstore
|
|
||||||
ds datastore.Batching
|
ds datastore.Batching
|
||||||
|
|
||||||
|
Blockstore blockstore.Blockstore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Label string
|
||||||
|
const (
|
||||||
|
LSource = "source" // Function which created the import
|
||||||
|
LRootCid = "root" // Root CID
|
||||||
|
LFileName = "filename" // Local file path
|
||||||
|
LMTime = "mtime" // File modification timestamp
|
||||||
|
)
|
||||||
|
|
||||||
func New(mds *MultiStore, ds datastore.Batching) *Mgr {
|
func New(mds *MultiStore, ds datastore.Batching) *Mgr {
|
||||||
return &Mgr{
|
return &Mgr{
|
||||||
mds: mds,
|
mds: mds,
|
||||||
bs: &multiReadBs{
|
Blockstore: &multiReadBs{
|
||||||
mds: mds,
|
mds: mds,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -26,7 +37,7 @@ func New(mds *MultiStore, ds datastore.Batching) *Mgr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type storeMeta struct {
|
type StoreMeta struct {
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +48,7 @@ func (m *Mgr) NewStore() (int64, *Store, error) {
|
|||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
meta, err := json.Marshal(&storeMeta{Labels: map[string]string{
|
meta, err := json.Marshal(&StoreMeta{Labels: map[string]string{
|
||||||
"source": "unknown",
|
"source": "unknown",
|
||||||
}})
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,14 +65,14 @@ func (m *Mgr) AddLabel(id int64, key, value string) error { // source, file path
|
|||||||
return xerrors.Errorf("getting metadata form datastore: %w", err)
|
return xerrors.Errorf("getting metadata form datastore: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sm storeMeta
|
var sm StoreMeta
|
||||||
if err := json.Unmarshal(meta, &sm); err != nil {
|
if err := json.Unmarshal(meta, &sm); err != nil {
|
||||||
return xerrors.Errorf("unmarshaling store meta: %w", err)
|
return xerrors.Errorf("unmarshaling store meta: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sm.Labels[key] = value
|
sm.Labels[key] = value
|
||||||
|
|
||||||
meta, err = json.Marshal(&storeMeta{})
|
meta, err = json.Marshal(&StoreMeta{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("marshaling store meta: %w", err)
|
return xerrors.Errorf("marshaling store meta: %w", err)
|
||||||
}
|
}
|
||||||
@ -69,6 +80,23 @@ func (m *Mgr) AddLabel(id int64, key, value string) error { // source, file path
|
|||||||
return m.ds.Put(datastore.NewKey(fmt.Sprintf("%d", id)), meta)
|
return m.ds.Put(datastore.NewKey(fmt.Sprintf("%d", id)), meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// m.List
|
func (m *Mgr) List() []int64 {
|
||||||
|
return m.mds.List()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mgr) Info(id int64) (*StoreMeta, error) {
|
||||||
|
meta, err := m.ds.Get(datastore.NewKey(fmt.Sprintf("%d", id)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("getting metadata form datastore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sm StoreMeta
|
||||||
|
if err := json.Unmarshal(meta, &sm); err != nil {
|
||||||
|
return nil, xerrors.Errorf("unmarshaling store meta: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sm, nil
|
||||||
|
}
|
||||||
|
|
||||||
// m.Info
|
// m.Info
|
||||||
// m.Delete
|
// m.Delete
|
@ -1,16 +1,12 @@
|
|||||||
package importmgr
|
package importmgr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
blocks "github.com/ipfs/go-block-format"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
@ -83,6 +79,17 @@ func (mds *MultiStore) Get(i int64) (*Store, error) {
|
|||||||
return mds.open[i], err
|
return mds.open[i], err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mds *MultiStore) List() []int64 {
|
||||||
|
mds.lk.RLock()
|
||||||
|
defer mds.lk.RUnlock()
|
||||||
|
out := make([]int64, 0, len(mds.open))
|
||||||
|
for i := range mds.open {
|
||||||
|
out = append(out, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func (mds *MultiStore) Delete(i int64) error {
|
func (mds *MultiStore) Delete(i int64) error {
|
||||||
mds.lk.Lock()
|
mds.lk.Lock()
|
||||||
defer mds.lk.Unlock()
|
defer mds.lk.Unlock()
|
||||||
@ -113,86 +120,3 @@ func (mds *MultiStore) Close() error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type multiReadBs struct {
|
|
||||||
// TODO: some caching
|
|
||||||
mds *MultiStore
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) Has(cid cid.Cid) (bool, error) {
|
|
||||||
m.mds.lk.RLock()
|
|
||||||
defer m.mds.lk.RUnlock()
|
|
||||||
|
|
||||||
var merr error
|
|
||||||
for i, store := range m.mds.open {
|
|
||||||
has, err := store.Bstore.Has(cid)
|
|
||||||
if err != nil {
|
|
||||||
merr = multierror.Append(merr, xerrors.Errorf("has (ds %d): %w", i, err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !has {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, merr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) Get(cid cid.Cid) (blocks.Block, error) {
|
|
||||||
m.mds.lk.RLock()
|
|
||||||
defer m.mds.lk.RUnlock()
|
|
||||||
|
|
||||||
var merr error
|
|
||||||
for i, store := range m.mds.open {
|
|
||||||
has, err := store.Bstore.Has(cid)
|
|
||||||
if err != nil {
|
|
||||||
merr = multierror.Append(merr, xerrors.Errorf("has (ds %d): %w", i, err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !has {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := store.Bstore.Get(cid)
|
|
||||||
if err != nil {
|
|
||||||
merr = multierror.Append(merr, xerrors.Errorf("get (ds %d): %w", i, err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if merr == nil {
|
|
||||||
return nil, datastore.ErrNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, merr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) DeleteBlock(cid cid.Cid) error {
|
|
||||||
return xerrors.Errorf("operation not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) GetSize(cid cid.Cid) (int, error) {
|
|
||||||
return 0, xerrors.Errorf("operation not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) Put(block blocks.Block) error {
|
|
||||||
return xerrors.Errorf("operation not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) PutMany(blocks []blocks.Block) error {
|
|
||||||
return xerrors.Errorf("operation not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
|
||||||
return nil, xerrors.Errorf("operation not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *multiReadBs) HashOnRead(enabled bool) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ blockstore.Blockstore = &multiReadBs{}
|
|
Loading…
Reference in New Issue
Block a user