mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-24 05:59:55 +08:00
Merge pull request #2359 from mildred/ipld
Simplify merkledag package interface to ease IPLD inclusion
This commit is contained in:
@ -77,12 +77,13 @@ Displays the links an IPFS or IPNS object(s) contains, with the following format
|
||||
Links: make([]LsLink, len(dagnode.Links)),
|
||||
}
|
||||
for j, link := range dagnode.Links {
|
||||
link.Node, err = link.GetNode(req.Context(), node.DAG)
|
||||
var linkNode *merkledag.Node
|
||||
linkNode, err = link.GetNode(req.Context(), node.DAG)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
d, err := unixfs.FromBytes(link.Node.Data)
|
||||
d, err := unixfs.FromBytes(linkNode.Data)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
|
@ -486,7 +486,7 @@ func objectPut(n *core.IpfsNode, input io.Reader, encoding string) (*Object, err
|
||||
}
|
||||
|
||||
case objectEncodingProtobuf:
|
||||
dagnode, err = dag.Decoded(data)
|
||||
dagnode, err = dag.DecodeProtobuf(data)
|
||||
|
||||
case objectEncodingXML:
|
||||
node := new(Node)
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
path "github.com/ipfs/go-ipfs/path"
|
||||
unixfs "github.com/ipfs/go-ipfs/unixfs"
|
||||
unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
|
||||
merkledag "github.com/ipfs/go-ipfs/merkledag"
|
||||
)
|
||||
|
||||
type LsLink struct {
|
||||
@ -104,12 +105,13 @@ size is the IPFS link size.
|
||||
links := make([]LsLink, len(merkleNode.Links))
|
||||
output.Objects[hash].Links = links
|
||||
for i, link := range merkleNode.Links {
|
||||
link.Node, err = link.GetNode(ctx, node.DAG)
|
||||
var linkNode *merkledag.Node
|
||||
linkNode, err = link.GetNode(ctx, node.DAG)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
d, err := unixfs.FromBytes(link.Node.Data)
|
||||
d, err := unixfs.FromBytes(linkNode.Data)
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
|
@ -453,16 +453,20 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
newnode := pathNodes[len(pathNodes)-1]
|
||||
for i := len(pathNodes) - 2; i >= 0; i-- {
|
||||
newnode, err = pathNodes[i].UpdateNodeLink(components[i], newnode)
|
||||
for j := len(pathNodes) - 2; j >= 0; j-- {
|
||||
if _, err := i.node.DAG.Add(newnode); err != nil {
|
||||
webError(w, "Could not add node", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
newnode, err = pathNodes[j].UpdateNodeLink(components[j], newnode)
|
||||
if err != nil {
|
||||
webError(w, "Could not update node links", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := i.node.DAG.AddRecursive(newnode); err != nil {
|
||||
webError(w, "Could not add recursively new node", err, http.StatusInternalServerError)
|
||||
if _, err := i.node.DAG.Add(newnode); err != nil {
|
||||
webError(w, "Could not add root node", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,12 @@ func TestIPNSHostnameRedirect(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = n.DAG.AddRecursive(dagn1)
|
||||
_, err = n.DAG.Add(dagn2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = n.DAG.Add(dagn1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -266,7 +271,15 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = n.DAG.AddRecursive(dagn1)
|
||||
_, err = n.DAG.Add(dagn3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = n.DAG.Add(dagn2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = n.DAG.Add(dagn1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ import (
|
||||
// for now, we use a PBNode intermediate thing.
|
||||
// because native go objects are nice.
|
||||
|
||||
// Unmarshal decodes raw data into a *Node instance.
|
||||
// unmarshal decodes raw data into a *Node instance.
|
||||
// The conversion uses an intermediate PBNode.
|
||||
func (n *Node) Unmarshal(encoded []byte) error {
|
||||
func (n *Node) unmarshal(encoded []byte) error {
|
||||
var pbn pb.PBNode
|
||||
if err := pbn.Unmarshal(encoded); err != nil {
|
||||
return fmt.Errorf("Unmarshal failed. %v", err)
|
||||
@ -27,7 +27,7 @@ func (n *Node) Unmarshal(encoded []byte) error {
|
||||
n.Links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
|
||||
h, err := mh.Cast(l.GetHash())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Link hash is not valid multihash. %v", err)
|
||||
return fmt.Errorf("Link hash #%d is not valid multihash. %v", i, err)
|
||||
}
|
||||
n.Links[i].Hash = h
|
||||
}
|
||||
@ -68,9 +68,9 @@ func (n *Node) getPBNode() *pb.PBNode {
|
||||
return pbn
|
||||
}
|
||||
|
||||
// Encoded returns the encoded raw data version of a Node instance.
|
||||
// EncodeProtobuf returns the encoded raw data version of a Node instance.
|
||||
// It may use a cached encoded version, unless the force flag is given.
|
||||
func (n *Node) Encoded(force bool) ([]byte, error) {
|
||||
func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
|
||||
sort.Stable(LinkSlice(n.Links)) // keep links sorted
|
||||
if n.encoded == nil || force {
|
||||
var err error
|
||||
@ -85,9 +85,9 @@ func (n *Node) Encoded(force bool) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Decoded decodes raw data and returns a new Node instance.
|
||||
func Decoded(encoded []byte) (*Node, error) {
|
||||
func DecodeProtobuf(encoded []byte) (*Node, error) {
|
||||
n := new(Node)
|
||||
err := n.Unmarshal(encoded)
|
||||
err := n.unmarshal(encoded)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("incorrectly formatted merkledag node: %s", err)
|
||||
}
|
||||
|
@ -18,10 +18,8 @@ var ErrNotFound = fmt.Errorf("merkledag: not found")
|
||||
// DAGService is an IPFS Merkle DAG service.
|
||||
type DAGService interface {
|
||||
Add(*Node) (key.Key, error)
|
||||
AddRecursive(*Node) error
|
||||
Get(context.Context, key.Key) (*Node, error)
|
||||
Remove(*Node) error
|
||||
RemoveRecursive(*Node) error
|
||||
|
||||
// GetDAG returns, in order, all the single leve child
|
||||
// nodes of the passed in node.
|
||||
@ -49,7 +47,7 @@ func (n *dagService) Add(nd *Node) (key.Key, error) {
|
||||
return "", fmt.Errorf("dagService is nil")
|
||||
}
|
||||
|
||||
d, err := nd.Encoded(false)
|
||||
d, err := nd.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -68,26 +66,6 @@ func (n *dagService) Batch() *Batch {
|
||||
return &Batch{ds: n, MaxSize: 8 * 1024 * 1024}
|
||||
}
|
||||
|
||||
// AddRecursive adds the given node and all child nodes to the BlockService
|
||||
func (n *dagService) AddRecursive(nd *Node) error {
|
||||
_, err := n.Add(nd)
|
||||
if err != nil {
|
||||
log.Info("AddRecursive Error: %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, link := range nd.Links {
|
||||
if link.Node != nil {
|
||||
err := n.AddRecursive(link.Node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves a node from the dagService, fetching the block in the BlockService
|
||||
func (n *dagService) Get(ctx context.Context, k key.Key) (*Node, error) {
|
||||
if n == nil {
|
||||
@ -101,24 +79,14 @@ func (n *dagService) Get(ctx context.Context, k key.Key) (*Node, error) {
|
||||
if err == bserv.ErrNotFound {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("Failed to get block for %s: %v", k.B58String(), err)
|
||||
}
|
||||
|
||||
return Decoded(b.Data)
|
||||
}
|
||||
|
||||
// Remove deletes the given node and all of its children from the BlockService
|
||||
func (n *dagService) RemoveRecursive(nd *Node) error {
|
||||
for _, l := range nd.Links {
|
||||
if l.Node != nil {
|
||||
n.RemoveRecursive(l.Node)
|
||||
}
|
||||
}
|
||||
k, err := nd.Key()
|
||||
res, err := DecodeProtobuf(b.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err)
|
||||
}
|
||||
return n.Blocks.DeleteBlock(k)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (n *dagService) Remove(nd *Node) error {
|
||||
@ -167,7 +135,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []key.Key) <-chan *NodeO
|
||||
}
|
||||
return
|
||||
}
|
||||
nd, err := Decoded(b.Data)
|
||||
nd, err := DecodeProtobuf(b.Data)
|
||||
if err != nil {
|
||||
out <- &NodeOption{Err: err}
|
||||
return
|
||||
@ -313,7 +281,7 @@ type Batch struct {
|
||||
}
|
||||
|
||||
func (t *Batch) Add(nd *Node) (key.Key, error) {
|
||||
d, err := nd.Encoded(false)
|
||||
d, err := nd.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func TestNode(t *testing.T) {
|
||||
fmt.Println("-", l.Name, l.Size, l.Hash)
|
||||
}
|
||||
|
||||
e, err := n.Encoded(false)
|
||||
e, err := n.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
@ -96,9 +96,9 @@ func TestNode(t *testing.T) {
|
||||
}
|
||||
|
||||
func SubtestNodeStat(t *testing.T, n *Node) {
|
||||
enc, err := n.Encoded(true)
|
||||
enc, err := n.EncodeProtobuf(true)
|
||||
if err != nil {
|
||||
t.Error("n.Encoded(true) failed")
|
||||
t.Error("n.EncodeProtobuf(true) failed")
|
||||
return
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = dagservs[0].AddRecursive(root)
|
||||
_, err = dagservs[0].Add(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -232,45 +232,6 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestRecursiveAdd(t *testing.T) {
|
||||
a := &Node{Data: []byte("A")}
|
||||
b := &Node{Data: []byte("B")}
|
||||
c := &Node{Data: []byte("C")}
|
||||
d := &Node{Data: []byte("D")}
|
||||
e := &Node{Data: []byte("E")}
|
||||
|
||||
err := a.AddNodeLink("blah", b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = b.AddNodeLink("foo", c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = b.AddNodeLink("bar", d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = d.AddNodeLink("baz", e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dsp := getDagservAndPinner(t)
|
||||
err = dsp.ds.AddRecursive(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertCanGet(t, dsp.ds, a)
|
||||
assertCanGet(t, dsp.ds, b)
|
||||
assertCanGet(t, dsp.ds, c)
|
||||
assertCanGet(t, dsp.ds, d)
|
||||
assertCanGet(t, dsp.ds, e)
|
||||
}
|
||||
|
||||
func assertCanGet(t *testing.T, ds DAGService, n *Node) {
|
||||
k, err := n.Key()
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
|
||||
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
|
||||
|
||||
mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
|
||||
key "github.com/ipfs/go-ipfs/blocks/key"
|
||||
mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
|
||||
)
|
||||
|
||||
var ErrLinkNotFound = fmt.Errorf("no link by that name")
|
||||
@ -48,9 +48,6 @@ type Link struct {
|
||||
|
||||
// multihash of the target object
|
||||
Hash mh.Multihash
|
||||
|
||||
// a ptr to the actual node for graph manipulation
|
||||
Node *Node
|
||||
}
|
||||
|
||||
type LinkSlice []*Link
|
||||
@ -78,10 +75,6 @@ func MakeLink(n *Node) (*Link, error) {
|
||||
|
||||
// GetNode returns the MDAG Node that this link points to
|
||||
func (l *Link) GetNode(ctx context.Context, serv DAGService) (*Node, error) {
|
||||
if l.Node != nil {
|
||||
return l.Node, nil
|
||||
}
|
||||
|
||||
return serv.Get(ctx, key.Key(l.Hash))
|
||||
}
|
||||
|
||||
@ -92,7 +85,6 @@ func (n *Node) AddNodeLink(name string, that *Node) error {
|
||||
lnk, err := MakeLink(that)
|
||||
|
||||
lnk.Name = name
|
||||
lnk.Node = that
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -122,7 +114,6 @@ func (n *Node) AddRawLink(name string, l *Link) error {
|
||||
Name: name,
|
||||
Size: l.Size,
|
||||
Hash: l.Hash,
|
||||
Node: l.Node,
|
||||
})
|
||||
|
||||
return nil
|
||||
@ -158,7 +149,6 @@ func (n *Node) GetNodeLink(name string) (*Link, error) {
|
||||
Name: l.Name,
|
||||
Size: l.Size,
|
||||
Hash: l.Hash,
|
||||
Node: l.Node,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
@ -203,7 +193,7 @@ func (n *Node) UpdateNodeLink(name string, that *Node) (*Node, error) {
|
||||
// Size returns the total size of the data addressed by node,
|
||||
// including the total sizes of references.
|
||||
func (n *Node) Size() (uint64, error) {
|
||||
b, err := n.Encoded(false)
|
||||
b, err := n.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -217,7 +207,7 @@ func (n *Node) Size() (uint64, error) {
|
||||
|
||||
// Stat returns statistics on the node.
|
||||
func (n *Node) Stat() (*NodeStat, error) {
|
||||
enc, err := n.Encoded(false)
|
||||
enc, err := n.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -244,8 +234,8 @@ func (n *Node) Stat() (*NodeStat, error) {
|
||||
|
||||
// Multihash hashes the encoded data of this node.
|
||||
func (n *Node) Multihash() (mh.Multihash, error) {
|
||||
// Note: Encoded generates the hash and puts it in n.cached.
|
||||
_, err := n.Encoded(false)
|
||||
// Note: EncodeProtobuf generates the hash and puts it in n.cached.
|
||||
_, err := n.EncodeProtobuf(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,12 +6,14 @@ import (
|
||||
"testing"
|
||||
|
||||
mdag "github.com/ipfs/go-ipfs/merkledag"
|
||||
mdagtest "github.com/ipfs/go-ipfs/merkledag/test"
|
||||
)
|
||||
|
||||
func TestDFSPreNoSkip(t *testing.T) {
|
||||
opts := Options{Order: DFSPre}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: DFSPre, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -19,7 +21,7 @@ func TestDFSPreNoSkip(t *testing.T) {
|
||||
1 /a/ad
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -27,7 +29,7 @@ func TestDFSPreNoSkip(t *testing.T) {
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -37,7 +39,7 @@ func TestDFSPreNoSkip(t *testing.T) {
|
||||
2 /a/ab/abb
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -73,9 +75,10 @@ func TestDFSPreNoSkip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDFSPreSkip(t *testing.T) {
|
||||
opts := Options{Order: DFSPre, SkipDuplicates: true}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: DFSPre, SkipDuplicates: true, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -83,7 +86,7 @@ func TestDFSPreSkip(t *testing.T) {
|
||||
1 /a/ad
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -91,7 +94,7 @@ func TestDFSPreSkip(t *testing.T) {
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -101,7 +104,7 @@ func TestDFSPreSkip(t *testing.T) {
|
||||
2 /a/ab/abb
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -111,9 +114,10 @@ func TestDFSPreSkip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDFSPostNoSkip(t *testing.T) {
|
||||
opts := Options{Order: DFSPost}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: DFSPost, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
1 /a/ac
|
||||
@ -121,7 +125,7 @@ func TestDFSPostNoSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
3 /a/aa/aaa/aaaa
|
||||
2 /a/aa/aaa
|
||||
@ -129,7 +133,7 @@ func TestDFSPostNoSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
2 /a/aa/aaa
|
||||
2 /a/aa/aab
|
||||
1 /a/aa
|
||||
@ -139,7 +143,7 @@ func TestDFSPostNoSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
3 /a/aa/aaa/aaaa
|
||||
@ -175,9 +179,10 @@ func TestDFSPostNoSkip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDFSPostSkip(t *testing.T) {
|
||||
opts := Options{Order: DFSPost, SkipDuplicates: true}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: DFSPost, SkipDuplicates: true, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
1 /a/ac
|
||||
@ -185,7 +190,7 @@ func TestDFSPostSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
3 /a/aa/aaa/aaaa
|
||||
2 /a/aa/aaa
|
||||
@ -193,7 +198,7 @@ func TestDFSPostSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
2 /a/aa/aaa
|
||||
2 /a/aa/aab
|
||||
1 /a/aa
|
||||
@ -203,7 +208,7 @@ func TestDFSPostSkip(t *testing.T) {
|
||||
0 /a
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
3 /a/aa/aaa/aaaa
|
||||
2 /a/aa/aaa
|
||||
@ -213,9 +218,10 @@ func TestDFSPostSkip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBFSNoSkip(t *testing.T) {
|
||||
opts := Options{Order: BFS}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: BFS, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -223,7 +229,7 @@ func TestBFSNoSkip(t *testing.T) {
|
||||
1 /a/ad
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -231,7 +237,7 @@ func TestBFSNoSkip(t *testing.T) {
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -241,7 +247,7 @@ func TestBFSNoSkip(t *testing.T) {
|
||||
2 /a/ab/abb
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/aa
|
||||
@ -277,9 +283,10 @@ func TestBFSNoSkip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBFSSkip(t *testing.T) {
|
||||
opts := Options{Order: BFS, SkipDuplicates: true}
|
||||
ds := mdagtest.Mock()
|
||||
opts := Options{Order: BFS, SkipDuplicates: true, DAG: ds}
|
||||
|
||||
testWalkOutputs(t, newFan(t), opts, []byte(`
|
||||
testWalkOutputs(t, newFan(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -287,7 +294,7 @@ func TestBFSSkip(t *testing.T) {
|
||||
1 /a/ad
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newLinkedList(t), opts, []byte(`
|
||||
testWalkOutputs(t, newLinkedList(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -295,7 +302,7 @@ func TestBFSSkip(t *testing.T) {
|
||||
4 /a/aa/aaa/aaaa/aaaaa
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryTree(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryTree(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
1 /a/ab
|
||||
@ -305,7 +312,7 @@ func TestBFSSkip(t *testing.T) {
|
||||
2 /a/ab/abb
|
||||
`))
|
||||
|
||||
testWalkOutputs(t, newBinaryDAG(t), opts, []byte(`
|
||||
testWalkOutputs(t, newBinaryDAG(t, ds), opts, []byte(`
|
||||
0 /a
|
||||
1 /a/aa
|
||||
2 /a/aa/aaa
|
||||
@ -341,57 +348,68 @@ func testWalkOutputs(t *testing.T, root *mdag.Node, opts Options, expect []byte)
|
||||
}
|
||||
}
|
||||
|
||||
func newFan(t *testing.T) *mdag.Node {
|
||||
func newFan(t *testing.T, ds mdag.DAGService) *mdag.Node {
|
||||
a := &mdag.Node{Data: []byte("/a")}
|
||||
addChild(t, a, "aa")
|
||||
addChild(t, a, "ab")
|
||||
addChild(t, a, "ac")
|
||||
addChild(t, a, "ad")
|
||||
addLink(t, ds, a, child(t, ds, a, "aa"))
|
||||
addLink(t, ds, a, child(t, ds, a, "ab"))
|
||||
addLink(t, ds, a, child(t, ds, a, "ac"))
|
||||
addLink(t, ds, a, child(t, ds, a, "ad"))
|
||||
return a
|
||||
}
|
||||
|
||||
func newLinkedList(t *testing.T) *mdag.Node {
|
||||
func newLinkedList(t *testing.T, ds mdag.DAGService) *mdag.Node {
|
||||
a := &mdag.Node{Data: []byte("/a")}
|
||||
aa := addChild(t, a, "aa")
|
||||
aaa := addChild(t, aa, "aaa")
|
||||
aaaa := addChild(t, aaa, "aaaa")
|
||||
addChild(t, aaaa, "aaaaa")
|
||||
aa := child(t, ds, a, "aa")
|
||||
aaa := child(t, ds, aa, "aaa")
|
||||
aaaa := child(t, ds, aaa, "aaaa")
|
||||
aaaaa := child(t, ds, aaaa, "aaaaa")
|
||||
addLink(t, ds, aaaa, aaaaa)
|
||||
addLink(t, ds, aaa, aaaa)
|
||||
addLink(t, ds, aa, aaa)
|
||||
addLink(t, ds, a, aa)
|
||||
return a
|
||||
}
|
||||
|
||||
func newBinaryTree(t *testing.T) *mdag.Node {
|
||||
func newBinaryTree(t *testing.T, ds mdag.DAGService) *mdag.Node {
|
||||
a := &mdag.Node{Data: []byte("/a")}
|
||||
aa := addChild(t, a, "aa")
|
||||
ab := addChild(t, a, "ab")
|
||||
addChild(t, aa, "aaa")
|
||||
addChild(t, aa, "aab")
|
||||
addChild(t, ab, "aba")
|
||||
addChild(t, ab, "abb")
|
||||
aa := child(t, ds, a, "aa")
|
||||
ab := child(t, ds, a, "ab")
|
||||
addLink(t, ds, aa, child(t, ds, aa, "aaa"))
|
||||
addLink(t, ds, aa, child(t, ds, aa, "aab"))
|
||||
addLink(t, ds, ab, child(t, ds, ab, "aba"))
|
||||
addLink(t, ds, ab, child(t, ds, ab, "abb"))
|
||||
addLink(t, ds, a, aa)
|
||||
addLink(t, ds, a, ab)
|
||||
return a
|
||||
}
|
||||
|
||||
func newBinaryDAG(t *testing.T) *mdag.Node {
|
||||
func newBinaryDAG(t *testing.T, ds mdag.DAGService) *mdag.Node {
|
||||
a := &mdag.Node{Data: []byte("/a")}
|
||||
aa := addChild(t, a, "aa")
|
||||
aaa := addChild(t, aa, "aaa")
|
||||
aaaa := addChild(t, aaa, "aaaa")
|
||||
aaaaa := addChild(t, aaaa, "aaaaa")
|
||||
addLink(t, a, aa)
|
||||
addLink(t, aa, aaa)
|
||||
addLink(t, aaa, aaaa)
|
||||
addLink(t, aaaa, aaaaa)
|
||||
aa := child(t, ds, a, "aa")
|
||||
aaa := child(t, ds, aa, "aaa")
|
||||
aaaa := child(t, ds, aaa, "aaaa")
|
||||
aaaaa := child(t, ds, aaaa, "aaaaa")
|
||||
addLink(t, ds, aaaa, aaaaa)
|
||||
addLink(t, ds, aaaa, aaaaa)
|
||||
addLink(t, ds, aaa, aaaa)
|
||||
addLink(t, ds, aaa, aaaa)
|
||||
addLink(t, ds, aa, aaa)
|
||||
addLink(t, ds, aa, aaa)
|
||||
addLink(t, ds, a, aa)
|
||||
addLink(t, ds, a, aa)
|
||||
return a
|
||||
}
|
||||
|
||||
func addLink(t *testing.T, a, b *mdag.Node) {
|
||||
func addLink(t *testing.T, ds mdag.DAGService, a, b *mdag.Node) {
|
||||
to := string(a.Data) + "2" + string(b.Data)
|
||||
if _, err := ds.Add(b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := a.AddNodeLink(to, b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func addChild(t *testing.T, a *mdag.Node, name string) *mdag.Node {
|
||||
c := &mdag.Node{Data: []byte(string(a.Data) + "/" + name)}
|
||||
addLink(t, a, c)
|
||||
return c
|
||||
func child(t *testing.T, ds mdag.DAGService, a *mdag.Node, name string) *mdag.Node {
|
||||
return &mdag.Node{Data: []byte(string(a.Data) + "/" + name)}
|
||||
}
|
||||
|
@ -111,37 +111,20 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd *merkledag.Node, names
|
||||
// for each of the path components
|
||||
for _, name := range names {
|
||||
|
||||
var next key.Key
|
||||
var nlink *merkledag.Link
|
||||
// for each of the links in nd, the current object
|
||||
for _, link := range nd.Links {
|
||||
if link.Name == name {
|
||||
next = key.Key(link.Hash)
|
||||
nlink = link
|
||||
break
|
||||
}
|
||||
}
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Minute)
|
||||
defer cancel()
|
||||
|
||||
if next == "" {
|
||||
nextnode, err := nd.GetLinkedNode(ctx, s.DAG, name)
|
||||
if err == merkledag.ErrLinkNotFound {
|
||||
n, _ := nd.Multihash()
|
||||
return result, ErrNoLink{Name: name, Node: n}
|
||||
} else if err != nil {
|
||||
return append(result, nextnode), err
|
||||
}
|
||||
|
||||
if nlink.Node == nil {
|
||||
// fetch object for link and assign to nd
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Minute)
|
||||
defer cancel()
|
||||
var err error
|
||||
nd, err = s.DAG.Get(ctx, next)
|
||||
if err != nil {
|
||||
return append(result, nd), err
|
||||
}
|
||||
nlink.Node = nd
|
||||
} else {
|
||||
nd = nlink.Node
|
||||
}
|
||||
|
||||
result = append(result, nlink.Node)
|
||||
nd = nextnode
|
||||
result = append(result, nextnode)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
@ -39,9 +39,11 @@ func TestRecurivePathResolution(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = dagService.AddRecursive(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
for _, n := range []*merkledag.Node{a, b, c} {
|
||||
_, err = dagService.Add(n)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
aKey, err := a.Key()
|
||||
|
@ -104,7 +104,11 @@ func TestPinnerBasic(t *testing.T) {
|
||||
d.AddNodeLink("e", e)
|
||||
|
||||
// Must be in dagserv for unpin to work
|
||||
err = dserv.AddRecursive(d)
|
||||
_, err = dserv.Add(e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = dserv.Add(d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ import (
|
||||
"sort"
|
||||
"unsafe"
|
||||
|
||||
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
|
||||
"github.com/ipfs/go-ipfs/blocks/key"
|
||||
"github.com/ipfs/go-ipfs/merkledag"
|
||||
"github.com/ipfs/go-ipfs/pin/internal/pb"
|
||||
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
|
||||
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
|
||||
)
|
||||
|
||||
@ -172,7 +172,6 @@ func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint
|
||||
Name: "",
|
||||
Hash: childKey.ToMultihash(),
|
||||
Size: size,
|
||||
Node: child,
|
||||
}
|
||||
n.Links[int(h%defaultFanout)] = l
|
||||
}
|
||||
@ -272,12 +271,12 @@ func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node
|
||||
func loadMultiset(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node, name string, internalKeys keyObserver) (map[key.Key]uint64, error) {
|
||||
l, err := root.GetNodeLink(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("Failed to get link %s: %v", name, err)
|
||||
}
|
||||
internalKeys(key.Key(l.Hash))
|
||||
n, err := l.GetNode(ctx, dag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("Failed to get node from link %s: %v", name, err)
|
||||
}
|
||||
|
||||
refcounts := make(map[key.Key]uint64)
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"github.com/ipfs/go-ipfs/blockservice"
|
||||
"github.com/ipfs/go-ipfs/exchange/offline"
|
||||
"github.com/ipfs/go-ipfs/merkledag"
|
||||
mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
|
||||
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
|
||||
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
|
||||
)
|
||||
|
||||
@ -31,6 +33,14 @@ func TestMultisetRoundtrip(t *testing.T) {
|
||||
dag := merkledag.NewDAGService(bserv)
|
||||
|
||||
fn := func(m map[key.Key]uint16) bool {
|
||||
// Convert invalid multihash from input to valid ones
|
||||
for k, v := range m {
|
||||
if _, err := mh.Cast([]byte(k)); err != nil {
|
||||
delete(m, k)
|
||||
m[key.Key(u.Hash([]byte(k)))] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a smaller range for refcounts than full uint64, as
|
||||
// otherwise this just becomes overly cpu heavy, splitting it
|
||||
// out into too many items. That means we need to convert to
|
||||
@ -43,6 +53,17 @@ func TestMultisetRoundtrip(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("storing multiset: %v", err)
|
||||
}
|
||||
|
||||
// Check that the node n is in the DAG
|
||||
k, err := n.Key()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get key: %v", err)
|
||||
}
|
||||
_, err = dag.Get(ctx, k)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get node: %v", err)
|
||||
}
|
||||
|
||||
root := &merkledag.Node{}
|
||||
const linkName = "dummylink"
|
||||
if err := root.AddNodeLink(linkName, n); err != nil {
|
||||
|
@ -258,7 +258,7 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
|
||||
node.Links[i].Hash = mh.Multihash(k)
|
||||
|
||||
// Recache serialized node
|
||||
_, err = node.Encoded(true)
|
||||
_, err = node.EncodeProtobuf(true)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
@ -489,7 +489,7 @@ func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGSer
|
||||
nd.Data = d
|
||||
|
||||
// invalidate cache and recompute serialized data
|
||||
_, err = nd.Encoded(true)
|
||||
_, err = nd.EncodeProtobuf(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user