iterator technique for unixfs dir listing
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Nov 15, 2016 at 16:17 UTC
c8af993a8c89d8301be7fe77c5714d4fd5b9e95d
3 files changed
+54
-51
mfs/dir.go
+31
-43
@@ -221,71 +221,59 @@ func (d *Directory) ListNames() ([]string, error) {
221
d.lock.Lock()
222
defer d.lock.Unlock()
223
224
- names := make(map[string]struct{})
225
- for n, _ := range d.childDirs {
226
- names[n] = struct{}{}
227
- }
228
- for n, _ := range d.files {
229
- names[n] = struct{}{}
230
- }
231
-
232
- links, err := d.dirbuilder.Links()
224
+ var out []string
225
+ err := d.dirbuilder.ForEachLink(func(l *node.Link) error {
226
+ out = append(out, l.Name)
227
+ return nil
228
+ })
229
if err != nil {
230
return nil, err
231
}
232
237
- for _, l := range links {
238
- names[l.Name] = struct{}{}
239
- }
240
-
241
- var out []string
242
- for n, _ := range names {
243
- out = append(out, n)
244
- }
233
sort.Strings(out)
234
235
return out, nil
236
}
237
238
func (d *Directory) List() ([]NodeListing, error) {
251
- d.lock.Lock()
252
- defer d.lock.Unlock()
253
-
239
var out []NodeListing
240
+ err := d.ForEachEntry(context.TODO(), func(nl NodeListing) error {
241
+ out = append(out, nl)
242
+ return nil
243
+ })
244
+ return out, err
245
+}
246
256
- links, err := d.dirbuilder.Links()
257
- if err != nil {
258
- return nil, err
259
- }
260
-
261
- for _, l := range links {
262
- child := NodeListing{}
263
- child.Name = l.Name
264
-
247
+func (d *Directory) ForEachEntry(ctx context.Context, f func(NodeListing) error) error {
248
+ d.lock.Lock()
249
+ defer d.lock.Unlock()
250
+ return d.dirbuilder.ForEachLink(func(l *node.Link) error {
251
c, err := d.childUnsync(l.Name)
252
if err != nil {
267
- return nil, err
253
+ return err
254
+ }
255
+
256
+ nd, err := c.GetNode()
257
+ if err != nil {
258
+ return err
259
+ }
260
+
261
+ child := NodeListing{
262
+ Name: l.Name,
263
+ Type: int(c.Type()),
264
+ Hash: nd.Cid().String(),
265
}
266
270
- child.Type = int(c.Type())
267
if c, ok := c.(*File); ok {
268
size, err := c.Size()
269
if err != nil {
274
- return nil, err
270
+ return err
271
}
272
child.Size = size
273
}
278
- nd, err := c.GetNode()
279
- if err != nil {
280
- return nil, err
281
- }
274
283
- child.Hash = nd.Cid().String()
284
-
285
- out = append(out, child)
286
- }
287
-
288
- return out, nil
275
+ return f(child)
276
+ })
277
}
278
279
func (d *Directory) Mkdir(name string) (*Directory, error) {
@@ -433,5 +421,5 @@ func (d *Directory) GetNode() (node.Node, error) {
421
return nil, err
422
}
423
436
- return nd, err
424
+ return nd.Copy(), err
425
}
unixfs/hamt/hamt.go
+10
-8
@@ -321,7 +321,15 @@ func (ds *HamtShard) getValue(ctx context.Context, hv *hashBits, key string, cb
321
322
func (ds *HamtShard) EnumLinks() ([]*node.Link, error) {
323
var links []*node.Link
324
- err := ds.walkTrie(func(sv *shardValue) error {
324
+ err := ds.ForEachLink(func(l *node.Link) error {
325
+ links = append(links, l)
326
+ return nil
327
+ })
328
+ return links, err
329
+}
330
+
331
+func (ds *HamtShard) ForEachLink(f func(*node.Link) error) error {
332
+ return ds.walkTrie(func(sv *shardValue) error {
333
lnk, err := node.MakeLink(sv.val)
334
if err != nil {
335
return err
@@ -329,14 +337,8 @@ func (ds *HamtShard) EnumLinks() ([]*node.Link, error) {
337
338
lnk.Name = sv.key
339
332
- links = append(links, lnk)
333
- return nil
340
+ return f(lnk)
341
})
335
- if err != nil {
336
- return nil, err
337
- }
338
-
339
- return links, nil
342
}
343
344
func (ds *HamtShard) walkTrie(cb func(*shardValue) error) error {
unixfs/io/dirbuilder.go
+13
@@ -102,6 +102,19 @@ func (d *Directory) switchToSharding(ctx context.Context) error {
102
return nil
103
}
104
105
+func (d *Directory) ForEachLink(f func(*node.Link) error) error {
106
+ if d.shard == nil {
107
+ for _, l := range d.dirnode.Links() {
108
+ if err := f(l); err != nil {
109
+ return err
110
+ }
111
+ }
112
+ return nil
113
+ }
114
+
115
+ return d.shard.ForEachLink(f)
116
+}
117
+
118
func (d *Directory) Links() ([]*node.Link, error) {
119
if d.shard == nil {
120
return d.dirnode.Links(), nil