forked from weaveworks/scope
-
Notifications
You must be signed in to change notification settings - Fork 0
/
walker.go
66 lines (56 loc) · 1.48 KB
/
walker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package process
import "sync"
// Process represents a single process.
type Process struct {
PID, PPID int
Name string
Cmdline string
Threads int
Jiffies uint64
RSSBytes uint64
RSSBytesLimit uint64
OpenFilesCount int
OpenFilesLimit uint64
}
// Walker is something that walks the /proc directory
type Walker interface {
Walk(func(Process, Process)) error
}
// CachingWalker is a walker than caches a copy of the output from another
// Walker, and then allows other concurrent readers to Walk that copy.
type CachingWalker struct {
cache map[int]Process
previousByPID map[int]Process
cacheLock sync.RWMutex
source Walker
}
// NewCachingWalker returns a new CachingWalker
func NewCachingWalker(source Walker) *CachingWalker {
return &CachingWalker{source: source}
}
// Name of this ticker, for metrics gathering
func (*CachingWalker) Name() string { return "Process" }
// Walk walks a cached copy of process list
func (c *CachingWalker) Walk(f func(Process, Process)) error {
c.cacheLock.RLock()
defer c.cacheLock.RUnlock()
for _, p := range c.cache {
f(p, c.previousByPID[p.PID])
}
return nil
}
// Tick updates cached copy of process list
func (c *CachingWalker) Tick() error {
newCache := map[int]Process{}
err := c.source.Walk(func(p, _ Process) {
newCache[p.PID] = p
})
if err != nil {
return err
}
c.cacheLock.Lock()
defer c.cacheLock.Unlock()
c.previousByPID = c.cache
c.cache = newCache
return nil
}