github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/mirror/utils.go (about) 1 // Package mirror provides local mirroring and replica management 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package mirror 6 7 import ( 8 "fmt" 9 10 "github.com/NVIDIA/aistore/cmn/nlog" 11 "github.com/NVIDIA/aistore/core" 12 "github.com/NVIDIA/aistore/fs" 13 ) 14 15 // is under lock 16 func delCopies(lom *core.LOM, copies int) (size int64, err error) { 17 // force reloading metadata 18 lom.UncacheUnless() 19 if err := lom.Load(false /*cache it*/, true /*locked*/); err != nil { 20 return 0, err 21 } 22 23 ndel := lom.NumCopies() - copies 24 if ndel <= 0 { 25 return 26 } 27 28 copiesFQN := make([]string, 0, ndel) 29 for copyFQN := range lom.GetCopies() { 30 if copyFQN == lom.FQN { 31 continue 32 } 33 copiesFQN = append(copiesFQN, copyFQN) 34 ndel-- 35 if ndel == 0 { 36 break 37 } 38 } 39 40 size = int64(len(copiesFQN)) * lom.SizeBytes() 41 if err = lom.DelCopies(copiesFQN...); err != nil { 42 return 43 } 44 err = lom.Persist() 45 return 46 } 47 48 // under LOM's w-lock => TODO: a finer-grade mechanism to write-protect 49 // metadata only, md.copies in this case 50 func addCopies(lom *core.LOM, copies int, buf []byte) (size int64, err error) { 51 // Reload metadata, it is necessary to have it fresh. 52 lom.UncacheUnless() 53 if err := lom.Load(false /*cache it*/, true /*locked*/); err != nil { 54 return 0, err 55 } 56 57 // Recheck if we still need to create the copy. 58 if lom.NumCopies() >= copies { 59 return 0, nil 60 } 61 62 // While copying we may find out that some copies do not exist - 63 // these copies will be removed and `NumCopies()` will decrease. 64 for lom.NumCopies() < copies { 65 var mi *fs.Mountpath 66 if mi = lom.LeastUtilNoCopy(); mi == nil { 67 err = fmt.Errorf("%s (copies=%d): cannot find dst mountpath", lom, lom.NumCopies()) 68 return 69 } 70 if err = lom.Copy(mi, buf); err != nil { 71 nlog.Errorln(err) 72 return 73 } 74 size += lom.SizeBytes() 75 } 76 return 77 } 78 79 func drainWorkCh(workCh chan core.LIF) (n int) { 80 for { 81 select { 82 case <-workCh: 83 n++ 84 default: 85 return 86 } 87 } 88 }