merkledag: change 'Node' to be an interface
Also change existing 'Node' type to 'ProtoNode' and use that most everywhere for now. As we move forward with the integration we will try and use the Node interface in more places that we're currently using ProtoNode. License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Oct 9, 2016 at 12:59 UTC
01aee44679dd8cacd0ca198206041e3c3d7c48af
61 files changed
+850
-521
blocks/blocks.go
-1
@@ -14,7 +14,6 @@ import (
14
var ErrWrongHash = errors.New("data did not match given hash!")
15
16
type Block interface {
17
- Multihash() mh.Multihash
17
RawData() []byte
18
Cid() *cid.Cid
19
String() string
blockservice/test/blocks_test.go
+6
-20
@@ -18,18 +18,8 @@ import (
18
dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
19
)
20
21
-func newObject(data []byte) *testObject {
22
- return &testObject{
23
- Block: blocks.NewBlock(data),
24
- }
25
-}
26
-
27
-type testObject struct {
28
- blocks.Block
29
-}
30
-
31
-func (o *testObject) Cid() *cid.Cid {
32
- return cid.NewCidV0(o.Block.Multihash())
21
+func newObject(data []byte) blocks.Block {
22
+ return blocks.NewBlock(data)
23
}
24
25
func TestBlocks(t *testing.T) {
@@ -38,12 +28,8 @@ func TestBlocks(t *testing.T) {
28
defer bs.Close()
29
30
o := newObject([]byte("beep boop"))
41
- h := u.Hash([]byte("beep boop"))
42
- if !bytes.Equal(o.Multihash(), h) {
43
- t.Error("Block Multihash and data multihash not equal")
44
- }
45
-
46
- if !o.Cid().Equals(cid.NewCidV0(h)) {
31
+ h := cid.NewCidV0(u.Hash([]byte("beep boop")))
32
+ if !o.Cid().Equals(h) {
33
t.Error("Block key and data multihash key not equal")
34
}
35
@@ -74,8 +60,8 @@ func TestBlocks(t *testing.T) {
60
}
61
}
62
77
-func makeObjects(n int) []*testObject {
78
- var out []*testObject
63
+func makeObjects(n int) []blocks.Block {
64
+ var out []blocks.Block
65
for i := 0; i < n; i++ {
66
out = append(out, newObject([]byte(fmt.Sprintf("object %d", i))))
67
}
core/commands/files/files.go
+13
-3
@@ -182,7 +182,7 @@ func statNode(ds dag.DAGService, fsn mfs.FSNode) (*Object, error) {
182
183
return &Object{
184
Hash: c.String(),
185
- Blocks: len(nd.Links),
185
+ Blocks: len(nd.Links()),
186
Size: d.GetFilesize(),
187
CumulativeSize: cumulsize,
188
Type: ndtype,
@@ -245,7 +245,7 @@ var FilesCpCmd = &cmds.Command{
245
},
246
}
247
248
-func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.Node, error) {
248
+func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.ProtoNode, error) {
249
switch {
250
case strings.HasPrefix(p, "/ipfs/"):
251
np, err := path.ParsePath(p)
@@ -253,7 +253,17 @@ func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.N
253
return nil, err
254
}
255
256
- return core.Resolve(ctx, node, np)
256
+ nd, err := core.Resolve(ctx, node, np)
257
+ if err != nil {
258
+ return nil, err
259
+ }
260
+
261
+ pbnd, ok := nd.(*dag.ProtoNode)
262
+ if !ok {
263
+ return nil, dag.ErrNotProtobuf
264
+ }
265
+
266
+ return pbnd, nil
267
default:
268
fsn, err := mfs.Lookup(node.FilesRoot, p)
269
if err != nil {
core/commands/get.go
+8
-1
@@ -13,6 +13,7 @@ import (
13
14
cmds "github.com/ipfs/go-ipfs/commands"
15
core "github.com/ipfs/go-ipfs/core"
16
+ dag "github.com/ipfs/go-ipfs/merkledag"
17
path "github.com/ipfs/go-ipfs/path"
18
tar "github.com/ipfs/go-ipfs/thirdparty/tar"
19
uarchive "github.com/ipfs/go-ipfs/unixfs/archive"
@@ -69,6 +70,12 @@ may also specify the level of compression by specifying '-l=<1-9>'.
70
return
71
}
72
73
+ pbnd, ok := dn.(*dag.ProtoNode)
74
+ if !ok {
75
+ res.SetError(err, cmds.ErrNormal)
76
+ return
77
+ }
78
+
79
size, err := dn.Size()
80
if err != nil {
81
res.SetError(err, cmds.ErrNormal)
@@ -78,7 +85,7 @@ may also specify the level of compression by specifying '-l=<1-9>'.
85
res.SetLength(size)
86
87
archive, _, _ := req.Option("archive").Bool()
81
- reader, err := uarchive.DagArchive(ctx, dn, p.String(), node.DAG, archive, cmplvl)
88
+ reader, err := uarchive.DagArchive(ctx, pbnd, p.String(), node.DAG, archive, cmplvl)
89
if err != nil {
90
res.SetError(err, cmds.ErrNormal)
91
return
core/commands/ls.go
+15
-9
@@ -12,8 +12,6 @@ import (
12
path "github.com/ipfs/go-ipfs/path"
13
unixfs "github.com/ipfs/go-ipfs/unixfs"
14
unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
15
-
16
- cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
15
)
16
17
type LsLink struct {
@@ -72,7 +70,7 @@ The JSON output contains type information.
70
71
paths := req.Arguments()
72
75
- var dagnodes []*merkledag.Node
73
+ var dagnodes []merkledag.Node
74
for _, fpath := range paths {
75
dagnode, err := core.Resolve(req.Context(), node, path.Path(fpath))
76
if err != nil {
@@ -86,12 +84,12 @@ The JSON output contains type information.
84
for i, dagnode := range dagnodes {
85
output[i] = LsObject{
86
Hash: paths[i],
89
- Links: make([]LsLink, len(dagnode.Links)),
87
+ Links: make([]LsLink, len(dagnode.Links())),
88
}
91
- for j, link := range dagnode.Links {
92
- var linkNode *merkledag.Node
89
+ for j, link := range dagnode.Links() {
90
+ var linkNode *merkledag.ProtoNode
91
t := unixfspb.Data_DataType(-1)
94
- linkKey := cid.NewCidV0(link.Hash)
92
+ linkKey := link.Cid
93
if ok, err := node.Blockstore.Has(linkKey); ok && err == nil {
94
b, err := node.Blockstore.Get(linkKey)
95
if err != nil {
@@ -106,11 +104,19 @@ The JSON output contains type information.
104
}
105
106
if linkNode == nil && resolve {
109
- linkNode, err = link.GetNode(req.Context(), node.DAG)
107
+ nd, err := link.GetNode(req.Context(), node.DAG)
108
if err != nil {
109
res.SetError(err, cmds.ErrNormal)
110
return
111
}
112
+
113
+ pbnd, ok := nd.(*merkledag.ProtoNode)
114
+ if !ok {
115
+ res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
116
+ return
117
+ }
118
+
119
+ linkNode = pbnd
120
}
121
if linkNode != nil {
122
d, err := unixfs.FromBytes(linkNode.Data())
@@ -123,7 +129,7 @@ The JSON output contains type information.
129
}
130
output[i].Links[j] = LsLink{
131
Name: link.Name,
126
- Hash: link.Hash.B58String(),
132
+ Hash: link.Cid.String(),
133
Size: link.Size,
134
Type: t,
135
}
core/commands/object/diff.go
+14
-1
@@ -7,6 +7,7 @@ import (
7
8
cmds "github.com/ipfs/go-ipfs/commands"
9
core "github.com/ipfs/go-ipfs/core"
10
+ dag "github.com/ipfs/go-ipfs/merkledag"
11
dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
12
path "github.com/ipfs/go-ipfs/path"
13
)
@@ -85,7 +86,19 @@ Example:
86
return
87
}
88
88
- changes, err := dagutils.Diff(ctx, node.DAG, obj_a, obj_b)
89
+ pbobj_a, ok := obj_a.(*dag.ProtoNode)
90
+ if !ok {
91
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
92
+ return
93
+ }
94
+
95
+ pbobj_b, ok := obj_b.(*dag.ProtoNode)
96
+ if !ok {
97
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
98
+ return
99
+ }
100
+
101
+ changes, err := dagutils.Diff(ctx, node.DAG, pbobj_a, pbobj_b)
102
if err != nil {
103
res.SetError(err, cmds.ErrNormal)
104
return
core/commands/object/object.go
+35
-21
@@ -12,13 +12,13 @@ import (
12
"strings"
13
"text/tabwriter"
14
15
- mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
16
-
15
cmds "github.com/ipfs/go-ipfs/commands"
16
core "github.com/ipfs/go-ipfs/core"
17
dag "github.com/ipfs/go-ipfs/merkledag"
18
path "github.com/ipfs/go-ipfs/path"
19
ft "github.com/ipfs/go-ipfs/unixfs"
20
+
21
+ cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
22
)
23
24
// ErrObjectTooLarge is returned when too much data was read from stdin. current limit 2m
@@ -98,7 +98,14 @@ is the raw data of the object.
98
res.SetError(err, cmds.ErrNormal)
99
return
100
}
101
- res.SetOutput(bytes.NewReader(node.Data()))
101
+
102
+ pbnode, ok := node.(*dag.ProtoNode)
103
+ if !ok {
104
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
105
+ return
106
+ }
107
+
108
+ res.SetOutput(bytes.NewReader(pbnode.Data()))
109
},
110
}
111
@@ -137,6 +144,7 @@ multihash.
144
res.SetError(err, cmds.ErrNormal)
145
return
146
}
147
+
148
output, err := getOutput(node)
149
if err != nil {
150
res.SetError(err, cmds.ErrNormal)
@@ -201,14 +209,20 @@ This command outputs data in the following encodings:
209
return
210
}
211
212
+ pbo, ok := object.(*dag.ProtoNode)
213
+ if !ok {
214
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
215
+ return
216
+ }
217
+
218
node := &Node{
205
- Links: make([]Link, len(object.Links)),
206
- Data: string(object.Data()),
219
+ Links: make([]Link, len(object.Links())),
220
+ Data: string(pbo.Data()),
221
}
222
209
- for i, link := range object.Links {
223
+ for i, link := range object.Links() {
224
node.Links[i] = Link{
211
- Hash: link.Hash.B58String(),
225
+ Hash: link.Cid.String(),
226
Name: link.Name,
227
Size: link.Size,
228
}
@@ -413,7 +427,7 @@ Available templates:
427
return
428
}
429
416
- node := new(dag.Node)
430
+ node := new(dag.ProtoNode)
431
if len(req.Arguments()) == 1 {
432
template := req.Arguments()[0]
433
var err error
@@ -440,7 +454,7 @@ Available templates:
454
Type: Object{},
455
}
456
443
-func nodeFromTemplate(template string) (*dag.Node, error) {
457
+func nodeFromTemplate(template string) (*dag.ProtoNode, error) {
458
switch template {
459
case "unixfs-dir":
460
return ft.EmptyDirNode(), nil
@@ -464,7 +478,7 @@ func objectPut(n *core.IpfsNode, input io.Reader, encoding string, dataFieldEnco
478
return nil, ErrObjectTooLarge
479
}
480
467
- var dagnode *dag.Node
481
+ var dagnode *dag.ProtoNode
482
switch getObjectEnc(encoding) {
483
case objectEncodingJSON:
484
node := new(Node)
@@ -542,17 +556,17 @@ func getObjectEnc(o interface{}) objectEncoding {
556
return objectEncoding(v)
557
}
558
545
-func getOutput(dagnode *dag.Node) (*Object, error) {
559
+func getOutput(dagnode dag.Node) (*Object, error) {
560
c := dagnode.Cid()
561
output := &Object{
562
Hash: c.String(),
549
- Links: make([]Link, len(dagnode.Links)),
563
+ Links: make([]Link, len(dagnode.Links())),
564
}
565
552
- for i, link := range dagnode.Links {
566
+ for i, link := range dagnode.Links() {
567
output.Links[i] = Link{
568
Name: link.Name,
555
- Hash: link.Hash.B58String(),
569
+ Hash: link.Cid.String(),
570
Size: link.Size,
571
}
572
}
@@ -560,9 +574,9 @@ func getOutput(dagnode *dag.Node) (*Object, error) {
574
return output, nil
575
}
576
563
-// converts the Node object into a real dag.Node
564
-func deserializeNode(node *Node, dataFieldEncoding string) (*dag.Node, error) {
565
- dagnode := new(dag.Node)
577
+// converts the Node object into a real dag.ProtoNode
578
+func deserializeNode(node *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
579
+ dagnode := new(dag.ProtoNode)
580
switch dataFieldEncoding {
581
case "text":
582
dagnode.SetData([]byte(node.Data))
@@ -573,16 +587,16 @@ func deserializeNode(node *Node, dataFieldEncoding string) (*dag.Node, error) {
587
return nil, fmt.Errorf("Unkown data field encoding")
588
}
589
576
- dagnode.Links = make([]*dag.Link, len(node.Links))
590
+ dagnode.SetLinks(make([]*dag.Link, len(node.Links)))
591
for i, link := range node.Links {
578
- hash, err := mh.FromB58String(link.Hash)
592
+ c, err := cid.Decode(link.Hash)
593
if err != nil {
594
return nil, err
595
}
582
- dagnode.Links[i] = &dag.Link{
596
+ dagnode.Links()[i] = &dag.Link{
597
Name: link.Name,
598
Size: link.Size,
585
- Hash: hash,
599
+ Cid: c,
600
}
601
}
602
core/commands/object/patch.go
+38
-8
@@ -79,6 +79,12 @@ the limit will not be respected by the network.
79
return
80
}
81
82
+ rtpb, ok := rootnd.(*dag.ProtoNode)
83
+ if !ok {
84
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
85
+ return
86
+ }
87
+
88
fi, err := req.Files().NextFile()
89
if err != nil {
90
res.SetError(err, cmds.ErrNormal)
@@ -91,9 +97,9 @@ the limit will not be respected by the network.
97
return
98
}
99
94
- rootnd.SetData(append(rootnd.Data(), data...))
100
+ rtpb.SetData(append(rtpb.Data(), data...))
101
96
- newkey, err := nd.DAG.Add(rootnd)
102
+ newkey, err := nd.DAG.Add(rtpb)
103
if err != nil {
104
res.SetError(err, cmds.ErrNormal)
105
return
@@ -141,6 +147,12 @@ Example:
147
return
148
}
149
150
+ rtpb, ok := root.(*dag.ProtoNode)
151
+ if !ok {
152
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
153
+ return
154
+ }
155
+
156
fi, err := req.Files().NextFile()
157
if err != nil {
158
res.SetError(err, cmds.ErrNormal)
@@ -153,9 +165,9 @@ Example:
165
return
166
}
167
156
- root.SetData(data)
168
+ rtpb.SetData(data)
169
158
- newkey, err := nd.DAG.Add(root)
170
+ newkey, err := nd.DAG.Add(rtpb)
171
if err != nil {
172
res.SetError(err, cmds.ErrNormal)
173
return
@@ -199,9 +211,15 @@ Removes a link by the given name from root.
211
return
212
}
213
214
+ rtpb, ok := root.(*dag.ProtoNode)
215
+ if !ok {
216
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
217
+ return
218
+ }
219
+
220
path := req.Arguments()[1]
221
204
- e := dagutils.NewDagEditor(root, nd.DAG)
222
+ e := dagutils.NewDagEditor(rtpb, nd.DAG)
223
224
err = e.RmLink(req.Context(), path)
225
if err != nil {
@@ -268,6 +286,12 @@ to a file containing 'bar', and returns the hash of the new object.
286
return
287
}
288
289
+ rtpb, ok := root.(*dag.ProtoNode)
290
+ if !ok {
291
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
292
+ return
293
+ }
294
+
295
npath := req.Arguments()[1]
296
childp, err := path.ParsePath(req.Arguments()[2])
297
if err != nil {
@@ -281,12 +305,12 @@ to a file containing 'bar', and returns the hash of the new object.
305
return
306
}
307
284
- var createfunc func() *dag.Node
308
+ var createfunc func() *dag.ProtoNode
309
if create {
310
createfunc = ft.EmptyDirNode
311
}
312
289
- e := dagutils.NewDagEditor(root, nd.DAG)
313
+ e := dagutils.NewDagEditor(rtpb, nd.DAG)
314
315
childnd, err := core.Resolve(req.Context(), nd, childp)
316
if err != nil {
@@ -294,7 +318,13 @@ to a file containing 'bar', and returns the hash of the new object.
318
return
319
}
320
297
- err = e.InsertNodeAtPath(req.Context(), npath, childnd, createfunc)
321
+ chpb, ok := childnd.(*dag.ProtoNode)
322
+ if !ok {
323
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
324
+ return
325
+ }
326
+
327
+ err = e.InsertNodeAtPath(req.Context(), npath, chpb, createfunc)
328
if err != nil {
329
res.SetError(err, cmds.ErrNormal)
330
return
core/commands/refs.go
+9
-10
@@ -195,8 +195,8 @@ var refsMarshallerMap = cmds.MarshalerMap{
195
},
196
}
197
198
-func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]*dag.Node, error) {
199
- objects := make([]*dag.Node, len(paths))
198
+func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]dag.Node, error) {
199
+ objects := make([]dag.Node, len(paths))
200
for i, p := range paths {
201
o, err := core.Resolve(ctx, n, path.Path(p))
202
if err != nil {
@@ -225,24 +225,24 @@ type RefWriter struct {
225
}
226
227
// WriteRefs writes refs of the given object to the underlying writer.
228
-func (rw *RefWriter) WriteRefs(n *dag.Node) (int, error) {
228
+func (rw *RefWriter) WriteRefs(n dag.Node) (int, error) {
229
if rw.Recursive {
230
return rw.writeRefsRecursive(n)
231
}
232
return rw.writeRefsSingle(n)
233
}
234
235
-func (rw *RefWriter) writeRefsRecursive(n *dag.Node) (int, error) {
235
+func (rw *RefWriter) writeRefsRecursive(n dag.Node) (int, error) {
236
nc := n.Cid()
237
238
var count int
239
for i, ng := range dag.GetDAG(rw.Ctx, rw.DAG, n) {
240
- lc := cid.NewCidV0(n.Links[i].Hash)
240
+ lc := n.Links()[i].Cid
241
if rw.skip(lc) {
242
continue
243
}
244
245
- if err := rw.WriteEdge(nc, lc, n.Links[i].Name); err != nil {
245
+ if err := rw.WriteEdge(nc, lc, n.Links()[i].Name); err != nil {
246
return count, err
247
}
248
@@ -260,7 +260,7 @@ func (rw *RefWriter) writeRefsRecursive(n *dag.Node) (int, error) {
260
return count, nil
261
}
262
263
-func (rw *RefWriter) writeRefsSingle(n *dag.Node) (int, error) {
263
+func (rw *RefWriter) writeRefsSingle(n dag.Node) (int, error) {
264
c := n.Cid()
265
266
if rw.skip(c) {
@@ -268,9 +268,8 @@ func (rw *RefWriter) writeRefsSingle(n *dag.Node) (int, error) {
268
}
269
270
count := 0
271
- for _, l := range n.Links {
272
- lc := cid.NewCidV0(l.Hash)
273
-
271
+ for _, l := range n.Links() {
272
+ lc := l.Cid
273
if rw.skip(lc) {
274
continue
275
}
core/commands/tar.go
+8
-1
@@ -7,6 +7,7 @@ import (
7
cmds "github.com/ipfs/go-ipfs/commands"
8
core "github.com/ipfs/go-ipfs/core"
9
"github.com/ipfs/go-ipfs/core/coreunix"
10
+ dag "github.com/ipfs/go-ipfs/merkledag"
11
path "github.com/ipfs/go-ipfs/path"
12
tar "github.com/ipfs/go-ipfs/tar"
13
)
@@ -100,7 +101,13 @@ var tarCatCmd = &cmds.Command{
101
return
102
}
103
103
- r, err := tar.ExportTar(req.Context(), root, nd.DAG)
104
+ rootpb, ok := root.(*dag.ProtoNode)
105
+ if !ok {
106
+ res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
107
+ return
108
+ }
109
+
110
+ r, err := tar.ExportTar(req.Context(), rootpb, nd.DAG)
111
if err != nil {
112
res.SetError(err, cmds.ErrNormal)
113
return
core/commands/unixfs/ls.go
+18
-7
@@ -103,7 +103,13 @@ possible, please use 'ipfs ls' instead.
103
continue
104
}
105
106
- unixFSNode, err := unixfs.FromBytes(merkleNode.Data())
106
+ ndpb, ok := merkleNode.(*merkledag.ProtoNode)
107
+ if !ok {
108
+ res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
109
+ return
110
+ }
111
+
112
+ unixFSNode, err := unixfs.FromBytes(ndpb.Data())
113
if err != nil {
114
res.SetError(err, cmds.ErrNormal)
115
return
@@ -121,16 +127,21 @@ possible, please use 'ipfs ls' instead.
127
case unixfspb.Data_File:
128
break
129
case unixfspb.Data_Directory:
124
- links := make([]LsLink, len(merkleNode.Links))
130
+ links := make([]LsLink, len(merkleNode.Links()))
131
output.Objects[hash].Links = links
126
- for i, link := range merkleNode.Links {
127
- var linkNode *merkledag.Node
128
- linkNode, err = link.GetNode(ctx, node.DAG)
132
+ for i, link := range merkleNode.Links() {
133
+ linkNode, err := link.GetNode(ctx, node.DAG)
134
if err != nil {
135
res.SetError(err, cmds.ErrNormal)
136
return
137
}
133
- d, err := unixfs.FromBytes(linkNode.Data())
138
+ lnpb, ok := linkNode.(*merkledag.ProtoNode)
139
+ if !ok {
140
+ res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
141
+ return
142
+ }
143
+
144
+ d, err := unixfs.FromBytes(lnpb.Data())
145
if err != nil {
146
res.SetError(err, cmds.ErrNormal)
147
return
@@ -138,7 +149,7 @@ possible, please use 'ipfs ls' instead.
149
t := d.GetType()
150
lsLink := LsLink{
151
Name: link.Name,
141
- Hash: link.Hash.B58String(),
152
+ Hash: link.Cid.String(),
153
Type: t.String(),
154
}
155
if t == unixfspb.Data_File {
core/core.go
+9
-2
@@ -499,7 +499,7 @@ func (n *IpfsNode) loadFilesRoot() error {
499
return n.Repo.Datastore().Put(dsk, c.Bytes())
500
}
501
502
- var nd *merkledag.Node
502
+ var nd *merkledag.ProtoNode
503
val, err := n.Repo.Datastore().Get(dsk)
504
505
switch {
@@ -515,10 +515,17 @@ func (n *IpfsNode) loadFilesRoot() error {
515
return err
516
}
517
518
- nd, err = n.DAG.Get(n.Context(), c)
518
+ rnd, err := n.DAG.Get(n.Context(), c)
519
if err != nil {
520
return fmt.Errorf("error loading filesroot from DAG: %s", err)
521
}
522
+
523
+ pbnd, ok := rnd.(*merkledag.ProtoNode)
524
+ if !ok {
525
+ return merkledag.ErrNotProtobuf
526
+ }
527
+
528
+ nd = pbnd
529
default:
530
return err
531
}
core/corehttp/gateway_handler.go
+50
-12
@@ -45,7 +45,7 @@ func newGatewayHandler(node *core.IpfsNode, conf GatewayConfig) *gatewayHandler
45
}
46
47
// TODO(cryptix): find these helpers somewhere else
48
-func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
48
+func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.ProtoNode, error) {
49
// TODO(cryptix): change and remove this helper once PR1136 is merged
50
// return ufs.AddFromReader(i.node, r.Body)
51
return importer.BuildDagFromReader(
@@ -163,6 +163,12 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
163
return
164
}
165
166
+ pbnd, ok := nd.(*dag.ProtoNode)
167
+ if !ok {
168
+ webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
169
+ return
170
+ }
171
+
172
etag := gopath.Base(urlPath)
173
if r.Header.Get("If-None-Match") == etag {
174
w.WriteHeader(http.StatusNotModified)
@@ -190,7 +196,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
196
w.Header().Set("Suborigin", pathRoot)
197
}
198
193
- dr, err := uio.NewDagReader(ctx, nd, i.node.DAG)
199
+ dr, err := uio.NewDagReader(ctx, pbnd, i.node.DAG)
200
if err != nil && err != uio.ErrIsDir {
201
// not a directory and still an error
202
internalWebError(w, err)
@@ -221,7 +227,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
227
var dirListing []directoryItem
228
// loop through files
229
foundIndex := false
224
- for _, link := range nd.Links {
230
+ for _, link := range nd.Links() {
231
if link.Name == "index.html" {
232
log.Debugf("found index.html link for %s", urlPath)
233
foundIndex = true
@@ -239,7 +245,14 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
245
internalWebError(w, err)
246
return
247
}
242
- dr, err := uio.NewDagReader(ctx, nd, i.node.DAG)
248
+
249
+ pbnd, ok := nd.(*dag.ProtoNode)
250
+ if !ok {
251
+ internalWebError(w, dag.ErrNotProtobuf)
252
+ return
253
+ }
254
+
255
+ dr, err := uio.NewDagReader(ctx, pbnd, i.node.DAG)
256
if err != nil {
257
internalWebError(w, err)
258
return
@@ -340,7 +353,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
353
return
354
}
355
343
- var newnode *dag.Node
356
+ var newnode *dag.ProtoNode
357
if rsegs[len(rsegs)-1] == "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
358
newnode = uio.NewEmptyDirectory()
359
} else {
@@ -376,7 +389,13 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
389
return
390
}
391
379
- e := dagutils.NewDagEditor(rnode, i.node.DAG)
392
+ pbnd, ok := rnode.(*dag.ProtoNode)
393
+ if !ok {
394
+ webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
395
+ return
396
+ }
397
+
398
+ e := dagutils.NewDagEditor(pbnd, i.node.DAG)
399
err = e.InsertNodeAtPath(ctx, newPath, newnode, uio.NewEmptyDirectory)
400
if err != nil {
401
webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
@@ -392,13 +411,19 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
411
newcid = nnode.Cid()
412
413
case nil:
414
+ pbnd, ok := rnode.(*dag.ProtoNode)
415
+ if !ok {
416
+ webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
417
+ return
418
+ }
419
+
420
// object set-data case
396
- rnode.SetData(newnode.Data())
421
+ pbnd.SetData(newnode.Data())
422
398
- newcid, err = i.node.DAG.Add(rnode)
423
+ newcid, err = i.node.DAG.Add(pbnd)
424
if err != nil {
425
nnk := newnode.Cid()
401
- rk := rnode.Cid()
426
+ rk := pbnd.Cid()
427
webError(w, fmt.Sprintf("putHandler: Could not add newnode(%q) to root(%q)", nnk.String(), rk.String()), err, http.StatusInternalServerError)
428
return
429
}
@@ -444,20 +469,33 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
469
return
470
}
471
472
+ pbnd, ok := pathNodes[len(pathNodes)-1].(*dag.ProtoNode)
473
+ if !ok {
474
+ webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
475
+ return
476
+ }
477
+
478
// TODO(cyrptix): assumes len(pathNodes) > 1 - not found is an error above?
448
- err = pathNodes[len(pathNodes)-1].RemoveNodeLink(components[len(components)-1])
479
+ err = pbnd.RemoveNodeLink(components[len(components)-1])
480
if err != nil {
481
webError(w, "Could not delete link", err, http.StatusBadRequest)
482
return
483
}
484
454
- newnode := pathNodes[len(pathNodes)-1]
485
+ var newnode *dag.ProtoNode = pbnd
486
for j := len(pathNodes) - 2; j >= 0; j-- {
487
if _, err := i.node.DAG.Add(newnode); err != nil {
488
webError(w, "Could not add node", err, http.StatusInternalServerError)
489
return
490
}
460
- newnode, err = pathNodes[j].UpdateNodeLink(components[j], newnode)
491
+
492
+ pathpb, ok := pathNodes[j].(*dag.ProtoNode)
493
+ if !ok {
494
+ webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
495
+ return
496
+ }
497
+
498
+ newnode, err = pathpb.UpdateNodeLink(components[j], newnode)
499
if err != nil {
500
webError(w, "Could not update node links", err, http.StatusInternalServerError)
501
return
core/corerepo/pinning.go
+1
-1
@@ -25,7 +25,7 @@ import (
25
)
26
27
func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
28
- dagnodes := make([]*merkledag.Node, 0)
28
+ dagnodes := make([]merkledag.Node, 0)
29
for _, fpath := range paths {
30
dagnode, err := core.Resolve(ctx, n, path.Path(fpath))
31
if err != nil {
core/coreunix/add.go
+20
-14
@@ -100,7 +100,7 @@ type Adder struct {
100
Silent bool
101
Wrap bool
102
Chunker string
103
- root *dag.Node
103
+ root *dag.ProtoNode
104
mr *mfs.Root
105
unlocker bs.Unlocker
106
tempRoot *cid.Cid
@@ -111,7 +111,7 @@ func (adder *Adder) SetMfsRoot(r *mfs.Root) {
111
}
112
113
// Perform the actual add & pin locally, outputting results to reader
114
-func (adder Adder) add(reader io.Reader) (*dag.Node, error) {
114
+func (adder Adder) add(reader io.Reader) (*dag.ProtoNode, error) {
115
chnk, err := chunk.FromString(reader, adder.Chunker)
116
if err != nil {
117
return nil, err
@@ -129,7 +129,7 @@ func (adder Adder) add(reader io.Reader) (*dag.Node, error) {
129
)
130
}
131
132
-func (adder *Adder) RootNode() (*dag.Node, error) {
132
+func (adder *Adder) RootNode() (*dag.ProtoNode, error) {
133
// for memoizing
134
if adder.root != nil {
135
return adder.root, nil
@@ -141,11 +141,18 @@ func (adder *Adder) RootNode() (*dag.Node, error) {
141
}
142
143
// if not wrapping, AND one root file, use that hash as root.
144
- if !adder.Wrap && len(root.Links) == 1 {
145
- root, err = root.Links[0].GetNode(adder.ctx, adder.dagService)
144
+ if !adder.Wrap && len(root.Links()) == 1 {
145
+ nd, err := root.Links()[0].GetNode(adder.ctx, adder.dagService)
146
if err != nil {
147
return nil, err
148
}
149
+
150
+ pbnd, ok := nd.(*dag.ProtoNode)
151
+ if !ok {
152
+ return nil, dag.ErrNotProtobuf
153
+ }
154
+
155
+ root = pbnd
156
}
157
158
adder.root = root
@@ -178,7 +185,7 @@ func (adder *Adder) PinRoot() error {
185
return adder.pinning.Flush()
186
}
187
181
-func (adder *Adder) Finalize() (*dag.Node, error) {
188
+func (adder *Adder) Finalize() (*dag.ProtoNode, error) {
189
root := adder.mr.GetValue()
190
191
// cant just call adder.RootNode() here as we need the name for printing
@@ -189,7 +196,7 @@ func (adder *Adder) Finalize() (*dag.Node, error) {
196
197
var name string
198
if !adder.Wrap {
192
- name = rootNode.Links[0].Name
199
+ name = rootNode.Links()[0].Name
200
201
dir, ok := adder.mr.GetValue().(*mfs.Directory)
202
if !ok {
@@ -300,7 +307,7 @@ func AddR(n *core.IpfsNode, root string) (key string, err error) {
307
// to preserve the filename.
308
// Returns the path of the added file ("<dir hash>/filename"), the DAG node of
309
// the directory, and and error if any.
303
-func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.Node, error) {
310
+func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.ProtoNode, error) {
311
file := files.NewReaderFile(filename, filename, ioutil.NopCloser(r), nil)
312
fileAdder, err := NewAdder(n.Context(), n.Pinning, n.Blockstore, n.DAG)
313
if err != nil {
@@ -324,7 +331,7 @@ func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.No
331
return gopath.Join(c.String(), filename), dagnode, nil
332
}
333
327
-func (adder *Adder) addNode(node *dag.Node, path string) error {
334
+func (adder *Adder) addNode(node *dag.ProtoNode, path string) error {
335
// patch it into the root
336
if path == "" {
337
path = node.Cid().String()
@@ -449,7 +456,7 @@ func (adder *Adder) maybePauseForGC() error {
456
}
457
458
// outputDagnode sends dagnode info over the output channel
452
-func outputDagnode(out chan interface{}, name string, dn *dag.Node) error {
459
+func outputDagnode(out chan interface{}, name string, dn *dag.ProtoNode) error {
460
if out == nil {
461
return nil
462
}
@@ -475,18 +482,17 @@ func NewMemoryDagService() dag.DAGService {
482
}
483
484
// from core/commands/object.go
478
-func getOutput(dagnode *dag.Node) (*Object, error) {
485
+func getOutput(dagnode *dag.ProtoNode) (*Object, error) {
486
c := dagnode.Cid()
487
488
output := &Object{
489
Hash: c.String(),
483
- Links: make([]Link, len(dagnode.Links)),
490
+ Links: make([]Link, len(dagnode.Links())),
491
}
492
486
- for i, link := range dagnode.Links {
493
+ for i, link := range dagnode.Links() {
494
output.Links[i] = Link{
495
Name: link.Name,
489
- //Hash: link.Hash.B58String(),
496
Size: link.Size,
497
}
498
}
core/coreunix/cat.go
+10
-2
@@ -1,8 +1,10 @@
1
package coreunix
2
3
import (
4
- context "context"
4
+ "context"
5
+
6
core "github.com/ipfs/go-ipfs/core"
7
+ dag "github.com/ipfs/go-ipfs/merkledag"
8
path "github.com/ipfs/go-ipfs/path"
9
uio "github.com/ipfs/go-ipfs/unixfs/io"
10
)
@@ -12,5 +14,11 @@ func Cat(ctx context.Context, n *core.IpfsNode, pstr string) (*uio.DagReader, er
14
if err != nil {
15
return nil, err
16
}
15
- return uio.NewDagReader(ctx, dagNode, n.DAG)
17
+
18
+ dnpb, ok := dagNode.(*dag.ProtoNode)
19
+ if !ok {
20
+ return nil, dag.ErrNotProtobuf
21
+ }
22
+
23
+ return uio.NewDagReader(ctx, dnpb, n.DAG)
24
}
core/coreunix/metadata.go
+7
-2
@@ -18,7 +18,7 @@ func AddMetadataTo(n *core.IpfsNode, skey string, m *ft.Metadata) (string, error
18
return "", err
19
}
20
21
- mdnode := new(dag.Node)
21
+ mdnode := new(dag.ProtoNode)
22
mdata, err := ft.BytesForMetadata(m)
23
if err != nil {
24
return "", err
@@ -48,5 +48,10 @@ func Metadata(n *core.IpfsNode, skey string) (*ft.Metadata, error) {
48
return nil, err
49
}
50
51
- return ft.MetadataFromBytes(nd.Data())
51
+ pbnd, ok := nd.(*dag.ProtoNode)
52
+ if !ok {
53
+ return nil, dag.ErrNotProtobuf
54
+ }
55
+
56
+ return ft.MetadataFromBytes(pbnd.Data())
57
}
core/coreunix/metadata_test.go
+6
-1
@@ -72,7 +72,12 @@ func TestMetadata(t *testing.T) {
72
t.Fatal(err)
73
}
74
75
- ndr, err := uio.NewDagReader(ctx, retnode, ds)
75
+ rtnpb, ok := retnode.(*merkledag.ProtoNode)
76
+ if !ok {
77
+ t.Fatal("expected protobuf node")
78
+ }
79
+
80
+ ndr, err := uio.NewDagReader(ctx, rtnpb, ds)
81
if err != nil {
82
t.Fatal(err)
83
}
core/pathresolver.go
+3
-3
@@ -19,7 +19,7 @@ var ErrNoNamesys = errors.New(
19
// Resolve resolves the given path by parsing out protocol-specific
20
// entries (e.g. /ipns/<node-key>) and then going through the /ipfs/
21
// entries and returning the final merkledag node.
22
-func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) {
22
+func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (merkledag.Node, error) {
23
if strings.HasPrefix(p.String(), "/ipns/") {
24
// resolve ipns paths
25
@@ -82,10 +82,10 @@ func ResolveToCid(ctx context.Context, n *IpfsNode, p path.Path) (*cid.Cid, erro
82
}
83
84
// Extract and return the key of the link to the target dag node.
85
- link, err := dagnode.GetNodeLink(tail)
85
+ link, _, err := dagnode.Resolve([]string{tail})
86
if err != nil {
87
return nil, err
88
}
89
90
- return cid.NewCidV0(link.Hash), nil
90
+ return link.Cid, nil
91
}
exchange/bitswap/workers.go
+1
-1
@@ -60,7 +60,7 @@ func (bs *Bitswap) taskWorker(ctx context.Context, id int) {
60
log.Event(ctx, "Bitswap.TaskWorker.Work", logging.LoggableMap{
61
"ID": id,
62
"Target": envelope.Peer.Pretty(),
63
- "Block": envelope.Block.Multihash().B58String(),
63
+ "Block": envelope.Block.Cid().String(),
64
})
65
66
bs.wm.SendBlock(ctx, envelope)
fuse/ipns/ipns_unix.go
+6
-1
@@ -100,7 +100,12 @@ func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string
100
return nil, err
101
}
102
103
- root, err := mfs.NewRoot(ctx, ipfs.DAG, node, ipnsPubFunc(ipfs, rt.k))
103
+ pbnode, ok := node.(*dag.ProtoNode)
104
+ if !ok {
105
+ return nil, dag.ErrNotProtobuf
106
+ }
107
+
108
+ root, err := mfs.NewRoot(ctx, ipfs.DAG, pbnode, ipnsPubFunc(ipfs, rt.k))
109
if err != nil {
110
return nil, err
111
}
fuse/readonly/ipfs_test.go
+11
-5
@@ -33,7 +33,7 @@ func maybeSkipFuseTests(t *testing.T) {
33
}
34
}
35
36
-func randObj(t *testing.T, nd *core.IpfsNode, size int64) (*dag.Node, []byte) {
36
+func randObj(t *testing.T, nd *core.IpfsNode, size int64) (*dag.ProtoNode, []byte) {
37
buf := make([]byte, size)
38
u.NewTimeSeededRand().Read(buf)
39
read := bytes.NewReader(buf)
@@ -86,17 +86,23 @@ func TestIpfsBasicRead(t *testing.T) {
86
}
87
}
88
89
-func getPaths(t *testing.T, ipfs *core.IpfsNode, name string, n *dag.Node) []string {
90
- if len(n.Links) == 0 {
89
+func getPaths(t *testing.T, ipfs *core.IpfsNode, name string, n *dag.ProtoNode) []string {
90
+ if len(n.Links()) == 0 {
91
return []string{name}
92
}
93
var out []string
94
- for _, lnk := range n.Links {
94
+ for _, lnk := range n.Links() {
95
child, err := lnk.GetNode(ipfs.Context(), ipfs.DAG)
96
if err != nil {
97
t.Fatal(err)
98
}
99
- sub := getPaths(t, ipfs, path.Join(name, lnk.Name), child)
99
+
100
+ childpb, ok := child.(*dag.ProtoNode)
101
+ if !ok {
102
+ t.Fatal(dag.ErrNotProtobuf)
103
+ }
104
+
105
+ sub := getPaths(t, ipfs, path.Join(name, lnk.Name), childpb)
106
out = append(out, sub...)
107
}
108
return out
fuse/readonly/readonly_unix.go
+20
-8
@@ -66,7 +66,13 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
66
return nil, fuse.ENOENT
67
}
68
69
- return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
69
+ pbnd, ok := nd.(*mdag.ProtoNode)
70
+ if !ok {
71
+ log.Error("fuse node was not a protobuf node")
72
+ return nil, fuse.ENOTSUP
73
+ }
74
+
75
+ return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
76
}
77
78
// ReadDirAll reads a particular directory. Disallowed for root.
@@ -78,7 +84,7 @@ func (*Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
84
// Node is the core object representing a filesystem tree node.
85
type Node struct {
86
Ipfs *core.IpfsNode
81
- Nd *mdag.Node
87
+ Nd *mdag.ProtoNode
88
fd *uio.DagReader
89
cached *ftpb.Data
90
}
@@ -105,13 +111,13 @@ func (s *Node) Attr(ctx context.Context, a *fuse.Attr) error {
111
size := s.cached.GetFilesize()
112
a.Mode = 0444
113
a.Size = uint64(size)
108
- a.Blocks = uint64(len(s.Nd.Links))
114
+ a.Blocks = uint64(len(s.Nd.Links()))
115
a.Uid = uint32(os.Getuid())
116
a.Gid = uint32(os.Getgid())
117
case ftpb.Data_Raw:
118
a.Mode = 0444
119
a.Size = uint64(len(s.cached.GetData()))
114
- a.Blocks = uint64(len(s.Nd.Links))
120
+ a.Blocks = uint64(len(s.Nd.Links()))
121
a.Uid = uint32(os.Getuid())
122
a.Gid = uint32(os.Getgid())
123
case ftpb.Data_Symlink:
@@ -134,17 +140,23 @@ func (s *Node) Lookup(ctx context.Context, name string) (fs.Node, error) {
140
return nil, fuse.ENOENT
141
}
142
137
- return &Node{Ipfs: s.Ipfs, Nd: nodes[len(nodes)-1]}, nil
143
+ pbnd, ok := nodes[len(nodes)-1].(*mdag.ProtoNode)
144
+ if !ok {
145
+ log.Error("fuse lookup got non-protobuf node")
146
+ return nil, fuse.ENOTSUP
147
+ }
148
+
149
+ return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
150
}
151
152
// ReadDirAll reads the link structure as directory entries
153
func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
154
log.Debug("Node ReadDir")
143
- entries := make([]fuse.Dirent, len(s.Nd.Links))
144
- for i, link := range s.Nd.Links {
155
+ entries := make([]fuse.Dirent, len(s.Nd.Links()))
156
+ for i, link := range s.Nd.Links() {
157
n := link.Name
158
if len(n) == 0 {
147
- n = link.Hash.B58String()
159
+ n = link.Cid.String()
160
}
161
entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
162
}
importer/balanced/balanced_test.go
+2
-2
@@ -22,7 +22,7 @@ import (
22
23
// TODO: extract these tests and more as a generic layout test suite
24
25
-func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
25
+func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
26
dbp := h.DagBuilderParams{
27
Dagserv: ds,
28
Maxlinks: h.DefaultLinksPerBlock,
@@ -31,7 +31,7 @@ func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
31
return BalancedLayout(dbp.New(spl))
32
}
33
34
-func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.Node, []byte) {
34
+func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.ProtoNode, []byte) {
35
data := make([]byte, size)
36
u.NewTimeSeededRand().Read(data)
37
r := bytes.NewReader(data)
importer/balanced/builder.go
+1
-1
@@ -7,7 +7,7 @@ import (
7
dag "github.com/ipfs/go-ipfs/merkledag"
8
)
9
10
-func BalancedLayout(db *h.DagBuilderHelper) (*dag.Node, error) {
10
+func BalancedLayout(db *h.DagBuilderHelper) (*dag.ProtoNode, error) {
11
var root *h.UnixfsNode
12
for level := 0; !db.Done(); level++ {
13
importer/helpers/dagbuilder.go
+1
-1
@@ -106,7 +106,7 @@ func (db *DagBuilderHelper) FillNodeWithData(node *UnixfsNode) error {
106
return nil
107
}
108
109
-func (db *DagBuilderHelper) Add(node *UnixfsNode) (*dag.Node, error) {
109
+func (db *DagBuilderHelper) Add(node *UnixfsNode) (*dag.ProtoNode, error) {
110
dn, err := node.GetDagNode()
111
if err != nil {
112
return nil, err
importer/helpers/helpers.go
+13
-8
@@ -37,14 +37,14 @@ var ErrSizeLimitExceeded = fmt.Errorf("object size limit exceeded")
37
// UnixfsNode is a struct created to aid in the generation
38
// of unixfs DAG trees
39
type UnixfsNode struct {
40
- node *dag.Node
40
+ node *dag.ProtoNode
41
ufmt *ft.FSNode
42
}
43
44
// NewUnixfsNode creates a new Unixfs node to represent a file
45
func NewUnixfsNode() *UnixfsNode {
46
return &UnixfsNode{
47
- node: new(dag.Node),
47
+ node: new(dag.ProtoNode),
48
ufmt: &ft.FSNode{Type: ft.TFile},
49
}
50
}
@@ -52,13 +52,13 @@ func NewUnixfsNode() *UnixfsNode {
52
// NewUnixfsBlock creates a new Unixfs node to represent a raw data block
53
func NewUnixfsBlock() *UnixfsNode {
54
return &UnixfsNode{
55
- node: new(dag.Node),
55
+ node: new(dag.ProtoNode),
56
ufmt: &ft.FSNode{Type: ft.TRaw},
57
}
58
}
59
60
// NewUnixfsNodeFromDag reconstructs a Unixfs node from a given dag node
61
-func NewUnixfsNodeFromDag(nd *dag.Node) (*UnixfsNode, error) {
61
+func NewUnixfsNodeFromDag(nd *dag.ProtoNode) (*UnixfsNode, error) {
62
mb, err := ft.FSNodeFromBytes(nd.Data())
63
if err != nil {
64
return nil, err
@@ -75,12 +75,17 @@ func (n *UnixfsNode) NumChildren() int {
75
}
76
77
func (n *UnixfsNode) GetChild(ctx context.Context, i int, ds dag.DAGService) (*UnixfsNode, error) {
78
- nd, err := n.node.Links[i].GetNode(ctx, ds)
78
+ nd, err := n.node.Links()[i].GetNode(ctx, ds)
79
if err != nil {
80
return nil, err
81
}
82
83
- return NewUnixfsNodeFromDag(nd)
83
+ pbn, ok := nd.(*dag.ProtoNode)
84
+ if !ok {
85
+ return nil, dag.ErrNotProtobuf
86
+ }
87
+
88
+ return NewUnixfsNodeFromDag(pbn)
89
}
90
91
// addChild will add the given UnixfsNode as a child of the receiver.
@@ -112,7 +117,7 @@ func (n *UnixfsNode) AddChild(child *UnixfsNode, db *DagBuilderHelper) error {
117
// Removes the child node at the given index
118
func (n *UnixfsNode) RemoveChild(index int, dbh *DagBuilderHelper) {
119
n.ufmt.RemoveBlockSize(index)
115
- n.node.Links = append(n.node.Links[:index], n.node.Links[index+1:]...)
120
+ n.node.SetLinks(append(n.node.Links()[:index], n.node.Links()[index+1:]...))
121
}
122
123
func (n *UnixfsNode) SetData(data []byte) {
@@ -121,7 +126,7 @@ func (n *UnixfsNode) SetData(data []byte) {
126
127
// getDagNode fills out the proper formatting for the unixfs node
128
// inside of a DAG node and returns the dag node
124
-func (n *UnixfsNode) GetDagNode() (*dag.Node, error) {
129
+func (n *UnixfsNode) GetDagNode() (*dag.ProtoNode, error) {
130
data, err := n.ufmt.GetBytes()
131
if err != nil {
132
return nil, err
importer/importer.go
+3
-3
@@ -19,7 +19,7 @@ var log = logging.Logger("importer")
19
20
// Builds a DAG from the given file, writing created blocks to disk as they are
21
// created
22
-func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.Node, error) {
22
+func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.ProtoNode, error) {
23
stat, err := os.Lstat(fpath)
24
if err != nil {
25
return nil, err
@@ -38,7 +38,7 @@ func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.Node, error) {
38
return BuildDagFromReader(ds, chunk.NewSizeSplitter(f, chunk.DefaultBlockSize))
39
}
40
41
-func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
41
+func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
42
dbp := h.DagBuilderParams{
43
Dagserv: ds,
44
Maxlinks: h.DefaultLinksPerBlock,
@@ -47,7 +47,7 @@ func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error
47
return bal.BalancedLayout(dbp.New(spl))
48
}
49
50
-func BuildTrickleDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
50
+func BuildTrickleDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
51
dbp := h.DagBuilderParams{
52
Dagserv: ds,
53
Maxlinks: h.DefaultLinksPerBlock,
importer/importer_test.go
+3
-3
@@ -14,7 +14,7 @@ import (
14
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
15
)
16
17
-func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAGService) {
17
+func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.ProtoNode, dag.DAGService) {
18
ds := mdtest.Mock()
19
r := io.LimitReader(u.NewTimeSeededRand(), size)
20
nd, err := BuildDagFromReader(ds, chunk.NewSizeSplitter(r, blksize))
@@ -24,7 +24,7 @@ func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAG
24
return nd, ds
25
}
26
27
-func getTrickleDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAGService) {
27
+func getTrickleDag(t testing.TB, size int64, blksize int64) (*dag.ProtoNode, dag.DAGService) {
28
ds := mdtest.Mock()
29
r := io.LimitReader(u.NewTimeSeededRand(), size)
30
nd, err := BuildTrickleDagFromReader(ds, chunk.NewSizeSplitter(r, blksize))
@@ -100,7 +100,7 @@ func BenchmarkTrickleReadFull(b *testing.B) {
100
runReadBench(b, nd, ds)
101
}
102
103
-func runReadBench(b *testing.B, nd *dag.Node, ds dag.DAGService) {
103
+func runReadBench(b *testing.B, nd *dag.ProtoNode, ds dag.DAGService) {
104
for i := 0; i < b.N; i++ {
105
ctx, cancel := context.WithCancel(context.Background())
106
read, err := uio.NewDagReader(ctx, nd, ds)
importer/trickle/trickle_test.go
+7
-7
@@ -20,7 +20,7 @@ import (
20
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
21
)
22
23
-func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.Node, error) {
23
+func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.ProtoNode, error) {
24
dbp := h.DagBuilderParams{
25
Dagserv: ds,
26
Maxlinks: h.DefaultLinksPerBlock,
@@ -523,7 +523,7 @@ func TestAppendSingleBytesToEmpty(t *testing.T) {
523
524
data := []byte("AB")
525
526
- nd := new(merkledag.Node)
526
+ nd := new(merkledag.ProtoNode)
527
nd.SetData(ft.FilePBData(nil, 0))
528
529
dbp := &h.DagBuilderParams{
@@ -561,7 +561,7 @@ func TestAppendSingleBytesToEmpty(t *testing.T) {
561
}
562
}
563
564
-func printDag(nd *merkledag.Node, ds merkledag.DAGService, indent int) {
564
+func printDag(nd *merkledag.ProtoNode, ds merkledag.DAGService, indent int) {
565
pbd, err := ft.FromBytes(nd.Data())
566
if err != nil {
567
panic(err)
@@ -571,17 +571,17 @@ func printDag(nd *merkledag.Node, ds merkledag.DAGService, indent int) {
571
fmt.Print(" ")
572
}
573
fmt.Printf("{size = %d, type = %s, nc = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
574
- if len(nd.Links) > 0 {
574
+ if len(nd.Links()) > 0 {
575
fmt.Println()
576
}
577
- for _, lnk := range nd.Links {
577
+ for _, lnk := range nd.Links() {
578
child, err := lnk.GetNode(context.Background(), ds)
579
if err != nil {
580
panic(err)
581
}
582
- printDag(child, ds, indent+1)
582
+ printDag(child.(*merkledag.ProtoNode), ds, indent+1)
583
}
584
- if len(nd.Links) > 0 {
584
+ if len(nd.Links()) > 0 {
585
for i := 0; i < indent; i++ {
586
fmt.Print(" ")
587
}
importer/trickle/trickledag.go
+17
-12
@@ -1,9 +1,9 @@
1
package trickle
2
3
import (
4
+ "context"
5
"errors"
5
-
6
- context "context"
6
+ "fmt"
7
8
h "github.com/ipfs/go-ipfs/importer/helpers"
9
dag "github.com/ipfs/go-ipfs/merkledag"
@@ -15,7 +15,7 @@ import (
15
// improves seek speeds.
16
const layerRepeat = 4
17
18
-func TrickleLayout(db *h.DagBuilderHelper) (*dag.Node, error) {
18
+func TrickleLayout(db *h.DagBuilderHelper) (*dag.ProtoNode, error) {
19
root := h.NewUnixfsNode()
20
if err := db.FillNodeLayer(root); err != nil {
21
return nil, err
@@ -66,7 +66,7 @@ func fillTrickleRec(db *h.DagBuilderHelper, node *h.UnixfsNode, depth int) error
66
}
67
68
// TrickleAppend appends the data in `db` to the dag, using the Trickledag format
69
-func TrickleAppend(ctx context.Context, base *dag.Node, db *h.DagBuilderHelper) (out *dag.Node, err_out error) {
69
+func TrickleAppend(ctx context.Context, base *dag.ProtoNode, db *h.DagBuilderHelper) (out *dag.ProtoNode, err_out error) {
70
defer func() {
71
if err_out == nil {
72
if err := db.Close(); err != nil {
@@ -229,15 +229,15 @@ func trickleDepthInfo(node *h.UnixfsNode, maxlinks int) (int, int) {
229
230
// VerifyTrickleDagStructure checks that the given dag matches exactly the trickle dag datastructure
231
// layout
232
-func VerifyTrickleDagStructure(nd *dag.Node, ds dag.DAGService, direct int, layerRepeat int) error {
232
+func VerifyTrickleDagStructure(nd *dag.ProtoNode, ds dag.DAGService, direct int, layerRepeat int) error {
233
return verifyTDagRec(nd, -1, direct, layerRepeat, ds)
234
}
235
236
// Recursive call for verifying the structure of a trickledag
237
-func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGService) error {
237
+func verifyTDagRec(nd *dag.ProtoNode, depth, direct, layerRepeat int, ds dag.DAGService) error {
238
if depth == 0 {
239
// zero depth dag is raw data block
240
- if len(nd.Links) > 0 {
240
+ if len(nd.Links()) > 0 {
241
return errors.New("expected direct block")
242
}
243
@@ -259,22 +259,27 @@ func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGServi
259
}
260
261
if pbn.GetType() != ft.TFile {
262
- return errors.New("expected file as branch node")
262
+ return fmt.Errorf("expected file as branch node, got: %s", pbn.GetType())
263
}
264
265
if len(pbn.Data) > 0 {
266
return errors.New("branch node should not have data")
267
}
268
269
- for i := 0; i < len(nd.Links); i++ {
270
- child, err := nd.Links[i].GetNode(context.TODO(), ds)
269
+ for i := 0; i < len(nd.Links()); i++ {
270
+ childi, err := nd.Links()[i].GetNode(context.TODO(), ds)
271
if err != nil {
272
return err
273
}
274
275
+ childpb, ok := childi.(*dag.ProtoNode)
276
+ if !ok {
277
+ return fmt.Errorf("cannot operate on non-protobuf nodes")
278
+ }
279
+
280
if i < direct {
281
// Direct blocks
277
- err := verifyTDagRec(child, 0, direct, layerRepeat, ds)
282
+ err := verifyTDagRec(childpb, 0, direct, layerRepeat, ds)
283
if err != nil {
284
return err
285
}
@@ -284,7 +289,7 @@ func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGServi
289
if rdepth >= depth && depth > 0 {
290
return errors.New("Child dag was too deep!")
291
}
287
- err := verifyTDagRec(child, rdepth, direct, layerRepeat, ds)
292
+ err := verifyTDagRec(childpb, rdepth, direct, layerRepeat, ds)
293
if err != nil {
294
return err
295
}
merkledag/coding.go
+17
-18
@@ -7,7 +7,6 @@ import (
7
pb "github.com/ipfs/go-ipfs/merkledag/pb"
8
9
cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
10
- mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
10
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
11
)
12
@@ -16,23 +15,23 @@ import (
15
16
// unmarshal decodes raw data into a *Node instance.
17
// The conversion uses an intermediate PBNode.
19
-func (n *Node) unmarshal(encoded []byte) error {
18
+func (n *ProtoNode) unmarshal(encoded []byte) error {
19
var pbn pb.PBNode
20
if err := pbn.Unmarshal(encoded); err != nil {
21
return fmt.Errorf("Unmarshal failed. %v", err)
22
}
23
24
pbnl := pbn.GetLinks()
26
- n.Links = make([]*Link, len(pbnl))
25
+ n.links = make([]*Link, len(pbnl))
26
for i, l := range pbnl {
28
- n.Links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
29
- h, err := mh.Cast(l.GetHash())
27
+ n.links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
28
+ c, err := cid.Cast(l.GetHash())
29
if err != nil {
30
return fmt.Errorf("Link hash #%d is not valid multihash. %v", i, err)
31
}
33
- n.Links[i].Hash = h
32
+ n.links[i].Cid = c
33
}
35
- sort.Stable(LinkSlice(n.Links)) // keep links sorted
34
+ sort.Stable(LinkSlice(n.links)) // keep links sorted
35
36
n.data = pbn.GetData()
37
n.encoded = encoded
@@ -41,7 +40,7 @@ func (n *Node) unmarshal(encoded []byte) error {
40
41
// Marshal encodes a *Node instance into a new byte slice.
42
// The conversion uses an intermediate PBNode.
44
-func (n *Node) Marshal() ([]byte, error) {
43
+func (n *ProtoNode) Marshal() ([]byte, error) {
44
pbn := n.getPBNode()
45
data, err := pbn.Marshal()
46
if err != nil {
@@ -50,18 +49,18 @@ func (n *Node) Marshal() ([]byte, error) {
49
return data, nil
50
}
51
53
-func (n *Node) getPBNode() *pb.PBNode {
52
+func (n *ProtoNode) getPBNode() *pb.PBNode {
53
pbn := &pb.PBNode{}
55
- if len(n.Links) > 0 {
56
- pbn.Links = make([]*pb.PBLink, len(n.Links))
54
+ if len(n.links) > 0 {
55
+ pbn.Links = make([]*pb.PBLink, len(n.links))
56
}
57
59
- sort.Stable(LinkSlice(n.Links)) // keep links sorted
60
- for i, l := range n.Links {
58
+ sort.Stable(LinkSlice(n.links)) // keep links sorted
59
+ for i, l := range n.links {
60
pbn.Links[i] = &pb.PBLink{}
61
pbn.Links[i].Name = &l.Name
62
pbn.Links[i].Tsize = &l.Size
64
- pbn.Links[i].Hash = []byte(l.Hash)
63
+ pbn.Links[i].Hash = l.Cid.Bytes()
64
}
65
66
if len(n.data) > 0 {
@@ -72,8 +71,8 @@ func (n *Node) getPBNode() *pb.PBNode {
71
72
// EncodeProtobuf returns the encoded raw data version of a Node instance.
73
// It may use a cached encoded version, unless the force flag is given.
75
-func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
76
- sort.Stable(LinkSlice(n.Links)) // keep links sorted
74
+func (n *ProtoNode) EncodeProtobuf(force bool) ([]byte, error) {
75
+ sort.Stable(LinkSlice(n.links)) // keep links sorted
76
if n.encoded == nil || force {
77
n.cached = nil
78
var err error
@@ -91,8 +90,8 @@ func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
90
}
91
92
// Decoded decodes raw data and returns a new Node instance.
94
-func DecodeProtobuf(encoded []byte) (*Node, error) {
95
- n := new(Node)
93
+func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
94
+ n := new(ProtoNode)
95
err := n.unmarshal(encoded)
96
if err != nil {
97
return nil, fmt.Errorf("incorrectly formatted merkledag node: %s", err)
merkledag/merkledag.go
+40
-37
@@ -20,9 +20,9 @@ var ErrNotFound = fmt.Errorf("merkledag: not found")
20
21
// DAGService is an IPFS Merkle DAG service.
22
type DAGService interface {
23
- Add(*Node) (*cid.Cid, error)
24
- Get(context.Context, *cid.Cid) (*Node, error)
25
- Remove(*Node) error
23
+ Add(Node) (*cid.Cid, error)
24
+ Get(context.Context, *cid.Cid) (Node, error)
25
+ Remove(Node) error
26
27
// GetDAG returns, in order, all the single leve child
28
// nodes of the passed in node.
@@ -45,6 +45,19 @@ func NewDAGService(bs bserv.BlockService) *dagService {
45
return &dagService{Blocks: bs}
46
}
47
48
+type Node interface {
49
+ Resolve(path []string) (*Link, []string, error)
50
+ Links() []*Link
51
+ Tree() []string
52
+
53
+ Stat() (*NodeStat, error)
54
+ Size() (uint64, error)
55
+ Cid() *cid.Cid
56
+ Loggable() map[string]interface{}
57
+ RawData() []byte
58
+ String() string
59
+}
60
+
61
// dagService is an IPFS Merkle DAG service.
62
// - the root is virtual (like a forest)
63
// - stores nodes' data in a BlockService
@@ -55,7 +68,7 @@ type dagService struct {
68
}
69
70
// Add adds a node to the dagService, storing the block in the BlockService
58
-func (n *dagService) Add(nd *Node) (*cid.Cid, error) {
71
+func (n *dagService) Add(nd Node) (*cid.Cid, error) {
72
if n == nil { // FIXME remove this assertion. protect with constructor invariant
73
return nil, fmt.Errorf("dagService is nil")
74
}
@@ -68,7 +81,7 @@ func (n *dagService) Batch() *Batch {
81
}
82
83
// Get retrieves a node from the dagService, fetching the block in the BlockService
71
-func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
84
+func (n *dagService) Get(ctx context.Context, c *cid.Cid) (Node, error) {
85
if n == nil {
86
return nil, fmt.Errorf("dagService is nil")
87
}
@@ -84,7 +97,7 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
97
return nil, fmt.Errorf("Failed to get block for %s: %v", c, err)
98
}
99
87
- var res *Node
100
+ var res Node
101
switch c.Type() {
102
case cid.Protobuf:
103
out, err := DecodeProtobuf(b.RawData())
@@ -94,13 +107,12 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
107
}
108
return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err)
109
}
110
+ out.cached = c
111
res = out
112
default:
113
return nil, fmt.Errorf("unrecognized formatting type")
114
}
115
102
- res.cached = c
103
-
116
return res, nil
117
}
118
@@ -109,7 +121,7 @@ func (n *dagService) GetLinks(ctx context.Context, c *cid.Cid) ([]*Link, error)
121
if err != nil {
122
return nil, err
123
}
112
- return node.Links, nil
124
+ return node.Links(), nil
125
}
126
127
func (n *dagService) GetOfflineLinkService() LinkService {
@@ -121,7 +133,7 @@ func (n *dagService) GetOfflineLinkService() LinkService {
133
}
134
}
135
124
-func (n *dagService) Remove(nd *Node) error {
136
+func (n *dagService) Remove(nd Node) error {
137
return n.Blocks.DeleteBlock(nd)
138
}
139
@@ -143,7 +155,7 @@ func FindLinks(links []*cid.Cid, c *cid.Cid, start int) []int {
155
}
156
157
type NodeOption struct {
146
- Node *Node
158
+ Node Node
159
Err error
160
}
161
@@ -166,7 +178,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
178
179
c := b.Cid()
180
169
- var nd *Node
181
+ var nd Node
182
switch c.Type() {
183
case cid.Protobuf:
184
decnd, err := DecodeProtobuf(b.RawData())
@@ -174,7 +186,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
186
out <- &NodeOption{Err: err}
187
return
188
}
177
- decnd.cached = cid.NewCidV0(b.Multihash())
189
+ decnd.cached = b.Cid()
190
nd = decnd
191
default:
192
out <- &NodeOption{Err: fmt.Errorf("unrecognized object type: %s", c.Type())}
@@ -197,10 +209,10 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
209
// GetDAG will fill out all of the links of the given Node.
210
// It returns a channel of nodes, which the caller can receive
211
// all the child nodes of 'root' on, in proper order.
200
-func GetDAG(ctx context.Context, ds DAGService, root *Node) []NodeGetter {
212
+func GetDAG(ctx context.Context, ds DAGService, root Node) []NodeGetter {
213
var cids []*cid.Cid
202
- for _, lnk := range root.Links {
203
- cids = append(cids, cid.NewCidV0(lnk.Hash))
214
+ for _, lnk := range root.Links() {
215
+ cids = append(cids, lnk.Cid)
216
}
217
218
return GetNodes(ctx, ds, cids)
@@ -269,16 +281,16 @@ func dedupeKeys(cids []*cid.Cid) []*cid.Cid {
281
282
func newNodePromise(ctx context.Context) NodeGetter {
283
return &nodePromise{
272
- recv: make(chan *Node, 1),
284
+ recv: make(chan Node, 1),
285
ctx: ctx,
286
err: make(chan error, 1),
287
}
288
}
289
290
type nodePromise struct {
279
- cache *Node
291
+ cache Node
292
clk sync.Mutex
281
- recv chan *Node
293
+ recv chan Node
294
ctx context.Context
295
err chan error
296
}
@@ -288,9 +300,9 @@ type nodePromise struct {
300
// from its internal channels, subsequent calls will return the
301
// cached node.
302
type NodeGetter interface {
291
- Get(context.Context) (*Node, error)
303
+ Get(context.Context) (Node, error)
304
Fail(err error)
293
- Send(*Node)
305
+ Send(Node)
306
}
307
308
func (np *nodePromise) Fail(err error) {
@@ -306,7 +318,7 @@ func (np *nodePromise) Fail(err error) {
318
np.err <- err
319
}
320
309
-func (np *nodePromise) Send(nd *Node) {
321
+func (np *nodePromise) Send(nd Node) {
322
var already bool
323
np.clk.Lock()
324
if np.cache != nil {
@@ -322,7 +334,7 @@ func (np *nodePromise) Send(nd *Node) {
334
np.recv <- nd
335
}
336
325
-func (np *nodePromise) Get(ctx context.Context) (*Node, error) {
337
+func (np *nodePromise) Get(ctx context.Context) (Node, error) {
338
np.clk.Lock()
339
c := np.cache
340
np.clk.Unlock()
@@ -350,14 +362,9 @@ type Batch struct {
362
MaxSize int
363
}
364
353
-func (t *Batch) Add(nd *Node) (*cid.Cid, error) {
354
- d, err := nd.EncodeProtobuf(false)
355
- if err != nil {
356
- return nil, err
357
- }
358
-
365
+func (t *Batch) Add(nd Node) (*cid.Cid, error) {
366
t.blocks = append(t.blocks, nd)
360
- t.size += len(d)
367
+ t.size += len(nd.RawData())
368
if t.size > t.MaxSize {
369
return nd.Cid(), t.Commit()
370
}
@@ -371,10 +378,6 @@ func (t *Batch) Commit() error {
378
return err
379
}
380
374
-func legacyCidFromLink(lnk *Link) *cid.Cid {
375
- return cid.NewCidV0(lnk.Hash)
376
-}
377
-
381
// EnumerateChildren will walk the dag below the given root node and add all
382
// unseen children to the passed in set.
383
// TODO: parallelize to avoid disk latency perf hits?
@@ -386,7 +389,7 @@ func EnumerateChildren(ctx context.Context, ds LinkService, root *cid.Cid, visit
389
return err
390
}
391
for _, lnk := range links {
389
- c := legacyCidFromLink(lnk)
392
+ c := lnk.Cid
393
if visit(c) {
394
err = EnumerateChildren(ctx, ds, c, visit, bestEffort)
395
if err != nil {
@@ -432,8 +435,8 @@ func EnumerateChildrenAsync(ctx context.Context, ds DAGService, c *cid.Cid, visi
435
live--
436
437
var cids []*cid.Cid
435
- for _, lnk := range nd.Links {
436
- c := legacyCidFromLink(lnk)
438
+ for _, lnk := range nd.Links() {
439
+ c := lnk.Cid
440
if visit(c) {
441
live++
442
cids = append(cids, c)
merkledag/merkledag_test.go
+20
-15
@@ -38,13 +38,13 @@ func TestNode(t *testing.T) {
38
t.Error(err)
39
}
40
41
- printn := func(name string, n *Node) {
41
+ printn := func(name string, n *ProtoNode) {
42
fmt.Println(">", name)
43
fmt.Println("data:", string(n.Data()))
44
45
fmt.Println("links:")
46
- for _, l := range n.Links {
47
- fmt.Println("-", l.Name, l.Size, l.Hash)
46
+ for _, l := range n.Links() {
47
+ fmt.Println("-", l.Name, l.Size, l.Cid)
48
}
49
50
e, err := n.EncodeProtobuf(false)
@@ -70,7 +70,7 @@ func TestNode(t *testing.T) {
70
printn("beep boop", n3)
71
}
72
73
-func SubtestNodeStat(t *testing.T, n *Node) {
73
+func SubtestNodeStat(t *testing.T, n *ProtoNode) {
74
enc, err := n.EncodeProtobuf(true)
75
if err != nil {
76
t.Error("n.EncodeProtobuf(true) failed")
@@ -86,7 +86,7 @@ func SubtestNodeStat(t *testing.T, n *Node) {
86
k := n.Key()
87
88
expected := NodeStat{
89
- NumLinks: len(n.Links),
89
+ NumLinks: len(n.Links()),
90
BlockSize: len(enc),
91
LinksSize: len(enc) - len(n.Data()), // includes framing.
92
DataSize: len(n.Data()),
@@ -174,7 +174,12 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
174
}
175
fmt.Println("Got first node back.")
176
177
- read, err := uio.NewDagReader(ctx, first, dagservs[i])
177
+ firstpb, ok := first.(*ProtoNode)
178
+ if !ok {
179
+ errs <- ErrNotProtobuf
180
+ }
181
+
182
+ read, err := uio.NewDagReader(ctx, firstpb, dagservs[i])
183
if err != nil {
184
errs <- err
185
}
@@ -201,7 +206,7 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
206
}
207
}
208
204
-func assertCanGet(t *testing.T, ds DAGService, n *Node) {
209
+func assertCanGet(t *testing.T, ds DAGService, n Node) {
210
if _, err := ds.Get(context.Background(), n.Cid()); err != nil {
211
t.Fatal(err)
212
}
@@ -263,13 +268,13 @@ func TestEnumerateChildren(t *testing.T) {
268
t.Fatal(err)
269
}
270
266
- var traverse func(n *Node)
267
- traverse = func(n *Node) {
271
+ var traverse func(n Node)
272
+ traverse = func(n Node) {
273
// traverse dag and check
269
- for _, lnk := range n.Links {
270
- c := cid.NewCidV0(lnk.Hash)
274
+ for _, lnk := range n.Links() {
275
+ c := lnk.Cid
276
if !set.Has(c) {
272
- t.Fatal("missing key in set! ", lnk.Hash.B58String())
277
+ t.Fatal("missing key in set! ", lnk.Cid.String())
278
}
279
child, err := ds.Get(context.Background(), c)
280
if err != nil {
@@ -286,7 +291,7 @@ func TestFetchFailure(t *testing.T) {
291
ds := dstest.Mock()
292
ds_bad := dstest.Mock()
293
289
- top := new(Node)
294
+ top := new(ProtoNode)
295
for i := 0; i < 10; i++ {
296
nd := NodeWithData([]byte{byte('a' + i)})
297
_, err := ds.Add(nd)
@@ -345,13 +350,13 @@ func TestUnmarshalFailure(t *testing.T) {
350
t.Fatal("should have failed to parse node with bad link")
351
}
352
348
- n := &Node{}
353
+ n := &ProtoNode{}
354
n.Marshal()
355
}
356
357
func TestBasicAddGet(t *testing.T) {
358
ds := dstest.Mock()
354
- nd := new(Node)
359
+ nd := new(ProtoNode)
360
361
c, err := ds.Add(nd)
362
if err != nil {
merkledag/node.go
+85
-42
@@ -14,8 +14,8 @@ var ErrLinkNotFound = fmt.Errorf("no link by that name")
14
15
// Node represents a node in the IPFS Merkle DAG.
16
// nodes have opaque data and a set of navigable links.
17
-type Node struct {
18
- Links []*Link
17
+type ProtoNode struct {
18
+ links []*Link
19
data []byte
20
21
// cache encoded/marshaled value
@@ -48,7 +48,7 @@ type Link struct {
48
Size uint64
49
50
// multihash of the target object
51
- Hash mh.Multihash
51
+ Cid *cid.Cid
52
}
53
54
type LinkSlice []*Link
@@ -58,31 +58,29 @@ func (ls LinkSlice) Swap(a, b int) { ls[a], ls[b] = ls[b], ls[a] }
58
func (ls LinkSlice) Less(a, b int) bool { return ls[a].Name < ls[b].Name }
59
60
// MakeLink creates a link to the given node
61
-func MakeLink(n *Node) (*Link, error) {
61
+func MakeLink(n Node) (*Link, error) {
62
s, err := n.Size()
63
if err != nil {
64
return nil, err
65
}
66
67
- h := n.Multihash()
68
-
67
return &Link{
68
Size: s,
71
- Hash: h,
69
+ Cid: n.Cid(),
70
}, nil
71
}
72
73
// GetNode returns the MDAG Node that this link points to
76
-func (l *Link) GetNode(ctx context.Context, serv DAGService) (*Node, error) {
77
- return serv.Get(ctx, legacyCidFromLink(l))
74
+func (l *Link) GetNode(ctx context.Context, serv DAGService) (Node, error) {
75
+ return serv.Get(ctx, l.Cid)
76
}
77
80
-func NodeWithData(d []byte) *Node {
81
- return &Node{data: d}
78
+func NodeWithData(d []byte) *ProtoNode {
79
+ return &ProtoNode{data: d}
80
}
81
82
// AddNodeLink adds a link to another node.
85
-func (n *Node) AddNodeLink(name string, that *Node) error {
83
+func (n *ProtoNode) AddNodeLink(name string, that *ProtoNode) error {
84
n.encoded = nil
85
86
lnk, err := MakeLink(that)
@@ -99,7 +97,7 @@ func (n *Node) AddNodeLink(name string, that *Node) error {
97
98
// AddNodeLinkClean adds a link to another node. without keeping a reference to
99
// the child node
102
-func (n *Node) AddNodeLinkClean(name string, that *Node) error {
100
+func (n *ProtoNode) AddNodeLinkClean(name string, that Node) error {
101
n.encoded = nil
102
lnk, err := MakeLink(that)
103
if err != nil {
@@ -111,31 +109,31 @@ func (n *Node) AddNodeLinkClean(name string, that *Node) error {
109
}
110
111
// AddRawLink adds a copy of a link to this node
114
-func (n *Node) AddRawLink(name string, l *Link) error {
112
+func (n *ProtoNode) AddRawLink(name string, l *Link) error {
113
n.encoded = nil
116
- n.Links = append(n.Links, &Link{
114
+ n.links = append(n.links, &Link{
115
Name: name,
116
Size: l.Size,
119
- Hash: l.Hash,
117
+ Cid: l.Cid,
118
})
119
120
return nil
121
}
122
123
// Remove a link on this node by the given name
126
-func (n *Node) RemoveNodeLink(name string) error {
124
+func (n *ProtoNode) RemoveNodeLink(name string) error {
125
n.encoded = nil
128
- good := make([]*Link, 0, len(n.Links))
126
+ good := make([]*Link, 0, len(n.links))
127
var found bool
128
131
- for _, l := range n.Links {
129
+ for _, l := range n.links {
130
if l.Name != name {
131
good = append(good, l)
132
} else {
133
found = true
134
}
135
}
138
- n.Links = good
136
+ n.links = good
137
138
if !found {
139
return ErrNotFound
@@ -145,20 +143,36 @@ func (n *Node) RemoveNodeLink(name string) error {
143
}
144
145
// Return a copy of the link with given name
148
-func (n *Node) GetNodeLink(name string) (*Link, error) {
149
- for _, l := range n.Links {
146
+func (n *ProtoNode) GetNodeLink(name string) (*Link, error) {
147
+ for _, l := range n.links {
148
if l.Name == name {
149
return &Link{
150
Name: l.Name,
151
Size: l.Size,
154
- Hash: l.Hash,
152
+ Cid: l.Cid,
153
}, nil
154
}
155
}
156
return nil, ErrLinkNotFound
157
}
158
161
-func (n *Node) GetLinkedNode(ctx context.Context, ds DAGService, name string) (*Node, error) {
159
+var ErrNotProtobuf = fmt.Errorf("expected protobuf dag node")
160
+
161
+func (n *ProtoNode) GetLinkedProtoNode(ctx context.Context, ds DAGService, name string) (*ProtoNode, error) {
162
+ nd, err := n.GetLinkedNode(ctx, ds, name)
163
+ if err != nil {
164
+ return nil, err
165
+ }
166
+
167
+ pbnd, ok := nd.(*ProtoNode)
168
+ if !ok {
169
+ return nil, ErrNotProtobuf
170
+ }
171
+
172
+ return pbnd, nil
173
+}
174
+
175
+func (n *ProtoNode) GetLinkedNode(ctx context.Context, ds DAGService, name string) (Node, error) {
176
lnk, err := n.GetNodeLink(name)
177
if err != nil {
178
return nil, err
@@ -169,30 +183,30 @@ func (n *Node) GetLinkedNode(ctx context.Context, ds DAGService, name string) (*
183
184
// Copy returns a copy of the node.
185
// NOTE: Does not make copies of Node objects in the links.
172
-func (n *Node) Copy() *Node {
173
- nnode := new(Node)
186
+func (n *ProtoNode) Copy() *ProtoNode {
187
+ nnode := new(ProtoNode)
188
if len(n.data) > 0 {
189
nnode.data = make([]byte, len(n.data))
190
copy(nnode.data, n.data)
191
}
192
179
- if len(n.Links) > 0 {
180
- nnode.Links = make([]*Link, len(n.Links))
181
- copy(nnode.Links, n.Links)
193
+ if len(n.links) > 0 {
194
+ nnode.links = make([]*Link, len(n.links))
195
+ copy(nnode.links, n.links)
196
}
197
return nnode
198
}
199
186
-func (n *Node) RawData() []byte {
200
+func (n *ProtoNode) RawData() []byte {
201
out, _ := n.EncodeProtobuf(false)
202
return out
203
}
204
191
-func (n *Node) Data() []byte {
205
+func (n *ProtoNode) Data() []byte {
206
return n.data
207
}
208
195
-func (n *Node) SetData(d []byte) {
209
+func (n *ProtoNode) SetData(d []byte) {
210
n.encoded = nil
211
n.cached = nil
212
n.data = d
@@ -200,7 +214,7 @@ func (n *Node) SetData(d []byte) {
214
215
// UpdateNodeLink return a copy of the node with the link name set to point to
216
// that. If a link of the same name existed, it is removed.
203
-func (n *Node) UpdateNodeLink(name string, that *Node) (*Node, error) {
217
+func (n *ProtoNode) UpdateNodeLink(name string, that *ProtoNode) (*ProtoNode, error) {
218
newnode := n.Copy()
219
err := newnode.RemoveNodeLink(name)
220
err = nil // ignore error
@@ -210,21 +224,21 @@ func (n *Node) UpdateNodeLink(name string, that *Node) (*Node, error) {
224
225
// Size returns the total size of the data addressed by node,
226
// including the total sizes of references.
213
-func (n *Node) Size() (uint64, error) {
227
+func (n *ProtoNode) Size() (uint64, error) {
228
b, err := n.EncodeProtobuf(false)
229
if err != nil {
230
return 0, err
231
}
232
233
s := uint64(len(b))
220
- for _, l := range n.Links {
234
+ for _, l := range n.links {
235
s += l.Size
236
}
237
return s, nil
238
}
239
240
// Stat returns statistics on the node.
227
-func (n *Node) Stat() (*NodeStat, error) {
241
+func (n *ProtoNode) Stat() (*NodeStat, error) {
242
enc, err := n.EncodeProtobuf(false)
243
if err != nil {
244
return nil, err
@@ -237,7 +251,7 @@ func (n *Node) Stat() (*NodeStat, error) {
251
252
return &NodeStat{
253
Hash: n.Key().B58String(),
240
- NumLinks: len(n.Links),
254
+ NumLinks: len(n.links),
255
BlockSize: len(enc),
256
LinksSize: len(enc) - len(n.data), // includes framing.
257
DataSize: len(n.data),
@@ -245,28 +259,28 @@ func (n *Node) Stat() (*NodeStat, error) {
259
}, nil
260
}
261
248
-func (n *Node) Key() key.Key {
262
+func (n *ProtoNode) Key() key.Key {
263
return key.Key(n.Multihash())
264
}
265
252
-func (n *Node) Loggable() map[string]interface{} {
266
+func (n *ProtoNode) Loggable() map[string]interface{} {
267
return map[string]interface{}{
268
"node": n.String(),
269
}
270
}
271
258
-func (n *Node) Cid() *cid.Cid {
272
+func (n *ProtoNode) Cid() *cid.Cid {
273
h := n.Multihash()
274
275
return cid.NewCidV0(h)
276
}
277
264
-func (n *Node) String() string {
278
+func (n *ProtoNode) String() string {
279
return n.Cid().String()
280
}
281
282
// Multihash hashes the encoded data of this node.
269
-func (n *Node) Multihash() mh.Multihash {
283
+func (n *ProtoNode) Multihash() mh.Multihash {
284
// NOTE: EncodeProtobuf generates the hash and puts it in n.cached.
285
_, err := n.EncodeProtobuf(false)
286
if err != nil {
@@ -276,3 +290,32 @@ func (n *Node) Multihash() mh.Multihash {
290
291
return n.cached.Hash()
292
}
293
+
294
+func (n *ProtoNode) Links() []*Link {
295
+ return n.links
296
+}
297
+
298
+func (n *ProtoNode) SetLinks(links []*Link) {
299
+ n.links = links
300
+}
301
+
302
+func (n *ProtoNode) Resolve(path []string) (*Link, []string, error) {
303
+ if len(path) == 0 {
304
+ return nil, nil, fmt.Errorf("end of path, no more links to resolve")
305
+ }
306
+
307
+ lnk, err := n.GetNodeLink(path[0])
308
+ if err != nil {
309
+ return nil, nil, err
310
+ }
311
+
312
+ return lnk, path[1:], nil
313
+}
314
+
315
+func (n *ProtoNode) Tree() []string {
316
+ out := make([]string, 0, len(n.links))
317
+ for _, lnk := range n.links {
318
+ out = append(out, lnk.Name)
319
+ }
320
+ return out
321
+}
merkledag/node_test.go
+30
-32
@@ -10,31 +10,30 @@ import (
10
)
11
12
func TestRemoveLink(t *testing.T) {
13
- nd := &Node{
14
- Links: []*Link{
15
- &Link{Name: "a"},
16
- &Link{Name: "b"},
17
- &Link{Name: "a"},
18
- &Link{Name: "a"},
19
- &Link{Name: "c"},
20
- &Link{Name: "a"},
21
- },
22
- }
13
+ nd := &ProtoNode{}
14
+ nd.SetLinks([]*Link{
15
+ &Link{Name: "a"},
16
+ &Link{Name: "b"},
17
+ &Link{Name: "a"},
18
+ &Link{Name: "a"},
19
+ &Link{Name: "c"},
20
+ &Link{Name: "a"},
21
+ })
22
23
err := nd.RemoveNodeLink("a")
24
if err != nil {
25
t.Fatal(err)
26
}
27
29
- if len(nd.Links) != 2 {
28
+ if len(nd.Links()) != 2 {
29
t.Fatal("number of links incorrect")
30
}
31
33
- if nd.Links[0].Name != "b" {
32
+ if nd.Links()[0].Name != "b" {
33
t.Fatal("link order wrong")
34
}
35
37
- if nd.Links[1].Name != "c" {
36
+ if nd.Links()[1].Name != "c" {
37
t.Fatal("link order wrong")
38
}
39
@@ -45,33 +44,32 @@ func TestRemoveLink(t *testing.T) {
44
}
45
46
// ensure nothing else got touched
48
- if len(nd.Links) != 2 {
47
+ if len(nd.Links()) != 2 {
48
t.Fatal("number of links incorrect")
49
}
50
52
- if nd.Links[0].Name != "b" {
51
+ if nd.Links()[0].Name != "b" {
52
t.Fatal("link order wrong")
53
}
54
56
- if nd.Links[1].Name != "c" {
55
+ if nd.Links()[1].Name != "c" {
56
t.Fatal("link order wrong")
57
}
58
}
59
60
func TestFindLink(t *testing.T) {
61
ds := mdtest.Mock()
63
- k, err := ds.Add(new(Node))
62
+ k, err := ds.Add(new(ProtoNode))
63
if err != nil {
64
t.Fatal(err)
65
}
66
68
- nd := &Node{
69
- Links: []*Link{
70
- &Link{Name: "a", Hash: k.Hash()},
71
- &Link{Name: "c", Hash: k.Hash()},
72
- &Link{Name: "b", Hash: k.Hash()},
73
- },
74
- }
67
+ nd := &ProtoNode{}
68
+ nd.SetLinks([]*Link{
69
+ &Link{Name: "a", Cid: k},
70
+ &Link{Name: "c", Cid: k},
71
+ &Link{Name: "b", Cid: k},
72
+ })
73
74
_, err = ds.Add(nd)
75
if err != nil {
@@ -107,19 +105,19 @@ func TestFindLink(t *testing.T) {
105
t.Fatal(err)
106
}
107
110
- if olnk.Hash.B58String() == k.String() {
108
+ if olnk.Cid.String() == k.String() {
109
t.Fatal("new link should have different hash")
110
}
111
}
112
113
func TestNodeCopy(t *testing.T) {
116
- nd := &Node{
117
- Links: []*Link{
118
- &Link{Name: "a"},
119
- &Link{Name: "c"},
120
- &Link{Name: "b"},
121
- },
122
- }
114
+ nd := &ProtoNode{}
115
+ nd.SetLinks([]*Link{
116
+ &Link{Name: "a"},
117
+ &Link{Name: "c"},
118
+ &Link{Name: "b"},
119
+ })
120
+
121
nd.SetData([]byte("testing"))
122
123
ond := nd.Copy()
merkledag/traverse/traverse.go
+10
-10
@@ -30,7 +30,7 @@ type Options struct {
30
31
// State is a current traversal state
32
type State struct {
33
- Node *mdag.Node
33
+ Node mdag.Node
34
Depth int
35
}
36
@@ -39,13 +39,13 @@ type traversal struct {
39
seen map[string]struct{}
40
}
41
42
-func (t *traversal) shouldSkip(n *mdag.Node) (bool, error) {
42
+func (t *traversal) shouldSkip(n mdag.Node) (bool, error) {
43
if t.opts.SkipDuplicates {
44
- k := n.Key()
45
- if _, found := t.seen[string(k)]; found {
44
+ k := n.Cid()
45
+ if _, found := t.seen[k.KeyString()]; found {
46
return true, nil
47
}
48
- t.seen[string(k)] = struct{}{}
48
+ t.seen[k.KeyString()] = struct{}{}
49
}
50
51
return false, nil
@@ -59,9 +59,9 @@ func (t *traversal) callFunc(next State) error {
59
// stop processing. if it returns a nil node, just skip it.
60
//
61
// the error handling is a little complicated.
62
-func (t *traversal) getNode(link *mdag.Link) (*mdag.Node, error) {
62
+func (t *traversal) getNode(link *mdag.Link) (mdag.Node, error) {
63
64
- getNode := func(l *mdag.Link) (*mdag.Node, error) {
64
+ getNode := func(l *mdag.Link) (mdag.Node, error) {
65
next, err := l.GetNode(context.TODO(), t.opts.DAG)
66
if err != nil {
67
return nil, err
@@ -99,7 +99,7 @@ type Func func(current State) error
99
//
100
type ErrFunc func(err error) error
101
102
-func Traverse(root *mdag.Node, o Options) error {
102
+func Traverse(root mdag.Node, o Options) error {
103
t := traversal{
104
opts: o,
105
seen: map[string]struct{}{},
@@ -145,7 +145,7 @@ func dfsPostTraverse(state State, t *traversal) error {
145
}
146
147
func dfsDescend(df dfsFunc, curr State, t *traversal) error {
148
- for _, l := range curr.Node.Links {
148
+ for _, l := range curr.Node.Links() {
149
node, err := t.getNode(l)
150
if err != nil {
151
return err
@@ -184,7 +184,7 @@ func bfsTraverse(root State, t *traversal) error {
184
return err
185
}
186
187
- for _, l := range curr.Node.Links {
187
+ for _, l := range curr.Node.Links() {
188
node, err := t.getNode(l)
189
if err != nil {
190
return err
merkledag/traverse/traverse_test.go
+11
-11
@@ -321,12 +321,12 @@ func TestBFSSkip(t *testing.T) {
321
`))
322
}
323
324
-func testWalkOutputs(t *testing.T, root *mdag.Node, opts Options, expect []byte) {
324
+func testWalkOutputs(t *testing.T, root mdag.Node, opts Options, expect []byte) {
325
expect = bytes.TrimLeft(expect, "\n")
326
327
buf := new(bytes.Buffer)
328
walk := func(current State) error {
329
- s := fmt.Sprintf("%d %s\n", current.Depth, current.Node.Data())
329
+ s := fmt.Sprintf("%d %s\n", current.Depth, current.Node.(*mdag.ProtoNode).Data())
330
t.Logf("walk: %s", s)
331
buf.Write([]byte(s))
332
return nil
@@ -348,7 +348,7 @@ func testWalkOutputs(t *testing.T, root *mdag.Node, opts Options, expect []byte)
348
}
349
}
350
351
-func newFan(t *testing.T, ds mdag.DAGService) *mdag.Node {
351
+func newFan(t *testing.T, ds mdag.DAGService) mdag.Node {
352
a := mdag.NodeWithData([]byte("/a"))
353
addLink(t, ds, a, child(t, ds, a, "aa"))
354
addLink(t, ds, a, child(t, ds, a, "ab"))
@@ -357,7 +357,7 @@ func newFan(t *testing.T, ds mdag.DAGService) *mdag.Node {
357
return a
358
}
359
360
-func newLinkedList(t *testing.T, ds mdag.DAGService) *mdag.Node {
360
+func newLinkedList(t *testing.T, ds mdag.DAGService) mdag.Node {
361
a := mdag.NodeWithData([]byte("/a"))
362
aa := child(t, ds, a, "aa")
363
aaa := child(t, ds, aa, "aaa")
@@ -370,7 +370,7 @@ func newLinkedList(t *testing.T, ds mdag.DAGService) *mdag.Node {
370
return a
371
}
372
373
-func newBinaryTree(t *testing.T, ds mdag.DAGService) *mdag.Node {
373
+func newBinaryTree(t *testing.T, ds mdag.DAGService) mdag.Node {
374
a := mdag.NodeWithData([]byte("/a"))
375
aa := child(t, ds, a, "aa")
376
ab := child(t, ds, a, "ab")
@@ -383,7 +383,7 @@ func newBinaryTree(t *testing.T, ds mdag.DAGService) *mdag.Node {
383
return a
384
}
385
386
-func newBinaryDAG(t *testing.T, ds mdag.DAGService) *mdag.Node {
386
+func newBinaryDAG(t *testing.T, ds mdag.DAGService) mdag.Node {
387
a := mdag.NodeWithData([]byte("/a"))
388
aa := child(t, ds, a, "aa")
389
aaa := child(t, ds, aa, "aaa")
@@ -400,16 +400,16 @@ func newBinaryDAG(t *testing.T, ds mdag.DAGService) *mdag.Node {
400
return a
401
}
402
403
-func addLink(t *testing.T, ds mdag.DAGService, a, b *mdag.Node) {
404
- to := string(a.Data()) + "2" + string(b.Data())
403
+func addLink(t *testing.T, ds mdag.DAGService, a, b mdag.Node) {
404
+ to := string(a.(*mdag.ProtoNode).Data()) + "2" + string(b.(*mdag.ProtoNode).Data())
405
if _, err := ds.Add(b); err != nil {
406
t.Error(err)
407
}
408
- if err := a.AddNodeLink(to, b); err != nil {
408
+ if err := a.(*mdag.ProtoNode).AddNodeLink(to, b.(*mdag.ProtoNode)); err != nil {
409
t.Error(err)
410
}
411
}
412
413
-func child(t *testing.T, ds mdag.DAGService, a *mdag.Node, name string) *mdag.Node {
414
- return mdag.NodeWithData([]byte(string(a.Data()) + "/" + name))
413
+func child(t *testing.T, ds mdag.DAGService, a mdag.Node, name string) mdag.Node {
414
+ return mdag.NodeWithData([]byte(string(a.(*mdag.ProtoNode).Data()) + "/" + name))
415
}
merkledag/utils/diff.go
+34
-13
@@ -1,7 +1,6 @@
1
package dagutils
2
3
import (
4
- "bytes"
4
"fmt"
5
"path"
6
@@ -37,7 +36,7 @@ func (c *Change) String() string {
36
}
37
}
38
40
-func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Change) (*dag.Node, error) {
39
+func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.ProtoNode, cs []*Change) (*dag.ProtoNode, error) {
40
e := NewDagEditor(nd, ds)
41
for _, c := range cs {
42
switch c.Type {
@@ -46,7 +45,13 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
45
if err != nil {
46
return nil, err
47
}
49
- err = e.InsertNodeAtPath(ctx, c.Path, child, nil)
48
+
49
+ childpb, ok := child.(*dag.ProtoNode)
50
+ if !ok {
51
+ return nil, dag.ErrNotProtobuf
52
+ }
53
+
54
+ err = e.InsertNodeAtPath(ctx, c.Path, childpb, nil)
55
if err != nil {
56
return nil, err
57
}
@@ -66,7 +71,13 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
71
if err != nil {
72
return nil, err
73
}
69
- err = e.InsertNodeAtPath(ctx, c.Path, child, nil)
74
+
75
+ childpb, ok := child.(*dag.ProtoNode)
76
+ if !ok {
77
+ return nil, dag.ErrNotProtobuf
78
+ }
79
+
80
+ err = e.InsertNodeAtPath(ctx, c.Path, childpb, nil)
81
if err != nil {
82
return nil, err
83
}
@@ -76,8 +87,8 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
87
return e.Finalize(ds)
88
}
89
79
-func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, error) {
80
- if len(a.Links) == 0 && len(b.Links) == 0 {
90
+func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.ProtoNode) ([]*Change, error) {
91
+ if len(a.Links()) == 0 && len(b.Links()) == 0 {
92
return []*Change{
93
&Change{
94
Type: Mod,
@@ -92,10 +103,10 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
103
clean_b := b.Copy()
104
105
// strip out unchanged stuff
95
- for _, lnk := range a.Links {
106
+ for _, lnk := range a.Links() {
107
l, err := b.GetNodeLink(lnk.Name)
108
if err == nil {
98
- if bytes.Equal(l.Hash, lnk.Hash) {
109
+ if l.Cid.Equals(lnk.Cid) {
110
// no change... ignore it
111
} else {
112
anode, err := lnk.GetNode(ctx, ds)
@@ -108,7 +119,17 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
119
return nil, err
120
}
121
111
- sub, err := Diff(ctx, ds, anode, bnode)
122
+ anodepb, ok := anode.(*dag.ProtoNode)
123
+ if !ok {
124
+ return nil, dag.ErrNotProtobuf
125
+ }
126
+
127
+ bnodepb, ok := bnode.(*dag.ProtoNode)
128
+ if !ok {
129
+ return nil, dag.ErrNotProtobuf
130
+ }
131
+
132
+ sub, err := Diff(ctx, ds, anodepb, bnodepb)
133
if err != nil {
134
return nil, err
135
}
@@ -123,18 +144,18 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
144
}
145
}
146
126
- for _, lnk := range clean_a.Links {
147
+ for _, lnk := range clean_a.Links() {
148
out = append(out, &Change{
149
Type: Remove,
150
Path: lnk.Name,
130
- Before: cid.NewCidV0(lnk.Hash),
151
+ Before: lnk.Cid,
152
})
153
}
133
- for _, lnk := range clean_b.Links {
154
+ for _, lnk := range clean_b.Links() {
155
out = append(out, &Change{
156
Type: Add,
157
Path: lnk.Name,
137
- After: cid.NewCidV0(lnk.Hash),
158
+ After: lnk.Cid,
159
})
160
}
161
merkledag/utils/utils.go
+20
-15
@@ -15,7 +15,7 @@ import (
15
)
16
17
type Editor struct {
18
- root *dag.Node
18
+ root *dag.ProtoNode
19
20
// tmp is a temporary in memory (for now) dagstore for all of the
21
// intermediary nodes to be stored in
@@ -34,7 +34,7 @@ func NewMemoryDagService() dag.DAGService {
34
}
35
36
// root is the node to be modified, source is the dagstore to pull nodes from (optional)
37
-func NewDagEditor(root *dag.Node, source dag.DAGService) *Editor {
37
+func NewDagEditor(root *dag.ProtoNode, source dag.DAGService) *Editor {
38
return &Editor{
39
root: root,
40
tmp: NewMemoryDagService(),
@@ -42,7 +42,7 @@ func NewDagEditor(root *dag.Node, source dag.DAGService) *Editor {
42
}
43
}
44
45
-func (e *Editor) GetNode() *dag.Node {
45
+func (e *Editor) GetNode() *dag.ProtoNode {
46
return e.root.Copy()
47
}
48
@@ -50,7 +50,7 @@ func (e *Editor) GetDagService() dag.DAGService {
50
return e.tmp
51
}
52
53
-func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname string, childnd *dag.Node) (*dag.Node, error) {
53
+func addLink(ctx context.Context, ds dag.DAGService, root *dag.ProtoNode, childname string, childnd *dag.ProtoNode) (*dag.ProtoNode, error) {
54
if childname == "" {
55
return nil, errors.New("cannot create link with no name!")
56
}
@@ -76,7 +76,7 @@ func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname s
76
return root, nil
77
}
78
79
-func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag.Node, create func() *dag.Node) error {
79
+func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag.ProtoNode, create func() *dag.ProtoNode) error {
80
splpath := path.SplitList(pth)
81
nd, err := e.insertNodeAtPath(ctx, e.root, splpath, toinsert, create)
82
if err != nil {
@@ -86,12 +86,12 @@ func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag
86
return nil
87
}
88
89
-func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.Node, path []string, toinsert *dag.Node, create func() *dag.Node) (*dag.Node, error) {
89
+func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.ProtoNode, path []string, toinsert *dag.ProtoNode, create func() *dag.ProtoNode) (*dag.ProtoNode, error) {
90
if len(path) == 1 {
91
return addLink(ctx, e.tmp, root, path[0], toinsert)
92
}
93
94
- nd, err := root.GetLinkedNode(ctx, e.tmp, path[0])
94
+ nd, err := root.GetLinkedProtoNode(ctx, e.tmp, path[0])
95
if err != nil {
96
// if 'create' is true, we create directories on the way down as needed
97
if err == dag.ErrLinkNotFound && create != nil {
@@ -99,7 +99,7 @@ func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.Node, path []st
99
err = nil // no longer an error case
100
} else if err == dag.ErrNotFound {
101
// try finding it in our source dagstore
102
- nd, err = root.GetLinkedNode(ctx, e.src, path[0])
102
+ nd, err = root.GetLinkedProtoNode(ctx, e.src, path[0])
103
}
104
105
// if we receive an ErrNotFound, then our second 'GetLinkedNode' call
@@ -140,7 +140,7 @@ func (e *Editor) RmLink(ctx context.Context, pth string) error {
140
return nil
141
}
142
143
-func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*dag.Node, error) {
143
+func (e *Editor) rmLink(ctx context.Context, root *dag.ProtoNode, path []string) (*dag.ProtoNode, error) {
144
if len(path) == 1 {
145
// base case, remove node in question
146
err := root.RemoveNodeLink(path[0])
@@ -157,9 +157,9 @@ func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*da
157
}
158
159
// search for node in both tmp dagstore and source dagstore
160
- nd, err := root.GetLinkedNode(ctx, e.tmp, path[0])
160
+ nd, err := root.GetLinkedProtoNode(ctx, e.tmp, path[0])
161
if err == dag.ErrNotFound {
162
- nd, err = root.GetLinkedNode(ctx, e.src, path[0])
162
+ nd, err = root.GetLinkedProtoNode(ctx, e.src, path[0])
163
}
164
165
if err != nil {
@@ -187,19 +187,19 @@ func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*da
187
return root, nil
188
}
189
190
-func (e *Editor) Finalize(ds dag.DAGService) (*dag.Node, error) {
190
+func (e *Editor) Finalize(ds dag.DAGService) (*dag.ProtoNode, error) {
191
nd := e.GetNode()
192
err := copyDag(nd, e.tmp, ds)
193
return nd, err
194
}
195
196
-func copyDag(nd *dag.Node, from, to dag.DAGService) error {
196
+func copyDag(nd *dag.ProtoNode, from, to dag.DAGService) error {
197
_, err := to.Add(nd)
198
if err != nil {
199
return err
200
}
201
202
- for _, lnk := range nd.Links {
202
+ for _, lnk := range nd.Links() {
203
child, err := lnk.GetNode(context.Background(), from)
204
if err != nil {
205
if err == dag.ErrNotFound {
@@ -210,7 +210,12 @@ func copyDag(nd *dag.Node, from, to dag.DAGService) error {
210
return err
211
}
212
213
- err = copyDag(child, from, to)
213
+ childpb, ok := child.(*dag.ProtoNode)
214
+ if !ok {
215
+ return dag.ErrNotProtobuf
216
+ }
217
+
218
+ err = copyDag(childpb, from, to)
219
if err != nil {
220
return err
221
}
merkledag/utils/utils_test.go
+7
-7
@@ -20,7 +20,7 @@ func TestAddLink(t *testing.T) {
20
t.Fatal(err)
21
}
22
23
- nd := new(dag.Node)
23
+ nd := new(dag.ProtoNode)
24
nnode, err := addLink(context.Background(), ds, nd, "fish", fishnode)
25
if err != nil {
26
t.Fatal(err)
@@ -37,11 +37,11 @@ func TestAddLink(t *testing.T) {
37
}
38
}
39
40
-func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, pth string, exp *cid.Cid) {
40
+func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.ProtoNode, pth string, exp *cid.Cid) {
41
parts := path.SplitList(pth)
42
cur := root
43
for _, e := range parts {
44
- nxt, err := cur.GetLinkedNode(context.Background(), ds, e)
44
+ nxt, err := cur.GetLinkedProtoNode(context.Background(), ds, e)
45
if err != nil {
46
t.Fatal(err)
47
}
@@ -56,7 +56,7 @@ func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, pth strin
56
}
57
58
func TestInsertNode(t *testing.T) {
59
- root := new(dag.Node)
59
+ root := new(dag.ProtoNode)
60
e := NewDagEditor(root, nil)
61
62
testInsert(t, e, "a", "anodefortesting", false, "")
@@ -83,10 +83,10 @@ func testInsert(t *testing.T, e *Editor, path, data string, create bool, experr
83
t.Fatal(err)
84
}
85
86
- var c func() *dag.Node
86
+ var c func() *dag.ProtoNode
87
if create {
88
- c = func() *dag.Node {
89
- return &dag.Node{}
88
+ c = func() *dag.ProtoNode {
89
+ return &dag.ProtoNode{}
90
}
91
}
92
mfs/dir.go
+21
-19
@@ -28,7 +28,7 @@ type Directory struct {
28
files map[string]*File
29
30
lock sync.Mutex
31
- node *dag.Node
31
+ node *dag.ProtoNode
32
ctx context.Context
33
34
modTime time.Time
@@ -36,7 +36,7 @@ type Directory struct {
36
name string
37
}
38
39
-func NewDirectory(ctx context.Context, name string, node *dag.Node, parent childCloser, dserv dag.DAGService) *Directory {
39
+func NewDirectory(ctx context.Context, name string, node *dag.ProtoNode, parent childCloser, dserv dag.DAGService) *Directory {
40
return &Directory{
41
dserv: dserv,
42
ctx: ctx,
@@ -51,7 +51,7 @@ func NewDirectory(ctx context.Context, name string, node *dag.Node, parent child
51
52
// closeChild updates the child by the given name to the dag node 'nd'
53
// and changes its own dag node
54
-func (d *Directory) closeChild(name string, nd *dag.Node, sync bool) error {
54
+func (d *Directory) closeChild(name string, nd *dag.ProtoNode, sync bool) error {
55
mynd, err := d.closeChildUpdate(name, nd, sync)
56
if err != nil {
57
return err
@@ -64,7 +64,7 @@ func (d *Directory) closeChild(name string, nd *dag.Node, sync bool) error {
64
}
65
66
// closeChildUpdate is the portion of closeChild that needs to be locked around
67
-func (d *Directory) closeChildUpdate(name string, nd *dag.Node, sync bool) (*dag.Node, error) {
67
+func (d *Directory) closeChildUpdate(name string, nd *dag.ProtoNode, sync bool) (*dag.ProtoNode, error) {
68
d.lock.Lock()
69
defer d.lock.Unlock()
70
@@ -79,7 +79,7 @@ func (d *Directory) closeChildUpdate(name string, nd *dag.Node, sync bool) (*dag
79
return nil, nil
80
}
81
82
-func (d *Directory) flushCurrentNode() (*dag.Node, error) {
82
+func (d *Directory) flushCurrentNode() (*dag.ProtoNode, error) {
83
_, err := d.dserv.Add(d.node)
84
if err != nil {
85
return nil, err
@@ -88,7 +88,7 @@ func (d *Directory) flushCurrentNode() (*dag.Node, error) {
88
return d.node.Copy(), nil
89
}
90
91
-func (d *Directory) updateChild(name string, nd *dag.Node) error {
91
+func (d *Directory) updateChild(name string, nd *dag.ProtoNode) error {
92
err := d.node.RemoveNodeLink(name)
93
if err != nil && err != dag.ErrNotFound {
94
return err
@@ -120,7 +120,7 @@ func (d *Directory) childNode(name string) (FSNode, error) {
120
}
121
122
// cacheNode caches a node into d.childDirs or d.files and returns the FSNode.
123
-func (d *Directory) cacheNode(name string, nd *dag.Node) (FSNode, error) {
123
+func (d *Directory) cacheNode(name string, nd *dag.ProtoNode) (FSNode, error) {
124
i, err := ft.FromBytes(nd.Data())
125
if err != nil {
126
return nil, err
@@ -161,14 +161,16 @@ func (d *Directory) Uncache(name string) {
161
162
// childFromDag searches through this directories dag node for a child link
163
// with the given name
164
-func (d *Directory) childFromDag(name string) (*dag.Node, error) {
165
- for _, lnk := range d.node.Links {
166
- if lnk.Name == name {
167
- return lnk.GetNode(d.ctx, d.dserv)
168
- }
164
+func (d *Directory) childFromDag(name string) (*dag.ProtoNode, error) {
165
+ pbn, err := d.node.GetLinkedProtoNode(d.ctx, d.dserv, name)
166
+ switch err {
167
+ case nil:
168
+ return pbn, nil
169
+ case dag.ErrLinkNotFound:
170
+ return nil, os.ErrNotExist
171
+ default:
172
+ return nil, err
173
}
170
-
171
- return nil, os.ErrNotExist
174
}
175
176
// childUnsync returns the child under this directory by the given name
@@ -206,7 +208,7 @@ func (d *Directory) ListNames() []string {
208
names[n] = struct{}{}
209
}
210
209
- for _, l := range d.node.Links {
211
+ for _, l := range d.node.Links() {
212
names[l.Name] = struct{}{}
213
}
214
@@ -224,7 +226,7 @@ func (d *Directory) List() ([]NodeListing, error) {
226
defer d.lock.Unlock()
227
228
var out []NodeListing
227
- for _, l := range d.node.Links {
229
+ for _, l := range d.node.Links() {
230
child := NodeListing{}
231
child.Name = l.Name
232
@@ -270,7 +272,7 @@ func (d *Directory) Mkdir(name string) (*Directory, error) {
272
}
273
}
274
273
- ndir := new(dag.Node)
275
+ ndir := new(dag.ProtoNode)
276
ndir.SetData(ft.FolderPBData())
277
278
_, err = d.dserv.Add(ndir)
@@ -321,7 +323,7 @@ func (d *Directory) Flush() error {
323
}
324
325
// AddChild adds the node 'nd' under this directory giving it the name 'name'
324
-func (d *Directory) AddChild(name string, nd *dag.Node) error {
326
+func (d *Directory) AddChild(name string, nd *dag.ProtoNode) error {
327
d.lock.Lock()
328
defer d.lock.Unlock()
329
@@ -382,7 +384,7 @@ func (d *Directory) Path() string {
384
return out
385
}
386
385
-func (d *Directory) GetNode() (*dag.Node, error) {
387
+func (d *Directory) GetNode() (*dag.ProtoNode, error) {
388
d.lock.Lock()
389
defer d.lock.Unlock()
390
mfs/file.go
+3
-3
@@ -19,12 +19,12 @@ type File struct {
19
desclock sync.RWMutex
20
21
dserv dag.DAGService
22
- node *dag.Node
22
+ node *dag.ProtoNode
23
nodelk sync.Mutex
24
}
25
26
// NewFile returns a NewFile object with the given parameters
27
-func NewFile(name string, node *dag.Node, parent childCloser, dserv dag.DAGService) (*File, error) {
27
+func NewFile(name string, node *dag.ProtoNode, parent childCloser, dserv dag.DAGService) (*File, error) {
28
return &File{
29
dserv: dserv,
30
parent: parent,
@@ -94,7 +94,7 @@ func (fi *File) Size() (int64, error) {
94
}
95
96
// GetNode returns the dag node associated with this file
97
-func (fi *File) GetNode() (*dag.Node, error) {
97
+func (fi *File) GetNode() (*dag.ProtoNode, error) {
98
fi.nodelk.Lock()
99
defer fi.nodelk.Unlock()
100
return fi.node, nil
mfs/mfs_test.go
+11
-11
@@ -30,7 +30,7 @@ import (
30
dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
31
)
32
33
-func emptyDirNode() *dag.Node {
33
+func emptyDirNode() *dag.ProtoNode {
34
return dag.NodeWithData(ft.FolderPBData())
35
}
36
@@ -41,12 +41,12 @@ func getDagserv(t *testing.T) dag.DAGService {
41
return dag.NewDAGService(blockserv)
42
}
43
44
-func getRandFile(t *testing.T, ds dag.DAGService, size int64) *dag.Node {
44
+func getRandFile(t *testing.T, ds dag.DAGService, size int64) *dag.ProtoNode {
45
r := io.LimitReader(u.NewTimeSeededRand(), size)
46
return fileNodeFromReader(t, ds, r)
47
}
48
49
-func fileNodeFromReader(t *testing.T, ds dag.DAGService, r io.Reader) *dag.Node {
49
+func fileNodeFromReader(t *testing.T, ds dag.DAGService, r io.Reader) *dag.ProtoNode {
50
nd, err := importer.BuildDagFromReader(ds, chunk.DefaultSplitter(r))
51
if err != nil {
52
t.Fatal(err)
@@ -124,7 +124,7 @@ func compStrArrs(a, b []string) bool {
124
return true
125
}
126
127
-func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.Node, pth string) error {
127
+func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.ProtoNode, pth string) error {
128
parts := path.SplitList(pth)
129
cur := root
130
for i, d := range parts[:len(parts)-1] {
@@ -173,7 +173,7 @@ func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.Node, pth str
173
return nil
174
}
175
176
-func catNode(ds dag.DAGService, nd *dag.Node) ([]byte, error) {
176
+func catNode(ds dag.DAGService, nd *dag.ProtoNode) ([]byte, error) {
177
r, err := uio.NewDagReader(context.TODO(), nd, ds)
178
if err != nil {
179
return nil, err
@@ -280,7 +280,7 @@ func TestDirectoryLoadFromDag(t *testing.T) {
280
t.Fatal(err)
281
}
282
283
- fihash := nd.Multihash()
283
+ fihash := nd.Cid()
284
285
dir := emptyDirNode()
286
_, err = ds.Add(dir)
@@ -288,19 +288,19 @@ func TestDirectoryLoadFromDag(t *testing.T) {
288
t.Fatal(err)
289
}
290
291
- dirhash := dir.Multihash()
291
+ dirhash := dir.Cid()
292
293
top := emptyDirNode()
294
- top.Links = []*dag.Link{
294
+ top.SetLinks([]*dag.Link{
295
&dag.Link{
296
Name: "a",
297
- Hash: fihash,
297
+ Cid: fihash,
298
},
299
&dag.Link{
300
Name: "b",
301
- Hash: dirhash,
301
+ Cid: dirhash,
302
},
303
- }
303
+ })
304
305
err = rootdir.AddChild("foo", top)
306
if err != nil {
mfs/ops.go
+1
-1
@@ -87,7 +87,7 @@ func lookupDir(r *Root, path string) (*Directory, error) {
87
}
88
89
// PutNode inserts 'nd' at 'path' in the given mfs
90
-func PutNode(r *Root, path string, nd *dag.Node) error {
90
+func PutNode(r *Root, path string, nd *dag.ProtoNode) error {
91
dirp, filename := gopath.Split(path)
92
if filename == "" {
93
return fmt.Errorf("cannot create file with empty name")
mfs/system.go
+5
-5
@@ -29,7 +29,7 @@ var log = logging.Logger("mfs")
29
var ErrIsDirectory = errors.New("error: is a directory")
30
31
type childCloser interface {
32
- closeChild(string, *dag.Node, bool) error
32
+ closeChild(string, *dag.ProtoNode, bool) error
33
}
34
35
type NodeType int
@@ -41,7 +41,7 @@ const (
41
42
// FSNode represents any node (directory, root, or file) in the mfs filesystem
43
type FSNode interface {
44
- GetNode() (*dag.Node, error)
44
+ GetNode() (*dag.ProtoNode, error)
45
Flush() error
46
Type() NodeType
47
}
@@ -49,7 +49,7 @@ type FSNode interface {
49
// Root represents the root of a filesystem tree
50
type Root struct {
51
// node is the merkledag root
52
- node *dag.Node
52
+ node *dag.ProtoNode
53
54
// val represents the node. It can either be a File or a Directory
55
val FSNode
@@ -64,7 +64,7 @@ type Root struct {
64
type PubFunc func(context.Context, *cid.Cid) error
65
66
// newRoot creates a new Root and starts up a republisher routine for it
67
-func NewRoot(parent context.Context, ds dag.DAGService, node *dag.Node, pf PubFunc) (*Root, error) {
67
+func NewRoot(parent context.Context, ds dag.DAGService, node *dag.ProtoNode, pf PubFunc) (*Root, error) {
68
69
var repub *Republisher
70
if pf != nil {
@@ -118,7 +118,7 @@ func (kr *Root) Flush() error {
118
119
// closeChild implements the childCloser interface, and signals to the publisher that
120
// there are changes ready to be published
121
-func (kr *Root) closeChild(name string, nd *dag.Node, sync bool) error {
121
+func (kr *Root) closeChild(name string, nd *dag.ProtoNode, sync bool) error {
122
c, err := kr.dserv.Add(nd)
123
if err != nil {
124
return err
path/resolver.go
+19
-15
@@ -2,14 +2,13 @@
2
package path
3
4
import (
5
+ "context"
6
"errors"
7
"fmt"
8
"time"
9
9
- "context"
10
- mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
11
-
10
merkledag "github.com/ipfs/go-ipfs/merkledag"
11
+
12
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
13
cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
14
)
@@ -23,11 +22,11 @@ var ErrNoComponents = errors.New(
22
// ErrNoLink is returned when a link is not found in a path
23
type ErrNoLink struct {
24
Name string
26
- Node mh.Multihash
25
+ Node *cid.Cid
26
}
27
28
func (e ErrNoLink) Error() string {
30
- return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.B58String())
29
+ return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String())
30
}
31
32
// Resolver provides path resolution to IPFS
@@ -62,7 +61,7 @@ func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
61
62
// ResolvePath fetches the node for given path. It returns the last item
63
// returned by ResolvePathComponents.
65
-func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (*merkledag.Node, error) {
64
+func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (merkledag.Node, error) {
65
// validate path
66
if err := fpath.IsValid(); err != nil {
67
return nil, err
@@ -78,7 +77,7 @@ func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (*merkledag.Node
77
// ResolvePathComponents fetches the nodes for each segment of the given path.
78
// It uses the first path component as a hash (key) of the first node, then
79
// resolves all other components walking the links, with ResolveLinks.
81
-func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]*merkledag.Node, error) {
80
+func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]merkledag.Node, error) {
81
h, parts, err := SplitAbsPath(fpath)
82
if err != nil {
83
return nil, err
@@ -100,28 +99,33 @@ func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]*me
99
//
100
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
101
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
103
-func (s *Resolver) ResolveLinks(ctx context.Context, ndd *merkledag.Node, names []string) ([]*merkledag.Node, error) {
102
+func (s *Resolver) ResolveLinks(ctx context.Context, ndd merkledag.Node, names []string) ([]merkledag.Node, error) {
103
105
- result := make([]*merkledag.Node, 0, len(names)+1)
104
+ result := make([]merkledag.Node, 0, len(names)+1)
105
result = append(result, ndd)
106
nd := ndd // dup arg workaround
107
108
// for each of the path components
110
- for _, name := range names {
111
-
109
+ for len(names) > 0 {
110
var cancel context.CancelFunc
111
ctx, cancel = context.WithTimeout(ctx, time.Minute)
112
defer cancel()
113
116
- nextnode, err := nd.GetLinkedNode(ctx, s.DAG, name)
114
+ lnk, rest, err := nd.Resolve(names)
115
if err == merkledag.ErrLinkNotFound {
118
- n := nd.Multihash()
119
- return result, ErrNoLink{Name: name, Node: n}
116
+ n := nd.Cid()
117
+ return result, ErrNoLink{Name: names[0], Node: n}
118
} else if err != nil {
121
- return append(result, nextnode), err
119
+ return result, err
120
+ }
121
+
122
+ nextnode, err := s.DAG.Get(ctx, lnk.Cid)
123
+ if err != nil {
124
+ return result, err
125
}
126
127
nd = nextnode
128
+ names = rest
129
result = append(result, nextnode)
130
}
131
return result, nil
path/resolver_test.go
+4
-4
@@ -13,8 +13,8 @@ import (
13
util "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
14
)
15
16
-func randNode() (*merkledag.Node, key.Key) {
17
- node := new(merkledag.Node)
16
+func randNode() (*merkledag.ProtoNode, key.Key) {
17
+ node := new(merkledag.ProtoNode)
18
node.SetData(make([]byte, 32))
19
util.NewTimeSeededRand().Read(node.Data())
20
k := node.Key()
@@ -39,7 +39,7 @@ func TestRecurivePathResolution(t *testing.T) {
39
t.Fatal(err)
40
}
41
42
- for _, n := range []*merkledag.Node{a, b, c} {
42
+ for _, n := range []merkledag.Node{a, b, c} {
43
_, err = dagService.Add(n)
44
if err != nil {
45
t.Fatal(err)
@@ -60,7 +60,7 @@ func TestRecurivePathResolution(t *testing.T) {
60
t.Fatal(err)
61
}
62
63
- key := node.Key()
63
+ key := node.Cid()
64
if key.String() != cKey.String() {
65
t.Fatal(fmt.Errorf(
66
"recursive path resolution failed for %s: %s != %s",
pin/pin.go
+13
-8
@@ -83,7 +83,7 @@ func StringToPinMode(s string) (PinMode, bool) {
83
type Pinner interface {
84
IsPinned(*cid.Cid) (string, bool, error)
85
IsPinnedWithType(*cid.Cid, PinMode) (string, bool, error)
86
- Pin(context.Context, *mdag.Node, bool) error
86
+ Pin(context.Context, mdag.Node, bool) error
87
Unpin(context.Context, *cid.Cid, bool) error
88
89
// Check if a set of keys are pinned, more efficient than
@@ -162,7 +162,7 @@ func NewPinner(dstore ds.Datastore, serv, internal mdag.DAGService) Pinner {
162
}
163
164
// Pin the given node, optionally recursive
165
-func (p *pinner) Pin(ctx context.Context, node *mdag.Node, recurse bool) error {
165
+func (p *pinner) Pin(ctx context.Context, node mdag.Node, recurse bool) error {
166
p.lock.Lock()
167
defer p.lock.Unlock()
168
c := node.Cid()
@@ -317,7 +317,7 @@ func (p *pinner) CheckIfPinned(cids ...*cid.Cid) ([]Pinned, error) {
317
return err
318
}
319
for _, lnk := range links {
320
- c := cid.NewCidV0(lnk.Hash)
320
+ c := lnk.Cid
321
322
if toCheck.Has(c) {
323
pinned = append(pinned,
@@ -403,12 +403,17 @@ func LoadPinner(d ds.Datastore, dserv, internal mdag.DAGService) (Pinner, error)
403
return nil, fmt.Errorf("cannot find pinning root object: %v", err)
404
}
405
406
+ rootpb, ok := root.(*mdag.ProtoNode)
407
+ if !ok {
408
+ return nil, mdag.ErrNotProtobuf
409
+ }
410
+
411
internalset := cid.NewSet()
412
internalset.Add(rootCid)
413
recordInternal := internalset.Add
414
415
{ // load recursive set
411
- recurseKeys, err := loadSet(ctx, internal, root, linkRecursive, recordInternal)
416
+ recurseKeys, err := loadSet(ctx, internal, rootpb, linkRecursive, recordInternal)
417
if err != nil {
418
return nil, fmt.Errorf("cannot load recursive pins: %v", err)
419
}
@@ -416,7 +421,7 @@ func LoadPinner(d ds.Datastore, dserv, internal mdag.DAGService) (Pinner, error)
421
}
422
423
{ // load direct set
419
- directKeys, err := loadSet(ctx, internal, root, linkDirect, recordInternal)
424
+ directKeys, err := loadSet(ctx, internal, rootpb, linkDirect, recordInternal)
425
if err != nil {
426
return nil, fmt.Errorf("cannot load direct pins: %v", err)
427
}
@@ -453,7 +458,7 @@ func (p *pinner) Flush() error {
458
internalset := cid.NewSet()
459
recordInternal := internalset.Add
460
456
- root := &mdag.Node{}
461
+ root := &mdag.ProtoNode{}
462
{
463
n, err := storeSet(ctx, p.internal, p.directPin.Keys(), recordInternal)
464
if err != nil {
@@ -475,7 +480,7 @@ func (p *pinner) Flush() error {
480
}
481
482
// add the empty node, its referenced by the pin sets but never created
478
- _, err := p.internal.Add(new(mdag.Node))
483
+ _, err := p.internal.Add(new(mdag.ProtoNode))
484
if err != nil {
485
return err
486
}
@@ -522,7 +527,7 @@ func hasChild(ds mdag.LinkService, root *cid.Cid, child key.Key) (bool, error) {
527
return false, err
528
}
529
for _, lnk := range links {
525
- c := cid.NewCidV0(lnk.Hash)
530
+ c := lnk.Cid
531
if key.Key(c.Hash()) == child {
532
return true, nil
533
}
pin/pin_test.go
+2
-2
@@ -16,8 +16,8 @@ import (
16
dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
17
)
18
19
-func randNode() (*mdag.Node, *cid.Cid) {
20
- nd := new(mdag.Node)
19
+func randNode() (*mdag.ProtoNode, *cid.Cid) {
20
+ nd := new(mdag.ProtoNode)
21
nd.SetData(make([]byte, 32))
22
util.NewTimeSeededRand().Read(nd.Data())
23
k := nd.Cid()
pin/set.go
+41
-22
@@ -55,25 +55,27 @@ func (s sortByHash) Len() int {
55
}
56
57
func (s sortByHash) Less(a, b int) bool {
58
- return bytes.Compare(s.links[a].Hash, s.links[b].Hash) == -1
58
+ return bytes.Compare(s.links[a].Cid.Bytes(), s.links[b].Cid.Bytes()) == -1
59
}
60
61
func (s sortByHash) Swap(a, b int) {
62
s.links[a], s.links[b] = s.links[b], s.links[a]
63
}
64
65
-func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint64, iter itemIterator, internalKeys keyObserver) (*merkledag.Node, error) {
65
+func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint64, iter itemIterator, internalKeys keyObserver) (*merkledag.ProtoNode, error) {
66
seed, err := randomSeed()
67
if err != nil {
68
return nil, err
69
}
70
-
71
- n := &merkledag.Node{Links: make([]*merkledag.Link, 0, defaultFanout+maxItems)}
70
+ links := make([]*merkledag.Link, 0, defaultFanout+maxItems)
71
for i := 0; i < defaultFanout; i++ {
73
- n.Links = append(n.Links, &merkledag.Link{Hash: emptyKey.Hash()})
72
+ links = append(links, &merkledag.Link{Cid: emptyKey})
73
}
74
75
// add emptyKey to our set of internal pinset objects
76
+ n := &merkledag.ProtoNode{}
77
+ n.SetLinks(links)
78
+
79
internalKeys(emptyKey)
80
81
hdr := &pb.Set{
@@ -87,17 +89,22 @@ func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint
89
90
if estimatedLen < maxItems {
91
// it'll probably fit
92
+ links := n.Links()
93
for i := 0; i < maxItems; i++ {
94
k, ok := iter()
95
if !ok {
96
// all done
97
break
98
}
96
- n.Links = append(n.Links, &merkledag.Link{Hash: k.Hash()})
99
+
100
+ links = append(links, &merkledag.Link{Cid: k})
101
}
102
+
103
+ n.SetLinks(links)
104
+
105
// sort by hash, also swap item Data
106
s := sortByHash{
100
- links: n.Links[defaultFanout:],
107
+ links: n.Links()[defaultFanout:],
108
}
109
sort.Stable(s)
110
}
@@ -152,15 +159,15 @@ func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint
159
internalKeys(childKey)
160
161
// overwrite the 'empty key' in the existing links array
155
- n.Links[h] = &merkledag.Link{
156
- Hash: childKey.Hash(),
162
+ n.Links()[h] = &merkledag.Link{
163
+ Cid: childKey,
164
Size: size,
165
}
166
}
167
return n, nil
168
}
169
163
-func readHdr(n *merkledag.Node) (*pb.Set, error) {
170
+func readHdr(n *merkledag.ProtoNode) (*pb.Set, error) {
171
hdrLenRaw, consumed := binary.Uvarint(n.Data())
172
if consumed <= 0 {
173
return nil, errors.New("invalid Set header length")
@@ -180,13 +187,13 @@ func readHdr(n *merkledag.Node) (*pb.Set, error) {
187
if v := hdr.GetVersion(); v != 1 {
188
return nil, fmt.Errorf("unsupported Set version: %d", v)
189
}
183
- if uint64(hdr.GetFanout()) > uint64(len(n.Links)) {
190
+ if uint64(hdr.GetFanout()) > uint64(len(n.Links())) {
191
return nil, errors.New("impossibly large Fanout")
192
}
193
return &hdr, nil
194
}
195
189
-func writeHdr(n *merkledag.Node, hdr *pb.Set) error {
196
+func writeHdr(n *merkledag.ProtoNode, hdr *pb.Set) error {
197
hdrData, err := proto.Marshal(hdr)
198
if err != nil {
199
return err
@@ -207,20 +214,20 @@ func writeHdr(n *merkledag.Node, hdr *pb.Set) error {
214
215
type walkerFunc func(idx int, link *merkledag.Link) error
216
210
-func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.Node, fn walkerFunc, children keyObserver) error {
217
+func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.ProtoNode, fn walkerFunc, children keyObserver) error {
218
hdr, err := readHdr(n)
219
if err != nil {
220
return err
221
}
222
// readHdr guarantees fanout is a safe value
223
fanout := hdr.GetFanout()
217
- for i, l := range n.Links[fanout:] {
224
+ for i, l := range n.Links()[fanout:] {
225
if err := fn(i, l); err != nil {
226
return err
227
}
228
}
222
- for _, l := range n.Links[:fanout] {
223
- c := cid.NewCidV0(l.Hash)
229
+ for _, l := range n.Links()[:fanout] {
230
+ c := l.Cid
231
children(c)
232
if c.Equals(emptyKey) {
233
continue
@@ -229,20 +236,26 @@ func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.Node,
236
if err != nil {
237
return err
238
}
232
- if err := walkItems(ctx, dag, subtree, fn, children); err != nil {
239
+
240
+ stpb, ok := subtree.(*merkledag.ProtoNode)
241
+ if !ok {
242
+ return merkledag.ErrNotProtobuf
243
+ }
244
+
245
+ if err := walkItems(ctx, dag, stpb, fn, children); err != nil {
246
return err
247
}
248
}
249
return nil
250
}
251
239
-func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node, name string, internalKeys keyObserver) ([]*cid.Cid, error) {
252
+func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.ProtoNode, name string, internalKeys keyObserver) ([]*cid.Cid, error) {
253
l, err := root.GetNodeLink(name)
254
if err != nil {
255
return nil, err
256
}
257
245
- lnkc := cid.NewCidV0(l.Hash)
258
+ lnkc := l.Cid
259
internalKeys(lnkc)
260
261
n, err := l.GetNode(ctx, dag)
@@ -250,12 +263,18 @@ func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node
263
return nil, err
264
}
265
266
+ pbn, ok := n.(*merkledag.ProtoNode)
267
+ if !ok {
268
+ return nil, merkledag.ErrNotProtobuf
269
+ }
270
+
271
var res []*cid.Cid
272
walk := func(idx int, link *merkledag.Link) error {
255
- res = append(res, cid.NewCidV0(link.Hash))
273
+ res = append(res, link.Cid)
274
return nil
275
}
258
- if err := walkItems(ctx, dag, n, walk, internalKeys); err != nil {
276
+
277
+ if err := walkItems(ctx, dag, pbn, walk, internalKeys); err != nil {
278
return nil, err
279
}
280
return res, nil
@@ -273,7 +292,7 @@ func getCidListIterator(cids []*cid.Cid) itemIterator {
292
}
293
}
294
276
-func storeSet(ctx context.Context, dag merkledag.DAGService, cids []*cid.Cid, internalKeys keyObserver) (*merkledag.Node, error) {
295
+func storeSet(ctx context.Context, dag merkledag.DAGService, cids []*cid.Cid, internalKeys keyObserver) (*merkledag.ProtoNode, error) {
296
iter := getCidListIterator(cids)
297
298
n, err := storeItems(ctx, dag, uint64(len(cids)), iter, internalKeys)
pin/set_test.go
+1
-1
@@ -38,7 +38,7 @@ func TestSet(t *testing.T) {
38
39
// weird wrapper node because loadSet expects us to pass an
40
// object pointing to multiple named sets
41
- setroot := &dag.Node{}
41
+ setroot := &dag.ProtoNode{}
42
err = setroot.AddNodeLinkClean("foo", out)
43
if err != nil {
44
t.Fatal(err)
tar/format.go
+15
-10
@@ -34,7 +34,7 @@ func marshalHeader(h *tar.Header) ([]byte, error) {
34
return buf.Bytes(), nil
35
}
36
37
-func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
37
+func ImportTar(r io.Reader, ds dag.DAGService) (*dag.ProtoNode, error) {
38
rall, err := ioutil.ReadAll(r)
39
if err != nil {
40
return nil, err
@@ -44,7 +44,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
44
45
tr := tar.NewReader(r)
46
47
- root := new(dag.Node)
47
+ root := new(dag.ProtoNode)
48
root.SetData([]byte("ipfs/tar"))
49
50
e := dagutil.NewDagEditor(root, ds)
@@ -58,7 +58,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
58
return nil, err
59
}
60
61
- header := new(dag.Node)
61
+ header := new(dag.ProtoNode)
62
63
headerBytes, err := marshalHeader(h)
64
if err != nil {
@@ -86,7 +86,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
86
}
87
88
path := escapePath(h.Name)
89
- err = e.InsertNodeAtPath(context.Background(), path, header, func() *dag.Node { return new(dag.Node) })
89
+ err = e.InsertNodeAtPath(context.Background(), path, header, func() *dag.ProtoNode { return new(dag.ProtoNode) })
90
if err != nil {
91
return nil, err
92
}
@@ -170,9 +170,14 @@ func (tr *tarReader) Read(b []byte) (int, error) {
170
return 0, err
171
}
172
173
- tr.hdrBuf = bytes.NewReader(headerNd.Data())
173
+ hndpb, ok := headerNd.(*dag.ProtoNode)
174
+ if !ok {
175
+ return 0, dag.ErrNotProtobuf
176
+ }
177
+
178
+ tr.hdrBuf = bytes.NewReader(hndpb.Data())
179
175
- dataNd, err := headerNd.GetLinkedNode(tr.ctx, tr.ds, "data")
180
+ dataNd, err := hndpb.GetLinkedProtoNode(tr.ctx, tr.ds, "data")
181
if err != nil && err != dag.ErrLinkNotFound {
182
return 0, err
183
}
@@ -185,9 +190,9 @@ func (tr *tarReader) Read(b []byte) (int, error) {
190
}
191
192
tr.fileRead = &countReader{r: dr}
188
- } else if len(headerNd.Links) > 0 {
193
+ } else if len(headerNd.Links()) > 0 {
194
tr.childRead = &tarReader{
190
- links: headerNd.Links,
195
+ links: headerNd.Links(),
196
ds: tr.ds,
197
ctx: tr.ctx,
198
}
@@ -196,12 +201,12 @@ func (tr *tarReader) Read(b []byte) (int, error) {
201
return tr.Read(b)
202
}
203
199
-func ExportTar(ctx context.Context, root *dag.Node, ds dag.DAGService) (io.Reader, error) {
204
+func ExportTar(ctx context.Context, root *dag.ProtoNode, ds dag.DAGService) (io.Reader, error) {
205
if string(root.Data()) != "ipfs/tar" {
206
return nil, errors.New("not an ipfs tarchive")
207
}
208
return &tarReader{
204
- links: root.Links,
209
+ links: root.Links(),
210
ds: ds,
211
ctx: ctx,
212
}, nil
unixfs/archive/archive.go
+1
-1
@@ -30,7 +30,7 @@ func (i *identityWriteCloser) Close() error {
30
}
31
32
// DagArchive is equivalent to `ipfs getdag $hash | maybe_tar | maybe_gzip`
33
-func DagArchive(ctx cxt.Context, nd *mdag.Node, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
33
+func DagArchive(ctx cxt.Context, nd *mdag.ProtoNode, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
34
35
_, filename := path.Split(name)
36
unixfs/archive/tar/writer.go
+10
-5
@@ -34,7 +34,7 @@ func NewWriter(ctx cxt.Context, dag mdag.DAGService, archive bool, compression i
34
}, nil
35
}
36
37
-func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
37
+func (w *Writer) writeDir(nd *mdag.ProtoNode, fpath string) error {
38
if err := writeDirHeader(w.TarW, fpath); err != nil {
39
return err
40
}
@@ -45,8 +45,13 @@ func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
45
return err
46
}
47
48
- npath := path.Join(fpath, nd.Links[i].Name)
49
- if err := w.WriteNode(child, npath); err != nil {
48
+ childpb, ok := child.(*mdag.ProtoNode)
49
+ if !ok {
50
+ return mdag.ErrNotProtobuf
51
+ }
52
+
53
+ npath := path.Join(fpath, nd.Links()[i].Name)
54
+ if err := w.WriteNode(childpb, npath); err != nil {
55
return err
56
}
57
}
@@ -54,7 +59,7 @@ func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
59
return nil
60
}
61
57
-func (w *Writer) writeFile(nd *mdag.Node, pb *upb.Data, fpath string) error {
62
+func (w *Writer) writeFile(nd *mdag.ProtoNode, pb *upb.Data, fpath string) error {
63
if err := writeFileHeader(w.TarW, fpath, pb.GetFilesize()); err != nil {
64
return err
65
}
@@ -67,7 +72,7 @@ func (w *Writer) writeFile(nd *mdag.Node, pb *upb.Data, fpath string) error {
72
return nil
73
}
74
70
-func (w *Writer) WriteNode(nd *mdag.Node, fpath string) error {
75
+func (w *Writer) WriteNode(nd *mdag.ProtoNode, fpath string) error {
76
pb := new(upb.Data)
77
if err := proto.Unmarshal(nd.Data(), pb); err != nil {
78
return err
unixfs/format.go
+1
-1
@@ -224,6 +224,6 @@ func BytesForMetadata(m *Metadata) ([]byte, error) {
224
return proto.Marshal(pbd)
225
}
226
227
-func EmptyDirNode() *dag.Node {
227
+func EmptyDirNode() *dag.ProtoNode {
228
return dag.NodeWithData(FolderPBData())
229
}
unixfs/io/dagreader.go
+18
-8
@@ -24,7 +24,7 @@ type DagReader struct {
24
serv mdag.DAGService
25
26
// the node being read
27
- node *mdag.Node
27
+ node *mdag.ProtoNode
28
29
// cached protobuf structure from node.Data
30
pbdata *ftpb.Data
@@ -58,7 +58,7 @@ type ReadSeekCloser interface {
58
59
// NewDagReader creates a new reader object that reads the data represented by
60
// the given node, using the passed in DAGService for data retreival
61
-func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*DagReader, error) {
61
+func NewDagReader(ctx context.Context, n *mdag.ProtoNode, serv mdag.DAGService) (*DagReader, error) {
62
pb := new(ftpb.Data)
63
if err := proto.Unmarshal(n.Data(), pb); err != nil {
64
return nil, err
@@ -71,14 +71,19 @@ func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*Dag
71
case ftpb.Data_File, ftpb.Data_Raw:
72
return NewDataFileReader(ctx, n, pb, serv), nil
73
case ftpb.Data_Metadata:
74
- if len(n.Links) == 0 {
74
+ if len(n.Links()) == 0 {
75
return nil, errors.New("incorrectly formatted metadata object")
76
}
77
- child, err := n.Links[0].GetNode(ctx, serv)
77
+ child, err := n.Links()[0].GetNode(ctx, serv)
78
if err != nil {
79
return nil, err
80
}
81
- return NewDagReader(ctx, child, serv)
81
+
82
+ childpb, ok := child.(*mdag.ProtoNode)
83
+ if !ok {
84
+ return nil, mdag.ErrNotProtobuf
85
+ }
86
+ return NewDagReader(ctx, childpb, serv)
87
case ftpb.Data_Symlink:
88
return nil, ErrCantReadSymlinks
89
default:
@@ -86,7 +91,7 @@ func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*Dag
91
}
92
}
93
89
-func NewDataFileReader(ctx context.Context, n *mdag.Node, pb *ftpb.Data, serv mdag.DAGService) *DagReader {
94
+func NewDataFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv mdag.DAGService) *DagReader {
95
fctx, cancel := context.WithCancel(ctx)
96
promises := mdag.GetDAG(fctx, serv, n)
97
return &DagReader{
@@ -114,8 +119,13 @@ func (dr *DagReader) precalcNextBuf(ctx context.Context) error {
119
}
120
dr.linkPosition++
121
122
+ nxtpb, ok := nxt.(*mdag.ProtoNode)
123
+ if !ok {
124
+ return mdag.ErrNotProtobuf
125
+ }
126
+
127
pb := new(ftpb.Data)
118
- err = proto.Unmarshal(nxt.Data(), pb)
128
+ err = proto.Unmarshal(nxtpb.Data(), pb)
129
if err != nil {
130
return fmt.Errorf("incorrectly formatted protobuf: %s", err)
131
}
@@ -125,7 +135,7 @@ func (dr *DagReader) precalcNextBuf(ctx context.Context) error {
135
// A directory should not exist within a file
136
return ft.ErrInvalidDirLocation
137
case ftpb.Data_File:
128
- dr.buf = NewDataFileReader(dr.ctx, nxt, pb, dr.serv)
138
+ dr.buf = NewDataFileReader(dr.ctx, nxtpb, pb, dr.serv)
139
return nil
140
case ftpb.Data_Raw:
141
dr.buf = NewRSNCFromBytes(pb.GetData())
unixfs/io/dirbuilder.go
+10
-5
@@ -10,12 +10,12 @@ import (
10
11
type directoryBuilder struct {
12
dserv mdag.DAGService
13
- dirnode *mdag.Node
13
+ dirnode *mdag.ProtoNode
14
}
15
16
// NewEmptyDirectory returns an empty merkledag Node with a folder Data chunk
17
-func NewEmptyDirectory() *mdag.Node {
18
- nd := new(mdag.Node)
17
+func NewEmptyDirectory() *mdag.ProtoNode {
18
+ nd := new(mdag.ProtoNode)
19
nd.SetData(format.FolderPBData())
20
return nd
21
}
@@ -35,10 +35,15 @@ func (d *directoryBuilder) AddChild(ctx context.Context, name string, c *cid.Cid
35
return err
36
}
37
38
- return d.dirnode.AddNodeLinkClean(name, cnode)
38
+ cnpb, ok := cnode.(*mdag.ProtoNode)
39
+ if !ok {
40
+ return mdag.ErrNotProtobuf
41
+ }
42
+
43
+ return d.dirnode.AddNodeLinkClean(name, cnpb)
44
}
45
46
// GetNode returns the root of this directoryBuilder
42
-func (d *directoryBuilder) GetNode() *mdag.Node {
47
+func (d *directoryBuilder) GetNode() *mdag.ProtoNode {
48
return d.dirnode
49
}
unixfs/io/dirbuilder_test.go
+2
-2
@@ -10,7 +10,7 @@ import (
10
11
func TestEmptyNode(t *testing.T) {
12
n := NewEmptyDirectory()
13
- if len(n.Links) != 0 {
13
+ if len(n.Links()) != 0 {
14
t.Fatal("empty node should have 0 links")
15
}
16
}
@@ -27,7 +27,7 @@ func TestDirBuilder(t *testing.T) {
27
b.AddChild(ctx, "random", key)
28
29
dir := b.GetNode()
30
- outn, err := dir.GetLinkedNode(ctx, dserv, "random")
30
+ outn, err := dir.GetLinkedProtoNode(ctx, dserv, "random")
31
if err != nil {
32
t.Fatal(err)
33
}
unixfs/mod/dagmodifier.go
+35
-19
@@ -32,7 +32,7 @@ var log = logging.Logger("dagio")
32
// Dear god, please rename this to something more pleasant
33
type DagModifier struct {
34
dagserv mdag.DAGService
35
- curNode *mdag.Node
35
+ curNode *mdag.ProtoNode
36
37
splitter chunk.SplitterGen
38
ctx context.Context
@@ -45,7 +45,7 @@ type DagModifier struct {
45
read *uio.DagReader
46
}
47
48
-func NewDagModifier(ctx context.Context, from *mdag.Node, serv mdag.DAGService, spl chunk.SplitterGen) (*DagModifier, error) {
48
+func NewDagModifier(ctx context.Context, from *mdag.ProtoNode, serv mdag.DAGService, spl chunk.SplitterGen) (*DagModifier, error) {
49
return &DagModifier{
50
curNode: from.Copy(),
51
dagserv: serv,
@@ -178,11 +178,16 @@ func (dm *DagModifier) Sync() error {
178
return err
179
}
180
181
- dm.curNode = nd
181
+ pbnd, ok := nd.(*mdag.ProtoNode)
182
+ if !ok {
183
+ return mdag.ErrNotProtobuf
184
+ }
185
+
186
+ dm.curNode = pbnd
187
188
// need to write past end of current dag
189
if !done {
185
- nd, err = dm.appendData(dm.curNode, dm.splitter(dm.wrBuf))
190
+ nd, err := dm.appendData(dm.curNode, dm.splitter(dm.wrBuf))
191
if err != nil {
192
return err
193
}
@@ -204,14 +209,14 @@ func (dm *DagModifier) Sync() error {
209
// modifyDag writes the data in 'data' over the data in 'node' starting at 'offset'
210
// returns the new key of the passed in node and whether or not all the data in the reader
211
// has been consumed.
207
-func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader) (*cid.Cid, bool, error) {
212
+func (dm *DagModifier) modifyDag(node *mdag.ProtoNode, offset uint64, data io.Reader) (*cid.Cid, bool, error) {
213
f, err := ft.FromBytes(node.Data())
214
if err != nil {
215
return nil, false, err
216
}
217
218
// If we've reached a leaf node.
214
- if len(node.Links) == 0 {
219
+ if len(node.Links()) == 0 {
220
n, err := data.Read(f.Data[offset:])
221
if err != nil && err != io.EOF {
222
return nil, false, err
@@ -223,7 +228,7 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
228
return nil, false, err
229
}
230
226
- nd := new(mdag.Node)
231
+ nd := new(mdag.ProtoNode)
232
nd.SetData(b)
233
k, err := dm.dagserv.Add(nd)
234
if err != nil {
@@ -244,17 +249,23 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
249
for i, bs := range f.GetBlocksizes() {
250
// We found the correct child to write into
251
if cur+bs > offset {
247
- child, err := node.Links[i].GetNode(dm.ctx, dm.dagserv)
252
+ child, err := node.Links()[i].GetNode(dm.ctx, dm.dagserv)
253
if err != nil {
254
return nil, false, err
255
}
251
- k, sdone, err := dm.modifyDag(child, offset-cur, data)
256
+
257
+ childpb, ok := child.(*mdag.ProtoNode)
258
+ if !ok {
259
+ return nil, false, mdag.ErrNotProtobuf
260
+ }
261
+
262
+ k, sdone, err := dm.modifyDag(childpb, offset-cur, data)
263
if err != nil {
264
return nil, false, err
265
}
266
267
offset += bs
257
- node.Links[i].Hash = k.Hash()
268
+ node.Links()[i].Cid = k
269
270
// Recache serialized node
271
_, err = node.EncodeProtobuf(true)
@@ -277,7 +288,7 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
288
}
289
290
// appendData appends the blocks from the given chan to the end of this dag
280
-func (dm *DagModifier) appendData(node *mdag.Node, spl chunk.Splitter) (*mdag.Node, error) {
291
+func (dm *DagModifier) appendData(node *mdag.ProtoNode, spl chunk.Splitter) (*mdag.ProtoNode, error) {
292
dbp := &help.DagBuilderParams{
293
Dagserv: dm.dagserv,
294
Maxlinks: help.DefaultLinksPerBlock,
@@ -340,7 +351,7 @@ func (dm *DagModifier) CtxReadFull(ctx context.Context, b []byte) (int, error) {
351
}
352
353
// GetNode gets the modified DAG Node
343
-func (dm *DagModifier) GetNode() (*mdag.Node, error) {
354
+func (dm *DagModifier) GetNode() (*mdag.ProtoNode, error) {
355
err := dm.Sync()
356
if err != nil {
357
return nil, err
@@ -425,8 +436,8 @@ func (dm *DagModifier) Truncate(size int64) error {
436
}
437
438
// dagTruncate truncates the given node to 'size' and returns the modified Node
428
-func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGService) (*mdag.Node, error) {
429
- if len(nd.Links) == 0 {
439
+func dagTruncate(ctx context.Context, nd *mdag.ProtoNode, size uint64, ds mdag.DAGService) (*mdag.ProtoNode, error) {
440
+ if len(nd.Links()) == 0 {
441
// TODO: this can likely be done without marshaling and remarshaling
442
pbn, err := ft.FromBytes(nd.Data())
443
if err != nil {
@@ -439,22 +450,27 @@ func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGSer
450
451
var cur uint64
452
end := 0
442
- var modified *mdag.Node
453
+ var modified *mdag.ProtoNode
454
ndata := new(ft.FSNode)
444
- for i, lnk := range nd.Links {
455
+ for i, lnk := range nd.Links() {
456
child, err := lnk.GetNode(ctx, ds)
457
if err != nil {
458
return nil, err
459
}
460
450
- childsize, err := ft.DataSize(child.Data())
461
+ childpb, ok := child.(*mdag.ProtoNode)
462
+ if !ok {
463
+ return nil, err
464
+ }
465
+
466
+ childsize, err := ft.DataSize(childpb.Data())
467
if err != nil {
468
return nil, err
469
}
470
471
// found the child we want to cut
472
if size < cur+childsize {
457
- nchild, err := dagTruncate(ctx, child, size-cur, ds)
473
+ nchild, err := dagTruncate(ctx, childpb, size-cur, ds)
474
if err != nil {
475
return nil, err
476
}
@@ -474,7 +490,7 @@ func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGSer
490
return nil, err
491
}
492
477
- nd.Links = nd.Links[:end]
493
+ nd.SetLinks(nd.Links()[:end])
494
err = nd.AddNodeLinkClean("", modified)
495
if err != nil {
496
return nil, err
unixfs/test/utils.go
+8
-8
@@ -27,7 +27,7 @@ func GetDAGServ() mdag.DAGService {
27
return mdagmock.Mock()
28
}
29
30
-func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
30
+func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.ProtoNode {
31
in := bytes.NewReader(data)
32
node, err := imp.BuildTrickleDagFromReader(dserv, SizeSplitterGen(500)(in))
33
if err != nil {
@@ -37,11 +37,11 @@ func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
37
return node
38
}
39
40
-func GetEmptyNode(t testing.TB, dserv mdag.DAGService) *mdag.Node {
40
+func GetEmptyNode(t testing.TB, dserv mdag.DAGService) *mdag.ProtoNode {
41
return GetNode(t, dserv, []byte{})
42
}
43
44
-func GetRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.Node) {
44
+func GetRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.ProtoNode) {
45
in := io.LimitReader(u.NewTimeSeededRand(), size)
46
buf, err := ioutil.ReadAll(in)
47
if err != nil {
@@ -64,7 +64,7 @@ func ArrComp(a, b []byte) error {
64
return nil
65
}
66
67
-func PrintDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
67
+func PrintDag(nd *mdag.ProtoNode, ds mdag.DAGService, indent int) {
68
pbd, err := ft.FromBytes(nd.Data())
69
if err != nil {
70
panic(err)
@@ -74,17 +74,17 @@ func PrintDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
74
fmt.Print(" ")
75
}
76
fmt.Printf("{size = %d, type = %s, children = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
77
- if len(nd.Links) > 0 {
77
+ if len(nd.Links()) > 0 {
78
fmt.Println()
79
}
80
- for _, lnk := range nd.Links {
80
+ for _, lnk := range nd.Links() {
81
child, err := lnk.GetNode(context.Background(), ds)
82
if err != nil {
83
panic(err)
84
}
85
- PrintDag(child, ds, indent+1)
85
+ PrintDag(child.(*mdag.ProtoNode), ds, indent+1)
86
}
87
- if len(nd.Links) > 0 {
87
+ if len(nd.Links()) > 0 {
88
for i := 0; i < indent; i++ {
89
fmt.Print(" ")
90
}