github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/union/policy/epmfs.go (about)

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