Add StopAtEOF to stop tailing when the end of the file is reached

This commit is contained in:
Jonathan Rudenberg 2014-12-24 16:48:29 -05:00
parent 0587510d19
commit 166cd27854
2 changed files with 39 additions and 3 deletions

23
tail.go
View File

@ -4,6 +4,7 @@ package tail
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"github.com/ActiveState/tail/ratelimiter" "github.com/ActiveState/tail/ratelimiter"
"github.com/ActiveState/tail/util" "github.com/ActiveState/tail/util"
@ -136,6 +137,14 @@ func (tail *Tail) Stop() error {
return tail.Wait() return tail.Wait()
} }
// StopAtEOF stops tailing as soon as the end of the file is reached.
func (tail *Tail) StopAtEOF() error {
tail.Kill(errStopAtEOF)
return tail.Wait()
}
var errStopAtEOF = errors.New("tail: stop at eof")
func (tail *Tail) close() { func (tail *Tail) close() {
close(tail.Lines) close(tail.Lines)
if tail.file != nil { if tail.file != nil {
@ -209,6 +218,8 @@ func (tail *Tail) tailFileSync() {
tail.openReader() tail.openReader()
var stopAtEOF bool
// Read line by line. // Read line by line.
for { for {
line, err := tail.readLine() line, err := tail.readLine()
@ -228,14 +239,16 @@ func (tail *Tail) tailFileSync() {
case <-tail.Dying(): case <-tail.Dying():
return return
} }
err = tail.seekEnd() if err := tail.seekEnd(); err != nil {
if err != nil {
tail.Kill(err) tail.Kill(err)
return return
} }
} }
if stopAtEOF && err == io.EOF {
return
}
} else if err == io.EOF { } else if err == io.EOF {
if !tail.Follow { if stopAtEOF || !tail.Follow {
return return
} }
// When EOF is reached, wait for more data to become // When EOF is reached, wait for more data to become
@ -256,6 +269,10 @@ func (tail *Tail) tailFileSync() {
select { select {
case <-tail.Dying(): case <-tail.Dying():
if tail.Err() == errStopAtEOF {
stopAtEOF = true
continue
}
return return
default: default:
} }

View File

@ -54,6 +54,25 @@ func TestStop(t *testing.T) {
Cleanup() Cleanup()
} }
func TestStopAtEOF(_t *testing.T) {
t := NewTailTest("maxlinesize", _t)
t.CreateFile("test.txt", "hello\nthere\nworld\n")
tail := t.StartTail("test.txt", Config{Follow: true, Location: nil})
// read "hello"
<-tail.Lines
done := make(chan struct{})
go func() {
<-time.After(100 * time.Millisecond)
t.VerifyTailOutput(tail, []string{"there", "world"})
close(done)
}()
tail.StopAtEOF()
<-done
Cleanup()
}
func TestMaxLineSize(_t *testing.T) { func TestMaxLineSize(_t *testing.T) {
t := NewTailTest("maxlinesize", _t) t := NewTailTest("maxlinesize", _t)
t.CreateFile("test.txt", "hello\nworld\nfin\nhe") t.CreateFile("test.txt", "hello\nworld\nfin\nhe")