From 035761b7bcc07b2702c7b00d48b1c12a26483414 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Wed, 1 Jul 2015 17:15:15 +0200 Subject: [PATCH 1/4] one watcher --- watch/inotify.go | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/watch/inotify.go b/watch/inotify.go index c134b37..94a2cec 100644 --- a/watch/inotify.go +++ b/watch/inotify.go @@ -4,11 +4,12 @@ package watch import ( "fmt" + "os" + "path/filepath" + "github.com/ActiveState/tail/util" "gopkg.in/fsnotify.v0" "gopkg.in/tomb.v1" - "os" - "path/filepath" ) var inotifyTracker *InotifyTracker @@ -17,27 +18,23 @@ var inotifyTracker *InotifyTracker type InotifyFileWatcher struct { Filename string Size int64 + w *fsnotify.Watcher } -func NewInotifyFileWatcher(filename string) *InotifyFileWatcher { - fw := &InotifyFileWatcher{filename, 0} +func NewInotifyFileWatcher(filename string, w *fsnotify.Watcher) *InotifyFileWatcher { + fw := &InotifyFileWatcher{filename, 0, w} return fw } func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { - w, err := inotifyTracker.NewWatcher() - if err != nil { - return err - } - defer inotifyTracker.CloseWatcher(w) - dirname := filepath.Dir(fw.Filename) // Watch for new files to be created in the parent directory. - err = w.WatchFlags(dirname, fsnotify.FSN_CREATE) + err := fw.w.WatchFlags(dirname, fsnotify.FSN_CREATE) if err != nil { return err } + defer fw.w.RemoveWatch(dirname) // Do a real check now as the file might have been created before // calling `WatchFlags` above. @@ -48,7 +45,7 @@ func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { for { select { - case evt, ok := <-w.Event: + case evt, ok := <-fw.w.Event: if !ok { return fmt.Errorf("inotify watcher has been closed") } else if evt.Name == fw.Filename { @@ -64,11 +61,7 @@ func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileChanges { changes := NewFileChanges() - w, err := inotifyTracker.NewWatcher() - if err != nil { - util.Fatal("Error creating fsnotify watcher: %v", err) - } - err = w.Watch(fw.Filename) + err := fw.w.Watch(fw.Filename) if err != nil { util.Fatal("Error watching %v: %v", fw.Filename, err) } @@ -76,7 +69,7 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileCh fw.Size = fi.Size() go func() { - defer inotifyTracker.CloseWatcher(w) + defer fw.w.RemoveWatch(fw.Filename) defer changes.Close() for { @@ -86,7 +79,7 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileCh var ok bool select { - case evt, ok = <-w.Event: + case evt, ok = <-fw.w.Event: if !ok { return } @@ -126,11 +119,3 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileCh return changes } - -func Cleanup() { - inotifyTracker.CloseAll() -} - -func init() { - inotifyTracker = NewInotifyTracker() -} From f96904ede78b6f21607cd6658222222a19665376 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Fri, 3 Jul 2015 16:51:41 +0200 Subject: [PATCH 2/4] go fmt --- tail.go | 9 +++++---- tail_test.go | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tail.go b/tail.go index 14f33a3..d746f4a 100644 --- a/tail.go +++ b/tail.go @@ -5,16 +5,17 @@ package tail import ( "bufio" "fmt" - "github.com/ActiveState/tail/ratelimiter" - "github.com/ActiveState/tail/util" - "github.com/ActiveState/tail/watch" - "gopkg.in/tomb.v1" "io" "io/ioutil" "log" "os" "strings" "time" + + "github.com/ActiveState/tail/ratelimiter" + "github.com/ActiveState/tail/util" + "github.com/ActiveState/tail/watch" + "gopkg.in/tomb.v1" ) var ( diff --git a/tail_test.go b/tail_test.go index c20e2b6..ffac3b5 100644 --- a/tail_test.go +++ b/tail_test.go @@ -6,14 +6,15 @@ package tail import ( - "./watch" _ "fmt" - "github.com/ActiveState/tail/ratelimiter" "io/ioutil" "os" "strings" "testing" "time" + + "./watch" + "github.com/ActiveState/tail/ratelimiter" ) func init() { From 48bc495430fa2f5fd444d26148874827a78651e0 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Fri, 3 Jul 2015 16:53:13 +0200 Subject: [PATCH 3/4] minor --- watch/inotify.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/watch/inotify.go b/watch/inotify.go index 94a2cec..f263b56 100644 --- a/watch/inotify.go +++ b/watch/inotify.go @@ -12,8 +12,6 @@ import ( "gopkg.in/tomb.v1" ) -var inotifyTracker *InotifyTracker - // InotifyFileWatcher uses inotify to monitor file changes. type InotifyFileWatcher struct { Filename string From 244ac5d165b8b545611925072a4c84a754600700 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Fri, 3 Jul 2015 16:53:42 +0200 Subject: [PATCH 4/4] use the single tracker instance --- tail.go | 15 ++++++++++++--- tail_test.go | 26 +++++++++++++------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/tail.go b/tail.go index d746f4a..93d40b7 100644 --- a/tail.go +++ b/tail.go @@ -64,6 +64,8 @@ type Tail struct { file *os.File reader *bufio.Reader + tracker *watch.InotifyTracker + watcher watch.FileWatcher changes *watch.FileChanges @@ -100,7 +102,12 @@ func TailFile(filename string, config Config) (*Tail, error) { if t.Poll { t.watcher = watch.NewPollingFileWatcher(filename) } else { - t.watcher = watch.NewInotifyFileWatcher(filename) + t.tracker = watch.NewInotifyTracker() + w, err := t.tracker.NewWatcher() + if err != nil { + return nil, err + } + t.watcher = watch.NewInotifyFileWatcher(filename, w) } if t.MustExist { @@ -382,6 +389,8 @@ func (tail *Tail) sendLine(line string) bool { // Cleanup removes inotify watches added by the tail package. This function is // meant to be invoked from a process's exit handler. Linux kernel may not // automatically remove inotify watches after the process exits. -func Cleanup() { - watch.Cleanup() +func (tail *Tail) Cleanup() { + if tail.tracker != nil { + tail.tracker.CloseAll() + } } diff --git a/tail_test.go b/tail_test.go index ffac3b5..6095f4f 100644 --- a/tail_test.go +++ b/tail_test.go @@ -41,7 +41,7 @@ func TestMustExist(t *testing.T) { t.Error("MustExist:true on an existing file is violated") } tail.Stop() - Cleanup() + tail.Cleanup() } func TestStop(t *testing.T) { @@ -52,7 +52,7 @@ func TestStop(t *testing.T) { if tail.Stop() != nil { t.Error("Should be stoped successfully") } - Cleanup() + tail.Cleanup() } func MaxLineSizeT(_t *testing.T, follow bool, fileContent string, expected []string) { @@ -66,7 +66,7 @@ func MaxLineSizeT(_t *testing.T, follow bool, fileContent string, expected []str <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") tail.Stop() - Cleanup() + tail.Cleanup() } func TestMaxLineSizeFollow(_t *testing.T) { @@ -90,7 +90,7 @@ func TestOver4096ByteLine(_t *testing.T) { <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") tail.Stop() - Cleanup() + tail.Cleanup() } func TestOver4096ByteLineWithSetMaxLineSize(_t *testing.T) { t := NewTailTest("Over4096ByteLineMaxLineSize", _t) @@ -104,7 +104,7 @@ func TestOver4096ByteLineWithSetMaxLineSize(_t *testing.T) { <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") // tail.Stop() - Cleanup() + tail.Cleanup() } func TestLocationFull(_t *testing.T) { @@ -118,7 +118,7 @@ func TestLocationFull(_t *testing.T) { <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") tail.Stop() - Cleanup() + tail.Cleanup() } func TestLocationFullDontFollow(_t *testing.T) { @@ -133,7 +133,7 @@ func TestLocationFullDontFollow(_t *testing.T) { <-time.After(100 * time.Millisecond) tail.Stop() - Cleanup() + tail.Cleanup() } func TestLocationEnd(_t *testing.T) { @@ -150,7 +150,7 @@ func TestLocationEnd(_t *testing.T) { <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") tail.Stop() - Cleanup() + tail.Cleanup() } func TestLocationMiddle(_t *testing.T) { @@ -168,7 +168,7 @@ func TestLocationMiddle(_t *testing.T) { <-time.After(100 * time.Millisecond) t.RemoveFile("test.txt") tail.Stop() - Cleanup() + tail.Cleanup() } func _TestReOpen(_t *testing.T, poll bool) { @@ -211,7 +211,7 @@ func _TestReOpen(_t *testing.T, poll bool) { // the reading of data written above. Timings can vary based on // test environment. // tail.Stop() - Cleanup() + tail.Cleanup() } // The use of polling file watcher could affect file rotation @@ -254,7 +254,7 @@ func _TestReSeek(_t *testing.T, poll bool) { // the reading of data written above. Timings can vary based on // test environment. // tail.Stop() - Cleanup() + tail.Cleanup() } // The use of polling file watcher could affect file rotation @@ -294,7 +294,7 @@ func TestRateLimiting(_t *testing.T) { t.RemoveFile("test.txt") // tail.Stop() - Cleanup() + tail.Cleanup() } func TestTell(_t *testing.T) { @@ -328,7 +328,7 @@ func TestTell(_t *testing.T) { } t.RemoveFile("test.txt") tail.Done() - Cleanup() + tail.Cleanup() } // Test library