github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/xact/xs/brename.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-2023, NVIDIA CORPORATION. All rights reserved. 5 */ 6 package xs 7 8 import ( 9 "fmt" 10 "sync" 11 "time" 12 13 "github.com/NVIDIA/aistore/api/apc" 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/xact" 20 "github.com/NVIDIA/aistore/xact/xreg" 21 ) 22 23 // tunables 24 const ( 25 bmvAvgWait = 2 * time.Minute 26 bmvMaxWait = 2 * time.Hour 27 bmvMaxSleep = 30 * time.Second 28 ) 29 30 type ( 31 bckRename struct { 32 bckFrom *meta.Bck 33 bckTo *meta.Bck 34 rebID string 35 xact.Base 36 } 37 bmvFactory struct { 38 xreg.RenewBase 39 xctn *bckRename 40 cargs *xreg.BckRenameArgs 41 phase string 42 } 43 TestBmvFactory = bmvFactory 44 ) 45 46 // interface guard 47 var ( 48 _ core.Xact = (*bckRename)(nil) 49 _ xreg.Renewable = (*bmvFactory)(nil) 50 ) 51 52 //////////////// 53 // bmvFactory // 54 //////////////// 55 56 func (*bmvFactory) New(args xreg.Args, bck *meta.Bck) xreg.Renewable { 57 p := &bmvFactory{RenewBase: xreg.RenewBase{Args: args, Bck: bck}, cargs: args.Custom.(*xreg.BckRenameArgs)} 58 return p 59 } 60 61 func (*bmvFactory) Kind() string { return apc.ActMoveBck } 62 func (p *bmvFactory) Get() core.Xact { return p.xctn } 63 64 func (p *bmvFactory) Start() error { 65 p.xctn = newBckRename(p.UUID(), p.Kind(), p.cargs.RebID, p.Bck, p.cargs.BckFrom, p.cargs.BckTo) 66 return nil 67 } 68 69 func (p *bmvFactory) WhenPrevIsRunning(prevEntry xreg.Renewable) (wpr xreg.WPR, err error) { 70 if p.phase == apc.ActBegin { 71 if !prevEntry.Get().Finished() { 72 err = fmt.Errorf("%s: cannot(%s=>%s) older rename still in progress", 73 p.Kind(), p.cargs.BckFrom, p.cargs.BckTo) 74 return 75 } 76 // TODO: more checks 77 } 78 prev := prevEntry.(*bmvFactory) 79 bckEq := prev.cargs.BckTo.Equal(p.cargs.BckTo, false /*sameID*/, false /* same backend */) 80 if prev.phase == apc.ActBegin && p.phase == apc.ActCommit && bckEq { 81 prev.phase = apc.ActCommit // transition 82 wpr = xreg.WprUse 83 return 84 } 85 err = fmt.Errorf("%s(%s=>%s, phase %s): cannot %s(=>%s)", 86 p.Kind(), prev.cargs.BckFrom, prev.cargs.BckTo, prev.phase, p.phase, p.cargs.BckFrom) 87 return 88 } 89 90 /////////////// 91 // bckRename // 92 /////////////// 93 94 func newBckRename(uuid, kind, rebID string, bck, bckFrom, bckTo *meta.Bck) (x *bckRename) { 95 // NOTE: `bck` = `bckTo` = (the new name) while `bckFrom` is the existing bucket to be renamed 96 debug.Assert(bck.Equal(bckTo, false, true), bck.String()+" vs "+bckTo.String()) 97 98 debug.Assert(xact.IsValidRebID(rebID), rebID) 99 x = &bckRename{bckFrom: bckFrom, bckTo: bckTo, rebID: rebID} 100 x.InitBase(uuid, kind, bck) 101 return 102 } 103 104 // NOTE: assuming that rebalance takes longer than resilvering 105 func (r *bckRename) Run(wg *sync.WaitGroup) { 106 var ( 107 total time.Duration 108 flt = xreg.Flt{ID: r.rebID, Kind: apc.ActRebalance} 109 sleep = cos.ProbingFrequency(bmvAvgWait) 110 ) 111 nlog.Infoln(r.Name()) 112 wg.Done() 113 loop: 114 for total < bmvMaxWait { 115 time.Sleep(sleep) 116 total += sleep 117 rebStats, err := xreg.GetSnap(flt) 118 debug.AssertNoErr(err) 119 for _, stat := range rebStats { 120 if stat.Finished() || stat.IsAborted() { 121 break loop 122 } 123 } 124 if total > bmvAvgWait { 125 sleep = min(sleep+sleep/2, bmvMaxSleep) 126 } 127 } 128 if total >= bmvMaxWait { 129 r.AddErr(fmt.Errorf("timeout %s", total)) 130 } 131 core.T.BMDVersionFixup(nil, r.bckFrom.Clone()) // piggyback bucket renaming (last step) on getting updated BMD 132 r.Finish() 133 } 134 135 func (r *bckRename) String() string { 136 return fmt.Sprintf("%s <= %s", r.Base.String(), r.bckFrom) 137 } 138 139 func (r *bckRename) Name() string { 140 return fmt.Sprintf("%s <= %s", r.Base.Name(), r.bckFrom) 141 } 142 143 func (r *bckRename) FromTo() (*meta.Bck, *meta.Bck) { return r.bckFrom, r.bckTo } 144 145 func (r *bckRename) Snap() (snap *core.Snap) { 146 snap = &core.Snap{} 147 r.ToSnap(snap) 148 149 snap.IdleX = r.IsIdle() 150 f, t := r.FromTo() 151 snap.SrcBck, snap.DstBck = f.Clone(), t.Clone() 152 return 153 }