Skip to content

Commit 92c79d2

Browse files
feature(s3): implement ListCB
1 parent cc910f3 commit 92c79d2

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

backend/s3/s3.go

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,25 +1979,28 @@ func (f *Fs) itemToDirEntry(ctx context.Context, remote string, object *s3.Objec
19791979
return o, nil
19801980
}
19811981

1982-
// listDir lists files and directories to out
1983-
func (f *Fs) listDir(ctx context.Context, bucket, directory, prefix string, addBucket bool) (entries fs.DirEntries, err error) {
1984-
// List the objects and directories
1985-
err = f.list(ctx, bucket, directory, prefix, addBucket, false, func(remote string, object *s3.Object, isDirectory bool) error {
1982+
// listDirCB calls callback on files as they are being listed.
1983+
func (f *Fs) listDir(ctx context.Context, bucket, directory, prefix string, addBucket bool, cb fs.ListCBCallback) error {
1984+
// List the objects and directories.
1985+
// Batch callbacks by 100 with walk.NewListRHelper (compatible callback type)
1986+
// in order to reduce the amount of allocations and function calls.
1987+
list := walk.NewListRHelper(fs.ListRCallback(cb))
1988+
err := f.list(ctx, bucket, directory, prefix, addBucket, false, func(remote string, object *s3.Object, isDirectory bool) error {
19861989
entry, err := f.itemToDirEntry(ctx, remote, object, isDirectory)
19871990
if err != nil {
19881991
return err
19891992
}
19901993
if entry != nil {
1991-
entries = append(entries, entry)
1994+
return list.Add(entry)
19921995
}
19931996
return nil
19941997
})
19951998
if err != nil {
1996-
return nil, err
1999+
return err
19972000
}
19982001
// bucket must be present if listing succeeded
19992002
f.cache.MarkOK(bucket)
2000-
return entries, nil
2003+
return list.Flush()
20012004
}
20022005

20032006
// listBuckets lists the buckets to out
@@ -2029,15 +2032,48 @@ func (f *Fs) listBuckets(ctx context.Context) (entries fs.DirEntries, err error)
20292032
//
20302033
// This should return ErrDirNotFound if the directory isn't
20312034
// found.
2032-
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
2035+
func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
20332036
bucket, directory := f.split(dir)
20342037
if bucket == "" {
20352038
if directory != "" {
20362039
return nil, fs.ErrorListBucketRequired
20372040
}
20382041
return f.listBuckets(ctx)
20392042
}
2040-
return f.listDir(ctx, bucket, directory, f.rootDirectory, f.rootBucket == "")
2043+
2044+
// Use callback for regular listing
2045+
var entries fs.DirEntries
2046+
err := f.listDir(ctx, bucket, directory, f.rootDirectory, f.rootBucket == "", func(e fs.DirEntries) error {
2047+
entries = append(entries, e...)
2048+
return nil
2049+
})
2050+
if err != nil {
2051+
return nil, err
2052+
}
2053+
return entries, nil
2054+
}
2055+
2056+
// ListCB calls callback to the objects and directories in dir as they are being listed.
2057+
// The callback might be called for just a subset of directory entries.
2058+
// When listing buckets, the callback is called just once for all of them.
2059+
//
2060+
// dir should be "" to list the root, and should not have
2061+
// trailing slashes.
2062+
//
2063+
// This should return ErrDirNotFound if the directory isn't found.
2064+
func (f *Fs) ListCB(ctx context.Context, dir string, cb fs.ListCBCallback) error {
2065+
bucket, directory := f.split(dir)
2066+
if bucket == "" {
2067+
if directory != "" {
2068+
return fs.ErrorListBucketRequired
2069+
}
2070+
entries, err := f.listBuckets(ctx)
2071+
if err != nil {
2072+
return err
2073+
}
2074+
return cb(entries)
2075+
}
2076+
return f.listDir(ctx, bucket, directory, f.rootDirectory, f.rootBucket == "", cb)
20412077
}
20422078

20432079
// ListR lists the objects and directories of the Fs starting

0 commit comments

Comments
 (0)