Skip to content

Commit c8f0fa0

Browse files
committed
implement an HAMT for unixfs directory sharding
License: MIT Signed-off-by: Jeromy <[email protected]>
1 parent 9eba0e4 commit c8f0fa0

21 files changed

+1971
-127
lines changed

assets/assets.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,27 @@ func addAssetList(nd *core.IpfsNode, l []string) (*cid.Cid, error) {
5353
}
5454

5555
fname := filepath.Base(p)
56+
5657
c, err := cid.Decode(s)
5758
if err != nil {
5859
return nil, err
5960
}
6061

61-
if err := dirb.AddChild(nd.Context(), fname, c); err != nil {
62+
node, err := nd.DAG.Get(nd.Context(), c)
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
if err := dirb.AddChild(nd.Context(), fname, node); err != nil {
6268
return nil, fmt.Errorf("assets: could not add '%s' as a child: %s", fname, err)
6369
}
6470
}
6571

66-
dir := dirb.GetNode()
72+
dir, err := dirb.GetNode()
73+
if err != nil {
74+
return nil, err
75+
}
76+
6777
dcid, err := nd.DAG.Add(dir)
6878
if err != nil {
6979
return nil, fmt.Errorf("assets: DAG.Add(dir) failed: %s", err)

commands/request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package commands
22

33
import (
44
"bufio"
5+
"context"
56
"errors"
67
"fmt"
78
"io"
@@ -10,7 +11,6 @@ import (
1011
"strconv"
1112
"time"
1213

13-
context "context"
1414
"github.com/ipfs/go-ipfs/commands/files"
1515
"github.com/ipfs/go-ipfs/core"
1616
"github.com/ipfs/go-ipfs/repo/config"

core/commands/files/files.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,16 +265,7 @@ func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (node.N
265265
ResolveOnce: uio.ResolveUnixfsOnce,
266266
}
267267

268-
nd, err := core.Resolve(ctx, node.Namesys, resolver, np)
269-
if err != nil {
270-
return nil, err
271-
}
272-
pbnd, ok := nd.(*dag.ProtoNode)
273-
if !ok {
274-
return nil, dag.ErrNotProtobuf
275-
}
276-
277-
return pbnd, nil
268+
return core.Resolve(ctx, node.Namesys, resolver, np)
278269
default:
279270
fsn, err := mfs.Lookup(node.FilesRoot, p)
280271
if err != nil {
@@ -357,7 +348,13 @@ Examples:
357348
case *mfs.Directory:
358349
if !long {
359350
var output []mfs.NodeListing
360-
for _, name := range fsn.ListNames() {
351+
names, err := fsn.ListNames()
352+
if err != nil {
353+
res.SetError(err, cmds.ErrNormal)
354+
return
355+
}
356+
357+
for _, name := range names {
361358
output = append(output, mfs.NodeListing{
362359
Name: name,
363360
})

core/corehttp/gateway_handler.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,14 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
403403
return
404404
}
405405

406-
pbnd, ok := rnode.(*dag.ProtoNode)
406+
pbrnode, ok := rnode.(*dag.ProtoNode)
407407
if !ok {
408-
webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
408+
webError(w, "putHandler: Can only operate on protobuf nodes", dag.ErrNotProtobuf, http.StatusInternalServerError)
409409
return
410410
}
411411

412-
e := dagutils.NewDagEditor(pbnd, i.node.DAG)
412+
e := dagutils.NewDagEditor(pbrnode, i.node.DAG)
413+
413414
err = e.InsertNodeAtPath(ctx, newPath, newnode, ft.EmptyDirNode)
414415
if err != nil {
415416
webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)

core/coreunix/add.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,12 @@ func (adder *Adder) outputDirs(path string, fsn mfs.FSNode) error {
226226
case *mfs.File:
227227
return nil
228228
case *mfs.Directory:
229-
for _, name := range fsn.ListNames() {
229+
names, err := fsn.ListNames()
230+
if err != nil {
231+
return err
232+
}
233+
234+
for _, name := range names {
230235
child, err := fsn.Child(name)
231236
if err != nil {
232237
return err

mfs/dir.go

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
dag "github.com/ipfs/go-ipfs/merkledag"
1414
ft "github.com/ipfs/go-ipfs/unixfs"
15+
uio "github.com/ipfs/go-ipfs/unixfs/io"
1516
ufspb "github.com/ipfs/go-ipfs/unixfs/pb"
1617

1718
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
@@ -29,25 +30,31 @@ type Directory struct {
2930
files map[string]*File
3031

3132
lock sync.Mutex
32-
node *dag.ProtoNode
3333
ctx context.Context
3434

35+
dirbuilder *uio.Directory
36+
3537
modTime time.Time
3638

3739
name string
3840
}
3941

40-
func NewDirectory(ctx context.Context, name string, node *dag.ProtoNode, parent childCloser, dserv dag.DAGService) *Directory {
41-
return &Directory{
42-
dserv: dserv,
43-
ctx: ctx,
44-
name: name,
45-
node: node,
46-
parent: parent,
47-
childDirs: make(map[string]*Directory),
48-
files: make(map[string]*File),
49-
modTime: time.Now(),
42+
func NewDirectory(ctx context.Context, name string, node node.Node, parent childCloser, dserv dag.DAGService) (*Directory, error) {
43+
db, err := uio.NewDirectoryFromNode(dserv, node)
44+
if err != nil {
45+
return nil, err
5046
}
47+
48+
return &Directory{
49+
dserv: dserv,
50+
ctx: ctx,
51+
name: name,
52+
dirbuilder: db,
53+
parent: parent,
54+
childDirs: make(map[string]*Directory),
55+
files: make(map[string]*File),
56+
modTime: time.Now(),
57+
}, nil
5158
}
5259

5360
// closeChild updates the child by the given name to the dag node 'nd'
@@ -81,21 +88,26 @@ func (d *Directory) closeChildUpdate(name string, nd *dag.ProtoNode, sync bool)
8188
}
8289

8390
func (d *Directory) flushCurrentNode() (*dag.ProtoNode, error) {
84-
_, err := d.dserv.Add(d.node)
91+
nd, err := d.dirbuilder.GetNode()
8592
if err != nil {
8693
return nil, err
8794
}
8895

89-
return d.node.Copy(), nil
90-
}
96+
_, err = d.dserv.Add(nd)
97+
if err != nil {
98+
return nil, err
99+
}
91100

92-
func (d *Directory) updateChild(name string, nd node.Node) error {
93-
err := d.node.RemoveNodeLink(name)
94-
if err != nil && err != dag.ErrNotFound {
95-
return err
101+
pbnd, ok := nd.(*dag.ProtoNode)
102+
if !ok {
103+
return nil, dag.ErrNotProtobuf
96104
}
97105

98-
err = d.node.AddNodeLinkClean(name, nd)
106+
return pbnd.Copy(), nil
107+
}
108+
109+
func (d *Directory) updateChild(name string, nd node.Node) error {
110+
err := d.dirbuilder.AddChild(d.ctx, name, nd)
99111
if err != nil {
100112
return err
101113
}
@@ -130,8 +142,12 @@ func (d *Directory) cacheNode(name string, nd node.Node) (FSNode, error) {
130142
}
131143

132144
switch i.GetType() {
133-
case ufspb.Data_Directory:
134-
ndir := NewDirectory(d.ctx, name, nd, d, d.dserv)
145+
case ufspb.Data_Directory, ufspb.Data_HAMTShard:
146+
ndir, err := NewDirectory(d.ctx, name, nd, d, d.dserv)
147+
if err != nil {
148+
return nil, err
149+
}
150+
135151
d.childDirs[name] = ndir
136152
return ndir, nil
137153
case ufspb.Data_File, ufspb.Data_Raw, ufspb.Data_Symlink:
@@ -175,15 +191,7 @@ func (d *Directory) Uncache(name string) {
175191
// childFromDag searches through this directories dag node for a child link
176192
// with the given name
177193
func (d *Directory) childFromDag(name string) (node.Node, error) {
178-
pbn, err := d.node.GetLinkedNode(d.ctx, d.dserv, name)
179-
switch err {
180-
case nil:
181-
return pbn, nil
182-
case dag.ErrLinkNotFound:
183-
return nil, os.ErrNotExist
184-
default:
185-
return nil, err
186-
}
194+
return d.dirbuilder.Find(d.ctx, name)
187195
}
188196

189197
// childUnsync returns the child under this directory by the given name
@@ -209,7 +217,7 @@ type NodeListing struct {
209217
Hash string
210218
}
211219

212-
func (d *Directory) ListNames() []string {
220+
func (d *Directory) ListNames() ([]string, error) {
213221
d.lock.Lock()
214222
defer d.lock.Unlock()
215223

@@ -221,7 +229,12 @@ func (d *Directory) ListNames() []string {
221229
names[n] = struct{}{}
222230
}
223231

224-
for _, l := range d.node.Links() {
232+
links, err := d.dirbuilder.Links()
233+
if err != nil {
234+
return nil, err
235+
}
236+
237+
for _, l := range links {
225238
names[l.Name] = struct{}{}
226239
}
227240

@@ -231,15 +244,21 @@ func (d *Directory) ListNames() []string {
231244
}
232245
sort.Strings(out)
233246

234-
return out
247+
return out, nil
235248
}
236249

237250
func (d *Directory) List() ([]NodeListing, error) {
238251
d.lock.Lock()
239252
defer d.lock.Unlock()
240253

241254
var out []NodeListing
242-
for _, l := range d.node.Links() {
255+
256+
links, err := d.dirbuilder.Links()
257+
if err != nil {
258+
return nil, err
259+
}
260+
261+
for _, l := range links {
243262
child := NodeListing{}
244263
child.Name = l.Name
245264

@@ -285,20 +304,23 @@ func (d *Directory) Mkdir(name string) (*Directory, error) {
285304
}
286305
}
287306

288-
ndir := new(dag.ProtoNode)
289-
ndir.SetData(ft.FolderPBData())
307+
ndir := ft.EmptyDirNode()
290308

291309
_, err = d.dserv.Add(ndir)
292310
if err != nil {
293311
return nil, err
294312
}
295313

296-
err = d.node.AddNodeLinkClean(name, ndir)
314+
err = d.dirbuilder.AddChild(d.ctx, name, ndir)
315+
if err != nil {
316+
return nil, err
317+
}
318+
319+
dirobj, err := NewDirectory(d.ctx, name, ndir, d, d.dserv)
297320
if err != nil {
298321
return nil, err
299322
}
300323

301-
dirobj := NewDirectory(d.ctx, name, ndir, d, d.dserv)
302324
d.childDirs[name] = dirobj
303325
return dirobj, nil
304326
}
@@ -310,12 +332,7 @@ func (d *Directory) Unlink(name string) error {
310332
delete(d.childDirs, name)
311333
delete(d.files, name)
312334

313-
err := d.node.RemoveNodeLink(name)
314-
if err != nil {
315-
return err
316-
}
317-
318-
_, err = d.dserv.Add(d.node)
335+
err := d.dirbuilder.RemoveChild(d.ctx, name)
319336
if err != nil {
320337
return err
321338
}
@@ -350,7 +367,7 @@ func (d *Directory) AddChild(name string, nd node.Node) error {
350367
return err
351368
}
352369

353-
err = d.node.AddNodeLinkClean(name, nd)
370+
err = d.dirbuilder.AddChild(d.ctx, name, nd)
354371
if err != nil {
355372
return err
356373
}
@@ -406,10 +423,15 @@ func (d *Directory) GetNode() (node.Node, error) {
406423
return nil, err
407424
}
408425

409-
_, err = d.dserv.Add(d.node)
426+
nd, err := d.dirbuilder.GetNode()
427+
if err != nil {
428+
return nil, err
429+
}
430+
431+
_, err = d.dserv.Add(nd)
410432
if err != nil {
411433
return nil, err
412434
}
413435

414-
return d.node.Copy(), nil
436+
return nd, err
415437
}

0 commit comments

Comments
 (0)