@ -5,9 +5,7 @@ package mem
import (
"context"
"errors"
"os/exec"
"strconv"
"strings"
"unsafe"
"golang.org/x/sys/unix"
)
@ -69,53 +67,66 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
}
// Return swapinfo
// FreeBSD can have multiple swap devices. but use only first device
func SwapMemory ( ) ( * SwapMemoryStat , error ) {
return SwapMemoryWithContext ( context . Background ( ) )
}
// Constants from vm/vm_param.h
// nolint: golint
const (
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
}
func SwapMemoryWithContext ( ctx context . Context ) ( * SwapMemoryStat , error ) {
swapinfo , err := exec . LookPath ( "swapinfo" )
// FreeBSD can have multiple swap devices so we total them up
i , err := unix . SysctlUint32 ( "vm.nswapdev" )
if err != nil {
return nil , err
}
out , err := invoke . Command ( swapinfo )
if i == 0 {
return nil , errors . New ( "no swap devices found" )
}
c := int ( i )
i , err = unix . SysctlUint32 ( "vm.stats.vm.v_page_size" )
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
}
pageSize := uint64 ( i )
u := strings . Replace ( values [ 4 ] , "%" , "" , 1 )
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 )
var buf [ ] byte
s := & SwapMemoryStat { }
for n := 0 ; n < c ; n ++ {
buf , err = unix . SysctlRaw ( "vm.swap_info" , n )
if err != nil {
return nil , err
}
up_v , err := strconv . ParseFloat ( u , 64 )
if err != nil {
return nil , err
xsw := ( * xswdev ) ( unsafe . Pointer ( & buf [ 0 ] ) )
if xsw . Version != XSWDEV_VERSION {
return nil , errors . New ( "xswdev version mismatch" )
}
s . Total += uint64 ( xsw . NBlks )
s . Used += uint64 ( xsw . Used )
}
return & SwapMemoryStat {
Total : total_v ,
Used : used_v ,
Free : free_v ,
UsedPercent : up_v ,
} , nil
if s . Total != 0 {
s . UsedPercent = float64 ( s . Used ) / float64 ( s . Total ) * 100
}
s . Total *= pageSize
s . Used *= pageSize
s . Free = s . Total - s . Used
return nil , errors . New ( "no swap devices found" )
return s , nil
}