@cryptotaxi247 / kubo / commits / d06a678e4

coreapi: asunc ls option

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Feb 1, 2019 at 20:12 UTC d06a678e488b3498f0df1614413c18de35023cca
4 files changed +86 -19
core/coreapi/interface/options/unixfs.go
+30
@@ -42,7 +42,12 @@ type UnixfsAddSettings struct {
42 Progress bool
43 }
44
45 +type UnixfsLsSettings struct {
46 + Async bool
47 +}
48 +
49 type UnixfsAddOption func(*UnixfsAddSettings) error
50 +type UnixfsLsOption func(*UnixfsLsSettings) error
51
52 func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix, error) {
53 options := &UnixfsAddSettings{
@@ -122,6 +127,21 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
127 return options, prefix, nil
128 }
129
130 +func UnixfsLsOptions(opts ...UnixfsLsOption) (*UnixfsLsSettings, error) {
131 + options := &UnixfsLsSettings{
132 + Async: true,
133 + }
134 +
135 + for _, opt := range opts {
136 + err := opt(options)
137 + if err != nil {
138 + return nil, err
139 + }
140 + }
141 +
142 + return options, nil
143 +}
144 +
145 type unixfsOpts struct{}
146
147 var Unixfs unixfsOpts
@@ -290,3 +310,13 @@ func (unixfsOpts) Nocopy(enable bool) UnixfsAddOption {
310 return nil
311 }
312 }
313 +
314 +// Async tells ls to return results as soon as they are available, which can be
315 +// useful for listing HAMT directories. When this option is set to true returned
316 +// results won't be returned in order
317 +func (unixfsOpts) Async(async bool) UnixfsLsOption {
318 + return func(settings *UnixfsLsSettings) error {
319 + settings.Async = async
320 + return nil
321 + }
322 +}
core/coreapi/interface/tests/unixfs.go
+20 -2
@@ -749,12 +749,12 @@ func (tp *provider) TestLs(t *testing.T) {
749 t.Error(err)
750 }
751
752 - links, err := api.Unixfs().Ls(ctx, p)
752 + links, err := api.Unixfs().Ls(ctx, p, options.Unixfs.Async(false))
753 if err != nil {
754 t.Error(err)
755 }
756
757 - link := <- links
757 + link := (<-links).Link
758 if link.Size != 23 {
759 t.Fatalf("expected size = 23, got %d", link.Size)
760 }
@@ -768,6 +768,24 @@ func (tp *provider) TestLs(t *testing.T) {
768 t.Errorf("didn't expect a second link")
769 }
770
771 + links, err = api.Unixfs().Ls(ctx, p, options.Unixfs.Async(true))
772 + if err != nil {
773 + t.Error(err)
774 + }
775 +
776 + link = (<-links).Link
777 + if link.Size != 23 {
778 + t.Fatalf("expected size = 23, got %d", link.Size)
779 + }
780 + if link.Name != "name-of-file" {
781 + t.Fatalf("expected name = name-of-file, got %s", link.Name)
782 + }
783 + if link.Cid.String() != "QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr" {
784 + t.Fatalf("expected cid = QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr, got %s", link.Cid)
785 + }
786 + if _, ok := <-links; ok {
787 + t.Errorf("didn't expect a second link")
788 + }
789 }
790
791 func (tp *provider) TestEntriesExpired(t *testing.T) {
core/coreapi/interface/unixfs.go
+3 -3
@@ -5,8 +5,8 @@ import (
5
6 "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
7
8 - ipld "gx/ipfs/QmRL22E4paat7ky7vx9MLpR97JHHbFPrg3ytFQw6qp1y1s/go-ipld-format"
9 - files "gx/ipfs/QmaXvvAVAQ5ABqM5xtjYmV85xmN5MkWAZsX9H9Fwo4FVXp/go-ipfs-files"
8 + ft "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs"
9 + "gx/ipfs/QmaXvvAVAQ5ABqM5xtjYmV85xmN5MkWAZsX9H9Fwo4FVXp/go-ipfs-files"
10 )
11
12 type AddEvent struct {
@@ -31,5 +31,5 @@ type UnixfsAPI interface {
31 Get(context.Context, Path) (files.Node, error)
32
33 // Ls returns the list of links in a directory
34 - Ls(context.Context, Path) (<-chan *ipld.Link, error)
34 + Ls(context.Context, Path, ...options.UnixfsLsOption) (<-chan ft.LinkResult, error)
35 }
core/coreapi/unixfs.go
+33 -14
@@ -143,30 +143,49 @@ func (api *UnixfsAPI) Get(ctx context.Context, p coreiface.Path) (files.Node, er
143
144 // Ls returns the contents of an IPFS or IPNS object(s) at path p, with the format:
145 // `<link base58 hash> <link size in bytes> <link name>`
146 -func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path) (<-chan *ipld.Link, error) {
146 +func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path, opts ...options.UnixfsLsOption) (<-chan ft.LinkResult, error) {
147 + settings, err := options.UnixfsLsOptions(opts...)
148 + if err != nil {
149 + return nil, err
150 + }
151 +
152 dagnode, err := api.core().ResolveNode(ctx, p)
153 if err != nil {
154 return nil, err
155 }
156
152 - var ndlinks []*ipld.Link
157 dir, err := uio.NewDirectoryFromNode(api.dag, dagnode)
154 - switch err {
155 - case nil:
156 - l, err := dir.Links(ctx)
157 - if err != nil {
158 - return nil, err
159 - }
160 - ndlinks = l
161 - case uio.ErrNotADir:
162 - ndlinks = dagnode.Links()
163 - default:
158 + if err == uio.ErrNotADir {
159 + return lsFromLinks(dagnode.Links())
160 + }
161 + if err != nil {
162 + return nil, err
163 + }
164 +
165 + if !settings.Async {
166 + return lsFromDir(ctx, dir)
167 + }
168 +
169 + return lsFromLinksAsync(ctx, dir)
170 +}
171 +
172 +func lsFromLinksAsync(ctx context.Context, dir uio.Directory) (<-chan ft.LinkResult, error) {
173 +
174 + return dir.EnumLinksAsync(ctx), nil
175 +}
176 +
177 +func lsFromDir(ctx context.Context, dir uio.Directory) (<-chan ft.LinkResult, error) {
178 + l, err := dir.Links(ctx)
179 + if err != nil {
180 return nil, err
181 }
182 + return lsFromLinks(l)
183 +}
184
167 - links := make(chan *ipld.Link, len(ndlinks))
185 +func lsFromLinks(ndlinks []*ipld.Link) (<-chan ft.LinkResult, error) {
186 + links := make(chan ft.LinkResult, len(ndlinks))
187 for _, l := range ndlinks {
169 - links <- &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}
188 + links <- ft.LinkResult{Link: &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}}
189 }
190 close(links)
191 return links, nil