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  }