Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 360 lines (274 sloc) 6.636 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
9d112dd @dougm Add Cpu and CpuList APIs
dougm authored
98 func (self *Cpu) Get() error {
99 return readFile(procd+"stat", func(line string) bool {
100 if line[0:4] == "cpu " {
101 parseCpuStat(self, line)
102 return false
103 }
104 return true
105 })
106 }
107
108 func (self *CpuList) Get() error {
109 capacity := len(self.List)
110 if capacity == 0 {
111 capacity = 4
112 }
113 list := make([]Cpu, 0, capacity)
114
115 err := readFile(procd+"stat", func(line string) bool {
116 if line[0:3] == "cpu" && line[3] != ' ' {
117 cpu := Cpu{}
118 parseCpuStat(&cpu, line)
119 list = append(list, cpu)
120 }
121 return true
122 })
123
124 self.List = list
125
126 return err
127 }
128
fb874eb @dougm Initial import
dougm authored
129 func (self *FileSystemList) Get() error {
130 capacity := len(self.List)
131 if capacity == 0 {
132 capacity = 10
133 }
134 fslist := make([]FileSystem, 0, capacity)
135
136 err := readFile("/etc/mtab", func(line string) bool {
137 fields := strings.Fields(line)
138
139 fs := FileSystem{}
140 fs.DevName = fields[0]
141 fs.DirName = fields[1]
142 fs.SysTypeName = fields[2]
143 fs.Options = fields[3]
144
145 fslist = append(fslist, fs)
146
147 return true
148 })
149
150 self.List = fslist
151
152 return err
153 }
154
35d6c1b @dougm Start process interfaces
dougm authored
155 func (self *ProcList) Get() error {
156 dir, err := os.Open(procd)
157 if err != nil {
158 return err
159 }
160 defer dir.Close()
161
162 const readAllDirnames = -1 // see os.File.Readdirnames doc
163
164 names, err := dir.Readdirnames(readAllDirnames)
165 if err != nil {
166 return err
167 }
168
169 capacity := len(names)
170 list := make([]int, 0, capacity)
171
172 for _, name := range names {
173 if name[0] < '0' || name[0] > '9' {
174 continue
175 }
176 pid, err := strconv.Atoi(name)
177 if err == nil {
178 list = append(list, pid)
179 }
180 }
181
182 self.List = list
183
184 return nil
185 }
186
187 func (self *ProcState) Get(pid int) error {
188 contents, err := readProcFile(pid, "stat")
189 if err != nil {
190 return err
191 }
192
193 fields := strings.Fields(string(contents))
194
195 self.Name = fields[1][1 : len(fields[1])-1] // strip ()'s
196
197 self.State = RunState(fields[2][0])
198
199 self.Ppid, _ = strconv.Atoi(fields[3])
200
201 self.Tty, _ = strconv.Atoi(fields[6])
202
203 self.Priority, _ = strconv.Atoi(fields[17])
204
205 self.Nice, _ = strconv.Atoi(fields[18])
206
207 self.Processor, _ = strconv.Atoi(fields[38])
208
209 return nil
210 }
211
212 func (self *ProcMem) Get(pid int) error {
213 contents, err := readProcFile(pid, "statm")
214 if err != nil {
215 return err
216 }
217
218 fields := strings.Fields(string(contents))
219
220 size, _ := strtoull(fields[0])
221 self.Size = size << 12
222
223 rss, _ := strtoull(fields[1])
224 self.Resident = rss << 12
225
226 share, _ := strtoull(fields[2])
227 self.Share = share << 12
228
229 contents, err = readProcFile(pid, "stat")
230 if err != nil {
231 return err
232 }
233
234 fields = strings.Fields(string(contents))
235
236 self.MinorFaults, _ = strtoull(fields[10])
237 self.MajorFaults, _ = strtoull(fields[12])
238 self.PageFaults = self.MinorFaults + self.MajorFaults
239
240 return nil
241 }
242
243 func (self *ProcTime) Get(pid int) error {
244 contents, err := readProcFile(pid, "stat")
245 if err != nil {
246 return err
247 }
248
249 fields := strings.Fields(string(contents))
250
251 user, _ := strtoull(fields[13])
252 sys, _ := strtoull(fields[14])
253 // convert to millis
254 self.User = user * (1000 / system.ticks)
255 self.Sys = sys * (1000 / system.ticks)
256 self.Total = self.User + self.Sys
257
258 // convert to millis
259 self.StartTime, _ = strtoull(fields[21])
260 self.StartTime /= system.ticks
261 self.StartTime += system.btime
262 self.StartTime *= 1000
263
264 return nil
265 }
266
ffca5cf @dougm ProcArgs - get process arguments
dougm authored
267 func (self *ProcArgs) Get(pid int) error {
268 contents, err := readProcFile(pid, "cmdline")
269 if err != nil {
270 return err
271 }
272
273 bbuf := bytes.NewBuffer(contents)
274
275 var args []string
276
277 for {
278 arg, err := bbuf.ReadBytes(0)
279 if err == io.EOF {
280 break
281 }
282 args = append(args, string(chop(arg)))
283 }
284
285 self.List = args
286
287 return nil
288 }
289
fb874eb @dougm Initial import
dougm authored
290 func parseMeminfo(table map[string]*uint64) error {
291 return readFile(procd+"meminfo", func(line string) bool {
292 fields := strings.Split(line, ":")
293
294 if ptr := table[fields[0]]; ptr != nil {
295 num := strings.TrimLeft(fields[1], " ")
296 val, err := strtoull(strings.Fields(num)[0])
297 if err == nil {
298 *ptr = val * 1024
299 }
300 }
301
302 return true
303 })
304 }
305
9d112dd @dougm Add Cpu and CpuList APIs
dougm authored
306 func parseCpuStat(self *Cpu, line string) error {
307 fields := strings.Fields(line)
308
309 self.User, _ = strtoull(fields[1])
310 self.Nice, _ = strtoull(fields[2])
311 self.Sys, _ = strtoull(fields[3])
312 self.Idle, _ = strtoull(fields[4])
313 self.Wait, _ = strtoull(fields[5])
314 self.Irq, _ = strtoull(fields[6])
315 self.SoftIrq, _ = strtoull(fields[7])
316 self.Stolen, _ = strtoull(fields[8])
317
318 return nil
319 }
320
fb874eb @dougm Initial import
dougm authored
321 func readFile(file string, handler func(string) bool) error {
322 contents, err := ioutil.ReadFile(file)
323 if err != nil {
324 return err
325 }
326
327 reader := bufio.NewReader(bytes.NewBuffer(contents))
328
329 for {
330 line, _, err := reader.ReadLine()
331 if err == io.EOF {
332 break
333 }
334 if !handler(string(line)) {
335 break
336 }
337 }
338
339 return nil
340 }
341
342 func strtoull(val string) (uint64, error) {
343 return strconv.ParseUint(val, 10, 64)
344 }
35d6c1b @dougm Start process interfaces
dougm authored
345
346 func readProcFile(pid int, name string) ([]byte, error) {
347 path := procd + strconv.Itoa(pid) + "/" + name
348 contents, err := ioutil.ReadFile(path)
349
350 if err != nil {
351 if perr, ok := err.(*os.PathError); ok {
352 if perr.Err == syscall.ENOENT {
353 return nil, syscall.ESRCH
354 }
355 }
356 }
357
358 return contents, err
359 }
Something went wrong with that request. Please try again.