podman

Форк
0
119 строк · 2.5 Кб
1
// Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail
2
// Copyright (c) 2015 HPE Software Inc. All rights reserved.
3
// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
4

5
package watch
6

7
import (
8
	"os"
9
	"runtime"
10
	"time"
11

12
	"github.com/nxadm/tail/util"
13
	"gopkg.in/tomb.v1"
14
)
15

16
// PollingFileWatcher polls the file for changes.
17
type PollingFileWatcher struct {
18
	Filename string
19
	Size     int64
20
}
21

22
func NewPollingFileWatcher(filename string) *PollingFileWatcher {
23
	fw := &PollingFileWatcher{filename, 0}
24
	return fw
25
}
26

27
var POLL_DURATION time.Duration
28

29
func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
30
	for {
31
		if _, err := os.Stat(fw.Filename); err == nil {
32
			return nil
33
		} else if !os.IsNotExist(err) {
34
			return err
35
		}
36
		select {
37
		case <-time.After(POLL_DURATION):
38
			continue
39
		case <-t.Dying():
40
			return tomb.ErrDying
41
		}
42
	}
43
	panic("unreachable")
44
}
45

46
func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
47
	origFi, err := os.Stat(fw.Filename)
48
	if err != nil {
49
		return nil, err
50
	}
51

52
	changes := NewFileChanges()
53
	var prevModTime time.Time
54

55
	// XXX: use tomb.Tomb to cleanly manage these goroutines. replace
56
	// the fatal (below) with tomb's Kill.
57

58
	fw.Size = pos
59

60
	go func() {
61
		prevSize := fw.Size
62
		for {
63
			select {
64
			case <-t.Dying():
65
				return
66
			default:
67
			}
68

69
			time.Sleep(POLL_DURATION)
70
			fi, err := os.Stat(fw.Filename)
71
			if err != nil {
72
				// Windows cannot delete a file if a handle is still open (tail keeps one open)
73
				// so it gives access denied to anything trying to read it until all handles are released.
74
				if os.IsNotExist(err) || (runtime.GOOS == "windows" && os.IsPermission(err)) {
75
					// File does not exist (has been deleted).
76
					changes.NotifyDeleted()
77
					return
78
				}
79

80
				// XXX: report this error back to the user
81
				util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
82
			}
83

84
			// File got moved/renamed?
85
			if !os.SameFile(origFi, fi) {
86
				changes.NotifyDeleted()
87
				return
88
			}
89

90
			// File got truncated?
91
			fw.Size = fi.Size()
92
			if prevSize > 0 && prevSize > fw.Size {
93
				changes.NotifyTruncated()
94
				prevSize = fw.Size
95
				continue
96
			}
97
			// File got bigger?
98
			if prevSize > 0 && prevSize < fw.Size {
99
				changes.NotifyModified()
100
				prevSize = fw.Size
101
				continue
102
			}
103
			prevSize = fw.Size
104

105
			// File was appended to (changed)?
106
			modTime := fi.ModTime()
107
			if modTime != prevModTime {
108
				prevModTime = modTime
109
				changes.NotifyModified()
110
			}
111
		}
112
	}()
113

114
	return changes, nil
115
}
116

117
func init() {
118
	POLL_DURATION = 250 * time.Millisecond
119
}
120

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.