ipld-eth-server/vendor/github.com/ipfs/go-ipfs/exchange/reprovide/providers.go

74 lines
1.6 KiB
Go

package reprovide
import (
"context"
pin "github.com/ipfs/go-ipfs/pin"
cid "github.com/ipfs/go-cid"
cidutil "github.com/ipfs/go-cidutil"
blocks "github.com/ipfs/go-ipfs-blockstore"
ipld "github.com/ipfs/go-ipld-format"
merkledag "github.com/ipfs/go-merkledag"
)
// NewBlockstoreProvider returns key provider using bstore.AllKeysChan
func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc {
return func(ctx context.Context) (<-chan cid.Cid, error) {
return bstore.AllKeysChan(ctx)
}
}
// NewPinnedProvider returns provider supplying pinned keys
func NewPinnedProvider(pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) KeyChanFunc {
return func(ctx context.Context) (<-chan cid.Cid, error) {
set, err := pinSet(ctx, pinning, dag, onlyRoots)
if err != nil {
return nil, err
}
outCh := make(chan cid.Cid)
go func() {
defer close(outCh)
for c := range set.New {
select {
case <-ctx.Done():
return
case outCh <- c:
}
}
}()
return outCh, nil
}
}
func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) {
set := cidutil.NewStreamingSet()
go func() {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
defer close(set.New)
for _, key := range pinning.DirectKeys() {
set.Visitor(ctx)(key)
}
for _, key := range pinning.RecursiveKeys() {
set.Visitor(ctx)(key)
if !onlyRoots {
err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx))
if err != nil {
log.Errorf("reprovide indirect pins: %s", err)
return
}
}
}
}()
return set, nil
}