diff --git a/go_bindings/gotoc/cpu.go b/go_bindings/gotoc/cpu.go index 5b8269b7..04840490 100644 --- a/go_bindings/gotoc/cpu.go +++ b/go_bindings/gotoc/cpu.go @@ -2,19 +2,134 @@ package gotoc import ( - - + "github.com/vmware/leap/util" "unsafe" + "fmt" + "time" + "strconv" ) //#include "../../../../../Include/sigar.h" +//#include "../../../../../Include/sigar_format.h" import "C" - - - +var _prevCpuUsage C.sigar_cpu_t //usged for percentage calculation +var prevSampleTs int64 + +type CpuUsageInfo struct { + User uint64 + Sys uint64 + Nice uint64 + Idle uint64 + Wait uint64 + Irq uint64 + SoftIrq uint64 + Stolen uint64 + Total uint64 +} +type CpuPctUsageInfo struct { + User float64 + Sys float64 + Nice float64 + Idle float64 + Wait float64 + Irq float64 + SoftIrq float64 + Stolen float64 + Combined float64 +} +func (this *CpuPctUsageInfo) String() string { + return "CPU states: "+ + strconv.FormatFloat(this.User,'f', 1, 64)+"% user, "+ + strconv.FormatFloat(this.Sys,'f', 1, 64)+"% system, "+ + strconv.FormatFloat(this.Nice,'f', 1, 64)+"% nice, "+ + strconv.FormatFloat(this.Wait,'f', 1, 64) +"% wait, "+ + strconv.FormatFloat(this.Idle,'f', 1, 64)+"% idle" +} + +//------------------------------------------------------------------------------------------------------------------------------------------------ +// CpuPctUsageInfo (Float64) CpuPctUsageInfo (Float64) CpuPctUsageInfo (Float64) CpuPctUsageInfo (Float64) CpuPctUsageInfo (Float64) +//------------------------------------------------------------------------------------------------------------------------------------------------ +func GetCpuPctUsageInfo() (result *CpuPctUsageInfo, err error) { + defer util.Panic2Error(&err) + + sigar := GetSigarHandle() + cur_c_cpu_t, err := _getCpu(sigar) + if err != nil { + return nil,err + } + + if prevSampleTs == 0 { + + _prevCpuUsage = *cur_c_cpu_t + time.Sleep(500*time.Millisecond) + + cur_c_cpu_t, err = _getCpu(sigar) + if err != nil { + return nil,err + } + } + + var c_pct_cpu_t C.sigar_cpu_perc_t + C.sigar_cpu_perc_calculate(&_prevCpuUsage, cur_c_cpu_t, &c_pct_cpu_t) + _prevCpuUsage = *cur_c_cpu_t + prevSampleTs = util.NowEpoch() + + return &CpuPctUsageInfo{ + User : float64(c_pct_cpu_t.user), + Sys : float64(c_pct_cpu_t.sys), + Nice : float64(c_pct_cpu_t.nice), + Idle : float64(c_pct_cpu_t.idle), + Wait : float64(c_pct_cpu_t.wait), + Irq : float64(c_pct_cpu_t.irq), + SoftIrq : float64(c_pct_cpu_t.soft_irq), + Stolen : float64(c_pct_cpu_t.stolen), + Combined : float64(c_pct_cpu_t.combined), + },nil + +} + +//------------------------------------------------------------------------------------------------------------------------------------------------ +//CpuUsageInfo (uint64) CpuUsageInfo (uint64) CpuUsageInfo (uint64) CpuUsageInfo (uint64) CpuUsageInfo (uint64) CpuUsageInfo (uint64) +//------------------------------------------------------------------------------------------------------------------------------------------------ +func GetCpuUsageInfo() (result *CpuUsageInfo, err error) { + defer util.Panic2Error(&err) + + c_cpu_t, err := _getCpu(GetSigarHandle()) + if err != nil { + return nil,err + } + + return &CpuUsageInfo{ + User : uint64(c_cpu_t.user), + Sys : uint64(c_cpu_t.sys), + Nice : uint64(c_cpu_t.nice), + Idle : uint64(c_cpu_t.idle), + Wait : uint64(c_cpu_t.wait), + Irq : uint64(c_cpu_t.irq), + SoftIrq : uint64(c_cpu_t.soft_irq), + Stolen : uint64(c_cpu_t.stolen), + Total : uint64(c_cpu_t.total), + },nil +} + +//------------------------------------------------------------------------------------------------------------------------------------------------ +//Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers +//------------------------------------------------------------------------------------------------------------------------------------------------ +func _getCpu(sigar *C.sigar_t) (*C.sigar_cpu_t, error) { + + var c_cpu_t C.sigar_cpu_t + if status := int(C.sigar_cpu_get(sigar, &c_cpu_t)) ; status != SIGAR_OK { + return nil,fmt.Errorf("Failed to retrieve cpu usage info with error: %v", status) + } + + return &c_cpu_t,nil +} +//------------------------------------------------------------------------------------------------------------------------------------------------ +//List List List List List List List List List List List List List List List List List List List List List List List List List List List List +//------------------------------------------------------------------------------------------------------------------------------------------------ func Cpu() (C.sigar_cpu_list_t,[]C.sigar_cpu_t){ diff --git a/go_bindings/gotoc/fileInfo.go b/go_bindings/gotoc/fileInfo.go index db959e95..21b50559 100644 --- a/go_bindings/gotoc/fileInfo.go +++ b/go_bindings/gotoc/fileInfo.go @@ -2,9 +2,9 @@ package gotoc import ( - - + "fmt" "unsafe" + "strconv" ) /* #include "../../../../../Include/sigar.h" @@ -15,30 +15,77 @@ import ( import "C" -func FileInfo() []C.sigar_file_system_t{ +const ( + FSTYPE_UNKNOWN = iota + FSTYPE_NONE + FSTYPE_LOCAL_DISK + FSTYPE_NETWORK + FSTYPE_RAM_DISK + FSTYPE_CDROM + FSTYPE_SWAP + FSTYPE_MAX +) + +type FsInfo struct { + DirName string + DevName string + TypeName string + SysTypeName string + Options string + Type int + Flags uint64 +} +func (this *FsInfo) String() string { + return fmt.Sprintf("{Dirname: %v, DevName: %v, TypeName: %v, SysTypeName: %v, Options: %v, Type: %v, Flags:%v", + this.DirName, + this.DevName, + this.TypeName, + this.SysTypeName, + this.Options, + this.Type, + this.Flags, + ) +} + +func GetFsInfo() (result []*FsInfo, err error){ + defer func() { + if r := recover() ; r != nil{ + err = fmt.Errorf("Failed to discover file systems due to: " + err.Error()) + } + }() var sigar *C.sigar_t=GetSigarHandle() var fileSystemList C.sigar_file_system_list_t - //C.fileInfo(sigar,&fileSystemList) C.sigar_file_system_list_get(sigar, &fileSystemList); + defer C.sigar_file_system_list_destroy(sigar, &fileSystemList); var length int=int(fileSystemList.number) - cFs:=GetGoSlice(length, unsafe.Pointer(fileSystemList.data)) var goFs []C.sigar_file_system_t goFs = *(*[]C.sigar_file_system_t)(unsafe.Pointer(&cFs)) - - //fmt.Printf("%v\n", C.GoString(&goFs[1].dir_name[0])) - C.sigar_file_system_list_destroy(sigar, &fileSystemList); - return goFs - - + result = make([]*FsInfo, length) + for i,fs := range goFs { + fsType,err := strconv.Atoi(fmt.Sprintf("%v", fs._type)) + if err != nil { + fsType = FSTYPE_UNKNOWN + } + result[i] = &FsInfo{ + DirName : C.GoString(&fs.dir_name[0]), + DevName : C.GoString(&fs.dev_name[0]), + TypeName : C.GoString(&fs.type_name[0]), + SysTypeName : C.GoString(&fs.sys_type_name[0]), + Options : C.GoString(&fs.options[0]), + Type : fsType, + Flags : uint64(fs.flags), + } + } + + return result,nil } - diff --git a/go_bindings/gotoc/fsusage.go b/go_bindings/gotoc/fsusage.go new file mode 100644 index 00000000..8d056cbc --- /dev/null +++ b/go_bindings/gotoc/fsusage.go @@ -0,0 +1,122 @@ +package gotoc + + +import ( + "fmt" + "unsafe" +) +/* +#include +#include "../../../../../Include/sigar.h" +*/ +import "C" + +type sigar_file_system_usage_t struct { + UsedPct float64 + Total int64 + Free int64 + Used int64 + Avail int64 + Files int64 + FreeFiles int64 +} + +type FsUsage struct { + UsedPct float64 + Total int64 + Free int64 + Used int64 + Avail int64 + Files int64 + FreeFiles int64 +} + +func (this *FsUsage) String() string { return fmt.Sprintf("used: %v, total: %v, free: %v, used: %v, avail: %v, files: %v, freeFiles: %v", this.UsedPct, this.Total, this.Free, this.Used, this.Avail, this.Files, this.FreeFiles) } + +type DiskUsage struct { + Reads int64 + Writes int64 + WriteBytes int64 + ReadBytes int64 + Rtime int64 + Wtime int64 + Qtime int64 + Time int64 + SnapTime int64 + ServiceTime float64 + Queue float64 +} + +type FsUsageInfo struct { + Fs *FsUsage + Disk *DiskUsage +} + +func GetFsUsageInfo(dirName string, diskName string)(fsUsageInfo *FsUsageInfo,err error){ + + var sigar *C.sigar_t=GetSigarHandle() + //TODO: noticed that sigar_file_system_usage_t contains a sigar_disk_usage_t member, should there be two invocations? + fsUsage, err := _getFsUsage(dirName, sigar) + if err != nil { + return nil, err + } + + diskUsage, err := _getDiskUsage(diskName, sigar) ; + if err != nil { + return nil,err + } + + + return &FsUsageInfo {fsUsage, diskUsage}, err +} + + +func GetFsUsage(dirName string) (*FsUsage, error) { + return _getFsUsage(dirName, GetSigarHandle()) +} + +func _getFsUsage(dirName string, sigar *C.sigar_t) (out *FsUsage, err error) { + var fsusage C.sigar_file_system_usage_t + + dir:=C.CString(dirName) + + C.free(unsafe.Pointer(dir)) + + C.sigar_file_system_usage_get(sigar , dir, &fsusage) + + out = &FsUsage{ + float64(fsusage.use_percent), + int64(fsusage.total), + int64(fsusage.free), + int64(fsusage.used), + int64(fsusage.avail), + int64(fsusage.files), + int64(fsusage.free_files), + } + + return out,nil +} + +func GetDiskUsage(diskName string) (*DiskUsage, error) { + return _getDiskUsage(diskName, GetSigarHandle()) +} + +func _getDiskUsage(diskName string, sigar *C.sigar_t) (*DiskUsage, error) { + var diskusage C.sigar_disk_usage_t + disk:=C.CString(diskName) + defer C.free(unsafe.Pointer(disk)) + C.sigar_disk_usage_get(sigar , disk, &diskusage) + return &DiskUsage { + int64(diskusage.reads), + int64(diskusage.writes), + int64(diskusage.write_bytes), + int64(diskusage.read_bytes), + int64(diskusage.rtime), + int64(diskusage.wtime), + int64(diskusage.qtime), + int64(diskusage.time), + int64(diskusage.snaptime), + float64(diskusage.service_time), + float64(diskusage.queue), + },nil +} \ No newline at end of file diff --git a/go_bindings/gotoc/handle.go b/go_bindings/gotoc/handle.go index 3fa60670..d9862723 100644 --- a/go_bindings/gotoc/handle.go +++ b/go_bindings/gotoc/handle.go @@ -48,11 +48,19 @@ func GetGoSlice(number int, pointer unsafe.Pointer ) reflect.SliceHeader{ Len: length, Cap: length, } - - - return cObj +} + + +func CArr2SlicePtr(length int, cArray interface{}) unsafe.Pointer{ + vl := reflect.ValueOf(cArray) + header := reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(vl.Pointer())), + Len: length, + Cap: length, + } + return unsafe.Pointer(&header) } \ No newline at end of file diff --git a/go_bindings/gotoc/main.go b/go_bindings/gotoc/main.go deleted file mode 100644 index cf94faf0..00000000 --- a/go_bindings/gotoc/main.go +++ /dev/null @@ -1,11 +0,0 @@ -package gotoc - -import ( - -) - -func main(){ - - - NetInfo() -} \ No newline at end of file diff --git a/go_bindings/gotoc/mem.go b/go_bindings/gotoc/mem.go index 3c034703..29d7cf19 100644 --- a/go_bindings/gotoc/mem.go +++ b/go_bindings/gotoc/mem.go @@ -2,9 +2,8 @@ package gotoc import ( - - - + "fmt" + "github.com/vmware/leap/util" ) /* @@ -15,17 +14,49 @@ import ( */ import "C" -type Info struct { - Free int64 +type Mem struct { + Ram uint64 + Total uint64 + Used uint64 + Free uint64 + ActualUsed uint64 + ActualFree uint64 + UsedPerecent float64 + FreePerecent float64 +} +func (this *Mem) String() string { + return fmt.Sprintf("Mem: %vK av, %vK used, %vK free", (this.Total / 1024),(this.Used / 1024), (this.Free / 1024)) +} + +type Swap struct { + Total uint64 + Used uint64 + Free uint64 + PageIn uint64 + PageOut uint64 +} +func (this *Swap) String() string { + return fmt.Sprintf("Swap: %vK av, %vK used, %vK free", (this.Total / 1024),(this.Used / 1024), (this.Free / 1024)) } type MemInfo struct { - Mem *Info - Swap *Info + Mem *Mem + Swap *Swap } -func GetMemInfo() (*MemInfo, error){ +func GetTotalMem() (total uint64,err error) { + defer util.Panic2Error(&err) + var sigar *C.sigar_t=GetSigarHandle() + var mem C.sigar_mem_t + status := int(C.sigar_mem_get(sigar, &mem)) + if status != SIGAR_OK { + return 0,fmt.Errorf("Failed to rertieve sys mem info with error: %v", status) + } + return uint64(mem.total),nil +} +func GetMemInfo() (result *MemInfo,err error){ + defer util.Panic2Error(&err) var sigar *C.sigar_t=GetSigarHandle() var mem C.sigar_mem_t var swap C.sigar_swap_t @@ -34,11 +65,24 @@ func GetMemInfo() (*MemInfo, error){ C.sigar_swap_get(sigar, &swap); return &MemInfo{ - Mem : &Info{ Free : int64(mem.free)}, - Swap : &Info{ Free : int64(swap.free)}, + Mem : &Mem{ + Ram : uint64(mem.ram), + Total : uint64(mem.total), + Used : uint64(mem.used), + Free : uint64(mem.free), + ActualUsed : uint64(mem.actual_used), + ActualFree : uint64(mem.actual_free), + UsedPerecent : float64(mem.used_percent), + FreePerecent : float64(mem.free_percent), + }, + Swap : &Swap{ + Total : uint64(swap.total), + Used : uint64(swap.used), + Free : uint64(swap.free), + PageIn : uint64(swap.page_in), + PageOut : uint64(swap.page_out), + }, },nil - - } diff --git a/go_bindings/gotoc/netconfig.go b/go_bindings/gotoc/netconfig.go index 55103702..6f0da71a 100644 --- a/go_bindings/gotoc/netconfig.go +++ b/go_bindings/gotoc/netconfig.go @@ -2,47 +2,168 @@ package gotoc import ( - + "fmt" "unsafe" - - + "github.com/vmware/leap/util" ) /* #include "../../../../../Include/sigar.h" -#include #include +#include + typedef unsigned char byte; - void translateNetConfig(sigar_t *sigar){ - - - - - sigar_net_interface_config_t config; - - - - - sigar_net_interface_config_get(sigar, "eth10", &config); - sigar_uint32_t a=config.address.addr.in; - - - char buf[180]; - unsigned char* ucp = (unsigned char *)&a; - sprintf(buf, "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff); - printf("%s\n",buf); - - - - - - - } - + void translateNetConfig(sigar_t *sigar){ + + sigar_net_interface_list_t net_iflist; + size_t i; + + sigar_net_interface_list_get(sigar, &net_iflist); + printf("number: %lu\n", net_iflist.number) ; + for (i = 0; i < net_iflist.number; i++) { + char *ifname = net_iflist.data[i]; + sigar_net_interface_stat_t ifstat; + sigar_net_interface_config_t config; + + int ret=sigar_net_interface_config_get(sigar, ifname, &(config)); + if(ret!=SIGAR_OK){ + printf("error number: %d\n",ret); + return; + } + sigar_uint32_t a=config.address.addr.in; + char buf[180]; + unsigned char* ucp = (unsigned char *)&a; + sprintf(buf, "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff); + printf("%s: %s\n",ifname, buf); + + + } + sigar_net_interface_config_t netconfPrimary; + sigar_net_interface_config_primary_get(sigar, &netconfPrimary); + sigar_uint32_t a=netconfPrimary.address.addr.in; + + char buf[18]; + unsigned char* ucp = (unsigned char *)&a; + sprintf(buf, "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff); + printf("%s\n",buf); + + sigar_net_interface_list_destroy(sigar, &net_iflist); + + + //char *name=netinfo->name; + //char *type=netinfo->type; + + //sigar_uint32_t a=netinfo->address.addr.in; + //printf("%s broadcast:\n", netinfo->address.addr.mac[0]); + //printf("%d.%d.%d.%d", (byte)a>>24 & 0xFF, (byte)a>>16 & 0xFF, (byte)a>>8& 0xFF, (byte)a& 0xFF); + } + */ import "C" +type NetConfig struct { +} + +type NetAddress struct{ + Family string + In uint32 + In6 uint32 + Mac string +} +func (this *NetAddress) String() string { return fmt.Sprintf("{ Family: %v, In: %v, in6: %v, Mac: %v }", this.Family, this.In, this.In6, this.Mac) } + +type InterfaceConfigInfo struct { + Name string + Type string + Description string + Hwaddr *NetAddress + Address *NetAddress + Destination *NetAddress + Broadcast *NetAddress + Netmask *NetAddress + Address6 *NetAddress + Prefix6Length int + Scope6 int + Flags uint64 + Mtu uint64 + Metric uint64 + TxQueueLen int +} +func (this *InterfaceConfigInfo) String() string { + return fmt.Sprintf(`Name: %v, Type: %v, Description: %v, Hwaddr: %v, Address: %v, Destination: %v, Broadcast: %v, Netmask: %v, Address6: %v, Prefix6Length: %v, Scope6: %v, Flags: %v, Mtu: %v, Metric: %v, TxQueueLen: %v`, + this.Name, + this.Type, + this.Description, + this.Hwaddr, + this.Address, + this.Destination, + this.Broadcast, + this.Netmask, + this.Address6, + this.Prefix6Length, + this.Scope6, + this.Flags, + this.Mtu, + this.Metric, + this.TxQueueLen, + ) +} + +type NetIfaceUsageInfo struct { + RxPackets uint64 + RxBytes uint64 + RxErrors uint64 + RxDropped uint64 + RxOverruns uint64 + RxFrame uint64 + /* transmitted */ + TxPackets uint64 + TxBytes uint64 + TxErrors uint64 + TxDropped uint64 + TxOverruns uint64 + TxCollisions uint64 + TxCarrier uint64 + Speed uint64 +} + +//---------------------------------------------------------------------------------------- +//Top-Level Top-Level Top-Level Top-Level Top-Level Top-Level Top-Level Top-Level Top-Level +//---------------------------------------------------------------------------------------- +func GetNetInterfaceConfig() (result []*InterfaceConfigInfo, err error) { + return getNetInterfaceConfigWithSigar(GetSigarHandle()), nil +} + +func GetNetIfaceUsageInfo(netIfaceName string) (netifaceInfo *NetIfaceUsageInfo, err error) { + defer util.Panic2Error(&err) + + c_netifaceName := C.CString(netIfaceName) + defer Free(c_netifaceName) + + var c_sigar_net_interface_stat_t C.sigar_net_interface_stat_t + if status := int(C.sigar_net_interface_stat_get(GetSigarHandle(), c_netifaceName, &c_sigar_net_interface_stat_t)) ; status != SIGAR_OK { + return nil,fmt.Errorf("Failed to rertieve network interface status for: %v with error: %v", netIfaceName, status) + } + + return &NetIfaceUsageInfo{ + RxPackets: uint64(c_sigar_net_interface_stat_t.rx_packets), + RxBytes: uint64(c_sigar_net_interface_stat_t.rx_bytes), + RxErrors: uint64(c_sigar_net_interface_stat_t.rx_errors), + RxDropped: uint64(c_sigar_net_interface_stat_t.rx_dropped), + RxOverruns: uint64(c_sigar_net_interface_stat_t.rx_overruns), + RxFrame: uint64(c_sigar_net_interface_stat_t.rx_frame), + TxPackets: uint64(c_sigar_net_interface_stat_t.tx_packets), + TxBytes: uint64(c_sigar_net_interface_stat_t.tx_bytes), + TxErrors: uint64(c_sigar_net_interface_stat_t.tx_errors), + TxDropped: uint64(c_sigar_net_interface_stat_t.tx_dropped), + TxOverruns: uint64(c_sigar_net_interface_stat_t.tx_overruns), + TxCollisions: uint64(c_sigar_net_interface_stat_t.tx_collisions), + TxCarrier: uint64(c_sigar_net_interface_stat_t.tx_carrier), + Speed: uint64(c_sigar_net_interface_stat_t.speed), + },nil + +} func GetNetConfig()(C.sigar_net_interface_config_t,[]C.sigar_net_interface_config_t,[]C.sigar_net_interface_stat_t){ @@ -78,30 +199,103 @@ func GetNetConfig()(C.sigar_net_interface_config_t,[]C.sigar_net_interface_confi return netconfPrimary, netconf, netstat } -func GetNetInterfaceConfig(){ - - - //_,netconf,_:=GetNetConfig() - - - var sigar *C.sigar_t=GetSigarHandle() - C.translateNetConfig(sigar) +//---------------------------------------------------------------------------------------- +//Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers Helpers +//---------------------------------------------------------------------------------------- + +func getNetInterfaceConfigWithSigar(sigar *C.sigar_t) (result []*InterfaceConfigInfo) { + goInterfacesNames, length, closeable := getNetInterfaceNamesWithSigar(sigar) + defer closeable(sigar) + result = make([]*InterfaceConfigInfo, length) + var sigarNetInterfaceConfig C.sigar_net_interface_config_t + for i:=0;i 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 +} diff --git a/go_bindings/gotoc/ptql.go b/go_bindings/gotoc/ptql.go new file mode 100644 index 00000000..8d9ab73c --- /dev/null +++ b/go_bindings/gotoc/ptql.go @@ -0,0 +1,56 @@ +package gotoc + +/* +#include "../../../../../Include/sigar.h" +#include "../../../../../Include/sigar_ptql.h" +#include +#include +*/ +import "C" + +import ( + "fmt" + "github.com/vmware/leap/util" +) + + +func ExecutePtql(ptql string, infoTypesMask ProcInfoType) (result []*ProcessInfo, err error){ + defer util.Panic2Error(&err) + + var query *C.sigar_ptql_query_t + var queryError *C.sigar_ptql_error_t + var proclist C.sigar_proc_list_t + + sigar := GetSigarHandle() + ptqlC := C.CString(ptql) + //defer C.sigar_ptql_query_destroy(query) + defer C.sigar_proc_list_destroy(sigar, &proclist) + defer C.sigar_ptql_re_impl_set(sigar, nil, nil) + defer Free(ptqlC) + + if status := C.sigar_ptql_query_create(&query, ptqlC, queryError) ; status != SIGAR_OK { + err = fmt.Errorf("Failed to create sigar ptql query for: %v with errorcode: %v", ptql, status) + return nil,err + } + + C.sigar_ptql_query_find(sigar, query, &proclist) + C.sigar_ptql_query_destroy(query) + + /* + noOfProcesses := int(proclist.number) + result = make([]*ProcessInfo, noOfProcesses) + pids := *(*[]C.sigar_pid_t) (CArr2SlicePtr(noOfProcesses, proclist.data)) + for i,pid := range pids { + procInfo,err := GetProcInfo(uint64(pid), infoTypesMask) + if err != nil { + return nil,err + } + result[i] = procInfo + } + + return result,nil*/ + + processes,err := getProcInfos(&proclist, infoTypesMask, sigar) + return processes.Processes,err +} + diff --git a/go_bindings/gotoc/sysInfo.go b/go_bindings/gotoc/sysInfo.go index 12d67f33..6d80e6d2 100644 --- a/go_bindings/gotoc/sysInfo.go +++ b/go_bindings/gotoc/sysInfo.go @@ -1,25 +1,63 @@ package gotoc import ( - - "unsafe" + "github.com/vmware/leap/util" ) /* - #include "../../../../../Include/sigar.h" - - - #cgo CFLAGS: -I../../../../../Include -#cgo LDFLAGS: C:/Users/iuriel/workspace/vmeerkat/leap-project/Include/sigar-amd64-winnt.dll - - +#cgo darwin LDFLAGS: -L ${SRCDIR}/../../../../../Libs/darwin/ -lsigar +#cgo linux LDFLAGS: -ldl -L ${SRCDIR}/../../../../../Libs/linux-amd64/ -lsigar */ -import "C" +import "C" + +var SYS_INFO *SysInfo -func SysInfo() (C.sigar_sys_info_t, []C.sigar_who_t) { +func init() { + + var err error + if SYS_INFO,err = GetSysInfo() ; err != nil { + panic("Failed to extract system info due to " + err.Error()) + } +} + +type SysInfo struct { + Name string `json:"type"` + Version string `json:"version"` + Arch string `json:"arch"` + Machine string `json:"-"` + Description string `json:"description"` + PatchLevel string `json:"patchLevel"` + Vendor string `json:"vendor"` + VendorVersion string `json:"version"` + VendorName string `json:"vendorName"` + VendorCodeName string `json:"codeName"` +} + +func GetSysInfo() (sysinfo *SysInfo, err error) { + defer util.Panic2Error(&err) + + var sigar *C.sigar_t=GetSigarHandle() + var c_sysInfo C.sigar_sys_info_t + C.sigar_sys_info_get(sigar, &c_sysInfo) + + return &SysInfo{ + Name : C.GoString(&c_sysInfo.name[0]), + Version : C.GoString(&c_sysInfo.version[0]), + Arch : C.GoString(&c_sysInfo.arch[0]), + Machine : C.GoString(&c_sysInfo.machine[0]), + Description : C.GoString(&c_sysInfo.description[0]), + PatchLevel : C.GoString(&c_sysInfo.patch_level[0]), + Vendor : C.GoString(&c_sysInfo.vendor[0]), + VendorName : C.GoString(&c_sysInfo.vendor_name[0]), + VendorVersion : C.GoString(&c_sysInfo.vendor_version[0]), + VendorCodeName : C.GoString(&c_sysInfo.vendor_code_name[0]), + },nil +} + +func _GetSysInfo() (C.sigar_sys_info_t, []C.sigar_who_t) { var sigar *C.sigar_t=GetSigarHandle() diff --git a/go_bindings/gotoc/uptime.go b/go_bindings/gotoc/uptime.go index 799966db..c74d09d6 100644 --- a/go_bindings/gotoc/uptime.go +++ b/go_bindings/gotoc/uptime.go @@ -1,27 +1,97 @@ package gotoc import ( - - - + "fmt" + "time" + "strconv" + "github.com/vmware/leap/util" ) /* - #include "../../../../../Include/sigar.h" - - */ import "C" -func UpTime()C.sigar_uptime_t{ +type UptimeInfo struct { + Time time.Time + Uptime float64 + LoadAvg []float64 +} +func (this *UptimeInfo) String() string { + + _uptime := this.Time.Format(time.Kitchen) + " up" + days := int((this.Uptime / (60 * 60 * 24))) + var minutes, hours int + if days != 0 { + _uptime = _uptime + " " + strconv.Itoa(days) + " " + if days > 1 { + _uptime = _uptime + "days" + }else{ + _uptime = _uptime + "day" + } + _uptime = _uptime + ", " + } + + minutes = int(this.Uptime / 60) + hours = int(minutes / 60) + hours = hours % 24 + minutes = minutes % 60 + + if hours != 0 { + _uptime = _uptime + strconv.Itoa(hours) + ":" + if minutes < 10 { + _uptime = _uptime + "0" + } + _uptime = _uptime + strconv.Itoa(minutes); + }else{ + _uptime = _uptime + strconv.Itoa(minutes) + " min"; + } + + for _,d := range this.LoadAvg { + _uptime = _uptime + ", " + strconv.FormatFloat(d, 'f', 2, 64) + } + + return _uptime +} + + +func GetUptimeInfo() (result *UptimeInfo, err error) { + defer util.Panic2Error(&err) var sigar *C.sigar_t=GetSigarHandle() + uptime, err := _uptime(sigar) + if err != nil { + return nil,err + } + + loadAvg, err := _loadAvg(sigar) + if err != nil { + return nil,err + } + + return &UptimeInfo{ Time: time.Now(), Uptime : uptime, LoadAvg : loadAvg},nil +} + +func _uptime(sigar *C.sigar_t) (result float64, err error){ + var uptime C.sigar_uptime_t - C.sigar_uptime_get(sigar, &uptime) - - - return uptime + if status := int(C.sigar_uptime_get(sigar, &uptime)); status != SIGAR_OK { + return -1,fmt.Errorf("Failed to rertieve uptime with error: %v", status) + } + return float64(uptime.uptime),nil +} + +func _loadAvg(sigar *C.sigar_t) (result []float64, err error){ + var c_loadAvg C.sigar_loadavg_t + + if status := int(C.sigar_loadavg_get(sigar, &c_loadAvg)) ; status != SIGAR_OK { + return nil,fmt.Errorf("Failed to rertieve load avg with error: %v", status) + } + + loadAvg := (([3]C.double)(c_loadAvg.loadavg)) //[:length] + + return []float64{ float64(loadAvg[0]), float64(loadAvg[1]), float64(loadAvg[2]) },nil + } \ No newline at end of file diff --git a/go_bindings/gotoc/utils.go b/go_bindings/gotoc/utils.go index 2e5e2807..4e51953a 100644 --- a/go_bindings/gotoc/utils.go +++ b/go_bindings/gotoc/utils.go @@ -1,14 +1,17 @@ package gotoc import ( - "unsafe" ) - -//#include +/* +#include +*/ import "C" +const ( + SIGAR_OK = 0 +) func SigarStringToGoString(cstring *C.char) string{ @@ -17,4 +20,9 @@ func SigarStringToGoString(cstring *C.char) string{ defer C.free(unsafe.Pointer(cstring)) return theString -} \ No newline at end of file +} + +func Free(cstring *C.char) { + C.free(unsafe.Pointer(cstring)) +} +