aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/hpcloud/tail
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hpcloud/tail')
-rw-r--r--vendor/github.com/hpcloud/tail/LICENSE.txt21
-rw-r--r--vendor/github.com/hpcloud/tail/README.md28
-rw-r--r--vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go97
-rw-r--r--vendor/github.com/hpcloud/tail/ratelimiter/memory.go58
-rw-r--r--vendor/github.com/hpcloud/tail/ratelimiter/storage.go6
-rw-r--r--vendor/github.com/hpcloud/tail/tail.go438
-rw-r--r--vendor/github.com/hpcloud/tail/tail_posix.go11
-rw-r--r--vendor/github.com/hpcloud/tail/tail_windows.go12
-rw-r--r--vendor/github.com/hpcloud/tail/util/util.go48
-rw-r--r--vendor/github.com/hpcloud/tail/watch/filechanges.go36
-rw-r--r--vendor/github.com/hpcloud/tail/watch/inotify.go128
-rw-r--r--vendor/github.com/hpcloud/tail/watch/inotify_tracker.go260
-rw-r--r--vendor/github.com/hpcloud/tail/watch/polling.go118
-rw-r--r--vendor/github.com/hpcloud/tail/watch/watch.go20
-rw-r--r--vendor/github.com/hpcloud/tail/winfile/winfile.go92
15 files changed, 0 insertions, 1373 deletions
diff --git a/vendor/github.com/hpcloud/tail/LICENSE.txt b/vendor/github.com/hpcloud/tail/LICENSE.txt
deleted file mode 100644
index 818d802a5..000000000
--- a/vendor/github.com/hpcloud/tail/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-# The MIT License (MIT)
-
-# © Copyright 2015 Hewlett Packard Enterprise Development LP
-Copyright (c) 2014 ActiveState
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/hpcloud/tail/README.md b/vendor/github.com/hpcloud/tail/README.md
deleted file mode 100644
index fb7fbc26c..000000000
--- a/vendor/github.com/hpcloud/tail/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[![Build Status](https://travis-ci.org/hpcloud/tail.svg)](https://travis-ci.org/hpcloud/tail)
-[![Build status](https://ci.appveyor.com/api/projects/status/kohpsf3rvhjhrox6?svg=true)](https://ci.appveyor.com/project/HelionCloudFoundry/tail)
-
-# Go package for tail-ing files
-
-A Go package striving to emulate the features of the BSD `tail` program.
-
-```Go
-t, err := tail.TailFile("/var/log/nginx.log", tail.Config{Follow: true})
-for line := range t.Lines {
- fmt.Println(line.Text)
-}
-```
-
-See [API documentation](http://godoc.org/github.com/hpcloud/tail).
-
-## Log rotation
-
-Tail comes with full support for truncation/move detection as it is
-designed to work with log rotation tools.
-
-## Installing
-
- go get github.com/hpcloud/tail/...
-
-## Windows support
-
-This package [needs assistance](https://github.com/hpcloud/tail/labels/Windows) for full Windows support.
diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go b/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go
deleted file mode 100644
index 358b69e7f..000000000
--- a/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Package ratelimiter implements the Leaky Bucket ratelimiting algorithm with memcached and in-memory backends.
-package ratelimiter
-
-import (
- "time"
-)
-
-type LeakyBucket struct {
- Size uint16
- Fill float64
- LeakInterval time.Duration // time.Duration for 1 unit of size to leak
- Lastupdate time.Time
- Now func() time.Time
-}
-
-func NewLeakyBucket(size uint16, leakInterval time.Duration) *LeakyBucket {
- bucket := LeakyBucket{
- Size: size,
- Fill: 0,
- LeakInterval: leakInterval,
- Now: time.Now,
- Lastupdate: time.Now(),
- }
-
- return &bucket
-}
-
-func (b *LeakyBucket) updateFill() {
- now := b.Now()
- if b.Fill > 0 {
- elapsed := now.Sub(b.Lastupdate)
-
- b.Fill -= float64(elapsed) / float64(b.LeakInterval)
- if b.Fill < 0 {
- b.Fill = 0
- }
- }
- b.Lastupdate = now
-}
-
-func (b *LeakyBucket) Pour(amount uint16) bool {
- b.updateFill()
-
- var newfill float64 = b.Fill + float64(amount)
-
- if newfill > float64(b.Size) {
- return false
- }
-
- b.Fill = newfill
-
- return true
-}
-
-// The time at which this bucket will be completely drained
-func (b *LeakyBucket) DrainedAt() time.Time {
- return b.Lastupdate.Add(time.Duration(b.Fill * float64(b.LeakInterval)))
-}
-
-// The duration until this bucket is completely drained
-func (b *LeakyBucket) TimeToDrain() time.Duration {
- return b.DrainedAt().Sub(b.Now())
-}
-
-func (b *LeakyBucket) TimeSinceLastUpdate() time.Duration {
- return b.Now().Sub(b.Lastupdate)
-}
-
-type LeakyBucketSer struct {
- Size uint16
- Fill float64
- LeakInterval time.Duration // time.Duration for 1 unit of size to leak
- Lastupdate time.Time
-}
-
-func (b *LeakyBucket) Serialise() *LeakyBucketSer {
- bucket := LeakyBucketSer{
- Size: b.Size,
- Fill: b.Fill,
- LeakInterval: b.LeakInterval,
- Lastupdate: b.Lastupdate,
- }
-
- return &bucket
-}
-
-func (b *LeakyBucketSer) DeSerialise() *LeakyBucket {
- bucket := LeakyBucket{
- Size: b.Size,
- Fill: b.Fill,
- LeakInterval: b.LeakInterval,
- Lastupdate: b.Lastupdate,
- Now: time.Now,
- }
-
- return &bucket
-}
diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/memory.go b/vendor/github.com/hpcloud/tail/ratelimiter/memory.go
deleted file mode 100644
index 8f6a5784a..000000000
--- a/vendor/github.com/hpcloud/tail/ratelimiter/memory.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package ratelimiter
-
-import (
- "errors"
- "time"
-)
-
-const GC_SIZE int = 100
-
-type Memory struct {
- store map[string]LeakyBucket
- lastGCCollected time.Time
-}
-
-func NewMemory() *Memory {
- m := new(Memory)
- m.store = make(map[string]LeakyBucket)
- m.lastGCCollected = time.Now()
- return m
-}
-
-func (m *Memory) GetBucketFor(key string) (*LeakyBucket, error) {
-
- bucket, ok := m.store[key]
- if !ok {
- return nil, errors.New("miss")
- }
-
- return &bucket, nil
-}
-
-func (m *Memory) SetBucketFor(key string, bucket LeakyBucket) error {
-
- if len(m.store) > GC_SIZE {
- m.GarbageCollect()
- }
-
- m.store[key] = bucket
-
- return nil
-}
-
-func (m *Memory) GarbageCollect() {
- now := time.Now()
-
- // rate limit GC to once per minute
- if now.Add(60*time.Second).Unix() > m.lastGCCollected.Unix() {
-
- for key, bucket := range m.store {
- // if the bucket is drained, then GC
- if bucket.DrainedAt().Unix() > now.Unix() {
- delete(m.store, key)
- }
- }
-
- m.lastGCCollected = now
- }
-}
diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/storage.go b/vendor/github.com/hpcloud/tail/ratelimiter/storage.go
deleted file mode 100644
index 89b2fe882..000000000
--- a/vendor/github.com/hpcloud/tail/ratelimiter/storage.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package ratelimiter
-
-type Storage interface {
- GetBucketFor(string) (*LeakyBucket, error)
- SetBucketFor(string, LeakyBucket) error
-}
diff --git a/vendor/github.com/hpcloud/tail/tail.go b/vendor/github.com/hpcloud/tail/tail.go
deleted file mode 100644
index 2d252d605..000000000
--- a/vendor/github.com/hpcloud/tail/tail.go
+++ /dev/null
@@ -1,438 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package tail
-
-import (
- "bufio"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "strings"
- "sync"
- "time"
-
- "github.com/hpcloud/tail/ratelimiter"
- "github.com/hpcloud/tail/util"
- "github.com/hpcloud/tail/watch"
- "gopkg.in/tomb.v1"
-)
-
-var (
- ErrStop = fmt.Errorf("tail should now stop")
-)
-
-type Line struct {
- Text string
- Time time.Time
- Err error // Error from tail
-}
-
-// NewLine returns a Line with present time.
-func NewLine(text string) *Line {
- return &Line{text, time.Now(), nil}
-}
-
-// SeekInfo represents arguments to `os.Seek`
-type SeekInfo struct {
- Offset int64
- Whence int // os.SEEK_*
-}
-
-type logger interface {
- Fatal(v ...interface{})
- Fatalf(format string, v ...interface{})
- Fatalln(v ...interface{})
- Panic(v ...interface{})
- Panicf(format string, v ...interface{})
- Panicln(v ...interface{})
- Print(v ...interface{})
- Printf(format string, v ...interface{})
- Println(v ...interface{})
-}
-
-// Config is used to specify how a file must be tailed.
-type Config struct {
- // File-specifc
- Location *SeekInfo // Seek to this location before tailing
- ReOpen bool // Reopen recreated files (tail -F)
- MustExist bool // Fail early if the file does not exist
- Poll bool // Poll for file changes instead of using inotify
- Pipe bool // Is a named pipe (mkfifo)
- RateLimiter *ratelimiter.LeakyBucket
-
- // Generic IO
- Follow bool // Continue looking for new lines (tail -f)
- MaxLineSize int // If non-zero, split longer lines into multiple lines
-
- // Logger, when nil, is set to tail.DefaultLogger
- // To disable logging: set field to tail.DiscardingLogger
- Logger logger
-}
-
-type Tail struct {
- Filename string
- Lines chan *Line
- Config
-
- file *os.File
- reader *bufio.Reader
-
- watcher watch.FileWatcher
- changes *watch.FileChanges
-
- tomb.Tomb // provides: Done, Kill, Dying
-
- lk sync.Mutex
-}
-
-var (
- // DefaultLogger is used when Config.Logger == nil
- DefaultLogger = log.New(os.Stderr, "", log.LstdFlags)
- // DiscardingLogger can be used to disable logging output
- DiscardingLogger = log.New(ioutil.Discard, "", 0)
-)
-
-// TailFile begins tailing the file. Output stream is made available
-// via the `Tail.Lines` channel. To handle errors during tailing,
-// invoke the `Wait` or `Err` method after finishing reading from the
-// `Lines` channel.
-func TailFile(filename string, config Config) (*Tail, error) {
- if config.ReOpen && !config.Follow {
- util.Fatal("cannot set ReOpen without Follow.")
- }
-
- t := &Tail{
- Filename: filename,
- Lines: make(chan *Line),
- Config: config,
- }
-
- // when Logger was not specified in config, use default logger
- if t.Logger == nil {
- t.Logger = log.New(os.Stderr, "", log.LstdFlags)
- }
-
- if t.Poll {
- t.watcher = watch.NewPollingFileWatcher(filename)
- } else {
- t.watcher = watch.NewInotifyFileWatcher(filename)
- }
-
- if t.MustExist {
- var err error
- t.file, err = OpenFile(t.Filename)
- if err != nil {
- return nil, err
- }
- }
-
- go t.tailFileSync()
-
- return t, nil
-}
-
-// Return the file's current position, like stdio's ftell().
-// But this value is not very accurate.
-// it may readed one line in the chan(tail.Lines),
-// so it may lost one line.
-func (tail *Tail) Tell() (offset int64, err error) {
- if tail.file == nil {
- return
- }
- offset, err = tail.file.Seek(0, os.SEEK_CUR)
- if err != nil {
- return
- }
-
- tail.lk.Lock()
- defer tail.lk.Unlock()
- if tail.reader == nil {
- return
- }
-
- offset -= int64(tail.reader.Buffered())
- return
-}
-
-// Stop stops the tailing activity.
-func (tail *Tail) Stop() error {
- tail.Kill(nil)
- 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() {
- close(tail.Lines)
- tail.closeFile()
-}
-
-func (tail *Tail) closeFile() {
- if tail.file != nil {
- tail.file.Close()
- tail.file = nil
- }
-}
-
-func (tail *Tail) reopen() error {
- tail.closeFile()
- for {
- var err error
- tail.file, err = OpenFile(tail.Filename)
- if err != nil {
- if os.IsNotExist(err) {
- tail.Logger.Printf("Waiting for %s to appear...", tail.Filename)
- if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil {
- if err == tomb.ErrDying {
- return err
- }
- return fmt.Errorf("Failed to detect creation of %s: %s", tail.Filename, err)
- }
- continue
- }
- return fmt.Errorf("Unable to open file %s: %s", tail.Filename, err)
- }
- break
- }
- return nil
-}
-
-func (tail *Tail) readLine() (string, error) {
- tail.lk.Lock()
- line, err := tail.reader.ReadString('\n')
- tail.lk.Unlock()
- if err != nil {
- // Note ReadString "returns the data read before the error" in
- // case of an error, including EOF, so we return it as is. The
- // caller is expected to process it if err is EOF.
- return line, err
- }
-
- line = strings.TrimRight(line, "\n")
-
- return line, err
-}
-
-func (tail *Tail) tailFileSync() {
- defer tail.Done()
- defer tail.close()
-
- if !tail.MustExist {
- // deferred first open.
- err := tail.reopen()
- if err != nil {
- if err != tomb.ErrDying {
- tail.Kill(err)
- }
- return
- }
- }
-
- // Seek to requested location on first open of the file.
- if tail.Location != nil {
- _, err := tail.file.Seek(tail.Location.Offset, tail.Location.Whence)
- tail.Logger.Printf("Seeked %s - %+v\n", tail.Filename, tail.Location)
- if err != nil {
- tail.Killf("Seek error on %s: %s", tail.Filename, err)
- return
- }
- }
-
- tail.openReader()
-
- var offset int64 = 0
- var err error
-
- // Read line by line.
- for {
- // do not seek in named pipes
- if !tail.Pipe {
- // grab the position in case we need to back up in the event of a half-line
- offset, err = tail.Tell()
- if err != nil {
- tail.Kill(err)
- return
- }
- }
-
- line, err := tail.readLine()
-
- // Process `line` even if err is EOF.
- if err == nil {
- cooloff := !tail.sendLine(line)
- if cooloff {
- // Wait a second before seeking till the end of
- // file when rate limit is reached.
- msg := fmt.Sprintf(
- "Too much log activity; waiting a second " +
- "before resuming tailing")
- tail.Lines <- &Line{msg, time.Now(), fmt.Errorf(msg)}
- select {
- case <-time.After(time.Second):
- case <-tail.Dying():
- return
- }
- if err := tail.seekEnd(); err != nil {
- tail.Kill(err)
- return
- }
- }
- } else if err == io.EOF {
- if !tail.Follow {
- if line != "" {
- tail.sendLine(line)
- }
- return
- }
-
- if tail.Follow && line != "" {
- // this has the potential to never return the last line if
- // it's not followed by a newline; seems a fair trade here
- err := tail.seekTo(SeekInfo{Offset: offset, Whence: 0})
- if err != nil {
- tail.Kill(err)
- return
- }
- }
-
- // When EOF is reached, wait for more data to become
- // available. Wait strategy is based on the `tail.watcher`
- // implementation (inotify or polling).
- err := tail.waitForChanges()
- if err != nil {
- if err != ErrStop {
- tail.Kill(err)
- }
- return
- }
- } else {
- // non-EOF error
- tail.Killf("Error reading %s: %s", tail.Filename, err)
- return
- }
-
- select {
- case <-tail.Dying():
- if tail.Err() == errStopAtEOF {
- continue
- }
- return
- default:
- }
- }
-}
-
-// waitForChanges waits until the file has been appended, deleted,
-// moved or truncated. When moved or deleted - the file will be
-// reopened if ReOpen is true. Truncated files are always reopened.
-func (tail *Tail) waitForChanges() error {
- if tail.changes == nil {
- pos, err := tail.file.Seek(0, os.SEEK_CUR)
- if err != nil {
- return err
- }
- tail.changes, err = tail.watcher.ChangeEvents(&tail.Tomb, pos)
- if err != nil {
- return err
- }
- }
-
- select {
- case <-tail.changes.Modified:
- return nil
- case <-tail.changes.Deleted:
- tail.changes = nil
- if tail.ReOpen {
- // XXX: we must not log from a library.
- tail.Logger.Printf("Re-opening moved/deleted file %s ...", tail.Filename)
- if err := tail.reopen(); err != nil {
- return err
- }
- tail.Logger.Printf("Successfully reopened %s", tail.Filename)
- tail.openReader()
- return nil
- } else {
- tail.Logger.Printf("Stopping tail as file no longer exists: %s", tail.Filename)
- return ErrStop
- }
- case <-tail.changes.Truncated:
- // Always reopen truncated files (Follow is true)
- tail.Logger.Printf("Re-opening truncated file %s ...", tail.Filename)
- if err := tail.reopen(); err != nil {
- return err
- }
- tail.Logger.Printf("Successfully reopened truncated %s", tail.Filename)
- tail.openReader()
- return nil
- case <-tail.Dying():
- return ErrStop
- }
- panic("unreachable")
-}
-
-func (tail *Tail) openReader() {
- if tail.MaxLineSize > 0 {
- // add 2 to account for newline characters
- tail.reader = bufio.NewReaderSize(tail.file, tail.MaxLineSize+2)
- } else {
- tail.reader = bufio.NewReader(tail.file)
- }
-}
-
-func (tail *Tail) seekEnd() error {
- return tail.seekTo(SeekInfo{Offset: 0, Whence: os.SEEK_END})
-}
-
-func (tail *Tail) seekTo(pos SeekInfo) error {
- _, err := tail.file.Seek(pos.Offset, pos.Whence)
- if err != nil {
- return fmt.Errorf("Seek error on %s: %s", tail.Filename, err)
- }
- // Reset the read buffer whenever the file is re-seek'ed
- tail.reader.Reset(tail.file)
- return nil
-}
-
-// sendLine sends the line(s) to Lines channel, splitting longer lines
-// if necessary. Return false if rate limit is reached.
-func (tail *Tail) sendLine(line string) bool {
- now := time.Now()
- lines := []string{line}
-
- // Split longer lines
- if tail.MaxLineSize > 0 && len(line) > tail.MaxLineSize {
- lines = util.PartitionString(line, tail.MaxLineSize)
- }
-
- for _, line := range lines {
- tail.Lines <- &Line{line, now, nil}
- }
-
- if tail.Config.RateLimiter != nil {
- ok := tail.Config.RateLimiter.Pour(uint16(len(lines)))
- if !ok {
- tail.Logger.Printf("Leaky bucket full (%v); entering 1s cooloff period.\n",
- tail.Filename)
- return false
- }
- }
-
- return true
-}
-
-// 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 (tail *Tail) Cleanup() {
- watch.Cleanup(tail.Filename)
-}
diff --git a/vendor/github.com/hpcloud/tail/tail_posix.go b/vendor/github.com/hpcloud/tail/tail_posix.go
deleted file mode 100644
index bc4dc3357..000000000
--- a/vendor/github.com/hpcloud/tail/tail_posix.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// +build linux darwin freebsd netbsd openbsd
-
-package tail
-
-import (
- "os"
-)
-
-func OpenFile(name string) (file *os.File, err error) {
- return os.Open(name)
-}
diff --git a/vendor/github.com/hpcloud/tail/tail_windows.go b/vendor/github.com/hpcloud/tail/tail_windows.go
deleted file mode 100644
index ef2cfca1b..000000000
--- a/vendor/github.com/hpcloud/tail/tail_windows.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// +build windows
-
-package tail
-
-import (
- "github.com/hpcloud/tail/winfile"
- "os"
-)
-
-func OpenFile(name string) (file *os.File, err error) {
- return winfile.OpenFile(name, os.O_RDONLY, 0)
-}
diff --git a/vendor/github.com/hpcloud/tail/util/util.go b/vendor/github.com/hpcloud/tail/util/util.go
deleted file mode 100644
index 54151fe39..000000000
--- a/vendor/github.com/hpcloud/tail/util/util.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package util
-
-import (
- "fmt"
- "log"
- "os"
- "runtime/debug"
-)
-
-type Logger struct {
- *log.Logger
-}
-
-var LOGGER = &Logger{log.New(os.Stderr, "", log.LstdFlags)}
-
-// fatal is like panic except it displays only the current goroutine's stack.
-func Fatal(format string, v ...interface{}) {
- // https://github.com/hpcloud/log/blob/master/log.go#L45
- LOGGER.Output(2, fmt.Sprintf("FATAL -- "+format, v...)+"\n"+string(debug.Stack()))
- os.Exit(1)
-}
-
-// partitionString partitions the string into chunks of given size,
-// with the last chunk of variable size.
-func PartitionString(s string, chunkSize int) []string {
- if chunkSize <= 0 {
- panic("invalid chunkSize")
- }
- length := len(s)
- chunks := 1 + length/chunkSize
- start := 0
- end := chunkSize
- parts := make([]string, 0, chunks)
- for {
- if end > length {
- end = length
- }
- parts = append(parts, s[start:end])
- if end == length {
- break
- }
- start, end = end, end+chunkSize
- }
- return parts
-}
diff --git a/vendor/github.com/hpcloud/tail/watch/filechanges.go b/vendor/github.com/hpcloud/tail/watch/filechanges.go
deleted file mode 100644
index 3ce5dcecb..000000000
--- a/vendor/github.com/hpcloud/tail/watch/filechanges.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package watch
-
-type FileChanges struct {
- Modified chan bool // Channel to get notified of modifications
- Truncated chan bool // Channel to get notified of truncations
- Deleted chan bool // Channel to get notified of deletions/renames
-}
-
-func NewFileChanges() *FileChanges {
- return &FileChanges{
- make(chan bool), make(chan bool), make(chan bool)}
-}
-
-func (fc *FileChanges) NotifyModified() {
- sendOnlyIfEmpty(fc.Modified)
-}
-
-func (fc *FileChanges) NotifyTruncated() {
- sendOnlyIfEmpty(fc.Truncated)
-}
-
-func (fc *FileChanges) NotifyDeleted() {
- sendOnlyIfEmpty(fc.Deleted)
-}
-
-// sendOnlyIfEmpty sends on a bool channel only if the channel has no
-// backlog to be read by other goroutines. This concurrency pattern
-// can be used to notify other goroutines if and only if they are
-// looking for it (i.e., subsequent notifications can be compressed
-// into one).
-func sendOnlyIfEmpty(ch chan bool) {
- select {
- case ch <- true:
- default:
- }
-}
diff --git a/vendor/github.com/hpcloud/tail/watch/inotify.go b/vendor/github.com/hpcloud/tail/watch/inotify.go
deleted file mode 100644
index 4478f1e1a..000000000
--- a/vendor/github.com/hpcloud/tail/watch/inotify.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package watch
-
-import (
- "fmt"
- "os"
- "path/filepath"
-
- "github.com/hpcloud/tail/util"
-
- "gopkg.in/fsnotify.v1"
- "gopkg.in/tomb.v1"
-)
-
-// InotifyFileWatcher uses inotify to monitor file changes.
-type InotifyFileWatcher struct {
- Filename string
- Size int64
-}
-
-func NewInotifyFileWatcher(filename string) *InotifyFileWatcher {
- fw := &InotifyFileWatcher{filepath.Clean(filename), 0}
- return fw
-}
-
-func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
- err := WatchCreate(fw.Filename)
- if err != nil {
- return err
- }
- defer RemoveWatchCreate(fw.Filename)
-
- // Do a real check now as the file might have been created before
- // calling `WatchFlags` above.
- if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) {
- // file exists, or stat returned an error.
- return err
- }
-
- events := Events(fw.Filename)
-
- for {
- select {
- case evt, ok := <-events:
- if !ok {
- return fmt.Errorf("inotify watcher has been closed")
- }
- evtName, err := filepath.Abs(evt.Name)
- if err != nil {
- return err
- }
- fwFilename, err := filepath.Abs(fw.Filename)
- if err != nil {
- return err
- }
- if evtName == fwFilename {
- return nil
- }
- case <-t.Dying():
- return tomb.ErrDying
- }
- }
- panic("unreachable")
-}
-
-func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
- err := Watch(fw.Filename)
- if err != nil {
- return nil, err
- }
-
- changes := NewFileChanges()
- fw.Size = pos
-
- go func() {
- defer RemoveWatch(fw.Filename)
-
- events := Events(fw.Filename)
-
- for {
- prevSize := fw.Size
-
- var evt fsnotify.Event
- var ok bool
-
- select {
- case evt, ok = <-events:
- if !ok {
- return
- }
- case <-t.Dying():
- return
- }
-
- switch {
- case evt.Op&fsnotify.Remove == fsnotify.Remove:
- fallthrough
-
- case evt.Op&fsnotify.Rename == fsnotify.Rename:
- changes.NotifyDeleted()
- return
-
- case evt.Op&fsnotify.Write == fsnotify.Write:
- fi, err := os.Stat(fw.Filename)
- if err != nil {
- if os.IsNotExist(err) {
- changes.NotifyDeleted()
- return
- }
- // XXX: report this error back to the user
- util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
- }
- fw.Size = fi.Size()
-
- if prevSize > 0 && prevSize > fw.Size {
- changes.NotifyTruncated()
- } else {
- changes.NotifyModified()
- }
- prevSize = fw.Size
- }
- }
- }()
-
- return changes, nil
-}
diff --git a/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go b/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go
deleted file mode 100644
index 03be4275c..000000000
--- a/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package watch
-
-import (
- "log"
- "os"
- "path/filepath"
- "sync"
- "syscall"
-
- "github.com/hpcloud/tail/util"
-
- "gopkg.in/fsnotify.v1"
-)
-
-type InotifyTracker struct {
- mux sync.Mutex
- watcher *fsnotify.Watcher
- chans map[string]chan fsnotify.Event
- done map[string]chan bool
- watchNums map[string]int
- watch chan *watchInfo
- remove chan *watchInfo
- error chan error
-}
-
-type watchInfo struct {
- op fsnotify.Op
- fname string
-}
-
-func (this *watchInfo) isCreate() bool {
- return this.op == fsnotify.Create
-}
-
-var (
- // globally shared InotifyTracker; ensures only one fsnotify.Watcher is used
- shared *InotifyTracker
-
- // these are used to ensure the shared InotifyTracker is run exactly once
- once = sync.Once{}
- goRun = func() {
- shared = &InotifyTracker{
- mux: sync.Mutex{},
- chans: make(map[string]chan fsnotify.Event),
- done: make(map[string]chan bool),
- watchNums: make(map[string]int),
- watch: make(chan *watchInfo),
- remove: make(chan *watchInfo),
- error: make(chan error),
- }
- go shared.run()
- }
-
- logger = log.New(os.Stderr, "", log.LstdFlags)
-)
-
-// Watch signals the run goroutine to begin watching the input filename
-func Watch(fname string) error {
- return watch(&watchInfo{
- fname: fname,
- })
-}
-
-// Watch create signals the run goroutine to begin watching the input filename
-// if call the WatchCreate function, don't call the Cleanup, call the RemoveWatchCreate
-func WatchCreate(fname string) error {
- return watch(&watchInfo{
- op: fsnotify.Create,
- fname: fname,
- })
-}
-
-func watch(winfo *watchInfo) error {
- // start running the shared InotifyTracker if not already running
- once.Do(goRun)
-
- winfo.fname = filepath.Clean(winfo.fname)
- shared.watch <- winfo
- return <-shared.error
-}
-
-// RemoveWatch signals the run goroutine to remove the watch for the input filename
-func RemoveWatch(fname string) {
- remove(&watchInfo{
- fname: fname,
- })
-}
-
-// RemoveWatch create signals the run goroutine to remove the watch for the input filename
-func RemoveWatchCreate(fname string) {
- remove(&watchInfo{
- op: fsnotify.Create,
- fname: fname,
- })
-}
-
-func remove(winfo *watchInfo) {
- // start running the shared InotifyTracker if not already running
- once.Do(goRun)
-
- winfo.fname = filepath.Clean(winfo.fname)
- shared.mux.Lock()
- done := shared.done[winfo.fname]
- if done != nil {
- delete(shared.done, winfo.fname)
- close(done)
- }
-
- fname := winfo.fname
- if winfo.isCreate() {
- // Watch for new files to be created in the parent directory.
- fname = filepath.Dir(fname)
- }
- shared.watchNums[fname]--
- watchNum := shared.watchNums[fname]
- if watchNum == 0 {
- delete(shared.watchNums, fname)
- }
- shared.mux.Unlock()
-
- // If we were the last ones to watch this file, unsubscribe from inotify.
- // This needs to happen after releasing the lock because fsnotify waits
- // synchronously for the kernel to acknowledge the removal of the watch
- // for this file, which causes us to deadlock if we still held the lock.
- if watchNum == 0 {
- shared.watcher.Remove(fname)
- }
- shared.remove <- winfo
-}
-
-// Events returns a channel to which FileEvents corresponding to the input filename
-// will be sent. This channel will be closed when removeWatch is called on this
-// filename.
-func Events(fname string) <-chan fsnotify.Event {
- shared.mux.Lock()
- defer shared.mux.Unlock()
-
- return shared.chans[fname]
-}
-
-// Cleanup removes the watch for the input filename if necessary.
-func Cleanup(fname string) {
- RemoveWatch(fname)
-}
-
-// watchFlags calls fsnotify.WatchFlags for the input filename and flags, creating
-// a new Watcher if the previous Watcher was closed.
-func (shared *InotifyTracker) addWatch(winfo *watchInfo) error {
- shared.mux.Lock()
- defer shared.mux.Unlock()
-
- if shared.chans[winfo.fname] == nil {
- shared.chans[winfo.fname] = make(chan fsnotify.Event)
- shared.done[winfo.fname] = make(chan bool)
- }
-
- fname := winfo.fname
- if winfo.isCreate() {
- // Watch for new files to be created in the parent directory.
- fname = filepath.Dir(fname)
- }
-
- // already in inotify watch
- if shared.watchNums[fname] > 0 {
- shared.watchNums[fname]++
- if winfo.isCreate() {
- shared.watchNums[winfo.fname]++
- }
- return nil
- }
-
- err := shared.watcher.Add(fname)
- if err == nil {
- shared.watchNums[fname]++
- if winfo.isCreate() {
- shared.watchNums[winfo.fname]++
- }
- }
- return err
-}
-
-// removeWatch calls fsnotify.RemoveWatch for the input filename and closes the
-// corresponding events channel.
-func (shared *InotifyTracker) removeWatch(winfo *watchInfo) {
- shared.mux.Lock()
- defer shared.mux.Unlock()
-
- ch := shared.chans[winfo.fname]
- if ch == nil {
- return
- }
-
- delete(shared.chans, winfo.fname)
- close(ch)
-
- if !winfo.isCreate() {
- return
- }
-
- shared.watchNums[winfo.fname]--
- if shared.watchNums[winfo.fname] == 0 {
- delete(shared.watchNums, winfo.fname)
- }
-}
-
-// sendEvent sends the input event to the appropriate Tail.
-func (shared *InotifyTracker) sendEvent(event fsnotify.Event) {
- name := filepath.Clean(event.Name)
-
- shared.mux.Lock()
- ch := shared.chans[name]
- done := shared.done[name]
- shared.mux.Unlock()
-
- if ch != nil && done != nil {
- select {
- case ch <- event:
- case <-done:
- }
- }
-}
-
-// run starts the goroutine in which the shared struct reads events from its
-// Watcher's Event channel and sends the events to the appropriate Tail.
-func (shared *InotifyTracker) run() {
- watcher, err := fsnotify.NewWatcher()
- if err != nil {
- util.Fatal("failed to create Watcher")
- }
- shared.watcher = watcher
-
- for {
- select {
- case winfo := <-shared.watch:
- shared.error <- shared.addWatch(winfo)
-
- case winfo := <-shared.remove:
- shared.removeWatch(winfo)
-
- case event, open := <-shared.watcher.Events:
- if !open {
- return
- }
- shared.sendEvent(event)
-
- case err, open := <-shared.watcher.Errors:
- if !open {
- return
- } else if err != nil {
- sysErr, ok := err.(*os.SyscallError)
- if !ok || sysErr.Err != syscall.EINTR {
- logger.Printf("Error in Watcher Error channel: %s", err)
- }
- }
- }
- }
-}
diff --git a/vendor/github.com/hpcloud/tail/watch/polling.go b/vendor/github.com/hpcloud/tail/watch/polling.go
deleted file mode 100644
index 49491f21d..000000000
--- a/vendor/github.com/hpcloud/tail/watch/polling.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package watch
-
-import (
- "os"
- "runtime"
- "time"
-
- "github.com/hpcloud/tail/util"
- "gopkg.in/tomb.v1"
-)
-
-// PollingFileWatcher polls the file for changes.
-type PollingFileWatcher struct {
- Filename string
- Size int64
-}
-
-func NewPollingFileWatcher(filename string) *PollingFileWatcher {
- fw := &PollingFileWatcher{filename, 0}
- return fw
-}
-
-var POLL_DURATION time.Duration
-
-func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
- for {
- if _, err := os.Stat(fw.Filename); err == nil {
- return nil
- } else if !os.IsNotExist(err) {
- return err
- }
- select {
- case <-time.After(POLL_DURATION):
- continue
- case <-t.Dying():
- return tomb.ErrDying
- }
- }
- panic("unreachable")
-}
-
-func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
- origFi, err := os.Stat(fw.Filename)
- if err != nil {
- return nil, err
- }
-
- changes := NewFileChanges()
- var prevModTime time.Time
-
- // XXX: use tomb.Tomb to cleanly manage these goroutines. replace
- // the fatal (below) with tomb's Kill.
-
- fw.Size = pos
-
- go func() {
- prevSize := fw.Size
- for {
- select {
- case <-t.Dying():
- return
- default:
- }
-
- time.Sleep(POLL_DURATION)
- fi, err := os.Stat(fw.Filename)
- if err != nil {
- // Windows cannot delete a file if a handle is still open (tail keeps one open)
- // so it gives access denied to anything trying to read it until all handles are released.
- if os.IsNotExist(err) || (runtime.GOOS == "windows" && os.IsPermission(err)) {
- // File does not exist (has been deleted).
- changes.NotifyDeleted()
- return
- }
-
- // XXX: report this error back to the user
- util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
- }
-
- // File got moved/renamed?
- if !os.SameFile(origFi, fi) {
- changes.NotifyDeleted()
- return
- }
-
- // File got truncated?
- fw.Size = fi.Size()
- if prevSize > 0 && prevSize > fw.Size {
- changes.NotifyTruncated()
- prevSize = fw.Size
- continue
- }
- // File got bigger?
- if prevSize > 0 && prevSize < fw.Size {
- changes.NotifyModified()
- prevSize = fw.Size
- continue
- }
- prevSize = fw.Size
-
- // File was appended to (changed)?
- modTime := fi.ModTime()
- if modTime != prevModTime {
- prevModTime = modTime
- changes.NotifyModified()
- }
- }
- }()
-
- return changes, nil
-}
-
-func init() {
- POLL_DURATION = 250 * time.Millisecond
-}
diff --git a/vendor/github.com/hpcloud/tail/watch/watch.go b/vendor/github.com/hpcloud/tail/watch/watch.go
deleted file mode 100644
index 2e1783ef0..000000000
--- a/vendor/github.com/hpcloud/tail/watch/watch.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2015 HPE Software Inc. All rights reserved.
-// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
-
-package watch
-
-import "gopkg.in/tomb.v1"
-
-// FileWatcher monitors file-level events.
-type FileWatcher interface {
- // BlockUntilExists blocks until the file comes into existence.
- BlockUntilExists(*tomb.Tomb) error
-
- // ChangeEvents reports on changes to a file, be it modification,
- // deletion, renames or truncations. Returned FileChanges group of
- // channels will be closed, thus become unusable, after a deletion
- // or truncation event.
- // In order to properly report truncations, ChangeEvents requires
- // the caller to pass their current offset in the file.
- ChangeEvents(*tomb.Tomb, int64) (*FileChanges, error)
-}
diff --git a/vendor/github.com/hpcloud/tail/winfile/winfile.go b/vendor/github.com/hpcloud/tail/winfile/winfile.go
deleted file mode 100644
index aa7e7bc5d..000000000
--- a/vendor/github.com/hpcloud/tail/winfile/winfile.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// +build windows
-
-package winfile
-
-import (
- "os"
- "syscall"
- "unsafe"
-)
-
-// issue also described here
-//https://codereview.appspot.com/8203043/
-
-// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L218
-func Open(path string, mode int, perm uint32) (fd syscall.Handle, err error) {
- if len(path) == 0 {
- return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND
- }
- pathp, err := syscall.UTF16PtrFromString(path)
- if err != nil {
- return syscall.InvalidHandle, err
- }
- var access uint32
- switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) {
- case syscall.O_RDONLY:
- access = syscall.GENERIC_READ
- case syscall.O_WRONLY:
- access = syscall.GENERIC_WRITE
- case syscall.O_RDWR:
- access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
- }
- if mode&syscall.O_CREAT != 0 {
- access |= syscall.GENERIC_WRITE
- }
- if mode&syscall.O_APPEND != 0 {
- access &^= syscall.GENERIC_WRITE
- access |= syscall.FILE_APPEND_DATA
- }
- sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE)
- var sa *syscall.SecurityAttributes
- if mode&syscall.O_CLOEXEC == 0 {
- sa = makeInheritSa()
- }
- var createmode uint32
- switch {
- case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
- createmode = syscall.CREATE_NEW
- case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC):
- createmode = syscall.CREATE_ALWAYS
- case mode&syscall.O_CREAT == syscall.O_CREAT:
- createmode = syscall.OPEN_ALWAYS
- case mode&syscall.O_TRUNC == syscall.O_TRUNC:
- createmode = syscall.TRUNCATE_EXISTING
- default:
- createmode = syscall.OPEN_EXISTING
- }
- h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0)
- return h, e
-}
-
-// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L211
-func makeInheritSa() *syscall.SecurityAttributes {
- var sa syscall.SecurityAttributes
- sa.Length = uint32(unsafe.Sizeof(sa))
- sa.InheritHandle = 1
- return &sa
-}
-
-// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_windows.go#L133
-func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) {
- r, e := Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
- if e != nil {
- return nil, e
- }
- return os.NewFile(uintptr(r), name), nil
-}
-
-// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_posix.go#L61
-func syscallMode(i os.FileMode) (o uint32) {
- o |= uint32(i.Perm())
- if i&os.ModeSetuid != 0 {
- o |= syscall.S_ISUID
- }
- if i&os.ModeSetgid != 0 {
- o |= syscall.S_ISGID
- }
- if i&os.ModeSticky != 0 {
- o |= syscall.S_ISVTX
- }
- // No mapping for Go's ModeTemporary (plan9 only).
- return
-}