github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/fs2objectcache/walk.go (about) 1 package main 2 3 import ( 4 "os" 5 "path" 6 "sync" 7 "syscall" 8 9 "github.com/Cloud-Foundations/Dominator/lib/concurrent" 10 ) 11 12 type stateType struct { 13 sync.Mutex 14 processedInodes map[uint64]struct{} 15 directoriesToRemove []string 16 concurrencyState *concurrent.State 17 } 18 19 func walk(rootDirName, dirName, objectsDir string) error { 20 var state stateType 21 state.processedInodes = make(map[uint64]struct{}) 22 state.directoriesToRemove = make([]string, 0) 23 state.concurrencyState = concurrent.NewState(0) 24 if err := state.walk(rootDirName, dirName, objectsDir); err != nil { 25 return err 26 } 27 if err := state.concurrencyState.Reap(); err != nil { 28 return err 29 } 30 for _, dirname := range state.directoriesToRemove { 31 if err := os.Remove(dirname); err != nil { 32 return err 33 } 34 } 35 return nil 36 } 37 38 func (state *stateType) walk(rootDirName, dirName, objectsDir string) error { 39 file, err := os.Open(path.Join(rootDirName, dirName)) 40 if err != nil { 41 return err 42 } 43 names, err := file.Readdirnames(-1) 44 file.Close() 45 if err != nil { 46 return err 47 } 48 for _, name := range names { 49 if dirName == "/" && name == ".subd" { 50 continue 51 } 52 filename := path.Join(dirName, name) 53 pathname := path.Join(rootDirName, filename) 54 var stat syscall.Stat_t 55 err := syscall.Lstat(pathname, &stat) 56 if err != nil { 57 return err 58 } 59 if stat.Mode&syscall.S_IFMT == syscall.S_IFDIR { 60 err = state.walk(rootDirName, filename, objectsDir) 61 if err == nil { 62 state.directoriesToRemove = append(state.directoriesToRemove, 63 pathname) 64 } 65 } else if stat.Mode&syscall.S_IFMT == syscall.S_IFREG { 66 err = state.concurrencyState.GoRun(func() error { 67 return state.handleFile(pathname, stat.Ino, objectsDir) 68 }) 69 } else { 70 err = os.RemoveAll(pathname) 71 } 72 if err != nil { 73 return err 74 } 75 } 76 return nil 77 } 78 79 func (state *stateType) handleFile(pathname string, inum uint64, 80 objectsDir string) error { 81 state.Lock() 82 if _, ok := state.processedInodes[inum]; ok { 83 state.Unlock() 84 return os.Remove(pathname) 85 } 86 state.processedInodes[inum] = struct{}{} 87 state.Unlock() 88 return convertToObject(pathname, objectsDir) 89 }