github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/xact/xs/dpromote.go (about)

     1  // Package xs is a collection of eXtended actions (xactions), including multi-object
     2  // operations, list-objects, (cluster) rebalance and (target) resilver, ETL, and more.
     3  /*
     4   * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
     5   */
     6  package xs
     7  
     8  import (
     9  	"path/filepath"
    10  	"sync"
    11  
    12  	"github.com/NVIDIA/aistore/api/apc"
    13  	"github.com/NVIDIA/aistore/cmn"
    14  	"github.com/NVIDIA/aistore/cmn/cos"
    15  	"github.com/NVIDIA/aistore/cmn/debug"
    16  	"github.com/NVIDIA/aistore/cmn/nlog"
    17  	"github.com/NVIDIA/aistore/core"
    18  	"github.com/NVIDIA/aistore/core/meta"
    19  	"github.com/NVIDIA/aistore/fs"
    20  	"github.com/NVIDIA/aistore/fs/mpather"
    21  	"github.com/NVIDIA/aistore/xact"
    22  	"github.com/NVIDIA/aistore/xact/xreg"
    23  )
    24  
    25  // promotes (i.e., copies) locally accessible (within the cluster) directory => bucket
    26  
    27  type (
    28  	proFactory struct {
    29  		xreg.RenewBase
    30  		xctn *XactDirPromote
    31  		args *apc.PromoteArgs
    32  	}
    33  	XactDirPromote struct {
    34  		p    *proFactory
    35  		smap *meta.Smap
    36  		xact.BckJog
    37  		confirmedFshare bool // set separately in the commit phase prior to Run
    38  	}
    39  )
    40  
    41  // interface guard
    42  var (
    43  	_ core.Xact      = (*XactDirPromote)(nil)
    44  	_ xreg.Renewable = (*proFactory)(nil)
    45  )
    46  
    47  ////////////////
    48  // proFactory //
    49  ////////////////
    50  
    51  func (*proFactory) New(args xreg.Args, bck *meta.Bck) xreg.Renewable {
    52  	c := args.Custom.(*apc.PromoteArgs)
    53  	p := &proFactory{RenewBase: xreg.RenewBase{Args: args, Bck: bck}, args: c}
    54  	return p
    55  }
    56  
    57  func (p *proFactory) Start() error {
    58  	xctn := &XactDirPromote{p: p}
    59  	xctn.BckJog.Init(p.Args.UUID /*global xID*/, apc.ActPromote, p.Bck, &mpather.JgroupOpts{}, cmn.GCO.Get())
    60  	p.xctn = xctn
    61  	return nil
    62  }
    63  
    64  func (*proFactory) Kind() string     { return apc.ActPromote }
    65  func (p *proFactory) Get() core.Xact { return p.xctn }
    66  
    67  func (*proFactory) WhenPrevIsRunning(xreg.Renewable) (xreg.WPR, error) {
    68  	return xreg.WprKeepAndStartNew, nil
    69  }
    70  
    71  ////////////////////
    72  // XactDirPromote //
    73  ////////////////////
    74  
    75  func (r *XactDirPromote) SetFshare(v bool) { r.confirmedFshare = v } // is called before Run()
    76  
    77  func (r *XactDirPromote) Run(wg *sync.WaitGroup) {
    78  	wg.Done()
    79  
    80  	dir := r.p.args.SrcFQN
    81  	nlog.Infof("%s(%s)", r.Name(), dir)
    82  
    83  	r.smap = core.T.Sowner().Get()
    84  	var (
    85  		err  error
    86  		opts = &fs.WalkOpts{Dir: dir, Callback: r.walk, Sorted: false}
    87  	)
    88  	if r.p.args.Recursive {
    89  		err = fs.Walk(opts) // godirwalk
    90  	} else {
    91  		err = fs.WalkDir(dir, r.walk) // Go filepath.WalkDir
    92  	}
    93  	if err != nil {
    94  		r.AddErr(err)
    95  	}
    96  	r.Finish()
    97  }
    98  
    99  func (r *XactDirPromote) walk(fqn string, de fs.DirEntry) error {
   100  	if de.IsDir() {
   101  		return nil
   102  	}
   103  	debug.Assert(filepath.IsAbs(fqn))
   104  	bck := r.Bck()
   105  
   106  	// promote
   107  	args := r.p.args
   108  	objName, err := PrmObjName(fqn, args.SrcFQN, args.ObjName)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	// file share == true: promote only the part of the namespace that "lands" locally
   113  	if r.confirmedFshare {
   114  		si, err := r.smap.HrwName2T(bck.MakeUname(objName))
   115  		if err != nil {
   116  			return err
   117  		}
   118  		if si.ID() != core.T.SID() {
   119  			return nil
   120  		}
   121  	}
   122  	params := core.PromoteParams{
   123  		Bck:    bck,
   124  		Xact:   r,
   125  		Config: r.Config,
   126  		PromoteArgs: apc.PromoteArgs{
   127  			SrcFQN:       fqn,
   128  			ObjName:      objName,
   129  			OverwriteDst: args.OverwriteDst,
   130  			DeleteSrc:    args.DeleteSrc,
   131  		},
   132  	}
   133  	// TODO: continue-on-error (unify w/ x-archive)
   134  	ecode, err := core.T.Promote(&params)
   135  	if cos.IsNotExist(err, ecode) {
   136  		err = nil
   137  	}
   138  	if cmn.Rom.FastV(5, cos.SmoduleXs) {
   139  		nlog.Infof("%s: %s => %s (over=%t, del=%t, share=%t): %v", r.Base.Name(), fqn, bck.Cname(objName),
   140  			args.OverwriteDst, args.DeleteSrc, r.confirmedFshare, err)
   141  	}
   142  	return err
   143  }
   144  
   145  func (r *XactDirPromote) Snap() (snap *core.Snap) {
   146  	snap = &core.Snap{}
   147  	r.ToSnap(snap)
   148  
   149  	snap.IdleX = r.IsIdle()
   150  	return
   151  }
   152  
   153  //
   154  // destination naming
   155  //
   156  
   157  func PrmObjName(objfqn, dirfqn, prefix string) (_ string, err error) {
   158  	var baseName string
   159  	if dirfqn == "" {
   160  		if prefix != "" && !cos.IsLastB(prefix, filepath.Separator) {
   161  			return prefix, nil
   162  		}
   163  		baseName = filepath.Base(objfqn)
   164  	} else {
   165  		baseName, err = filepath.Rel(dirfqn, objfqn)
   166  		if err != nil {
   167  			debug.Assert(false, err, dirfqn, objfqn)
   168  			return "", err
   169  		}
   170  	}
   171  	return prefix + baseName, nil
   172  }