Merge pull request #497 from stevenh/freebsd-mem

Eliminate call to swapinfo on FreeBSD
pull/501/head
shirou 7 years ago committed by GitHub
commit 6ce2ace794
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,9 +5,7 @@ package mem
import ( import (
"context" "context"
"errors" "errors"
"os/exec" "unsafe"
"strconv"
"strings"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -69,53 +67,66 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
} }
// Return swapinfo // Return swapinfo
// FreeBSD can have multiple swap devices. but use only first device
func SwapMemory() (*SwapMemoryStat, error) { func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background()) return SwapMemoryWithContext(context.Background())
} }
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { // Constants from vm/vm_param.h
swapinfo, err := exec.LookPath("swapinfo") // nolint: golint
if err != nil { const (
return nil, err XSWDEV_VERSION = 1
)
// Types from vm/vm_param.h
type xswdev struct {
Version uint32 // Version is the version
Dev uint32 // Dev is the device identifier
Flags int32 // Flags is the swap flags applied to the device
NBlks int32 // NBlks is the total number of blocks
Used int32 // Used is the number of blocks used
} }
out, err := invoke.Command(swapinfo) func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// FreeBSD can have multiple swap devices so we total them up
i, err := unix.SysctlUint32("vm.nswapdev")
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, line := range strings.Split(string(out), "\n") {
values := strings.Fields(line) if i == 0 {
// skip title line return nil, errors.New("no swap devices found")
if len(values) == 0 || values[0] == "Device" {
continue
} }
u := strings.Replace(values[4], "%", "", 1) c := int(i)
total_v, err := strconv.ParseUint(values[1], 10, 64)
i, err = unix.SysctlUint32("vm.stats.vm.v_page_size")
if err != nil { if err != nil {
return nil, err return nil, err
} }
used_v, err := strconv.ParseUint(values[2], 10, 64) pageSize := uint64(i)
var buf []byte
s := &SwapMemoryStat{}
for n := 0; n < c; n++ {
buf, err = unix.SysctlRaw("vm.swap_info", n)
if err != nil { if err != nil {
return nil, err return nil, err
} }
free_v, err := strconv.ParseUint(values[3], 10, 64)
if err != nil { xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
return nil, err if xsw.Version != XSWDEV_VERSION {
return nil, errors.New("xswdev version mismatch")
} }
up_v, err := strconv.ParseFloat(u, 64) s.Total += uint64(xsw.NBlks)
if err != nil { s.Used += uint64(xsw.Used)
return nil, err
} }
return &SwapMemoryStat{ if s.Total != 0 {
Total: total_v, s.UsedPercent = float64(s.Used) / float64(s.Total) * 100
Used: used_v,
Free: free_v,
UsedPercent: up_v,
}, nil
} }
s.Total *= pageSize
s.Used *= pageSize
s.Free = s.Total - s.Used
return nil, errors.New("no swap devices found") return s, nil
} }

Loading…
Cancel
Save