Lines Matching refs:tail

10 package tail  package
158 func (tail *Tail) Tell() (offset int64, err error) {
159 if tail.file == nil {
162 offset, err = tail.file.Seek(0, io.SeekCurrent)
167 tail.lk.Lock()
168 defer tail.lk.Unlock()
169 if tail.reader == nil {
173 offset -= int64(tail.reader.Buffered())
178 func (tail *Tail) Stop() error {
179 tail.Kill(nil)
180 return tail.Wait()
185 func (tail *Tail) StopAtEOF() error {
186 tail.Kill(errStopAtEOF)
187 return tail.Wait()
192 func (tail *Tail) close() {
193 close(tail.Lines)
194 tail.closeFile()
197 func (tail *Tail) closeFile() {
198 if tail.file != nil {
199 tail.file.Close()
200 tail.file = nil
204 func (tail *Tail) reopen() error {
205 tail.closeFile()
206 tail.lineNum = 0
209 tail.file, err = OpenFile(tail.Filename)
212 tail.Logger.Printf("Waiting for %s to appear...", tail.Filename)
213 if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil {
217 return fmt.Errorf("Failed to detect creation of %s: %s", tail.Filename, err)
221 return fmt.Errorf("Unable to open file %s: %s", tail.Filename, err)
228 func (tail *Tail) readLine() (string, error) {
229 tail.lk.Lock()
230 line, err := tail.reader.ReadString('\n')
231 tail.lk.Unlock()
244 func (tail *Tail) tailFileSync() {
245 defer tail.Done()
246 defer tail.close()
248 if !tail.MustExist {
250 err := tail.reopen()
253 tail.Kill(err)
260 if tail.Location != nil {
261 _, err := tail.file.Seek(tail.Location.Offset, tail.Location.Whence)
263 tail.Killf("Seek error on %s: %s", tail.Filename, err)
268 tail.openReader()
273 if !tail.Pipe {
275 if _, err := tail.Tell(); err != nil {
276 tail.Kill(err)
281 line, err := tail.readLine()
285 cooloff := !tail.sendLine(line)
290 offset, _ := tail.Tell()
291 tail.Lines <- &Line{msg, tail.lineNum, SeekInfo{Offset: offset}, time.Now(), errors.New(msg)}
294 case <-tail.Dying():
297 if err := tail.seekEnd(); err != nil {
298 tail.Kill(err)
303 if !tail.Follow {
305 tail.sendLine(line)
310 if tail.Follow && line != "" {
311 tail.sendLine(line)
312 if err := tail.seekEnd(); err != nil {
313 tail.Kill(err)
321 err := tail.waitForChanges()
324 tail.Kill(err)
330 tail.Killf("Error reading %s: %s", tail.Filename, err)
335 case <-tail.Dying():
336 if tail.Err() == errStopAtEOF {
348 func (tail *Tail) waitForChanges() error {
349 if tail.changes == nil {
350 pos, err := tail.file.Seek(0, io.SeekCurrent)
354 tail.changes, err = tail.watcher.ChangeEvents(&tail.Tomb, pos)
361 case <-tail.changes.Modified:
363 case <-tail.changes.Deleted:
364 tail.changes = nil
365 if tail.ReOpen {
367 tail.Logger.Printf("Re-opening moved/deleted file %s ...", tail.Filename)
368 if err := tail.reopen(); err != nil {
371 tail.Logger.Printf("Successfully reopened %s", tail.Filename)
372 tail.openReader()
375 tail.Logger.Printf("Stopping tail as file no longer exists: %s", tail.Filename)
377 case <-tail.changes.Truncated:
379 tail.Logger.Printf("Re-opening truncated file %s ...", tail.Filename)
380 if err := tail.reopen(); err != nil {
383 tail.Logger.Printf("Successfully reopened truncated %s", tail.Filename)
384 tail.openReader()
386 case <-tail.Dying():
391 func (tail *Tail) openReader() {
392 tail.lk.Lock()
393 if tail.MaxLineSize > 0 {
395 tail.reader = bufio.NewReaderSize(tail.file, tail.MaxLineSize+2)
397 tail.reader = bufio.NewReader(tail.file)
399 tail.lk.Unlock()
402 func (tail *Tail) seekEnd() error {
403 return tail.seekTo(SeekInfo{Offset: 0, Whence: io.SeekEnd})
406 func (tail *Tail) seekTo(pos SeekInfo) error {
407 _, err := tail.file.Seek(pos.Offset, pos.Whence)
409 return fmt.Errorf("Seek error on %s: %s", tail.Filename, err)
412 tail.reader.Reset(tail.file)
418 func (tail *Tail) sendLine(line string) bool {
423 if tail.MaxLineSize > 0 && len(line) > tail.MaxLineSize {
424 lines = util.PartitionString(line, tail.MaxLineSize)
428 tail.lineNum++
429 offset, _ := tail.Tell()
431 case tail.Lines <- &Line{line, tail.lineNum, SeekInfo{Offset: offset}, now, nil}:
432 case <-tail.Dying():
437 if tail.Config.RateLimiter != nil {
438 ok := tail.Config.RateLimiter.Pour(uint16(len(lines)))
440 tail.Logger.Printf("Leaky bucket full (%v); entering 1s cooloff period.",
441 tail.Filename)
453 func (tail *Tail) Cleanup() {
454 watch.Cleanup(tail.Filename)