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

Commit9cf5415

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

File tree

1 file changed

+117
-31
lines changed

1 file changed

+117
-31
lines changed

‎agent/agentcontainers/watcher/watcher.go

Lines changed: 117 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,91 @@ type Watcher interface {
3637

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

48+
// NewFSNotify creates a new file system watcher that watches parent directories
49+
// instead of individual files for more reliable event detection.
4350
funcNewFSNotify() (Watcher,error) {
4451
w,err:=fsnotify.NewWatcher()
4552
iferr!=nil {
4653
returnnil,xerrors.Errorf("create fsnotify watcher: %w",err)
4754
}
4855
return&fsnotifyWatcher{
49-
Watcher:w,
50-
closed:make(chanstruct{}),
56+
Watcher:w,
57+
done:make(chanstruct{}),
58+
watchedFiles:make(map[string]bool),
59+
watchedDirs:make(map[string]int),
5160
},nil
5261
}
5362

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

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

@@ -73,31 +133,57 @@ func (f *fsnotifyWatcher) Next(ctx context.Context) (event *fsnotify.Event, err
73133
}
74134
}()
75135

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 {
136+
for {
137+
select {
138+
case<-ctx.Done():
139+
returnnil,ctx.Err()
140+
caseevt,ok:=<-f.Events:
141+
if!ok {
142+
returnnil,ErrWatcherClosed
143+
}
144+
145+
// Get the absolute path to match against our watched files.
146+
absPath,err:=filepath.Abs(evt.Name)
147+
iferr!=nil {
148+
continue
149+
}
150+
151+
f.mu.Lock()
152+
isWatched:=f.watchedFiles[absPath]
153+
f.mu.Unlock()
154+
ifisWatched {
155+
return&evt,nil
156+
}
157+
158+
continue// Ignore events for files not being watched.
159+
160+
caseerr,ok:=<-f.Errors:
161+
if!ok {
162+
returnnil,ErrWatcherClosed
163+
}
164+
returnnil,xerrors.Errorf("watcher error: %w",err)
165+
case<-f.done:
86166
returnnil,ErrWatcherClosed
87167
}
88-
returnnil,xerrors.Errorf("watcher error: %w",err)
89-
case<-f.closed:
90-
returnnil,ErrWatcherClosed
91168
}
92169
}
93170

94171
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
172+
f.mu.Lock()
173+
f.watchedFiles=nil
174+
f.watchedDirs=nil
175+
closed:=f.closed
176+
f.mu.Unlock()
177+
178+
ifclosed {
179+
returnErrWatcherClosed
180+
}
181+
182+
close(f.done)
183+
184+
iferr:=f.Watcher.Close();err!=nil {
185+
returnxerrors.Errorf("close watcher: %w",err)
186+
}
187+
188+
returnnil
103189
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp