Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 291 lines (219 sloc) 5.366 kb
fb874eb @dougm Initial import
dougm authored
1 // Copyright (c) 2012 VMware, Inc.
2
3 package sigar
4
5 import (
6 "bufio"
7 "bytes"
8 "io"
9 "io/ioutil"
35d6c1b @dougm Start process interfaces
dougm authored
10 "os"
fb874eb @dougm Initial import
dougm authored
11 "strconv"
12 "strings"
13 "syscall"
14 )
15
16 const procd = "/proc/"
17
35d6c1b @dougm Start process interfaces
dougm authored
18 var system struct {
19 ticks uint64
20 btime uint64
21 }
22
23 func init() {
24 system.ticks = 100 // C.sysconf(C._SC_CLK_TCK)
25
26 // grab system boot time
27 readFile(procd+"stat", func(line string) bool {
28 if line[0:5] == "btime" {
29 system.btime, _ = strtoull(line[6:])
30 return false // stop reading
31 }
32 return true
33 })
34 }
35
fb874eb @dougm Initial import
dougm authored
36 func (self *LoadAverage) Get() error {
37 line, err := ioutil.ReadFile(procd + "loadavg")
38 if err != nil {
39 return nil
40 }
41
42 fields := strings.Fields(string(line))
43
44 self.One, _ = strconv.ParseFloat(fields[0], 64)
45 self.Five, _ = strconv.ParseFloat(fields[1], 64)
46 self.Fifteen, _ = strconv.ParseFloat(fields[2], 64)
47
48 return nil
49 }
50
51 func (self *Uptime) Get() error {
52 sysinfo := syscall.Sysinfo_t{}
53
54 if err := syscall.Sysinfo(&sysinfo); err != nil {
55 return err
56 }
57
58 self.Length = float64(sysinfo.Uptime)
59
60 return nil
61 }
62
63 func (self *Mem) Get() error {
64 var buffers, cached uint64
65 table := map[string]*uint64{
66 "MemTotal": &self.Total,
67 "MemFree": &self.Free,
68 "Buffers": &buffers,
69 "Cached": &cached,
70 }
71
72 if err := parseMeminfo(table); err != nil {
73 return err
74 }
75
76 self.Used = self.Total - self.Free
77 kern := buffers + cached
78 self.ActualFree = self.Free + kern
79 self.ActualUsed = self.Used - kern
80
81 return nil
82 }
83
84 func (self *Swap) Get() error {
85 sysinfo := syscall.Sysinfo_t{}
86
87 if err := syscall.Sysinfo(&sysinfo); err != nil {
88 return err
89 }
90
91 self.Total = sysinfo.Totalswap
92 self.Free = sysinfo.Freeswap
93 self.Used = self.Total - self.Free
94
95 return nil
96 }
97
98 func (self *FileSystemList) Get() error {
99 capacity := len(self.List)
100 if capacity == 0 {
101 capacity = 10
102 }
103 fslist := make([]FileSystem, 0, capacity)
104
105 err := readFile("/etc/mtab", func(line string) bool {
106 fields := strings.Fields(line)
107
108 fs := FileSystem{}
109 fs.DevName = fields[0]
110 fs.DirName = fields[1]
111 fs.SysTypeName = fields[2]
112 fs.Options = fields[3]
113
114 fslist = append(fslist, fs)
115
116 return true
117 })
118
119 self.List = fslist
120
121 return err
122 }
123
35d6c1b @dougm Start process interfaces
dougm authored
124 func (self *ProcList) Get() error {
125 dir, err := os.Open(procd)
126 if err != nil {
127 return err
128 }
129 defer dir.Close()
130
131 const readAllDirnames = -1 // see os.File.Readdirnames doc
132
133 names, err := dir.Readdirnames(readAllDirnames)
134 if err != nil {
135 return err
136 }
137
138 capacity := len(names)
139 list := make([]int, 0, capacity)
140
141 for _, name := range names {
142 if name[0] < '0' || name[0] > '9' {
143 continue
144 }
145 pid, err := strconv.Atoi(name)
146 if err == nil {
147 list = append(list, pid)
148 }
149 }
150
151 self.List = list
152
153 return nil
154 }
155
156 func (self *ProcState) Get(pid int) error {
157 contents, err := readProcFile(pid, "stat")
158 if err != nil {
159 return err
160 }
161
162 fields := strings.Fields(string(contents))
163
164 self.Name = fields[1][1 : len(fields[1])-1] // strip ()'s
165
166 self.State = RunState(fields[2][0])
167
168 self.Ppid, _ = strconv.Atoi(fields[3])
169
170 self.Tty, _ = strconv.Atoi(fields[6])
171
172 self.Priority, _ = strconv.Atoi(fields[17])
173
174 self.Nice, _ = strconv.Atoi(fields[18])
175
176 self.Processor, _ = strconv.Atoi(fields[38])
177
178 return nil
179 }
180
181 func (self *ProcMem) Get(pid int) error {
182 contents, err := readProcFile(pid, "statm")
183 if err != nil {
184 return err
185 }
186
187 fields := strings.Fields(string(contents))
188
189 size, _ := strtoull(fields[0])
190 self.Size = size << 12
191
192 rss, _ := strtoull(fields[1])
193 self.Resident = rss << 12
194
195 share, _ := strtoull(fields[2])
196 self.Share = share << 12
197
198 contents, err = readProcFile(pid, "stat")
199 if err != nil {
200 return err
201 }
202
203 fields = strings.Fields(string(contents))
204
205 self.MinorFaults, _ = strtoull(fields[10])
206 self.MajorFaults, _ = strtoull(fields[12])
207 self.PageFaults = self.MinorFaults + self.MajorFaults
208
209 return nil
210 }
211
212 func (self *ProcTime) Get(pid int) error {
213 contents, err := readProcFile(pid, "stat")
214 if err != nil {
215 return err
216 }
217
218 fields := strings.Fields(string(contents))
219
220 user, _ := strtoull(fields[13])
221 sys, _ := strtoull(fields[14])
222 // convert to millis
223 self.User = user * (1000 / system.ticks)
224 self.Sys = sys * (1000 / system.ticks)
225 self.Total = self.User + self.Sys
226
227 // convert to millis
228 self.StartTime, _ = strtoull(fields[21])
229 self.StartTime /= system.ticks
230 self.StartTime += system.btime
231 self.StartTime *= 1000
232
233 return nil
234 }
235
fb874eb @dougm Initial import
dougm authored
236 func parseMeminfo(table map[string]*uint64) error {
237 return readFile(procd+"meminfo", func(line string) bool {
238 fields := strings.Split(line, ":")
239
240 if ptr := table[fields[0]]; ptr != nil {
241 num := strings.TrimLeft(fields[1], " ")
242 val, err := strtoull(strings.Fields(num)[0])
243 if err == nil {
244 *ptr = val * 1024
245 }
246 }
247
248 return true
249 })
250 }
251
252 func readFile(file string, handler func(string) bool) error {
253 contents, err := ioutil.ReadFile(file)
254 if err != nil {
255 return err
256 }
257
258 reader := bufio.NewReader(bytes.NewBuffer(contents))
259
260 for {
261 line, _, err := reader.ReadLine()
262 if err == io.EOF {
263 break
264 }
265 if !handler(string(line)) {
266 break
267 }
268 }
269
270 return nil
271 }
272
273 func strtoull(val string) (uint64, error) {
274 return strconv.ParseUint(val, 10, 64)
275 }
35d6c1b @dougm Start process interfaces
dougm authored
276
277 func readProcFile(pid int, name string) ([]byte, error) {
278 path := procd + strconv.Itoa(pid) + "/" + name
279 contents, err := ioutil.ReadFile(path)
280
281 if err != nil {
282 if perr, ok := err.(*os.PathError); ok {
283 if perr.Err == syscall.ENOENT {
284 return nil, syscall.ESRCH
285 }
286 }
287 }
288
289 return contents, err
290 }
Something went wrong with that request. Please try again.