github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/union/policy/eplfs.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("eplfs", &EpLfs{}) 13 } 14 15 // EpLfs stands for existing path, least free space 16 // Of all the candidates on which the path exists choose the one with the least free space. 17 type EpLfs struct { 18 EpAll 19 } 20 21 func (p *EpLfs) lfs(upstreams []*upstream.Fs) (*upstream.Fs, error) { 22 var minFreeSpace int64 = math.MaxInt64 23 var lfsupstream *upstream.Fs 24 for _, u := range upstreams { 25 space, err := u.GetFreeSpace() 26 if err != nil { 27 fs.LogPrintf(fs.LogLevelNotice, nil, 28 "Free Space is not supported for upstream %s, treating as infinite", u.Name()) 29 } 30 if space < minFreeSpace { 31 minFreeSpace = space 32 lfsupstream = u 33 } 34 } 35 if lfsupstream == nil { 36 return nil, fs.ErrorObjectNotFound 37 } 38 return lfsupstream, nil 39 } 40 41 func (p *EpLfs) lfsEntries(entries []upstream.Entry) (upstream.Entry, error) { 42 var minFreeSpace int64 43 var lfsEntry upstream.Entry 44 for _, e := range entries { 45 space, err := e.UpstreamFs().GetFreeSpace() 46 if err != nil { 47 fs.LogPrintf(fs.LogLevelNotice, nil, 48 "Free Space is not supported for upstream %s, treating as infinite", e.UpstreamFs().Name()) 49 } 50 if space < minFreeSpace { 51 minFreeSpace = space 52 lfsEntry = e 53 } 54 } 55 return lfsEntry, nil 56 } 57 58 // Action category policy, governing the modification of files and directories 59 func (p *EpLfs) 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.lfs(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 *EpLfs) 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.lfsEntries(entries) 75 return []upstream.Entry{e}, err 76 } 77 78 // Create category policy, governing the creation of files and directories 79 func (p *EpLfs) 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.lfs(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 *EpLfs) 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.lfsEntries(entries) 95 return []upstream.Entry{e}, err 96 } 97 98 // Search category policy, governing the access to files and directories 99 func (p *EpLfs) 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.lfs(upstreams) 108 } 109 110 // SearchEntries is SEARCH category policy but receiving a set of candidate entries 111 func (p *EpLfs) SearchEntries(entries ...upstream.Entry) (upstream.Entry, error) { 112 if len(entries) == 0 { 113 return nil, fs.ErrorObjectNotFound 114 } 115 return p.lfsEntries(entries) 116 }