2014-04-22 10:58:03 +08:00
|
|
|
// +build freebsd
|
|
|
|
|
2014-12-30 21:09:05 +08:00
|
|
|
package mem
|
2014-04-22 10:58:03 +08:00
|
|
|
|
2014-05-16 14:33:23 +08:00
|
|
|
import (
|
2017-12-31 14:25:49 +08:00
|
|
|
"context"
|
2016-01-10 08:17:21 +08:00
|
|
|
"errors"
|
2014-05-16 14:33:23 +08:00
|
|
|
"os/exec"
|
2014-09-19 23:15:35 +08:00
|
|
|
"strconv"
|
2014-05-16 14:33:23 +08:00
|
|
|
"strings"
|
2016-01-10 08:17:21 +08:00
|
|
|
|
2017-10-05 15:36:05 +08:00
|
|
|
"golang.org/x/sys/unix"
|
2014-05-16 14:33:23 +08:00
|
|
|
)
|
|
|
|
|
2014-05-01 11:01:30 +08:00
|
|
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
2017-12-31 14:25:49 +08:00
|
|
|
return VirtualMemoryWithContext(context.Background())
|
|
|
|
}
|
|
|
|
|
|
|
|
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
2017-10-05 15:36:05 +08:00
|
|
|
pageSize, err := unix.SysctlUint32("vm.stats.vm.v_page_size")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
pageCount, err := unix.SysctlUint32("vm.stats.vm.v_page_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
free, err := unix.SysctlUint32("vm.stats.vm.v_free_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
active, err := unix.SysctlUint32("vm.stats.vm.v_active_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
inactive, err := unix.SysctlUint32("vm.stats.vm.v_inactive_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
cached, err := unix.SysctlUint32("vm.stats.vm.v_cache_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
buffers, err := unix.SysctlUint32("vfs.bufspace")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-05 15:36:05 +08:00
|
|
|
wired, err := unix.SysctlUint32("vm.stats.vm.v_wire_count")
|
2014-09-19 23:15:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-05-16 14:33:23 +08:00
|
|
|
|
2017-10-05 15:36:05 +08:00
|
|
|
p := uint64(pageSize)
|
2014-05-16 14:33:23 +08:00
|
|
|
ret := &VirtualMemoryStat{
|
2017-10-05 15:36:05 +08:00
|
|
|
Total: uint64(pageCount) * p,
|
|
|
|
Free: uint64(free) * p,
|
|
|
|
Active: uint64(active) * p,
|
|
|
|
Inactive: uint64(inactive) * p,
|
|
|
|
Cached: uint64(cached) * p,
|
|
|
|
Buffers: uint64(buffers),
|
|
|
|
Wired: uint64(wired) * p,
|
2014-05-16 14:33:23 +08:00
|
|
|
}
|
|
|
|
|
2015-09-18 13:01:49 +08:00
|
|
|
ret.Available = ret.Inactive + ret.Cached + ret.Free
|
2016-02-19 15:12:58 +08:00
|
|
|
ret.Used = ret.Total - ret.Available
|
|
|
|
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
2014-04-22 10:58:03 +08:00
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
2014-05-16 14:33:23 +08:00
|
|
|
// Return swapinfo
|
|
|
|
// FreeBSD can have multiple swap devices. but use only first device
|
2014-05-01 11:01:30 +08:00
|
|
|
func SwapMemory() (*SwapMemoryStat, error) {
|
2017-12-31 14:25:49 +08:00
|
|
|
return SwapMemoryWithContext(context.Background())
|
|
|
|
}
|
|
|
|
|
|
|
|
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
2016-04-01 20:34:39 +08:00
|
|
|
swapinfo, err := exec.LookPath("swapinfo")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-05-20 16:59:41 +08:00
|
|
|
out, err := invoke.Command(swapinfo)
|
2014-05-16 14:33:23 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, line := range strings.Split(string(out), "\n") {
|
|
|
|
values := strings.Fields(line)
|
|
|
|
// skip title line
|
|
|
|
if len(values) == 0 || values[0] == "Device" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
u := strings.Replace(values[4], "%", "", 1)
|
2014-09-19 23:15:35 +08:00
|
|
|
total_v, err := strconv.ParseUint(values[1], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
used_v, err := strconv.ParseUint(values[2], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
free_v, err := strconv.ParseUint(values[3], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
up_v, err := strconv.ParseFloat(u, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-05-16 14:33:23 +08:00
|
|
|
|
2015-11-23 17:44:35 +08:00
|
|
|
return &SwapMemoryStat{
|
2014-09-19 23:15:35 +08:00
|
|
|
Total: total_v,
|
|
|
|
Used: used_v,
|
|
|
|
Free: free_v,
|
|
|
|
UsedPercent: up_v,
|
2015-11-23 17:44:35 +08:00
|
|
|
}, nil
|
2014-05-16 14:33:23 +08:00
|
|
|
}
|
2014-04-22 10:58:03 +08:00
|
|
|
|
2015-11-23 17:44:35 +08:00
|
|
|
return nil, errors.New("no swap devices found")
|
2014-04-22 10:58:03 +08:00
|
|
|
}
|