-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updates #6711. Squashed commit of the following: commit 3ddfe80 Merge: 185957c d338451 Author: Eugene Burkov <[email protected]> Date: Tue Feb 13 13:01:30 2024 +0300 Merge branch 'master' into 6711-watch-hosts commit 185957c Author: Eugene Burkov <[email protected]> Date: Fri Feb 9 18:11:41 2024 +0300 aghos: imp docs commit 3afbbcb Author: Eugene Burkov <[email protected]> Date: Fri Feb 9 15:40:02 2024 +0300 all: upd golibs, imp fswatcher
- Loading branch information
1 parent
d338451
commit 2a546aa
Showing
18 changed files
with
101 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ import ( | |
|
||
"github.com/AdguardTeam/golibs/errors" | ||
"github.com/AdguardTeam/golibs/log" | ||
"github.com/AdguardTeam/golibs/osutil" | ||
"github.com/AdguardTeam/golibs/stringutil" | ||
"github.com/fsnotify/fsnotify" | ||
) | ||
|
||
|
@@ -18,31 +20,38 @@ type event = struct{} | |
// FSWatcher tracks all the fyle system events and notifies about those. | ||
// | ||
// TODO(e.burkov, a.garipov): Move into another package like aghfs. | ||
// | ||
// TODO(e.burkov): Add tests. | ||
type FSWatcher interface { | ||
// Start starts watching the added files. | ||
Start() (err error) | ||
|
||
// Close stops watching the files and closes an update channel. | ||
io.Closer | ||
|
||
// Events should return a read-only channel which notifies about events. | ||
// Events returns the channel to notify about the file system events. | ||
Events() (e <-chan event) | ||
|
||
// Add should check if the file named name is accessible and starts tracking | ||
// it. | ||
// Add starts tracking the file. It returns an error if the file can't be | ||
// tracked. It must not be called after Start. | ||
Add(name string) (err error) | ||
} | ||
|
||
// osWatcher tracks the file system provided by the OS. | ||
type osWatcher struct { | ||
// w is the actual notifier that is handled by osWatcher. | ||
w *fsnotify.Watcher | ||
// watcher is the actual notifier that is handled by osWatcher. | ||
watcher *fsnotify.Watcher | ||
|
||
// events is the channel to notify. | ||
events chan event | ||
|
||
// files is the set of tracked files. | ||
files *stringutil.Set | ||
} | ||
|
||
const ( | ||
// osWatcherPref is a prefix for logging and wrapping errors in osWathcer's | ||
// methods. | ||
osWatcherPref = "os watcher" | ||
) | ||
// osWatcherPref is a prefix for logging and wrapping errors in osWathcer's | ||
// methods. | ||
const osWatcherPref = "os watcher" | ||
|
||
// NewOSWritesWatcher creates FSWatcher that tracks the real file system of the | ||
// OS and notifies only about writing events. | ||
|
@@ -55,48 +64,58 @@ func NewOSWritesWatcher() (w FSWatcher, err error) { | |
return nil, fmt.Errorf("creating watcher: %w", err) | ||
} | ||
|
||
fsw := &osWatcher{ | ||
w: watcher, | ||
events: make(chan event, 1), | ||
} | ||
return &osWatcher{ | ||
watcher: watcher, | ||
events: make(chan event, 1), | ||
files: stringutil.NewSet(), | ||
}, nil | ||
} | ||
|
||
go fsw.handleErrors() | ||
go fsw.handleEvents() | ||
// type check | ||
var _ FSWatcher = (*osWatcher)(nil) | ||
|
||
return fsw, nil | ||
} | ||
// Start implements the FSWatcher interface for *osWatcher. | ||
func (w *osWatcher) Start() (err error) { | ||
go w.handleErrors() | ||
go w.handleEvents() | ||
|
||
// handleErrors handles accompanying errors. It is intended to be used as a | ||
// goroutine. | ||
func (w *osWatcher) handleErrors() { | ||
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref)) | ||
return nil | ||
} | ||
|
||
for err := range w.w.Errors { | ||
log.Error("%s: %s", osWatcherPref, err) | ||
} | ||
// Close implements the FSWatcher interface for *osWatcher. | ||
func (w *osWatcher) Close() (err error) { | ||
return w.watcher.Close() | ||
} | ||
|
||
// Events implements the FSWatcher interface for *osWatcher. | ||
func (w *osWatcher) Events() (e <-chan event) { | ||
return w.events | ||
} | ||
|
||
// Add implements the FSWatcher interface for *osWatcher. | ||
// Add implements the [FSWatcher] interface for *osWatcher. | ||
// | ||
// TODO(e.burkov): Make it accept non-existing files to detect it's creating. | ||
func (w *osWatcher) Add(name string) (err error) { | ||
defer func() { err = errors.Annotate(err, "%s: %w", osWatcherPref) }() | ||
|
||
if _, err = fs.Stat(RootDirFS(), name); err != nil { | ||
fi, err := fs.Stat(osutil.RootDirFS(), name) | ||
if err != nil { | ||
return fmt.Errorf("checking file %q: %w", name, err) | ||
} | ||
|
||
return w.w.Add(filepath.Join("/", name)) | ||
} | ||
name = filepath.Join("/", name) | ||
w.files.Add(name) | ||
|
||
// Close implements the FSWatcher interface for *osWatcher. | ||
func (w *osWatcher) Close() (err error) { | ||
return w.w.Close() | ||
// Watch the directory and filter the events by the file name, since the | ||
// common recomendation to the fsnotify package is to watch the directory | ||
// instead of the file itself. | ||
// | ||
// See https://pkg.go.dev/github.com/fsnotify/[email protected]#readme-watching-a-file-doesn-t-work-well. | ||
if !fi.IsDir() { | ||
name = filepath.Dir(name) | ||
} | ||
|
||
return w.watcher.Add(name) | ||
} | ||
|
||
// handleEvents notifies about the received file system's event if needed. It | ||
|
@@ -106,9 +125,9 @@ func (w *osWatcher) handleEvents() { | |
|
||
defer close(w.events) | ||
|
||
ch := w.w.Events | ||
ch := w.watcher.Events | ||
for e := range ch { | ||
if e.Op&fsnotify.Write == 0 { | ||
if e.Op&fsnotify.Write == 0 || !w.files.Has(e.Name) { | ||
continue | ||
} | ||
|
||
|
@@ -131,3 +150,13 @@ func (w *osWatcher) handleEvents() { | |
} | ||
} | ||
} | ||
|
||
// handleErrors handles accompanying errors. It used to be called in a separate | ||
// goroutine. | ||
func (w *osWatcher) handleErrors() { | ||
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref)) | ||
|
||
for err := range w.watcher.Errors { | ||
log.Error("%s: %s", osWatcherPref, err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.