Lines Matching refs:tail

4 package tail  package
145 func (tail *Tail) Tell() (offset int64, err error) {
146 if tail.file == nil {
149 offset, err = tail.file.Seek(0, io.SeekCurrent)
154 tail.lk.Lock()
155 defer tail.lk.Unlock()
156 if tail.reader == nil {
160 offset -= int64(tail.reader.Buffered())
165 func (tail *Tail) Stop() error {
166 tail.Kill(nil)
167 return tail.Wait()
171 func (tail *Tail) StopAtEOF() error {
172 tail.Kill(errStopAtEOF)
173 return tail.Wait()
178 func (tail *Tail) close() {
179 close(tail.Lines)
180 tail.closeFile()
183 func (tail *Tail) closeFile() {
184 if tail.file != nil {
185 tail.file.Close()
186 tail.file = nil
190 func (tail *Tail) reopen() error {
191 tail.closeFile()
192 tail.lineNum = 0
195 tail.file, err = OpenFile(tail.Filename)
198 tail.Logger.Printf("Waiting for %s to appear...", tail.Filename)
199 if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil {
203 return fmt.Errorf("Failed to detect creation of %s: %s", tail.Filename, err)
207 return fmt.Errorf("Unable to open file %s: %s", tail.Filename, err)
214 func (tail *Tail) readLine() (string, error) {
215 tail.lk.Lock()
216 line, err := tail.reader.ReadString('\n')
217 tail.lk.Unlock()
230 func (tail *Tail) tailFileSync() {
231 defer tail.Done()
232 defer tail.close()
234 if !tail.MustExist {
236 err := tail.reopen()
239 tail.Kill(err)
246 if tail.Location != nil {
247 _, err := tail.file.Seek(tail.Location.Offset, tail.Location.Whence)
249 tail.Killf("Seek error on %s: %s", tail.Filename, err)
254 tail.openReader()
259 if !tail.Pipe {
261 if _, err := tail.Tell(); err != nil {
262 tail.Kill(err)
267 line, err := tail.readLine()
271 cooloff := !tail.sendLine(line)
276 offset, _ := tail.Tell()
277 tail.Lines <- &Line{msg, tail.lineNum, SeekInfo{Offset: offset}, time.Now(), errors.New(msg)}
280 case <-tail.Dying():
283 if err := tail.seekEnd(); err != nil {
284 tail.Kill(err)
289 if !tail.Follow {
291 tail.sendLine(line)
296 if tail.Follow && line != "" {
297 tail.sendLine(line)
298 if err := tail.seekEnd(); err != nil {
299 tail.Kill(err)
307 err := tail.waitForChanges()
310 tail.Kill(err)
316 tail.Killf("Error reading %s: %s", tail.Filename, err)
321 case <-tail.Dying():
322 if tail.Err() == errStopAtEOF {
334 func (tail *Tail) waitForChanges() error {
335 if tail.changes == nil {
336 pos, err := tail.file.Seek(0, io.SeekCurrent)
340 tail.changes, err = tail.watcher.ChangeEvents(&tail.Tomb, pos)
347 case <-tail.changes.Modified:
349 case <-tail.changes.Deleted:
350 tail.changes = nil
351 if tail.ReOpen {
353 tail.Logger.Printf("Re-opening moved/deleted file %s ...", tail.Filename)
354 if err := tail.reopen(); err != nil {
357 tail.Logger.Printf("Successfully reopened %s", tail.Filename)
358 tail.openReader()
361 tail.Logger.Printf("Stopping tail as file no longer exists: %s", tail.Filename)
363 case <-tail.changes.Truncated:
365 tail.Logger.Printf("Re-opening truncated file %s ...", tail.Filename)
366 if err := tail.reopen(); err != nil {
369 tail.Logger.Printf("Successfully reopened truncated %s", tail.Filename)
370 tail.openReader()
372 case <-tail.Dying():
377 func (tail *Tail) openReader() {
378 tail.lk.Lock()
379 if tail.MaxLineSize > 0 {
381 tail.reader = bufio.NewReaderSize(tail.file, tail.MaxLineSize+2)
383 tail.reader = bufio.NewReader(tail.file)
385 tail.lk.Unlock()
388 func (tail *Tail) seekEnd() error {
389 return tail.seekTo(SeekInfo{Offset: 0, Whence: io.SeekEnd})
392 func (tail *Tail) seekTo(pos SeekInfo) error {
393 _, err := tail.file.Seek(pos.Offset, pos.Whence)
395 return fmt.Errorf("Seek error on %s: %s", tail.Filename, err)
398 tail.reader.Reset(tail.file)
404 func (tail *Tail) sendLine(line string) bool {
409 if tail.MaxLineSize > 0 && len(line) > tail.MaxLineSize {
410 lines = util.PartitionString(line, tail.MaxLineSize)
414 tail.lineNum++
415 offset, _ := tail.Tell()
417 case tail.Lines <- &Line{line, tail.lineNum, SeekInfo{Offset: offset}, now, nil}:
418 case <-tail.Dying():
423 if tail.Config.RateLimiter != nil {
424 ok := tail.Config.RateLimiter.Pour(uint16(len(lines)))
426 tail.Logger.Printf("Leaky bucket full (%v); entering 1s cooloff period.",
427 tail.Filename)
438 func (tail *Tail) Cleanup() {
439 watch.Cleanup(tail.Filename)