aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorCory Snider <csnider@mirantis.com>2022-02-23 17:48:10 -0500
committerCory Snider <csnider@mirantis.com>2022-05-19 15:23:18 -0400
commitc609523a8c006fdd404a8b99be2567401c3ec1b9 (patch)
treee4bc56356251386b21b47cd62f4cfc2920307ad5 /pkg
parent01915a725e8c1e8738150ef99463966e699de532 (diff)
pkg/filenotify: delete unused package
Signed-off-by: Cory Snider <csnider@mirantis.com>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/filenotify/filenotify.go40
-rw-r--r--pkg/filenotify/fsnotify.go18
-rw-r--r--pkg/filenotify/poller.go213
-rw-r--r--pkg/filenotify/poller_test.go131
4 files changed, 0 insertions, 402 deletions
diff --git a/pkg/filenotify/filenotify.go b/pkg/filenotify/filenotify.go
deleted file mode 100644
index 8b6cb56f17..0000000000
--- a/pkg/filenotify/filenotify.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Package filenotify provides a mechanism for watching file(s) for changes.
-// Generally leans on fsnotify, but provides a poll-based notifier which fsnotify does not support.
-// These are wrapped up in a common interface so that either can be used interchangeably in your code.
-package filenotify // import "github.com/docker/docker/pkg/filenotify"
-
-import "github.com/fsnotify/fsnotify"
-
-// FileWatcher is an interface for implementing file notification watchers
-type FileWatcher interface {
- Events() <-chan fsnotify.Event
- Errors() <-chan error
- Add(name string) error
- Remove(name string) error
- Close() error
-}
-
-// New tries to use an fs-event watcher, and falls back to the poller if there is an error
-func New() (FileWatcher, error) {
- if watcher, err := NewEventWatcher(); err == nil {
- return watcher, nil
- }
- return NewPollingWatcher(), nil
-}
-
-// NewPollingWatcher returns a poll-based file watcher
-func NewPollingWatcher() FileWatcher {
- return &filePoller{
- events: make(chan fsnotify.Event),
- errors: make(chan error),
- }
-}
-
-// NewEventWatcher returns an fs-event based file watcher
-func NewEventWatcher() (FileWatcher, error) {
- watcher, err := fsnotify.NewWatcher()
- if err != nil {
- return nil, err
- }
- return &fsNotifyWatcher{watcher}, nil
-}
diff --git a/pkg/filenotify/fsnotify.go b/pkg/filenotify/fsnotify.go
deleted file mode 100644
index 5a737d6530..0000000000
--- a/pkg/filenotify/fsnotify.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package filenotify // import "github.com/docker/docker/pkg/filenotify"
-
-import "github.com/fsnotify/fsnotify"
-
-// fsNotifyWatcher wraps the fsnotify package to satisfy the FileNotifier interface
-type fsNotifyWatcher struct {
- *fsnotify.Watcher
-}
-
-// Events returns the fsnotify event channel receiver
-func (w *fsNotifyWatcher) Events() <-chan fsnotify.Event {
- return w.Watcher.Events
-}
-
-// Errors returns the fsnotify error channel receiver
-func (w *fsNotifyWatcher) Errors() <-chan error {
- return w.Watcher.Errors
-}
diff --git a/pkg/filenotify/poller.go b/pkg/filenotify/poller.go
deleted file mode 100644
index 01ef057981..0000000000
--- a/pkg/filenotify/poller.go
+++ /dev/null
@@ -1,213 +0,0 @@
-package filenotify // import "github.com/docker/docker/pkg/filenotify"
-
-import (
- "errors"
- "fmt"
- "os"
- "sync"
- "time"
-
- "github.com/sirupsen/logrus"
-
- "github.com/fsnotify/fsnotify"
-)
-
-var (
- // errPollerClosed is returned when the poller is closed
- errPollerClosed = errors.New("poller is closed")
- // errNoSuchWatch is returned when trying to remove a watch that doesn't exist
- errNoSuchWatch = errors.New("watch does not exist")
-)
-
-// watchWaitTime is the time to wait between file poll loops
-const watchWaitTime = 200 * time.Millisecond
-
-// filePoller is used to poll files for changes, especially in cases where fsnotify
-// can't be run (e.g. when inotify handles are exhausted)
-// filePoller satisfies the FileWatcher interface
-type filePoller struct {
- // watches is the list of files currently being polled, close the associated channel to stop the watch
- watches map[string]chan struct{}
- // events is the channel to listen to for watch events
- events chan fsnotify.Event
- // errors is the channel to listen to for watch errors
- errors chan error
- // mu locks the poller for modification
- mu sync.Mutex
- // closed is used to specify when the poller has already closed
- closed bool
-}
-
-// Add adds a filename to the list of watches
-// once added the file is polled for changes in a separate goroutine
-func (w *filePoller) Add(name string) error {
- w.mu.Lock()
- defer w.mu.Unlock()
-
- if w.closed {
- return errPollerClosed
- }
-
- f, err := os.Open(name)
- if err != nil {
- return err
- }
- fi, err := os.Stat(name)
- if err != nil {
- f.Close()
- return err
- }
-
- if w.watches == nil {
- w.watches = make(map[string]chan struct{})
- }
- if _, exists := w.watches[name]; exists {
- f.Close()
- return fmt.Errorf("watch exists")
- }
- chClose := make(chan struct{})
- w.watches[name] = chClose
-
- go w.watch(f, fi, chClose)
- return nil
-}
-
-// Remove stops and removes watch with the specified name
-func (w *filePoller) Remove(name string) error {
- w.mu.Lock()
- defer w.mu.Unlock()
- return w.remove(name)
-}
-
-func (w *filePoller) remove(name string) error {
- if w.closed {
- return errPollerClosed
- }
-
- chClose, exists := w.watches[name]
- if !exists {
- return errNoSuchWatch
- }
- close(chClose)
- delete(w.watches, name)
- return nil
-}
-
-// Events returns the event channel
-// This is used for notifications on events about watched files
-func (w *filePoller) Events() <-chan fsnotify.Event {
- return w.events
-}
-
-// Errors returns the errors channel
-// This is used for notifications about errors on watched files
-func (w *filePoller) Errors() <-chan error {
- return w.errors
-}
-
-// Close closes the poller
-// All watches are stopped, removed, and the poller cannot be added to
-func (w *filePoller) Close() error {
- w.mu.Lock()
- defer w.mu.Unlock()
-
- if w.closed {
- return nil
- }
-
- for name := range w.watches {
- w.remove(name)
- }
- w.closed = true
- return nil
-}
-
-// sendEvent publishes the specified event to the events channel
-func (w *filePoller) sendEvent(e fsnotify.Event, chClose <-chan struct{}) error {
- select {
- case w.events <- e:
- case <-chClose:
- return fmt.Errorf("closed")
- }
- return nil
-}
-
-// sendErr publishes the specified error to the errors channel
-func (w *filePoller) sendErr(e error, chClose <-chan struct{}) error {
- select {
- case w.errors <- e:
- case <-chClose:
- return fmt.Errorf("closed")
- }
- return nil
-}
-
-// watch is responsible for polling the specified file for changes
-// upon finding changes to a file or errors, sendEvent/sendErr is called
-func (w *filePoller) watch(f *os.File, lastFi os.FileInfo, chClose chan struct{}) {
- defer f.Close()
-
- timer := time.NewTimer(watchWaitTime)
- if !timer.Stop() {
- <-timer.C
- }
- defer timer.Stop()
-
- for {
- timer.Reset(watchWaitTime)
-
- select {
- case <-timer.C:
- case <-chClose:
- logrus.Debugf("watch for %s closed", f.Name())
- return
- }
-
- fi, err := os.Stat(f.Name())
- if err != nil {
- // if we got an error here and lastFi is not set, we can presume that nothing has changed
- // This should be safe since before `watch()` is called, a stat is performed, there is any error `watch` is not called
- if lastFi == nil {
- continue
- }
- // If it doesn't exist at this point, it must have been removed
- // no need to send the error here since this is a valid operation
- if os.IsNotExist(err) {
- if err := w.sendEvent(fsnotify.Event{Op: fsnotify.Remove, Name: f.Name()}, chClose); err != nil {
- return
- }
- lastFi = nil
- continue
- }
- // at this point, send the error
- if err := w.sendErr(err, chClose); err != nil {
- return
- }
- continue
- }
-
- if lastFi == nil {
- if err := w.sendEvent(fsnotify.Event{Op: fsnotify.Create, Name: fi.Name()}, chClose); err != nil {
- return
- }
- lastFi = fi
- continue
- }
-
- if fi.Mode() != lastFi.Mode() {
- if err := w.sendEvent(fsnotify.Event{Op: fsnotify.Chmod, Name: fi.Name()}, chClose); err != nil {
- return
- }
- lastFi = fi
- continue
- }
-
- if fi.ModTime() != lastFi.ModTime() || fi.Size() != lastFi.Size() {
- if err := w.sendEvent(fsnotify.Event{Op: fsnotify.Write, Name: fi.Name()}, chClose); err != nil {
- return
- }
- lastFi = fi
- continue
- }
- }
-}
diff --git a/pkg/filenotify/poller_test.go b/pkg/filenotify/poller_test.go
deleted file mode 100644
index 53ec7b8508..0000000000
--- a/pkg/filenotify/poller_test.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package filenotify // import "github.com/docker/docker/pkg/filenotify"
-
-import (
- "fmt"
- "os"
- "runtime"
- "testing"
- "time"
-
- "github.com/fsnotify/fsnotify"
-)
-
-func TestPollerAddRemove(t *testing.T) {
- w := NewPollingWatcher()
-
- if err := w.Add("no-such-file"); err == nil {
- t.Fatal("should have gotten error when adding a non-existent file")
- }
- if err := w.Remove("no-such-file"); err == nil {
- t.Fatal("should have gotten error when removing non-existent watch")
- }
-
- f, err := os.CreateTemp("", "asdf")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(f.Name())
-
- if err := w.Add(f.Name()); err != nil {
- t.Fatal(err)
- }
-
- if err := w.Remove(f.Name()); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestPollerEvent(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("No chmod on Windows")
- }
- w := NewPollingWatcher()
-
- f, err := os.CreateTemp("", "test-poller")
- if err != nil {
- t.Fatal("error creating temp file")
- }
- defer os.RemoveAll(f.Name())
- f.Close()
-
- if err := w.Add(f.Name()); err != nil {
- t.Fatal(err)
- }
-
- select {
- case <-w.Events():
- t.Fatal("got event before anything happened")
- case <-w.Errors():
- t.Fatal("got error before anything happened")
- default:
- }
-
- if err := os.WriteFile(f.Name(), []byte("hello"), 0600); err != nil {
- t.Fatal(err)
- }
- assertFileMode(t, f.Name(), 0600)
- if err := assertEvent(w, fsnotify.Write); err != nil {
- t.Fatal(err)
- }
-
- if err := os.Chmod(f.Name(), 0644); err != nil {
- t.Fatal(err)
- }
- assertFileMode(t, f.Name(), 0644)
- if err := assertEvent(w, fsnotify.Chmod); err != nil {
- t.Fatal(err)
- }
-
- if err := os.Remove(f.Name()); err != nil {
- t.Fatal(err)
- }
- if err := assertEvent(w, fsnotify.Remove); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestPollerClose(t *testing.T) {
- w := NewPollingWatcher()
- if err := w.Close(); err != nil {
- t.Fatal(err)
- }
- // test double-close
- if err := w.Close(); err != nil {
- t.Fatal(err)
- }
-
- f, err := os.CreateTemp("", "asdf")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(f.Name())
- if err := w.Add(f.Name()); err == nil {
- t.Fatal("should have gotten error adding watch for closed watcher")
- }
-}
-
-func assertFileMode(t *testing.T, fileName string, mode uint32) {
- t.Helper()
- f, err := os.Stat(fileName)
- if err != nil {
- t.Fatal(err)
- }
- if f.Mode() != os.FileMode(mode) {
- t.Fatalf("expected file %s to have mode %#o, but got %#o", fileName, mode, f.Mode())
- }
-}
-
-func assertEvent(w FileWatcher, eType fsnotify.Op) error {
- var err error
- select {
- case e := <-w.Events():
- if e.Op != eType {
- err = fmt.Errorf("got wrong event type, expected %q: %v", eType, e.Op)
- }
- case e := <-w.Errors():
- err = fmt.Errorf("got unexpected error waiting for events %v: %v", eType, e)
- case <-time.After(watchWaitTime * 3):
- err = fmt.Errorf("timeout waiting for event %v", eType)
- }
- return err
-}