mirror of
https://github.com/containers/gvisor-tap-vsock.git
synced 2025-09-26 21:01:42 +08:00
Remove filewatcher package
Since #339 was reverted, the filewatcher functionality is no longer used. Signed-off-by: Jan Dubois <jan.dubois@suse.com>
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FileWatcher is an utility that
|
||||
type FileWatcher struct {
|
||||
path string
|
||||
|
||||
closeCh chan struct{}
|
||||
pollInterval time.Duration
|
||||
}
|
||||
|
||||
func NewFileWatcher(path string) *FileWatcher {
|
||||
return &FileWatcher{
|
||||
path: path,
|
||||
pollInterval: 5 * time.Second, // 5s is the default inode cache timeout in linux for most systems.
|
||||
closeCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) Start(changeHandler func()) {
|
||||
prevModTime := fw.fileModTime(fw.path)
|
||||
|
||||
// use polling-based approach to detect file changes
|
||||
// we can't use fsnotify/fsnotify due to issues with symlink+socket. see #462.
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case _, ok := <-fw.closeCh:
|
||||
if !ok {
|
||||
return // watcher is closed.
|
||||
}
|
||||
case <-time.After(fw.pollInterval):
|
||||
}
|
||||
|
||||
modTime := fw.fileModTime(fw.path)
|
||||
if modTime.IsZero() {
|
||||
continue // file does not exists
|
||||
}
|
||||
|
||||
if !prevModTime.Equal(modTime) {
|
||||
changeHandler()
|
||||
prevModTime = modTime
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) fileModTime(path string) time.Time {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
return info.ModTime()
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) Stop() {
|
||||
close(fw.closeCh)
|
||||
}
|
@@ -1,101 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFileWatcher(t *testing.T) {
|
||||
if testing.Short() {
|
||||
// we can't really speed up the test as we need to wait for the
|
||||
// inode cache to expire so that we can read the latest
|
||||
// file's modtime.
|
||||
t.Skip("skipping test in short mode.")
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
assertSpec := func(t *testing.T, watchedPath, filePath string) {
|
||||
t.Helper()
|
||||
|
||||
fw := NewFileWatcher(watchedPath)
|
||||
|
||||
var numTriggered atomic.Int64
|
||||
assertNumTriggered := func(expected int) {
|
||||
time.Sleep(fw.pollInterval + 200*time.Millisecond)
|
||||
assert.Equal(t, int64(expected), numTriggered.Load())
|
||||
}
|
||||
|
||||
fw.Start(func() {
|
||||
numTriggered.Add(1)
|
||||
})
|
||||
|
||||
// important: adding a random sleep here so that the next fw's poll
|
||||
// results in inode cache miss, hence calling stat will return the latest
|
||||
// modtime.
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// CASE: can detect changes to the file.
|
||||
if err := os.WriteFile(filePath, []byte("2"), 0o600); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
assertNumTriggered(1)
|
||||
|
||||
// CASE: can detect "swap"-based file modification.
|
||||
tmpFile := filepath.Join(filepath.Dir(filePath), "tmp.txt")
|
||||
if err := os.WriteFile(tmpFile, []byte("lol"), 0o600); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := os.Rename(tmpFile, filePath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
assertNumTriggered(2)
|
||||
|
||||
// CASE: combine multiple partial writes into single event.
|
||||
fd, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0o600)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// we assume these writes happens in less than 50ms.
|
||||
_, _ = fd.Write([]byte("a"))
|
||||
_ = fd.Sync()
|
||||
_, _ = fd.Write([]byte("b"))
|
||||
fd.Close()
|
||||
assertNumTriggered(3)
|
||||
|
||||
// CASE: closed file watcher should not call the callback after Stop() is called.
|
||||
fw.Stop()
|
||||
if err := os.WriteFile(filePath, []byte("2"), 0o600); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
assertNumTriggered(3) // does not change.
|
||||
|
||||
}
|
||||
|
||||
t.Run("normal file", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "file.txt")
|
||||
_ = os.WriteFile(path, []byte("1"), 0o600)
|
||||
|
||||
assertSpec(t, path, path)
|
||||
})
|
||||
|
||||
t.Run("symlink", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "file.txt")
|
||||
_ = os.WriteFile(path, []byte("1"), 0o600)
|
||||
|
||||
symlinkPath := filepath.Join(dir, "symlink.txt")
|
||||
_ = os.Symlink(path, symlinkPath)
|
||||
|
||||
assertSpec(t, symlinkPath, path)
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user