sigar/go_bindings/gotoc/ps.go

409 lines
10 KiB
Go

package gotoc
import (
"unsafe"
"fmt"
"strconv"
"github.com/vmware/leap/util"
log "github.com/jbrodriguez/mlog"
)
/*
#include "../../../../../Include/sigar.h"
*/
import "C"
func Ps() ([]C.sigar_proc_state_t ,
[]C.sigar_proc_time_t,
[]C.sigar_proc_mem_t,
[]C.sigar_proc_disk_io_t,
[]C.sigar_proc_cumulative_disk_io_t,
[]C.sigar_proc_cred_t,
[]C.sigar_proc_cred_name_t,
[]C.sigar_proc_cpu_t,
[]C.sigar_proc_args_t,
[]C.sigar_proc_fd_t,
[]C.sigar_proc_exe_t){
sigar:=GetSigarHandle()
var procList C.sigar_proc_list_t
C.sigar_proc_list_get(sigar, &procList)
var length int=int(procList.number)
var pstate =make([]C.sigar_proc_state_t, length)
var ptime =make([]C.sigar_proc_time_t,length)
var pmem =make([]C.sigar_proc_mem_t,length)
var pdiskio =make([]C.sigar_proc_disk_io_t,length)
var pcumdiskio =make([]C.sigar_proc_cumulative_disk_io_t,length)
var pcred =make([]C.sigar_proc_cred_t,length)
var pcredname =make([]C.sigar_proc_cred_name_t,length)
var pcpu =make([]C.sigar_proc_cpu_t,length)
var pargs =make([]C.sigar_proc_args_t,length)
var pfd =make([]C.sigar_proc_fd_t,length)
var pexe =make([]C.sigar_proc_exe_t,length)
cpid:=GetGoSlice(length, unsafe.Pointer(procList.data))
var goPid []C.sigar_pid_t
goPid = *(*[]C.sigar_pid_t)(unsafe.Pointer(&cpid))
for i:=0;i<length;i++{
C.sigar_proc_state_get(sigar, goPid[i], &pstate[i])
C.sigar_proc_time_get(sigar, goPid[i], &ptime[i])
C.sigar_proc_mem_get(sigar, goPid[i], &pmem[i])
C.sigar_proc_disk_io_get(sigar, goPid[i], &pdiskio[i])
C.sigar_proc_cumulative_disk_io_get(sigar, goPid[i], &pcumdiskio[i])
C.sigar_proc_cred_get(sigar, goPid[i], &pcred[i])
C.sigar_proc_cred_name_get(sigar, goPid[i], &pcredname[i])
C.sigar_proc_cpu_get(sigar, goPid[i], &pcpu[i])
C.sigar_proc_fd_get(sigar, goPid[i], &pfd[i])
C.sigar_proc_exe_get(sigar, goPid[i], &pexe[i])
C.sigar_proc_args_get(sigar, goPid[i], &pargs[i])
C.sigar_proc_args_destroy(sigar, &pargs[i])
}
C.sigar_proc_list_destroy(sigar, &procList)
return pstate,
ptime,
pmem,
pdiskio,
pcumdiskio,
pcred,
pcredname,
pcpu,
pargs,
pfd,
pexe
}
//-------------------------------------------------------------------------------
//ProcessInfoList ProcessInfoList ProcessInfoList ProcessInfoList ProcessInfoList
//-------------------------------------------------------------------------------
func GetProcInfo(pid uint64, infoTypesMask ProcInfoType) (procInfo *ProcessInfo, err error) {
procInfo,_,err = _getProcInfo(pid, infoTypesMask, nil, GetSigarHandle())
return
}
func GetAllProcInfos(infoTypesMask ProcInfoType) (processes *ProcessInfoList, err error) {
var procList C.sigar_proc_list_t
defer util.Panic2Error(&err)
defer C.sigar_proc_list_destroy(sigar, &procList)
sigar:=GetSigarHandle()
C.sigar_proc_list_get(sigar, &procList)
return getProcInfos(&procList, infoTypesMask, sigar)
}
func getProcInfos(procList *C.sigar_proc_list_t, infoTypesMask ProcInfoType, sigar *C.sigar_t) (processes *ProcessInfoList, err error) {
defer util.Panic2Error(&err)
noOfProcesses := int(procList.number)
pids := *(*[]C.sigar_pid_t) (CArr2SlicePtr(noOfProcesses, procList.data))
procInfos := make([]*ProcessInfo, noOfProcesses)
var errors, index int
var sysMemInfoOut *MemInfo
for _,pid := range pids {
procInfo,sysMemInfo, err := _getProcInfo(uint64(pid), infoTypesMask, sysMemInfoOut, sigar)
if err != nil {
log.ErrorS(err.Error())
errors = errors+1
continue
}
if sysMemInfoOut == nil {
sysMemInfoOut = sysMemInfo
}
procInfos[index] = procInfo
index = index+1
}
if errors > 0 {
newSize := noOfProcesses-errors
procInfos = append(([]*ProcessInfo)(nil), procInfos[:newSize]...)
log.ErrorS("%v errors have occurred, prunning array size from %v to %v index is: %v, newSize: %v", errors, noOfProcesses, newSize, index, len(procInfos))
}
return &ProcessInfoList { procInfos, sysMemInfoOut },nil
}
//---------------------------------------------------------------------------
//ProcInfo ProcInfo ProcInfo ProcInfo ProcInfo ProcInfo ProcInfo ProcInfo
//---------------------------------------------------------------------------
type ProcInfoType uint64
const (
MEM ProcInfoType = 1 << iota
CPU
TIME
DISK
ARGS
STATE
CRED_NAME
)
type ProcessInfoList struct {
Processes []*ProcessInfo
SysMemInfo *MemInfo
}
type ProcessInfo struct {
Pid uint64
Args []string
State *ProcessStateInfo
CredName *ProcessCredName
Mem *ProcessMemInfo
Cpu *ProcessCpuInfo
Disk *ProcessDiskInfo
Error error
}
type ProcessCredName struct {
User string
Group string
}
type ProcessStateInfo struct {
Name string
State rune
Tty int
Priority int
Nice int
Processor int
Threads uint64
}
type ProcessMemInfo struct {
Size uint64
Resident uint64
Share uint64
MinorFaults uint64
MajorFaults uint64
PageFaults uint64
Percent float64
}
type ProcessCpuInfo struct {
StartTime uint64
User uint64
Sys uint64
Total uint64
LastTime uint64
Percent float64
}
type ProcessDiskInfo struct{ //sigar_proc_cumulative_disk_io_t
BytesRead uint64
BytesWritten uint64
BytesTotal uint64
}
func _getProcInfo(pid uint64, infoTypesMask ProcInfoType, sysMemInfoIn *MemInfo, sigar *C.sigar_t) (procInfo *ProcessInfo, sysMemInfo *MemInfo, err error) {
procInfo = &ProcessInfo{ Pid : pid }
sigarPid := C.sigar_pid_t(pid)
if infoTypesMask&MEM != 0 {
sysMemInfo = sysMemInfoIn
if sysMemInfo == nil {
sysMemInfo,err = GetMemInfo()
if err != nil {
return nil,nil,err
}
}
if err = _populateProcessMemInfo(sigarPid, procInfo, sysMemInfo, sigar) ; err != nil {
return nil,nil,err
}
}
if infoTypesMask&CPU != 0 {
if err = _populateProcessCpuInfo(sigarPid, procInfo, sigar) ; err != nil {
return nil,nil,err
}
}
if infoTypesMask&TIME != 0 {
}
if infoTypesMask&DISK != 0 {
if err = _populateProcessDiskInfo(sigarPid, procInfo, sigar) ; err != nil {
return nil,nil,err
}
}
if infoTypesMask&ARGS != 0 {
if err = _populateProcessArgs(sigarPid, procInfo, sigar) ; err != nil {
return nil,nil,err
}
}
if infoTypesMask&STATE != 0 {
if err = _populateProcessState(sigarPid, procInfo, sigar) ; err != nil {
return nil,nil,err
}
}
if infoTypesMask&CRED_NAME != 0 {
if err = _populateProcessCredName(sigarPid, procInfo, sigar) ; err != nil {
return nil,nil,err
}
}
return procInfo,sysMemInfo,nil
}
func _populateProcessMemInfo(pid C.sigar_pid_t, procInfo *ProcessInfo, sysMemInfo *MemInfo, sigar *C.sigar_t) error {
var procMem C.sigar_proc_mem_t
status := int(C.sigar_proc_mem_get(sigar, pid, &procMem))
if status != SIGAR_OK {
return fmt.Errorf("Failed to rertieve proc mem info for pid: "+ strconv.FormatUint(procInfo.Pid,10) +" with error: " + strconv.Itoa(status))
}
procInfo.Mem = &ProcessMemInfo{
Size : uint64(procMem.size),
Resident : uint64(procMem.resident),
Share : uint64(procMem.share),
MinorFaults : uint64(procMem.minor_faults),
MajorFaults : uint64(procMem.major_faults),
PageFaults : uint64(procMem.page_faults),
}
procInfo.Mem.Percent = float64(sysMemInfo.Mem.Total/procInfo.Mem.Resident)
return nil
}
func _populateProcessCpuInfo(pid C.sigar_pid_t, procInfo *ProcessInfo, sigar *C.sigar_t) error {
var procCpu C.sigar_proc_cpu_t
status := int(C.sigar_proc_cpu_get(sigar, pid, &procCpu))
if status != SIGAR_OK {
return fmt.Errorf("Failed to rertieve proc mem info for pid: %v", procInfo.Pid)
}
procInfo.Cpu = &ProcessCpuInfo{
StartTime : uint64(procCpu.start_time),
User : uint64(procCpu.user),
Sys : uint64(procCpu.sys),
Total : uint64(procCpu.total),
LastTime : uint64(procCpu.last_time),
Percent : float64(procCpu.percent),
}
return nil
}
func _populateProcessDiskInfo(pid C.sigar_pid_t, procInfo *ProcessInfo, sigar *C.sigar_t) error {
var c_procDiskIo C.sigar_proc_disk_io_t
status := int(C.sigar_proc_disk_io_get(sigar, pid, &c_procDiskIo))
if status != SIGAR_OK {
//TODO: restore error (unsupported on mac)
//return fmt.Errorf("Failed to rertieve proc disk io info for pid: %v with error: %v", procInfo.Pid, status)
procInfo.Disk = &ProcessDiskInfo{
BytesRead : 100000,
BytesWritten : 23423432,
BytesTotal : 2345543,
}
}
procInfo.Disk = &ProcessDiskInfo{
BytesRead : uint64(c_procDiskIo.bytes_read),
BytesWritten : uint64(c_procDiskIo.bytes_written),
BytesTotal : uint64(c_procDiskIo.bytes_total),
}
return nil
}
func _populateProcessArgs(pid C.sigar_pid_t, procInfo *ProcessInfo, sigar *C.sigar_t) error {
var c_procArgs C.sigar_proc_args_t
defer C.sigar_proc_args_destroy(sigar, &c_procArgs)
status := int(C.sigar_proc_args_get(sigar, pid, &c_procArgs))
if status != SIGAR_OK {
return fmt.Errorf("error: proc args for pid: " + strconv.FormatUint(procInfo.Pid ,10))
}
noOfArgs := int(c_procArgs.number)
args := *(*[]*C.char) (CArr2SlicePtr(noOfArgs, c_procArgs.data))
procInfo.Args = make([]string, noOfArgs)
for i,arg := range args {
procInfo.Args[i] = C.GoString(arg)
}
return nil
}
func _populateProcessState(pid C.sigar_pid_t, procInfo *ProcessInfo, sigar *C.sigar_t) error {
var c_procState C.sigar_proc_state_t
status := int(C.sigar_proc_state_get(sigar, pid, &c_procState))
if status != SIGAR_OK {
return fmt.Errorf("Failed to rertieve proc state info for pid: %v", procInfo.Pid)
}
procInfo.State = &ProcessStateInfo{
Name : C.GoString(&c_procState.name[0]),
State: rune(c_procState.state),
Tty : int(c_procState.tty),
Priority : int(c_procState.priority),
Nice : int(c_procState.nice),
Processor : int(c_procState.processor),
Threads : uint64(c_procState.threads),
}
return nil
}
var c_credName C.sigar_proc_cred_name_t
func _populateProcessCredName(pid C.sigar_pid_t, procInfo *ProcessInfo, sigar *C.sigar_t) error {
status := int(C.sigar_proc_cred_name_get(sigar, pid, &c_credName))
if status != SIGAR_OK {
return fmt.Errorf("Failed to rertieve proc cred name for pid: %v", procInfo.Pid)
}
procInfo.CredName = &ProcessCredName{
User : C.GoString(&c_credName.user[0]),
Group : C.GoString(&c_credName.group[0]),
}
return nil
}