github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/fs/utils.go (about) 1 // Package fs provides mountpath and FQN abstractions and methods to resolve/map stored content 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package fs 6 7 import ( 8 "fmt" 9 "io" 10 "os" 11 "path/filepath" 12 "strconv" 13 14 "github.com/NVIDIA/aistore/cmn/cos" 15 ) 16 17 const maxNumCopies = 16 18 19 var ( 20 pid int64 = 0xDEADBEEF // pid of the current process 21 spid = "0xDEADBEEF" // string version of the pid 22 ) 23 24 func init() { 25 pid = int64(os.Getpid()) 26 spid = strconv.FormatInt(pid, 16) 27 28 CSM = &contentSpecMgr{m: make(map[string]ContentResolver, 8)} 29 } 30 31 func IsDirEmpty(dir string) (names []string, empty bool, err error) { 32 var f *os.File 33 f, err = os.Open(dir) 34 if err != nil { 35 return nil, false, err 36 } 37 defer cos.Close(f) 38 39 // Try listing small number of files/dirs to do a quick emptiness check. 40 // If seems empty try a bigger sample to determine if it actually is. 41 for _, limit := range []int{10, 100, 1000, -1} { 42 names, err = f.Readdirnames(limit) 43 if err == io.EOF { 44 return nil, true, nil 45 } 46 if err != nil || len(names) == 0 { 47 return nil, true, err 48 } 49 // Firstly, check if there is any file at this level. 50 dirs := names[:0] 51 for _, sub := range names { 52 subDir := filepath.Join(dir, sub) 53 if finfo, erc := os.Stat(subDir); erc == nil { 54 if !finfo.IsDir() { 55 return names[:min(8, len(names))], false, nil 56 } 57 dirs = append(dirs, subDir) 58 } 59 } 60 // If not, then try to recurse into each directory. 61 for _, subDir := range dirs { 62 if nestedNames, empty, err := IsDirEmpty(subDir); err != nil { 63 return nil, false, err 64 } else if !empty { 65 return nestedNames, false, nil 66 } 67 } 68 // If we've just listed all the files/dirs then exit. 69 if len(names) < limit { 70 break 71 } 72 } 73 return nil, true, nil 74 } 75 76 func ValidateNCopies(tname string, copies int) (err error) { 77 if copies < 1 || copies > maxNumCopies { 78 return fmt.Errorf("%s: invalid num copies %d, must be in [1, %d] range", 79 tname, copies, maxNumCopies) 80 } 81 avail := GetAvail() 82 if num := len(avail); num < copies { 83 return fmt.Errorf("%s: number of copies (%d) exceeds the number of mountpaths (%d)", 84 tname, copies, num) 85 } 86 return nil 87 }