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(¶ms) 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 }