Merge pull request #2025 from kurin/fixloop
b2: simplify object iteration
This commit is contained in:
commit
af4d822380
1 changed files with 25 additions and 50 deletions
|
@ -5,7 +5,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/restic/restic/internal/backend"
|
"github.com/restic/restic/internal/backend"
|
||||||
"github.com/restic/restic/internal/debug"
|
"github.com/restic/restic/internal/debug"
|
||||||
|
@ -257,69 +256,45 @@ func (be *b2Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
return errors.Wrap(obj.Delete(ctx), "Delete")
|
return errors.Wrap(obj.Delete(ctx), "Delete")
|
||||||
}
|
}
|
||||||
|
|
||||||
// List returns a channel that yields all names of blobs of type t. A
|
type semLocker struct {
|
||||||
// goroutine is started for this. If the channel done is closed, sending
|
*backend.Semaphore
|
||||||
// stops.
|
}
|
||||||
|
|
||||||
|
func (sm semLocker) Lock() { sm.GetToken() }
|
||||||
|
func (sm semLocker) Unlock() { sm.ReleaseToken() }
|
||||||
|
|
||||||
|
// List returns a channel that yields all names of blobs of type t.
|
||||||
func (be *b2Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
|
func (be *b2Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
|
||||||
debug.Log("List %v", t)
|
debug.Log("List %v", t)
|
||||||
|
|
||||||
prefix, _ := be.Basedir(t)
|
|
||||||
cur := &b2.Cursor{Prefix: prefix}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for {
|
prefix, _ := be.Basedir(t)
|
||||||
be.sem.GetToken()
|
iter := be.bucket.List(ctx, b2.ListPrefix(prefix), b2.ListPageSize(be.listMaxItems), b2.ListLocker(semLocker{be.sem}))
|
||||||
objs, c, err := be.bucket.ListCurrentObjects(ctx, be.listMaxItems, cur)
|
|
||||||
be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
if err != nil && err != io.EOF {
|
for iter.Next() {
|
||||||
debug.Log("List: %v", err)
|
obj := iter.Object()
|
||||||
|
|
||||||
|
attrs, err := obj.Attrs(ctx)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("returned %v items", len(objs))
|
fi := restic.FileInfo{
|
||||||
for _, obj := range objs {
|
Name: path.Base(obj.Name()),
|
||||||
// Skip objects returned that do not have the specified prefix.
|
Size: attrs.Size,
|
||||||
if !strings.HasPrefix(obj.Name(), prefix) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m := path.Base(obj.Name())
|
|
||||||
if m == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs, err := obj.Attrs(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fi := restic.FileInfo{
|
|
||||||
Name: m,
|
|
||||||
Size: attrs.Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fn(fi)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == io.EOF {
|
if err := fn(fi); err != nil {
|
||||||
return ctx.Err()
|
return err
|
||||||
}
|
}
|
||||||
cur = c
|
|
||||||
}
|
}
|
||||||
|
if err := iter.Err(); err != nil {
|
||||||
|
debug.Log("List: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove keys for a specified backend type.
|
// Remove keys for a specified backend type.
|
||||||
|
|
Loading…
Reference in a new issue