diff --git a/backend/union/policy/eplno.go b/backend/union/policy/eplno.go index ee1878a11..db94f43e7 100644 --- a/backend/union/policy/eplno.go +++ b/backend/union/policy/eplno.go @@ -18,28 +18,11 @@ type EpLno struct { EpAll } -func (p *EpLno) getUpstreamObjectCount(ctx context.Context, upstream *upstream.Fs) int64 { - numObj, err := upstream.GetNumObjects() - if err != nil { - uName := upstream.Name() - fs.LogPrintf(fs.LogLevelNotice, nil, - "Number of Objects is not supported for upstream %s, falling back to listing (this may be slower)...", uName) - listing, err := upstream.List(ctx, "") - if err != nil { - fs.LogPrintf(fs.LogLevelError, nil, "Listing failed, treating as 0: %v", err) - return 0 - } - numObj = int64(len(listing)) - fs.LogPrintf(fs.LogLevelDebug, nil, "Counted %d objects for upstream %s by listing", numObj, uName) - } - return numObj -} - -func (p *EpLno) lno(ctx context.Context, upstreams []*upstream.Fs) (*upstream.Fs, error) { +func (p *EpLno) lno(upstreams []*upstream.Fs) (*upstream.Fs, error) { var minNumObj int64 = math.MaxInt64 var lnoUpstream *upstream.Fs for _, u := range upstreams { - numObj := p.getUpstreamObjectCount(ctx, u) + numObj := u.GetNumObjects() if minNumObj > numObj { minNumObj = numObj lnoUpstream = u @@ -51,11 +34,11 @@ func (p *EpLno) lno(ctx context.Context, upstreams []*upstream.Fs) (*upstream.Fs return lnoUpstream, nil } -func (p *EpLno) lnoEntries(ctx context.Context, entries []upstream.Entry) (upstream.Entry, error) { +func (p *EpLno) lnoEntries(entries []upstream.Entry) (upstream.Entry, error) { var minNumObj int64 = math.MaxInt64 var lnoEntry upstream.Entry for _, e := range entries { - numObj := p.getUpstreamObjectCount(ctx, e.UpstreamFs()) + numObj := e.UpstreamFs().GetNumObjects() if minNumObj > numObj { minNumObj = numObj lnoEntry = e @@ -70,7 +53,7 @@ func (p *EpLno) Action(ctx context.Context, upstreams []*upstream.Fs, path strin if err != nil { return nil, err } - u, err := p.lno(ctx, upstreams) + u, err := p.lno(upstreams) return []*upstream.Fs{u}, err } @@ -80,7 +63,7 @@ func (p *EpLno) ActionEntries(entries ...upstream.Entry) ([]upstream.Entry, erro if err != nil { return nil, err } - e, err := p.lnoEntries(context.Background(), entries) + e, err := p.lnoEntries(entries) return []upstream.Entry{e}, err } @@ -90,7 +73,7 @@ func (p *EpLno) Create(ctx context.Context, upstreams []*upstream.Fs, path strin if err != nil { return nil, err } - u, err := p.lno(ctx, upstreams) + u, err := p.lno(upstreams) return []*upstream.Fs{u}, err } @@ -100,7 +83,7 @@ func (p *EpLno) CreateEntries(entries ...upstream.Entry) ([]upstream.Entry, erro if err != nil { return nil, err } - e, err := p.lnoEntries(context.Background(), entries) + e, err := p.lnoEntries(entries) return []upstream.Entry{e}, err } @@ -113,7 +96,7 @@ func (p *EpLno) Search(ctx context.Context, upstreams []*upstream.Fs, path strin if err != nil { return nil, err } - return p.lno(ctx, upstreams) + return p.lno(upstreams) } // SearchEntries is SEARCH category policy but receiving a set of candidate entries @@ -121,5 +104,5 @@ func (p *EpLno) SearchEntries(entries ...upstream.Entry) (upstream.Entry, error) if len(entries) == 0 { return nil, fs.ErrorObjectNotFound } - return p.lnoEntries(context.Background(), entries) + return p.lnoEntries(entries) } diff --git a/backend/union/policy/lno.go b/backend/union/policy/lno.go index 2e7625bd3..7d9a99d8a 100644 --- a/backend/union/policy/lno.go +++ b/backend/union/policy/lno.go @@ -28,6 +28,6 @@ func (p *Lno) Create(ctx context.Context, upstreams []*upstream.Fs, path string) if len(upstreams) == 0 { return nil, fs.ErrorPermissionDenied } - u, err := p.lno(ctx, upstreams) + u, err := p.lno(upstreams) return []*upstream.Fs{u}, err } diff --git a/backend/union/upstream/upstream.go b/backend/union/upstream/upstream.go index 747de830d..48d427e49 100644 --- a/backend/union/upstream/upstream.go +++ b/backend/union/upstream/upstream.go @@ -438,19 +438,37 @@ func (f *Fs) GetUsedSpace() (int64, error) { } // GetNumObjects get the number of objects of the fs -func (f *Fs) GetNumObjects() (int64, error) { +func (f *Fs) GetNumObjects() int64 { + var err error if f.cacheExpiry.Load() <= time.Now().Unix() { - err := f.updateUsage() - if err != nil { - return 0, ErrUsageFieldNotSupported + err = f.updateUsage() + } + + if f.usage.Objects == nil { + uName := f.Name() + fs.LogPrintf( + fs.LogLevelWarning, + nil, + "Number of objects not supported for upstream %s, falling back to listing (this will be slower)...", + uName, + ) + count, _, _, err := operations.Count(context.Background(), f) + if err == nil { + fs.Debugf(nil, "Counted %d objects for upstream %s by listing", count, uName) + f.cacheMutex.Lock() + f.usage.Objects = &count + f.cacheMutex.Unlock() } } + + if err != nil { + fs.Errorf(nil, "Error getting number of objects, treating as 0: %v", err) + return 0 + } + f.cacheMutex.RLock() defer f.cacheMutex.RUnlock() - if f.usage.Objects == nil { - return 0, ErrUsageFieldNotSupported - } - return *f.usage.Objects, nil + return *f.usage.Objects } func (f *Fs) updateUsage() (err error) {