github.com/Cloud-Foundations/Dominator@v0.3.4/lib/fsutil/watchFile_linux.go (about) 1 package fsutil 2 3 import ( 4 "path" 5 "sync" 6 7 "github.com/Cloud-Foundations/Dominator/lib/log" 8 "github.com/fsnotify/fsnotify" 9 ) 10 11 var ( 12 lock sync.RWMutex 13 watchers []*fsnotify.Watcher 14 ) 15 16 func watchFileWithFsNotify(pathname string, logger log.Logger) <-chan struct{} { 17 watcher, err := fsnotify.NewWatcher() 18 if err != nil { 19 logger.Println("Error creating watcher:", err) 20 return nil 21 } 22 lock.Lock() 23 defer lock.Unlock() 24 watchers = append(watchers, watcher) 25 pathname = path.Clean(pathname) 26 dirname := path.Dir(pathname) 27 if err := watcher.Add(dirname); err != nil { 28 logger.Println("Error adding watch:", err) 29 return nil 30 } 31 channel := make(chan struct{}, 1) 32 go waitForNotifyEvents(watcher, pathname, channel, logger) 33 return channel 34 } 35 36 func watchFileStopWithFsNotify() bool { 37 lock.Lock() 38 defer lock.Unlock() 39 // Send cleanup notification to watchers. 40 for _, watcher := range watchers { 41 watcher.Close() 42 } 43 // Wait for cleanup of each watcher. 44 for _, watcher := range watchers { 45 for { 46 if _, ok := <-watcher.Events; !ok { 47 break 48 } 49 } 50 } 51 watchers = nil 52 return true 53 } 54 55 func waitForNotifyEvents(watcher *fsnotify.Watcher, pathname string, 56 channel chan<- struct{}, logger log.Logger) { 57 for { 58 select { 59 case event, ok := <-watcher.Events: 60 if !ok { 61 return 62 } 63 if path.Clean(event.Name) != pathname { 64 continue 65 } 66 channel <- struct{}{} 67 case err, ok := <-watcher.Errors: 68 if !ok { 69 return 70 } 71 logger.Println("Error with watcher:", err) 72 } 73 } 74 }