github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/union/policy/eplno.go (about) 1 package policy 2 3 import ( 4 "context" 5 "math" 6 7 "github.com/rclone/rclone/backend/union/upstream" 8 "github.com/rclone/rclone/fs" 9 ) 10 11 func init() { 12 registerPolicy("eplno", &EpLno{}) 13 } 14 15 // EpLno stands for existing path, least number of objects 16 // Of all the candidates on which the path exists choose the one with the least number of objects 17 type EpLno struct { 18 EpAll 19 } 20 21 func (p *EpLno) lno(upstreams []*upstream.Fs) (*upstream.Fs, error) { 22 var minNumObj int64 = math.MaxInt64 23 var lnoUpstream *upstream.Fs 24 for _, u := range upstreams { 25 numObj, err := u.GetNumObjects() 26 if err != nil { 27 fs.LogPrintf(fs.LogLevelNotice, nil, 28 "Number of Objects is not supported for upstream %s, treating as 0", u.Name()) 29 } 30 if minNumObj > numObj { 31 minNumObj = numObj 32 lnoUpstream = u 33 } 34 } 35 if lnoUpstream == nil { 36 return nil, fs.ErrorObjectNotFound 37 } 38 return lnoUpstream, nil 39 } 40 41 func (p *EpLno) lnoEntries(entries []upstream.Entry) (upstream.Entry, error) { 42 var minNumObj int64 = math.MaxInt64 43 var lnoEntry upstream.Entry 44 for _, e := range entries { 45 numObj, err := e.UpstreamFs().GetNumObjects() 46 if err != nil { 47 fs.LogPrintf(fs.LogLevelNotice, nil, 48 "Number of Objects is not supported for upstream %s, treating as 0", e.UpstreamFs().Name()) 49 } 50 if minNumObj > numObj { 51 minNumObj = numObj 52 lnoEntry = e 53 } 54 } 55 return lnoEntry, nil 56 } 57 58 // Action category policy, governing the modification of files and directories 59 func (p *EpLno) Action(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) { 60 upstreams, err := p.EpAll.Action(ctx, upstreams, path) 61 if err != nil { 62 return nil, err 63 } 64 u, err := p.lno(upstreams) 65 return []*upstream.Fs{u}, err 66 } 67 68 // ActionEntries is ACTION category policy but receiving a set of candidate entries 69 func (p *EpLno) ActionEntries(entries ...upstream.Entry) ([]upstream.Entry, error) { 70 entries, err := p.EpAll.ActionEntries(entries...) 71 if err != nil { 72 return nil, err 73 } 74 e, err := p.lnoEntries(entries) 75 return []upstream.Entry{e}, err 76 } 77 78 // Create category policy, governing the creation of files and directories 79 func (p *EpLno) Create(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) { 80 upstreams, err := p.EpAll.Create(ctx, upstreams, path) 81 if err != nil { 82 return nil, err 83 } 84 u, err := p.lno(upstreams) 85 return []*upstream.Fs{u}, err 86 } 87 88 // CreateEntries is CREATE category policy but receiving a set of candidate entries 89 func (p *EpLno) CreateEntries(entries ...upstream.Entry) ([]upstream.Entry, error) { 90 entries, err := p.EpAll.CreateEntries(entries...) 91 if err != nil { 92 return nil, err 93 } 94 e, err := p.lnoEntries(entries) 95 return []upstream.Entry{e}, err 96 } 97 98 // Search category policy, governing the access to files and directories 99 func (p *EpLno) Search(ctx context.Context, upstreams []*upstream.Fs, path string) (*upstream.Fs, error) { 100 if len(upstreams) == 0 { 101 return nil, fs.ErrorObjectNotFound 102 } 103 upstreams, err := p.epall(ctx, upstreams, path) 104 if err != nil { 105 return nil, err 106 } 107 return p.lno(upstreams) 108 } 109 110 // SearchEntries is SEARCH category policy but receiving a set of candidate entries 111 func (p *EpLno) SearchEntries(entries ...upstream.Entry) (upstream.Entry, error) { 112 if len(entries) == 0 { 113 return nil, fs.ErrorObjectNotFound 114 } 115 return p.lnoEntries(entries) 116 }