Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9f483ed

Browse files
committed
rewrite watcher impl. to watch dirs
1 parent7edee90 commit9f483ed

File tree

1 file changed

+116
-31
lines changed

1 file changed

+116
-31
lines changed

‎agent/agentcontainers/watcher/watcher.go

Lines changed: 116 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package watcher
88

99
import (
1010
"context"
11+
"path/filepath"
1112
"sync"
1213

1314
"github.com/fsnotify/fsnotify"
@@ -36,32 +37,90 @@ type Watcher interface {
3637

3738
typefsnotifyWatcherstruct {
3839
*fsnotify.Watcher
39-
closeOnce sync.Once
40-
closedchanstruct{}
40+
closedbool
41+
donechanstruct{}
42+
mu sync.Mutex// Protects following.
43+
watchedFilesmap[string]bool// Files being watched (absolute path -> bool).
44+
watchedDirsmap[string]int// Refcount of directories being watched (absolute path -> count).
4145
}
4246

47+
// NewFSNotify creates a new file system watcher that watches parent directories
48+
// instead of individual files for more reliable event detection.
4349
funcNewFSNotify() (Watcher,error) {
4450
w,err:=fsnotify.NewWatcher()
4551
iferr!=nil {
4652
returnnil,xerrors.Errorf("create fsnotify watcher: %w",err)
4753
}
4854
return&fsnotifyWatcher{
49-
Watcher:w,
50-
closed:make(chanstruct{}),
55+
Watcher:w,
56+
done:make(chanstruct{}),
57+
watchedFiles:make(map[string]bool),
58+
watchedDirs:make(map[string]int),
5159
},nil
5260
}
5361

54-
func (f*fsnotifyWatcher)Add(pathstring)error {
55-
iferr:=f.Watcher.Add(path);err!=nil {
56-
returnxerrors.Errorf("add path to watcher: %w",err)
62+
func (f*fsnotifyWatcher)Add(filestring)error {
63+
absPath,err:=filepath.Abs(file)
64+
iferr!=nil {
65+
returnxerrors.Errorf("absolute path: %w",err)
66+
}
67+
68+
dir:=filepath.Dir(absPath)
69+
70+
f.mu.Lock()
71+
deferf.mu.Unlock()
72+
73+
// Already watching this file.
74+
iff.watchedFiles[absPath] {
75+
returnnil
5776
}
77+
78+
// Start watching the parent directory if not already watching.
79+
iff.watchedDirs[dir]==0 {
80+
iferr:=f.Watcher.Add(dir);err!=nil {
81+
returnxerrors.Errorf("add directory to watcher: %w",err)
82+
}
83+
}
84+
85+
// Increment the reference count for this directory.
86+
f.watchedDirs[dir]++
87+
// Mark this file as watched.
88+
f.watchedFiles[absPath]=true
89+
5890
returnnil
5991
}
6092

61-
func (f*fsnotifyWatcher)Remove(pathstring)error {
62-
iferr:=f.Watcher.Remove(path);err!=nil {
63-
returnxerrors.Errorf("remove path from watcher: %w",err)
93+
func (f*fsnotifyWatcher)Remove(filestring)error {
94+
absPath,err:=filepath.Abs(file)
95+
iferr!=nil {
96+
returnxerrors.Errorf("absolute path: %w",err)
6497
}
98+
99+
dir:=filepath.Dir(absPath)
100+
101+
f.mu.Lock()
102+
deferf.mu.Unlock()
103+
104+
// Not watching this file.
105+
if!f.watchedFiles[absPath] {
106+
returnnil
107+
}
108+
109+
// Remove the file from our watch list.
110+
delete(f.watchedFiles,absPath)
111+
112+
// Decrement the reference count for this directory.
113+
f.watchedDirs[dir]--
114+
115+
// If no more files in this directory are being watched, stop
116+
// watching the directory.
117+
iff.watchedDirs[dir]<=0 {
118+
iferr:=f.Watcher.Remove(dir);err!=nil {
119+
returnxerrors.Errorf("remove directory from watcher: %w",err)
120+
}
121+
delete(f.watchedDirs,dir)
122+
}
123+
65124
returnnil
66125
}
67126

@@ -73,31 +132,57 @@ func (f *fsnotifyWatcher) Next(ctx context.Context) (event *fsnotify.Event, err
73132
}
74133
}()
75134

76-
select {
77-
case<-ctx.Done():
78-
returnnil,ctx.Err()
79-
caseevent,ok:=<-f.Events:
80-
if!ok {
81-
returnnil,ErrWatcherClosed
82-
}
83-
return&event,nil
84-
caseerr,ok:=<-f.Errors:
85-
if!ok {
135+
for {
136+
select {
137+
case<-ctx.Done():
138+
returnnil,ctx.Err()
139+
caseevt,ok:=<-f.Events:
140+
if!ok {
141+
returnnil,ErrWatcherClosed
142+
}
143+
144+
// Get the absolute path to match against our watched files.
145+
absPath,err:=filepath.Abs(evt.Name)
146+
iferr!=nil {
147+
continue
148+
}
149+
150+
f.mu.Lock()
151+
isWatched:=f.watchedFiles[absPath]
152+
f.mu.Unlock()
153+
ifisWatched {
154+
return&evt,nil
155+
}
156+
157+
continue// Ignore events for files not being watched.
158+
159+
caseerr,ok:=<-f.Errors:
160+
if!ok {
161+
returnnil,ErrWatcherClosed
162+
}
163+
returnnil,xerrors.Errorf("watcher error: %w",err)
164+
case<-f.done:
86165
returnnil,ErrWatcherClosed
87166
}
88-
returnnil,xerrors.Errorf("watcher error: %w",err)
89-
case<-f.closed:
90-
returnnil,ErrWatcherClosed
91167
}
92168
}
93169

94170
func (f*fsnotifyWatcher)Close() (errerror) {
95-
err=ErrWatcherClosed
96-
f.closeOnce.Do(func() {
97-
iferr=f.Watcher.Close();err!=nil {
98-
err=xerrors.Errorf("close watcher: %w",err)
99-
}
100-
close(f.closed)
101-
})
102-
returnerr
171+
f.mu.Lock()
172+
f.watchedFiles=nil
173+
f.watchedDirs=nil
174+
closed:=f.closed
175+
f.mu.Unlock()
176+
177+
ifclosed {
178+
returnErrWatcherClosed
179+
}
180+
181+
close(f.done)
182+
183+
iferr:=f.Watcher.Close();err!=nil {
184+
returnxerrors.Errorf("close watcher: %w",err)
185+
}
186+
187+
returnnil
103188
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp