mirror of https://github.com/shirou/gopsutil
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
3.6 KiB
Go
158 lines
3.6 KiB
Go
// SPDX-License-Identifier: BSD-3-Clause
|
|
//go:build aix && !cgo
|
|
|
|
package cpu
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/shirou/gopsutil/v4/internal/common"
|
|
)
|
|
|
|
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
|
var ret []TimesStat
|
|
if percpu {
|
|
per_out, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lines := strings.Split(string(per_out), "\n")
|
|
if len(lines) < 6 {
|
|
return []TimesStat{}, common.ErrNotImplementedError
|
|
}
|
|
|
|
hp := strings.Fields(lines[5]) // headers
|
|
for l := 6; l < len(lines)-1; l++ {
|
|
ct := &TimesStat{}
|
|
v := strings.Fields(lines[l]) // values
|
|
for i, header := range hp {
|
|
// We're done in any of these use cases
|
|
if i >= len(v) || v[0] == "-" {
|
|
break
|
|
}
|
|
|
|
// Position variable for v
|
|
pos := i
|
|
// There is a missing field at the beginning of all but the first line
|
|
// so adjust the position
|
|
if l > 6 {
|
|
pos = i - 1
|
|
}
|
|
// We don't want invalid positions
|
|
if pos < 0 {
|
|
continue
|
|
}
|
|
|
|
if t, err := strconv.ParseFloat(v[pos], 64); err == nil {
|
|
switch header {
|
|
case `cpu`:
|
|
ct.CPU = strconv.FormatFloat(t, 'f', -1, 64)
|
|
case `%usr`:
|
|
ct.User = t
|
|
case `%sys`:
|
|
ct.System = t
|
|
case `%wio`:
|
|
ct.Iowait = t
|
|
case `%idle`:
|
|
ct.Idle = t
|
|
}
|
|
}
|
|
}
|
|
// Valid CPU data, so append it
|
|
ret = append(ret, *ct)
|
|
}
|
|
} else {
|
|
out, err := invoke.CommandWithContext(ctx, "sar", "-u", "10", "1")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lines := strings.Split(string(out), "\n")
|
|
if len(lines) < 5 {
|
|
return []TimesStat{}, common.ErrNotImplementedError
|
|
}
|
|
|
|
ct := &TimesStat{CPU: "cpu-total"}
|
|
h := strings.Fields(lines[len(lines)-3]) // headers
|
|
v := strings.Fields(lines[len(lines)-2]) // values
|
|
for i, header := range h {
|
|
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
|
|
switch header {
|
|
case `%usr`:
|
|
ct.User = t
|
|
case `%sys`:
|
|
ct.System = t
|
|
case `%wio`:
|
|
ct.Iowait = t
|
|
case `%idle`:
|
|
ct.Idle = t
|
|
}
|
|
}
|
|
}
|
|
|
|
ret = append(ret, *ct)
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
|
out, err := invoke.CommandWithContext(ctx, "prtconf")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := InfoStat{}
|
|
for _, line := range strings.Split(string(out), "\n") {
|
|
if strings.HasPrefix(line, "Number Of Processors:") {
|
|
p := strings.Fields(line)
|
|
if len(p) > 3 {
|
|
if t, err := strconv.ParseUint(p[3], 10, 64); err == nil {
|
|
ret.Cores = int32(t)
|
|
}
|
|
}
|
|
} else if strings.HasPrefix(line, "Processor Clock Speed:") {
|
|
p := strings.Fields(line)
|
|
if len(p) > 4 {
|
|
if t, err := strconv.ParseFloat(p[3], 64); err == nil {
|
|
switch strings.ToUpper(p[4]) {
|
|
case "MHZ":
|
|
ret.Mhz = t
|
|
case "GHZ":
|
|
ret.Mhz = t * 1000.0
|
|
case "KHZ":
|
|
ret.Mhz = t / 1000.0
|
|
default:
|
|
ret.Mhz = t
|
|
}
|
|
}
|
|
}
|
|
break
|
|
} else if strings.HasPrefix(line, "System Model:") {
|
|
p := strings.Split(string(line), ":")
|
|
if p != nil {
|
|
ret.VendorID = strings.TrimSpace(p[1])
|
|
}
|
|
} else if strings.HasPrefix(line, "Processor Type:") {
|
|
p := strings.Split(string(line), ":")
|
|
if p != nil {
|
|
c := strings.Split(string(p[1]), "_")
|
|
if c != nil {
|
|
ret.Family = strings.TrimSpace(c[0])
|
|
ret.Model = strings.TrimSpace(c[1])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return []InfoStat{ret}, nil
|
|
}
|
|
|
|
func CountsWithContext(ctx context.Context, _ bool) (int, error) {
|
|
info, err := InfoWithContext(ctx)
|
|
if err == nil {
|
|
return int(info[0].Cores), nil
|
|
}
|
|
return 0, err
|
|
}
|