ipfs-cluster/adder/dagservice.go

124 lines
2.8 KiB
Go
Raw Normal View History

package adder
import (
"context"
"errors"
"fmt"
"github.com/ipfs/ipfs-cluster/api"
cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
var errNotFound = errors.New("dagservice: block not found")
func isNotFound(err error) bool {
return err == errNotFound
}
// adderDAGService implemengs a DAG Service and
// outputs any nodes added using this service to an Added.
type adderDAGService struct {
addedSet *cid.Set
addedChan chan<- *api.NodeWithMeta
}
func newAdderDAGService(ch chan *api.NodeWithMeta) ipld.DAGService {
set := cid.NewSet()
return &adderDAGService{
addedSet: set,
addedChan: ch,
}
}
// Add passes the provided node through the output channel
func (dag *adderDAGService) Add(ctx context.Context, node ipld.Node) error {
// FIXME ? This set will grow in memory.
// Maybe better to use a bloom filter
ok := dag.addedSet.Visit(node.Cid())
if !ok {
// don't re-add
return nil
}
size, err := node.Size()
if err != nil {
return err
}
nodeSerial := api.NodeWithMeta{
Cid: node.Cid().String(),
Data: node.RawData(),
Size: size,
}
if uint64(len(nodeSerial.Data)) != size {
logger.Warningf("fixme: node size doesnt match raw data length")
}
select {
case dag.addedChan <- &nodeSerial:
return nil
case <-ctx.Done():
close(dag.addedChan)
return errors.New("canceled context preempted dagservice add")
}
}
// AddMany passes the provided nodes through the output channel
func (dag *adderDAGService) AddMany(ctx context.Context, nodes []ipld.Node) error {
for _, node := range nodes {
err := dag.Add(ctx, node)
if err != nil {
return err
}
}
return nil
}
// Get always returns errNotFound
func (dag *adderDAGService) Get(ctx context.Context, key *cid.Cid) (ipld.Node, error) {
return nil, errNotFound
}
// GetMany returns an output channel that always emits an error
func (dag *adderDAGService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *ipld.NodeOption {
out := make(chan *ipld.NodeOption, 1)
out <- &ipld.NodeOption{Err: fmt.Errorf("failed to fetch all nodes")}
close(out)
return out
}
// Remove is a nop
func (dag *adderDAGService) Remove(ctx context.Context, key *cid.Cid) error {
return nil
}
// RemoveMany is a nop
func (dag *adderDAGService) RemoveMany(ctx context.Context, keys []*cid.Cid) error {
return nil
}
// // printDAGService will "add" a node by printing it. printDAGService cannot Get nodes
// // that have already been seen and calls to Remove are noops. Nodes are
// // recorded after being added so that they will only be printed once.
// type printDAGService struct {
// ads ipld.DAGService
// }
// func newPDagService() *printDAGService {
// ch := make(chan *api.NodeWithMeta)
// ads := newAdderDAGService(ch)
// go func() {
// for n := range ch {
// fmt.Printf(n.Cid, " | ", n.Size)
// }
// }()
// return &printDAGService{
// ads: ads,
// }
// }