Merge pull request #1290 from timstclair/tail
Cleanup tail util from #1264
This commit is contained in:
commit
18e56007c1
@ -27,16 +27,10 @@ import (
|
|||||||
"golang.org/x/exp/inotify"
|
"golang.org/x/exp/inotify"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
readerStateOpening = 1 << iota
|
|
||||||
readerStateOpened
|
|
||||||
readerStateError
|
|
||||||
)
|
|
||||||
|
|
||||||
type Tail struct {
|
type Tail struct {
|
||||||
reader *bufio.Reader
|
reader *bufio.Reader
|
||||||
readerState int
|
readerErr error
|
||||||
readerLock sync.Mutex
|
readerLock sync.RWMutex
|
||||||
filename string
|
filename string
|
||||||
file *os.File
|
file *os.File
|
||||||
stop chan bool
|
stop chan bool
|
||||||
@ -57,20 +51,16 @@ func NewTail(filename string) (*Tail, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("inotify init failed on %s: %v", t.filename, err)
|
return nil, fmt.Errorf("inotify init failed on %s: %v", t.filename, err)
|
||||||
}
|
}
|
||||||
t.readerState = readerStateOpening
|
|
||||||
go t.watchLoop()
|
go t.watchLoop()
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read implements the io.Reader interface for Tail
|
// Read implements the io.Reader interface for Tail
|
||||||
func (t *Tail) Read(p []byte) (int, error) {
|
func (t *Tail) Read(p []byte) (int, error) {
|
||||||
t.readerLock.Lock()
|
t.readerLock.RLock()
|
||||||
defer t.readerLock.Unlock()
|
defer t.readerLock.RUnlock()
|
||||||
if t.reader == nil {
|
if t.reader == nil || t.readerErr != nil {
|
||||||
if t.readerState == readerStateOpening {
|
return 0, t.readerErr
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("can't open log file %s", t.filename)
|
|
||||||
}
|
}
|
||||||
return t.reader.Read(p)
|
return t.reader.Read(p)
|
||||||
}
|
}
|
||||||
@ -100,27 +90,30 @@ func (t *Tail) fileChanged() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tail) attemptOpen() (err error) {
|
func (t *Tail) attemptOpen() error {
|
||||||
t.readerLock.Lock()
|
t.readerLock.Lock()
|
||||||
defer t.readerLock.Unlock()
|
defer t.readerLock.Unlock()
|
||||||
|
t.reader = nil
|
||||||
|
t.readerErr = nil
|
||||||
for attempt := 1; attempt <= maxOpenAttempts; attempt++ {
|
for attempt := 1; attempt <= maxOpenAttempts; attempt++ {
|
||||||
glog.V(4).Infof("Opening %s (attempt %d of %d)", t.filename, attempt, maxOpenAttempts)
|
glog.V(4).Infof("Opening %s (attempt %d of %d)", t.filename, attempt, maxOpenAttempts)
|
||||||
|
var err error
|
||||||
t.file, err = os.Open(t.filename)
|
t.file, err = os.Open(t.filename)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// TODO: not interested in old events?
|
// TODO: not interested in old events?
|
||||||
//t.file.Seek(0, os.SEEK_END)
|
//t.file.Seek(0, os.SEEK_END)
|
||||||
t.reader = bufio.NewReader(t.file)
|
t.reader = bufio.NewReader(t.file)
|
||||||
t.readerState = readerStateOpened
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-time.After(retryOpenInterval):
|
case <-time.After(retryOpenInterval):
|
||||||
case <-t.stop:
|
case <-t.stop:
|
||||||
t.readerState = readerStateError
|
t.readerErr = io.EOF
|
||||||
return fmt.Errorf("watch was cancelled")
|
return fmt.Errorf("watch was cancelled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.readerState = readerStateError
|
err := fmt.Errorf("can't open log file %s", t.filename)
|
||||||
|
t.readerErr = err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +143,5 @@ func (t *Tail) watchFile() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(4).Infof("Log file %s moved/deleted", t.filename)
|
glog.V(4).Infof("Log file %s moved/deleted", t.filename)
|
||||||
t.readerLock.Lock()
|
|
||||||
defer t.readerLock.Unlock()
|
|
||||||
t.readerState = readerStateOpening
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user