Properly vendor the gopsutil dependency
This commit is contained in:
parent
dd7a3b37b0
commit
df651ab98e
|
@ -141,6 +141,41 @@
|
||||||
"ImportPath": "github.com/samuel/go-zookeeper/zk",
|
"ImportPath": "github.com/samuel/go-zookeeper/zk",
|
||||||
"Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4"
|
"Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/common",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/cpu",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/disk",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/docker",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/load",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/mem",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/shirou/gopsutil/net",
|
||||||
|
"Comment": "1.0.0-146-g9c0474c",
|
||||||
|
"Rev": "9c0474c2a7cbea73ea2d93fc5e1ef1c024caf761"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/streadway/amqp",
|
"ImportPath": "github.com/streadway/amqp",
|
||||||
"Rev": "f4879ba28fffbb576743b03622a9ff20461826b2"
|
"Rev": "f4879ba28fffbb576743b03622a9ff20461826b2"
|
||||||
|
|
209
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go
generated
vendored
Normal file
209
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go
generated
vendored
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
//
|
||||||
|
// gopsutil is a port of psutil(http://pythonhosted.org/psutil/).
|
||||||
|
// This covers these architectures.
|
||||||
|
// - linux (amd64, arm)
|
||||||
|
// - freebsd (amd64)
|
||||||
|
// - windows (amd64)
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Invoker interface {
|
||||||
|
Command(string, ...string) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Invoke struct{}
|
||||||
|
|
||||||
|
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
|
||||||
|
return exec.Command(name, arg...).Output()
|
||||||
|
}
|
||||||
|
|
||||||
|
type FakeInvoke struct {
|
||||||
|
CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs.
|
||||||
|
Suffix string // Suffix species expected file name suffix such as "fail"
|
||||||
|
Error error // If Error specfied, return the error.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command in FakeInvoke returns from expected file if exists.
|
||||||
|
func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
|
||||||
|
if i.Error != nil {
|
||||||
|
return []byte{}, i.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
arch := runtime.GOOS
|
||||||
|
|
||||||
|
fname := strings.Join(append([]string{name}, arg...), "")
|
||||||
|
fname = url.QueryEscape(fname)
|
||||||
|
var dir string
|
||||||
|
if i.CommandExpectedDir == "" {
|
||||||
|
dir = "expected"
|
||||||
|
} else {
|
||||||
|
dir = i.CommandExpectedDir
|
||||||
|
}
|
||||||
|
fpath := path.Join(dir, arch, fname)
|
||||||
|
if i.Suffix != "" {
|
||||||
|
fpath += "_" + i.Suffix
|
||||||
|
}
|
||||||
|
if PathExists(fpath) {
|
||||||
|
return ioutil.ReadFile(fpath)
|
||||||
|
} else {
|
||||||
|
return exec.Command(name, arg...).Output()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var NotImplementedError = errors.New("not implemented yet")
|
||||||
|
|
||||||
|
// ReadLines reads contents from a file and splits them by new lines.
|
||||||
|
// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1).
|
||||||
|
func ReadLines(filename string) ([]string, error) {
|
||||||
|
return ReadLinesOffsetN(filename, 0, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadLines reads contents from file and splits them by new line.
|
||||||
|
// The offset tells at which line number to start.
|
||||||
|
// The count determines the number of lines to read (starting from offset):
|
||||||
|
// n >= 0: at most n lines
|
||||||
|
// n < 0: whole file
|
||||||
|
func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return []string{""}, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var ret []string
|
||||||
|
|
||||||
|
r := bufio.NewReader(f)
|
||||||
|
for i := 0; i < n+int(offset) || n < 0; i++ {
|
||||||
|
line, err := r.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if i < int(offset) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, strings.Trim(line, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IntToString(orig []int8) string {
|
||||||
|
ret := make([]byte, len(orig))
|
||||||
|
size := -1
|
||||||
|
for i, o := range orig {
|
||||||
|
if o == 0 {
|
||||||
|
size = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ret[i] = byte(o)
|
||||||
|
}
|
||||||
|
if size == -1 {
|
||||||
|
size = len(orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(ret[0:size])
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByteToString(orig []byte) string {
|
||||||
|
n := -1
|
||||||
|
l := -1
|
||||||
|
for i, b := range orig {
|
||||||
|
// skip left side null
|
||||||
|
if l == -1 && b == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if l == -1 {
|
||||||
|
l = i
|
||||||
|
}
|
||||||
|
|
||||||
|
if b == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
n = i + 1
|
||||||
|
}
|
||||||
|
if n == -1 {
|
||||||
|
return string(orig)
|
||||||
|
}
|
||||||
|
return string(orig[l:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse to int32 without error
|
||||||
|
func mustParseInt32(val string) int32 {
|
||||||
|
vv, _ := strconv.ParseInt(val, 10, 32)
|
||||||
|
return int32(vv)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse to uint64 without error
|
||||||
|
func mustParseUint64(val string) uint64 {
|
||||||
|
vv, _ := strconv.ParseInt(val, 10, 64)
|
||||||
|
return uint64(vv)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse to Float64 without error
|
||||||
|
func mustParseFloat64(val string) float64 {
|
||||||
|
vv, _ := strconv.ParseFloat(val, 64)
|
||||||
|
return vv
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringsHas checks the target string slice containes src or not
|
||||||
|
func StringsHas(target []string, src string) bool {
|
||||||
|
for _, t := range target {
|
||||||
|
if strings.TrimSpace(t) == src {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringsContains checks the src in any string of the target string slice
|
||||||
|
func StringsContains(target []string, src string) bool {
|
||||||
|
for _, t := range target {
|
||||||
|
if strings.Contains(t, src) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// get struct attributes.
|
||||||
|
// This method is used only for debugging platform dependent code.
|
||||||
|
func attributes(m interface{}) map[string]reflect.Type {
|
||||||
|
typ := reflect.TypeOf(m)
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs := make(map[string]reflect.Type)
|
||||||
|
if typ.Kind() != reflect.Struct {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
p := typ.Field(i)
|
||||||
|
if !p.Anonymous {
|
||||||
|
attrs[p.Name] = p.Type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func PathExists(filename string) bool {
|
||||||
|
if _, err := os.Stat(filename); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
89
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go
generated
vendored
Normal file
89
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DoSysctrl(mib string) ([]string, error) {
|
||||||
|
out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output()
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
v := strings.Replace(string(out), "{ ", "", 1)
|
||||||
|
v = strings.Replace(string(v), " }", "", 1)
|
||||||
|
values := strings.Fields(string(v))
|
||||||
|
|
||||||
|
return values, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||||
|
miblen := uint64(len(mib))
|
||||||
|
|
||||||
|
// get required buffer size
|
||||||
|
length := uint64(0)
|
||||||
|
_, _, err := syscall.Syscall6(
|
||||||
|
syscall.SYS___SYSCTL,
|
||||||
|
uintptr(unsafe.Pointer(&mib[0])),
|
||||||
|
uintptr(miblen),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&length)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
if err != 0 {
|
||||||
|
var b []byte
|
||||||
|
return b, length, err
|
||||||
|
}
|
||||||
|
if length == 0 {
|
||||||
|
var b []byte
|
||||||
|
return b, length, err
|
||||||
|
}
|
||||||
|
// get proc info itself
|
||||||
|
buf := make([]byte, length)
|
||||||
|
_, _, err = syscall.Syscall6(
|
||||||
|
syscall.SYS___SYSCTL,
|
||||||
|
uintptr(unsafe.Pointer(&mib[0])),
|
||||||
|
uintptr(miblen),
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(&length)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
if err != 0 {
|
||||||
|
return buf, length, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf, length, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||||
|
var cmd []string
|
||||||
|
if pid == 0 { // will get from all processes.
|
||||||
|
cmd = []string{"-a", "-n", "-P"}
|
||||||
|
} else {
|
||||||
|
cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))}
|
||||||
|
}
|
||||||
|
cmd = append(cmd, args...)
|
||||||
|
lsof, err := exec.LookPath("lsof")
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
out, err := invoke.Command(lsof, cmd...)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
|
||||||
|
var ret []string
|
||||||
|
for _, l := range lines[1:] {
|
||||||
|
if len(l) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, l)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
61
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go
generated
vendored
Normal file
61
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DoSysctrl(mib string) ([]string, error) {
|
||||||
|
out, err := exec.Command("/sbin/sysctl", "-n", mib).Output()
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
v := strings.Replace(string(out), "{ ", "", 1)
|
||||||
|
v = strings.Replace(string(v), " }", "", 1)
|
||||||
|
values := strings.Fields(string(v))
|
||||||
|
|
||||||
|
return values, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||||
|
miblen := uint64(len(mib))
|
||||||
|
|
||||||
|
// get required buffer size
|
||||||
|
length := uint64(0)
|
||||||
|
_, _, err := syscall.Syscall6(
|
||||||
|
syscall.SYS___SYSCTL,
|
||||||
|
uintptr(unsafe.Pointer(&mib[0])),
|
||||||
|
uintptr(miblen),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&length)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
if err != 0 {
|
||||||
|
var b []byte
|
||||||
|
return b, length, err
|
||||||
|
}
|
||||||
|
if length == 0 {
|
||||||
|
var b []byte
|
||||||
|
return b, length, err
|
||||||
|
}
|
||||||
|
// get proc info itself
|
||||||
|
buf := make([]byte, length)
|
||||||
|
_, _, err = syscall.Syscall6(
|
||||||
|
syscall.SYS___SYSCTL,
|
||||||
|
uintptr(unsafe.Pointer(&mib[0])),
|
||||||
|
uintptr(miblen),
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(&length)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
if err != 0 {
|
||||||
|
return buf, length, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf, length, nil
|
||||||
|
}
|
||||||
|
|
37
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||||
|
var cmd []string
|
||||||
|
if pid == 0 { // will get from all processes.
|
||||||
|
cmd = []string{"-a", "-n", "-P"}
|
||||||
|
} else {
|
||||||
|
cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))}
|
||||||
|
}
|
||||||
|
cmd = append(cmd, args...)
|
||||||
|
lsof, err := exec.LookPath("lsof")
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
out, err := invoke.Command(lsof, cmd...)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
|
||||||
|
var ret []string
|
||||||
|
for _, l := range lines[1:] {
|
||||||
|
if len(l) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, l)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
90
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go
generated
vendored
Normal file
90
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadlines(t *testing.T) {
|
||||||
|
ret, err := ReadLines("common_test.go")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(ret[0], "package common") {
|
||||||
|
t.Error("could not read correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadLinesOffsetN(t *testing.T) {
|
||||||
|
ret, err := ReadLinesOffsetN("common_test.go", 2, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Println(ret[0])
|
||||||
|
if !strings.Contains(ret[0], `import (`) {
|
||||||
|
t.Error("could not read correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntToString(t *testing.T) {
|
||||||
|
src := []int8{65, 66, 67}
|
||||||
|
dst := IntToString(src)
|
||||||
|
if dst != "ABC" {
|
||||||
|
t.Error("could not convert")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestByteToString(t *testing.T) {
|
||||||
|
src := []byte{65, 66, 67}
|
||||||
|
dst := ByteToString(src)
|
||||||
|
if dst != "ABC" {
|
||||||
|
t.Error("could not convert")
|
||||||
|
}
|
||||||
|
|
||||||
|
src = []byte{0, 65, 66, 67}
|
||||||
|
dst = ByteToString(src)
|
||||||
|
if dst != "ABC" {
|
||||||
|
t.Error("could not convert")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestmustParseInt32(t *testing.T) {
|
||||||
|
ret := mustParseInt32("11111")
|
||||||
|
if ret != int32(11111) {
|
||||||
|
t.Error("could not parse")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestmustParseUint64(t *testing.T) {
|
||||||
|
ret := mustParseUint64("11111")
|
||||||
|
if ret != uint64(11111) {
|
||||||
|
t.Error("could not parse")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestmustParseFloat64(t *testing.T) {
|
||||||
|
ret := mustParseFloat64("11111.11")
|
||||||
|
if ret != float64(11111.11) {
|
||||||
|
t.Error("could not parse")
|
||||||
|
}
|
||||||
|
ret = mustParseFloat64("11111")
|
||||||
|
if ret != float64(11111) {
|
||||||
|
t.Error("could not parse")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestStringsContains(t *testing.T) {
|
||||||
|
target, err := ReadLines("common_test.go")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !StringsContains(target, "func TestStringsContains(t *testing.T) {") {
|
||||||
|
t.Error("cloud not test correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathExists(t *testing.T) {
|
||||||
|
if !PathExists("common_test.go") {
|
||||||
|
t.Error("exists but return not exists")
|
||||||
|
}
|
||||||
|
if PathExists("should_not_exists.go") {
|
||||||
|
t.Error("not exists but return exists")
|
||||||
|
}
|
||||||
|
}
|
110
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go
generated
vendored
Normal file
110
Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// for double values
|
||||||
|
type PDH_FMT_COUNTERVALUE_DOUBLE struct {
|
||||||
|
CStatus uint32
|
||||||
|
DoubleValue float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// for 64 bit integer values
|
||||||
|
type PDH_FMT_COUNTERVALUE_LARGE struct {
|
||||||
|
CStatus uint32
|
||||||
|
LargeValue int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// for long values
|
||||||
|
type PDH_FMT_COUNTERVALUE_LONG struct {
|
||||||
|
CStatus uint32
|
||||||
|
LongValue int32
|
||||||
|
padding [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// windows system const
|
||||||
|
const (
|
||||||
|
ERROR_SUCCESS = 0
|
||||||
|
ERROR_FILE_NOT_FOUND = 2
|
||||||
|
DRIVE_REMOVABLE = 2
|
||||||
|
DRIVE_FIXED = 3
|
||||||
|
HKEY_LOCAL_MACHINE = 0x80000002
|
||||||
|
RRF_RT_REG_SZ = 0x00000002
|
||||||
|
RRF_RT_REG_DWORD = 0x00000010
|
||||||
|
PDH_FMT_LONG = 0x00000100
|
||||||
|
PDH_FMT_DOUBLE = 0x00000200
|
||||||
|
PDH_FMT_LARGE = 0x00000400
|
||||||
|
PDH_INVALID_DATA = 0xc0000bc6
|
||||||
|
PDH_INVALID_HANDLE = 0xC0000bbc
|
||||||
|
PDH_NO_DATA = 0x800007d5
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
ModNt = syscall.NewLazyDLL("ntdll.dll")
|
||||||
|
ModPdh = syscall.NewLazyDLL("pdh.dll")
|
||||||
|
|
||||||
|
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
|
||||||
|
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
|
||||||
|
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
|
||||||
|
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
|
||||||
|
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
|
||||||
|
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
|
||||||
|
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
|
||||||
|
)
|
||||||
|
|
||||||
|
type FILETIME struct {
|
||||||
|
DwLowDateTime uint32
|
||||||
|
DwHighDateTime uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// borrowed from net/interface_windows.go
|
||||||
|
func BytePtrToString(p *uint8) string {
|
||||||
|
a := (*[10000]uint8)(unsafe.Pointer(p))
|
||||||
|
i := 0
|
||||||
|
for a[i] != 0 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return string(a[:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// CounterInfo
|
||||||
|
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||||
|
type CounterInfo struct {
|
||||||
|
PostName string
|
||||||
|
CounterName string
|
||||||
|
Counter syscall.Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateQuery XXX
|
||||||
|
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||||
|
func CreateQuery() (syscall.Handle, error) {
|
||||||
|
var query syscall.Handle
|
||||||
|
r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query)))
|
||||||
|
if r != 0 {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return query, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCounter XXX
|
||||||
|
func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) {
|
||||||
|
var counter syscall.Handle
|
||||||
|
r, _, err := PdhAddCounter.Call(
|
||||||
|
uintptr(query),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&counter)))
|
||||||
|
if r != 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &CounterInfo{
|
||||||
|
PostName: pname,
|
||||||
|
CounterName: cname,
|
||||||
|
Counter: counter,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CPUTimesStat struct {
|
||||||
|
CPU string `json:"cpu"`
|
||||||
|
User float64 `json:"user"`
|
||||||
|
System float64 `json:"system"`
|
||||||
|
Idle float64 `json:"idle"`
|
||||||
|
Nice float64 `json:"nice"`
|
||||||
|
Iowait float64 `json:"iowait"`
|
||||||
|
Irq float64 `json:"irq"`
|
||||||
|
Softirq float64 `json:"softirq"`
|
||||||
|
Steal float64 `json:"steal"`
|
||||||
|
Guest float64 `json:"guest"`
|
||||||
|
GuestNice float64 `json:"guest_nice"`
|
||||||
|
Stolen float64 `json:"stolen"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CPUInfoStat struct {
|
||||||
|
CPU int32 `json:"cpu"`
|
||||||
|
VendorID string `json:"vendor_id"`
|
||||||
|
Family string `json:"family"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Stepping int32 `json:"stepping"`
|
||||||
|
PhysicalID string `json:"physical_id"`
|
||||||
|
CoreID string `json:"core_id"`
|
||||||
|
Cores int32 `json:"cores"`
|
||||||
|
ModelName string `json:"model_name"`
|
||||||
|
Mhz float64 `json:"mhz"`
|
||||||
|
CacheSize int32 `json:"cache_size"`
|
||||||
|
Flags []string `json:"flags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastCPUTimes []CPUTimesStat
|
||||||
|
var lastPerCPUTimes []CPUTimesStat
|
||||||
|
|
||||||
|
func CPUCounts(logical bool) (int, error) {
|
||||||
|
return runtime.NumCPU(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CPUTimesStat) String() string {
|
||||||
|
v := []string{
|
||||||
|
`"cpu":"` + c.CPU + `"`,
|
||||||
|
`"user":` + strconv.FormatFloat(c.User, 'f', 1, 64),
|
||||||
|
`"system":` + strconv.FormatFloat(c.System, 'f', 1, 64),
|
||||||
|
`"idle":` + strconv.FormatFloat(c.Idle, 'f', 1, 64),
|
||||||
|
`"nice":` + strconv.FormatFloat(c.Nice, 'f', 1, 64),
|
||||||
|
`"iowait":` + strconv.FormatFloat(c.Iowait, 'f', 1, 64),
|
||||||
|
`"irq":` + strconv.FormatFloat(c.Irq, 'f', 1, 64),
|
||||||
|
`"softirq":` + strconv.FormatFloat(c.Softirq, 'f', 1, 64),
|
||||||
|
`"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64),
|
||||||
|
`"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64),
|
||||||
|
`"guest_nice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
|
||||||
|
`"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64),
|
||||||
|
}
|
||||||
|
|
||||||
|
return `{` + strings.Join(v, ",") + `}`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CPUInfoStat) String() string {
|
||||||
|
s, _ := json.Marshal(c)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
lastCPUTimes, _ = CPUTimes(false)
|
||||||
|
lastPerCPUTimes, _ = CPUTimes(true)
|
||||||
|
}
|
203
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
Normal file
203
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <mach/mach_init.h>
|
||||||
|
#include <mach/mach_host.h>
|
||||||
|
#include <mach/host_info.h>
|
||||||
|
#include <libproc.h>
|
||||||
|
#include <mach/processor_info.h>
|
||||||
|
#include <mach/vm_map.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sys/resource.h
|
||||||
|
const (
|
||||||
|
CPUser = 0
|
||||||
|
CPNice = 1
|
||||||
|
CPSys = 2
|
||||||
|
CPIntr = 3
|
||||||
|
CPIdle = 4
|
||||||
|
CPUStates = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
// default value. from time.h
|
||||||
|
var ClocksPerSec = float64(128)
|
||||||
|
|
||||||
|
// these CPU times for darwin is borrowed from influxdb/telegraf.
|
||||||
|
|
||||||
|
func perCPUTimes() ([]CPUTimesStat, error) {
|
||||||
|
var (
|
||||||
|
count C.mach_msg_type_number_t
|
||||||
|
cpuload *C.processor_cpu_load_info_data_t
|
||||||
|
ncpu C.natural_t
|
||||||
|
)
|
||||||
|
|
||||||
|
status := C.host_processor_info(C.host_t(C.mach_host_self()),
|
||||||
|
C.PROCESSOR_CPU_LOAD_INFO,
|
||||||
|
&ncpu,
|
||||||
|
(*C.processor_info_array_t)(unsafe.Pointer(&cpuload)),
|
||||||
|
&count)
|
||||||
|
|
||||||
|
if status != C.KERN_SUCCESS {
|
||||||
|
return nil, fmt.Errorf("host_processor_info error=%d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jump through some cgo casting hoops and ensure we properly free
|
||||||
|
// the memory that cpuload points to
|
||||||
|
target := C.vm_map_t(C.mach_task_self_)
|
||||||
|
address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload)))
|
||||||
|
defer C.vm_deallocate(target, address, C.vm_size_t(ncpu))
|
||||||
|
|
||||||
|
// the body of struct processor_cpu_load_info
|
||||||
|
// aka processor_cpu_load_info_data_t
|
||||||
|
var cpu_ticks [C.CPU_STATE_MAX]uint32
|
||||||
|
|
||||||
|
// copy the cpuload array to a []byte buffer
|
||||||
|
// where we can binary.Read the data
|
||||||
|
size := int(ncpu) * binary.Size(cpu_ticks)
|
||||||
|
buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size))
|
||||||
|
|
||||||
|
bbuf := bytes.NewBuffer(buf)
|
||||||
|
|
||||||
|
var ret []CPUTimesStat
|
||||||
|
|
||||||
|
for i := 0; i < int(ncpu); i++ {
|
||||||
|
err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := CPUTimesStat{
|
||||||
|
CPU: fmt.Sprintf("cpu%d", i),
|
||||||
|
User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
|
||||||
|
System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
|
||||||
|
Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
|
||||||
|
Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func allCPUTimes() ([]CPUTimesStat, error) {
|
||||||
|
var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT
|
||||||
|
var cpuload C.host_cpu_load_info_data_t
|
||||||
|
|
||||||
|
status := C.host_statistics(C.host_t(C.mach_host_self()),
|
||||||
|
C.HOST_CPU_LOAD_INFO,
|
||||||
|
C.host_info_t(unsafe.Pointer(&cpuload)),
|
||||||
|
&count)
|
||||||
|
|
||||||
|
if status != C.KERN_SUCCESS {
|
||||||
|
return nil, fmt.Errorf("host_statistics error=%d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := CPUTimesStat{
|
||||||
|
CPU: "cpu-total",
|
||||||
|
User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
|
||||||
|
System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
|
||||||
|
Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
|
||||||
|
Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []CPUTimesStat{c}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
||||||
|
if percpu {
|
||||||
|
return perCPUTimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
return allCPUTimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns only one CPUInfoStat on FreeBSD
|
||||||
|
func CPUInfo() ([]CPUInfoStat, error) {
|
||||||
|
var ret []CPUInfoStat
|
||||||
|
|
||||||
|
out, err := exec.Command("/usr/sbin/sysctl", "machdep.cpu").Output()
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := CPUInfoStat{}
|
||||||
|
for _, line := range strings.Split(string(out), "\n") {
|
||||||
|
values := strings.Fields(line)
|
||||||
|
if len(values) < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := strconv.ParseInt(values[1], 10, 64)
|
||||||
|
// err is not checked here because some value is string.
|
||||||
|
if strings.HasPrefix(line, "machdep.cpu.brand_string") {
|
||||||
|
c.ModelName = strings.Join(values[1:], " ")
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.family") {
|
||||||
|
c.Family = values[1]
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.model") {
|
||||||
|
c.Model = values[1]
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Stepping = int32(t)
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.features") {
|
||||||
|
for _, v := range values[1:] {
|
||||||
|
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
|
||||||
|
for _, v := range values[1:] {
|
||||||
|
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
|
||||||
|
for _, v := range values[1:] {
|
||||||
|
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Cores = int32(t)
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.CacheSize = int32(t)
|
||||||
|
} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
|
||||||
|
c.VendorID = values[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the rated frequency of the CPU. This is a static value and does not
|
||||||
|
// account for low power or Turbo Boost modes.
|
||||||
|
out, err = exec.Command("/usr/sbin/sysctl", "hw.cpufrequency").Output()
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
values := strings.Fields(string(out))
|
||||||
|
mhz, err := strconv.ParseFloat(values[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Mhz = mhz / 1000000.0
|
||||||
|
|
||||||
|
return append(ret, c), nil
|
||||||
|
}
|
143
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
Normal file
143
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sys/resource.h
|
||||||
|
const (
|
||||||
|
CPUser = 0
|
||||||
|
CPNice = 1
|
||||||
|
CPSys = 2
|
||||||
|
CPIntr = 3
|
||||||
|
CPIdle = 4
|
||||||
|
CPUStates = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
var ClocksPerSec = float64(128)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
out, err := exec.Command("/usr/bin/getconf", "CLK_TCK").Output()
|
||||||
|
// ignore errors
|
||||||
|
if err == nil {
|
||||||
|
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||||
|
if err == nil {
|
||||||
|
ClocksPerSec = float64(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
||||||
|
var ret []CPUTimesStat
|
||||||
|
|
||||||
|
var sysctlCall string
|
||||||
|
var ncpu int
|
||||||
|
if percpu {
|
||||||
|
sysctlCall = "kern.cp_times"
|
||||||
|
ncpu, _ = CPUCounts(true)
|
||||||
|
} else {
|
||||||
|
sysctlCall = "kern.cp_time"
|
||||||
|
ncpu = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuTimes, err := common.DoSysctrl(sysctlCall)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < ncpu; i++ {
|
||||||
|
offset := CPUStates * i
|
||||||
|
user, err := strconv.ParseFloat(cpuTimes[CPUser+offset], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
nice, err := strconv.ParseFloat(cpuTimes[CPNice+offset], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
sys, err := strconv.ParseFloat(cpuTimes[CPSys+offset], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
idle, err := strconv.ParseFloat(cpuTimes[CPIdle+offset], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
intr, err := strconv.ParseFloat(cpuTimes[CPIntr+offset], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := CPUTimesStat{
|
||||||
|
User: float64(user / ClocksPerSec),
|
||||||
|
Nice: float64(nice / ClocksPerSec),
|
||||||
|
System: float64(sys / ClocksPerSec),
|
||||||
|
Idle: float64(idle / ClocksPerSec),
|
||||||
|
Irq: float64(intr / ClocksPerSec),
|
||||||
|
}
|
||||||
|
if !percpu {
|
||||||
|
c.CPU = "cpu-total"
|
||||||
|
} else {
|
||||||
|
c.CPU = fmt.Sprintf("cpu%d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns only one CPUInfoStat on FreeBSD
|
||||||
|
func CPUInfo() ([]CPUInfoStat, error) {
|
||||||
|
filename := "/var/run/dmesg.boot"
|
||||||
|
lines, _ := common.ReadLines(filename)
|
||||||
|
|
||||||
|
var ret []CPUInfoStat
|
||||||
|
|
||||||
|
c := CPUInfoStat{}
|
||||||
|
for _, line := range lines {
|
||||||
|
if matches := regexp.MustCompile(`CPU:\s+(.+) \(([\d.]+).+\)`).FindStringSubmatch(line); matches != nil {
|
||||||
|
c.ModelName = matches[1]
|
||||||
|
t, err := strconv.ParseFloat(matches[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
c.Mhz = t
|
||||||
|
} else if matches := regexp.MustCompile(`Origin = "(.+)" Id = (.+) Family = (.+) Model = (.+) Stepping = (.+)`).FindStringSubmatch(line); matches != nil {
|
||||||
|
c.VendorID = matches[1]
|
||||||
|
c.Family = matches[3]
|
||||||
|
c.Model = matches[4]
|
||||||
|
t, err := strconv.ParseInt(matches[5], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
c.Stepping = int32(t)
|
||||||
|
} else if matches := regexp.MustCompile(`Features=.+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
||||||
|
for _, v := range strings.Split(matches[1], ",") {
|
||||||
|
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||||
|
}
|
||||||
|
} else if matches := regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
||||||
|
for _, v := range strings.Split(matches[1], ",") {
|
||||||
|
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||||
|
}
|
||||||
|
} else if matches := regexp.MustCompile(`Logical CPUs per core: (\d+)`).FindStringSubmatch(line); matches != nil {
|
||||||
|
// FIXME: no this line?
|
||||||
|
t, err := strconv.ParseInt(matches[1], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
c.Cores = int32(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(ret, c), nil
|
||||||
|
}
|
201
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
Normal file
201
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cpu_tick = float64(100)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
out, err := exec.Command("/usr/bin/getconf", "CLK_TCK").Output()
|
||||||
|
// ignore errors
|
||||||
|
if err == nil {
|
||||||
|
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||||
|
if err == nil {
|
||||||
|
cpu_tick = float64(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
||||||
|
filename := "/proc/stat"
|
||||||
|
var lines = []string{}
|
||||||
|
if percpu {
|
||||||
|
var startIdx uint = 1
|
||||||
|
for {
|
||||||
|
linen, _ := common.ReadLinesOffsetN(filename, startIdx, 1)
|
||||||
|
line := linen[0]
|
||||||
|
if !strings.HasPrefix(line, "cpu") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
lines = append(lines, line)
|
||||||
|
startIdx += 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines, _ = common.ReadLinesOffsetN(filename, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]CPUTimesStat, 0, len(lines))
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
ct, err := parseStatLine(line)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, *ct)
|
||||||
|
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUInfo() ([]CPUInfoStat, error) {
|
||||||
|
filename := "/proc/cpuinfo"
|
||||||
|
lines, _ := common.ReadLines(filename)
|
||||||
|
|
||||||
|
var ret []CPUInfoStat
|
||||||
|
|
||||||
|
var c CPUInfoStat
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Split(line, ":")
|
||||||
|
if len(fields) < 2 {
|
||||||
|
if c.VendorID != "" {
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key := strings.TrimSpace(fields[0])
|
||||||
|
value := strings.TrimSpace(fields[1])
|
||||||
|
|
||||||
|
switch key {
|
||||||
|
case "processor":
|
||||||
|
c = CPUInfoStat{}
|
||||||
|
t, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.CPU = int32(t)
|
||||||
|
case "vendor_id":
|
||||||
|
c.VendorID = value
|
||||||
|
case "cpu family":
|
||||||
|
c.Family = value
|
||||||
|
case "model":
|
||||||
|
c.Model = value
|
||||||
|
case "model name":
|
||||||
|
c.ModelName = value
|
||||||
|
case "stepping":
|
||||||
|
t, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Stepping = int32(t)
|
||||||
|
case "cpu MHz":
|
||||||
|
t, err := strconv.ParseFloat(value, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Mhz = t
|
||||||
|
case "cache size":
|
||||||
|
t, err := strconv.ParseInt(strings.Replace(value, " KB", "", 1), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.CacheSize = int32(t)
|
||||||
|
case "physical id":
|
||||||
|
c.PhysicalID = value
|
||||||
|
case "core id":
|
||||||
|
c.CoreID = value
|
||||||
|
case "cpu cores":
|
||||||
|
t, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
c.Cores = int32(t)
|
||||||
|
case "flags":
|
||||||
|
c.Flags = strings.Split(value, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseStatLine(line string) (*CPUTimesStat, error) {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
|
||||||
|
if strings.HasPrefix(fields[0], "cpu") == false {
|
||||||
|
// return CPUTimesStat{}, e
|
||||||
|
return nil, errors.New("not contain cpu")
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu := fields[0]
|
||||||
|
if cpu == "cpu" {
|
||||||
|
cpu = "cpu-total"
|
||||||
|
}
|
||||||
|
user, err := strconv.ParseFloat(fields[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nice, err := strconv.ParseFloat(fields[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
system, err := strconv.ParseFloat(fields[3], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
idle, err := strconv.ParseFloat(fields[4], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iowait, err := strconv.ParseFloat(fields[5], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
irq, err := strconv.ParseFloat(fields[6], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
softirq, err := strconv.ParseFloat(fields[7], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ct := &CPUTimesStat{
|
||||||
|
CPU: cpu,
|
||||||
|
User: float64(user) / cpu_tick,
|
||||||
|
Nice: float64(nice) / cpu_tick,
|
||||||
|
System: float64(system) / cpu_tick,
|
||||||
|
Idle: float64(idle) / cpu_tick,
|
||||||
|
Iowait: float64(iowait) / cpu_tick,
|
||||||
|
Irq: float64(irq) / cpu_tick,
|
||||||
|
Softirq: float64(softirq) / cpu_tick,
|
||||||
|
}
|
||||||
|
if len(fields) > 8 { // Linux >= 2.6.11
|
||||||
|
steal, err := strconv.ParseFloat(fields[8], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ct.Steal = float64(steal) / cpu_tick
|
||||||
|
}
|
||||||
|
if len(fields) > 9 { // Linux >= 2.6.24
|
||||||
|
guest, err := strconv.ParseFloat(fields[9], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ct.Guest = float64(guest) / cpu_tick
|
||||||
|
}
|
||||||
|
if len(fields) > 10 { // Linux >= 3.2.0
|
||||||
|
guestNice, err := strconv.ParseFloat(fields[10], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ct.GuestNice = float64(guestNice) / cpu_tick
|
||||||
|
}
|
||||||
|
|
||||||
|
return ct, nil
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCpu_times(t *testing.T) {
|
||||||
|
v, err := CPUTimes(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
t.Error("could not get CPUs ", err)
|
||||||
|
}
|
||||||
|
empty := CPUTimesStat{}
|
||||||
|
for _, vv := range v {
|
||||||
|
if vv == empty {
|
||||||
|
t.Errorf("could not get CPU User: %v", vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCpu_counts(t *testing.T) {
|
||||||
|
v, err := CPUCounts(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
t.Errorf("could not get CPU counts: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCPUTimeStat_String(t *testing.T) {
|
||||||
|
v := CPUTimesStat{
|
||||||
|
CPU: "cpu0",
|
||||||
|
User: 100.1,
|
||||||
|
System: 200.1,
|
||||||
|
Idle: 300.1,
|
||||||
|
}
|
||||||
|
e := `{"cpu":"cpu0","user":100.1,"system":200.1,"idle":300.1,"nice":0.0,"iowait":0.0,"irq":0.0,"softirq":0.0,"steal":0.0,"guest":0.0,"guest_nice":0.0,"stolen":0.0}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("CPUTimesStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCpuInfo(t *testing.T) {
|
||||||
|
v, err := CPUInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
t.Errorf("could not get CPU Info")
|
||||||
|
}
|
||||||
|
for _, vv := range v {
|
||||||
|
if vv.ModelName == "" {
|
||||||
|
t.Errorf("could not get CPU Info: %v", vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCPUPercent(t *testing.T, percpu bool) {
|
||||||
|
numcpu := runtime.NumCPU()
|
||||||
|
testCount := 3
|
||||||
|
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
testCount = 100
|
||||||
|
v, err := CPUPercent(time.Millisecond, percpu)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
||||||
|
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < testCount; i++ {
|
||||||
|
duration := time.Duration(10) * time.Microsecond
|
||||||
|
v, err := CPUPercent(duration, percpu)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
for _, percent := range v {
|
||||||
|
if percent < 0.0 || percent > 100.0*float64(numcpu) {
|
||||||
|
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCPUPercent(t *testing.T) {
|
||||||
|
testCPUPercent(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCPUPercentPerCpu(t *testing.T) {
|
||||||
|
testCPUPercent(t, true)
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
// +build linux freebsd darwin
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
lastCPUTimes, _ = CPUTimes(false)
|
||||||
|
lastPerCPUTimes, _ = CPUTimes(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||||
|
getAllBusy := func(t CPUTimesStat) (float64, float64) {
|
||||||
|
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
|
||||||
|
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen
|
||||||
|
return busy + t.Idle, busy
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate := func(t1, t2 CPUTimesStat) float64 {
|
||||||
|
t1All, t1Busy := getAllBusy(t1)
|
||||||
|
t2All, t2Busy := getAllBusy(t2)
|
||||||
|
|
||||||
|
if t2Busy <= t1Busy {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if t2All <= t1All {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuTimes, err := CPUTimes(percpu)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if interval > 0 {
|
||||||
|
if !percpu {
|
||||||
|
lastCPUTimes = cpuTimes
|
||||||
|
} else {
|
||||||
|
lastPerCPUTimes = cpuTimes
|
||||||
|
}
|
||||||
|
time.Sleep(interval)
|
||||||
|
cpuTimes, err = CPUTimes(percpu)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]float64, len(cpuTimes))
|
||||||
|
if !percpu {
|
||||||
|
ret[0] = calculate(lastCPUTimes[0], cpuTimes[0])
|
||||||
|
lastCPUTimes = cpuTimes
|
||||||
|
} else {
|
||||||
|
for i, t := range cpuTimes {
|
||||||
|
ret[i] = calculate(lastPerCPUTimes[i], t)
|
||||||
|
}
|
||||||
|
lastPerCPUTimes = cpuTimes
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
105
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
Normal file
105
Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/StackExchange/wmi"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Win32_Processor struct {
|
||||||
|
LoadPercentage *uint16
|
||||||
|
Family uint16
|
||||||
|
Manufacturer string
|
||||||
|
Name string
|
||||||
|
NumberOfLogicalProcessors uint32
|
||||||
|
ProcessorId *string
|
||||||
|
Stepping *string
|
||||||
|
MaxClockSpeed uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Get percpu
|
||||||
|
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
||||||
|
var ret []CPUTimesStat
|
||||||
|
|
||||||
|
var lpIdleTime common.FILETIME
|
||||||
|
var lpKernelTime common.FILETIME
|
||||||
|
var lpUserTime common.FILETIME
|
||||||
|
r, _, _ := common.ProcGetSystemTimes.Call(
|
||||||
|
uintptr(unsafe.Pointer(&lpIdleTime)),
|
||||||
|
uintptr(unsafe.Pointer(&lpKernelTime)),
|
||||||
|
uintptr(unsafe.Pointer(&lpUserTime)))
|
||||||
|
if r == 0 {
|
||||||
|
return ret, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
LOT := float64(0.0000001)
|
||||||
|
HIT := (LOT * 4294967296.0)
|
||||||
|
idle := ((HIT * float64(lpIdleTime.DwHighDateTime)) + (LOT * float64(lpIdleTime.DwLowDateTime)))
|
||||||
|
user := ((HIT * float64(lpUserTime.DwHighDateTime)) + (LOT * float64(lpUserTime.DwLowDateTime)))
|
||||||
|
kernel := ((HIT * float64(lpKernelTime.DwHighDateTime)) + (LOT * float64(lpKernelTime.DwLowDateTime)))
|
||||||
|
system := (kernel - idle)
|
||||||
|
|
||||||
|
ret = append(ret, CPUTimesStat{
|
||||||
|
Idle: float64(idle),
|
||||||
|
User: float64(user),
|
||||||
|
System: float64(system),
|
||||||
|
})
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUInfo() ([]CPUInfoStat, error) {
|
||||||
|
var ret []CPUInfoStat
|
||||||
|
var dst []Win32_Processor
|
||||||
|
q := wmi.CreateQuery(&dst, "")
|
||||||
|
err := wmi.Query(q, &dst)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var procID string
|
||||||
|
for i, l := range dst {
|
||||||
|
procID = ""
|
||||||
|
if l.ProcessorId != nil {
|
||||||
|
procID = *l.ProcessorId
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu := CPUInfoStat{
|
||||||
|
CPU: int32(i),
|
||||||
|
Family: fmt.Sprintf("%d", l.Family),
|
||||||
|
VendorID: l.Manufacturer,
|
||||||
|
ModelName: l.Name,
|
||||||
|
Cores: int32(l.NumberOfLogicalProcessors),
|
||||||
|
PhysicalID: procID,
|
||||||
|
Mhz: float64(l.MaxClockSpeed),
|
||||||
|
Flags: []string{},
|
||||||
|
}
|
||||||
|
ret = append(ret, cpu)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||||
|
var ret []float64
|
||||||
|
var dst []Win32_Processor
|
||||||
|
q := wmi.CreateQuery(&dst, "")
|
||||||
|
err := wmi.Query(q, &dst)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
for _, l := range dst {
|
||||||
|
// use range but windows can only get one percent.
|
||||||
|
if l.LoadPercentage == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, float64(*l.LoadPercentage))
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
|
@ -0,0 +1,634 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package binary implements simple translation between numbers and byte
|
||||||
|
// sequences and encoding and decoding of varints.
|
||||||
|
//
|
||||||
|
// Numbers are translated by reading and writing fixed-size values.
|
||||||
|
// A fixed-size value is either a fixed-size arithmetic
|
||||||
|
// type (int8, uint8, int16, float32, complex64, ...)
|
||||||
|
// or an array or struct containing only fixed-size values.
|
||||||
|
//
|
||||||
|
// The varint functions encode and decode single integer values using
|
||||||
|
// a variable-length encoding; smaller values require fewer bytes.
|
||||||
|
// For a specification, see
|
||||||
|
// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
|
||||||
|
//
|
||||||
|
// This package favors simplicity over efficiency. Clients that require
|
||||||
|
// high-performance serialization, especially for large data structures,
|
||||||
|
// should look at more advanced solutions such as the encoding/gob
|
||||||
|
// package or protocol buffers.
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ByteOrder specifies how to convert byte sequences into
|
||||||
|
// 16-, 32-, or 64-bit unsigned integers.
|
||||||
|
type ByteOrder interface {
|
||||||
|
Uint16([]byte) uint16
|
||||||
|
Uint32([]byte) uint32
|
||||||
|
Uint64([]byte) uint64
|
||||||
|
PutUint16([]byte, uint16)
|
||||||
|
PutUint32([]byte, uint32)
|
||||||
|
PutUint64([]byte, uint64)
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LittleEndian is the little-endian implementation of ByteOrder.
|
||||||
|
var LittleEndian littleEndian
|
||||||
|
|
||||||
|
// BigEndian is the big-endian implementation of ByteOrder.
|
||||||
|
var BigEndian bigEndian
|
||||||
|
|
||||||
|
type littleEndian struct{}
|
||||||
|
|
||||||
|
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
|
||||||
|
|
||||||
|
func (littleEndian) PutUint16(b []byte, v uint16) {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (littleEndian) Uint32(b []byte) uint32 {
|
||||||
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||||
|
}
|
||||||
|
|
||||||
|
func (littleEndian) PutUint32(b []byte, v uint32) {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (littleEndian) Uint64(b []byte) uint64 {
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||||
|
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||||
|
}
|
||||||
|
|
||||||
|
func (littleEndian) PutUint64(b []byte, v uint64) {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
b[4] = byte(v >> 32)
|
||||||
|
b[5] = byte(v >> 40)
|
||||||
|
b[6] = byte(v >> 48)
|
||||||
|
b[7] = byte(v >> 56)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (littleEndian) String() string { return "LittleEndian" }
|
||||||
|
|
||||||
|
func (littleEndian) GoString() string { return "binary.LittleEndian" }
|
||||||
|
|
||||||
|
type bigEndian struct{}
|
||||||
|
|
||||||
|
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
|
||||||
|
|
||||||
|
func (bigEndian) PutUint16(b []byte, v uint16) {
|
||||||
|
b[0] = byte(v >> 8)
|
||||||
|
b[1] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bigEndian) Uint32(b []byte) uint32 {
|
||||||
|
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bigEndian) PutUint32(b []byte, v uint32) {
|
||||||
|
b[0] = byte(v >> 24)
|
||||||
|
b[1] = byte(v >> 16)
|
||||||
|
b[2] = byte(v >> 8)
|
||||||
|
b[3] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bigEndian) Uint64(b []byte) uint64 {
|
||||||
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bigEndian) PutUint64(b []byte, v uint64) {
|
||||||
|
b[0] = byte(v >> 56)
|
||||||
|
b[1] = byte(v >> 48)
|
||||||
|
b[2] = byte(v >> 40)
|
||||||
|
b[3] = byte(v >> 32)
|
||||||
|
b[4] = byte(v >> 24)
|
||||||
|
b[5] = byte(v >> 16)
|
||||||
|
b[6] = byte(v >> 8)
|
||||||
|
b[7] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bigEndian) String() string { return "BigEndian" }
|
||||||
|
|
||||||
|
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
||||||
|
|
||||||
|
// Read reads structured binary data from r into data.
|
||||||
|
// Data must be a pointer to a fixed-size value or a slice
|
||||||
|
// of fixed-size values.
|
||||||
|
// Bytes read from r are decoded using the specified byte order
|
||||||
|
// and written to successive fields of the data.
|
||||||
|
// When reading into structs, the field data for fields with
|
||||||
|
// blank (_) field names is skipped; i.e., blank field names
|
||||||
|
// may be used for padding.
|
||||||
|
// When reading into a struct, all non-blank fields must be exported.
|
||||||
|
func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
||||||
|
// Fast path for basic types and slices.
|
||||||
|
if n := intDataSize(data); n != 0 {
|
||||||
|
var b [8]byte
|
||||||
|
var bs []byte
|
||||||
|
if n > len(b) {
|
||||||
|
bs = make([]byte, n)
|
||||||
|
} else {
|
||||||
|
bs = b[:n]
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(r, bs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch data := data.(type) {
|
||||||
|
case *int8:
|
||||||
|
*data = int8(b[0])
|
||||||
|
case *uint8:
|
||||||
|
*data = b[0]
|
||||||
|
case *int16:
|
||||||
|
*data = int16(order.Uint16(bs))
|
||||||
|
case *uint16:
|
||||||
|
*data = order.Uint16(bs)
|
||||||
|
case *int32:
|
||||||
|
*data = int32(order.Uint32(bs))
|
||||||
|
case *uint32:
|
||||||
|
*data = order.Uint32(bs)
|
||||||
|
case *int64:
|
||||||
|
*data = int64(order.Uint64(bs))
|
||||||
|
case *uint64:
|
||||||
|
*data = order.Uint64(bs)
|
||||||
|
case []int8:
|
||||||
|
for i, x := range bs { // Easier to loop over the input for 8-bit values.
|
||||||
|
data[i] = int8(x)
|
||||||
|
}
|
||||||
|
case []uint8:
|
||||||
|
copy(data, bs)
|
||||||
|
case []int16:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = int16(order.Uint16(bs[2*i:]))
|
||||||
|
}
|
||||||
|
case []uint16:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = order.Uint16(bs[2*i:])
|
||||||
|
}
|
||||||
|
case []int32:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = int32(order.Uint32(bs[4*i:]))
|
||||||
|
}
|
||||||
|
case []uint32:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = order.Uint32(bs[4*i:])
|
||||||
|
}
|
||||||
|
case []int64:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = int64(order.Uint64(bs[8*i:]))
|
||||||
|
}
|
||||||
|
case []uint64:
|
||||||
|
for i := range data {
|
||||||
|
data[i] = order.Uint64(bs[8*i:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to reflect-based decoding.
|
||||||
|
v := reflect.ValueOf(data)
|
||||||
|
size := -1
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
v = v.Elem()
|
||||||
|
size = dataSize(v)
|
||||||
|
case reflect.Slice:
|
||||||
|
size = dataSize(v)
|
||||||
|
}
|
||||||
|
if size < 0 {
|
||||||
|
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
|
||||||
|
}
|
||||||
|
d := &decoder{order: order, buf: make([]byte, size)}
|
||||||
|
if _, err := io.ReadFull(r, d.buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.value(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes the binary representation of data into w.
|
||||||
|
// Data must be a fixed-size value or a slice of fixed-size
|
||||||
|
// values, or a pointer to such data.
|
||||||
|
// Bytes written to w are encoded using the specified byte order
|
||||||
|
// and read from successive fields of the data.
|
||||||
|
// When writing structs, zero values are written for fields
|
||||||
|
// with blank (_) field names.
|
||||||
|
func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
||||||
|
// Fast path for basic types and slices.
|
||||||
|
if n := intDataSize(data); n != 0 {
|
||||||
|
var b [8]byte
|
||||||
|
var bs []byte
|
||||||
|
if n > len(b) {
|
||||||
|
bs = make([]byte, n)
|
||||||
|
} else {
|
||||||
|
bs = b[:n]
|
||||||
|
}
|
||||||
|
switch v := data.(type) {
|
||||||
|
case *int8:
|
||||||
|
bs = b[:1]
|
||||||
|
b[0] = byte(*v)
|
||||||
|
case int8:
|
||||||
|
bs = b[:1]
|
||||||
|
b[0] = byte(v)
|
||||||
|
case []int8:
|
||||||
|
for i, x := range v {
|
||||||
|
bs[i] = byte(x)
|
||||||
|
}
|
||||||
|
case *uint8:
|
||||||
|
bs = b[:1]
|
||||||
|
b[0] = *v
|
||||||
|
case uint8:
|
||||||
|
bs = b[:1]
|
||||||
|
b[0] = byte(v)
|
||||||
|
case []uint8:
|
||||||
|
bs = v
|
||||||
|
case *int16:
|
||||||
|
bs = b[:2]
|
||||||
|
order.PutUint16(bs, uint16(*v))
|
||||||
|
case int16:
|
||||||
|
bs = b[:2]
|
||||||
|
order.PutUint16(bs, uint16(v))
|
||||||
|
case []int16:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint16(bs[2*i:], uint16(x))
|
||||||
|
}
|
||||||
|
case *uint16:
|
||||||
|
bs = b[:2]
|
||||||
|
order.PutUint16(bs, *v)
|
||||||
|
case uint16:
|
||||||
|
bs = b[:2]
|
||||||
|
order.PutUint16(bs, v)
|
||||||
|
case []uint16:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint16(bs[2*i:], x)
|
||||||
|
}
|
||||||
|
case *int32:
|
||||||
|
bs = b[:4]
|
||||||
|
order.PutUint32(bs, uint32(*v))
|
||||||
|
case int32:
|
||||||
|
bs = b[:4]
|
||||||
|
order.PutUint32(bs, uint32(v))
|
||||||
|
case []int32:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint32(bs[4*i:], uint32(x))
|
||||||
|
}
|
||||||
|
case *uint32:
|
||||||
|
bs = b[:4]
|
||||||
|
order.PutUint32(bs, *v)
|
||||||
|
case uint32:
|
||||||
|
bs = b[:4]
|
||||||
|
order.PutUint32(bs, v)
|
||||||
|
case []uint32:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint32(bs[4*i:], x)
|
||||||
|
}
|
||||||
|
case *int64:
|
||||||
|
bs = b[:8]
|
||||||
|
order.PutUint64(bs, uint64(*v))
|
||||||
|
case int64:
|
||||||
|
bs = b[:8]
|
||||||
|
order.PutUint64(bs, uint64(v))
|
||||||
|
case []int64:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint64(bs[8*i:], uint64(x))
|
||||||
|
}
|
||||||
|
case *uint64:
|
||||||
|
bs = b[:8]
|
||||||
|
order.PutUint64(bs, *v)
|
||||||
|
case uint64:
|
||||||
|
bs = b[:8]
|
||||||
|
order.PutUint64(bs, v)
|
||||||
|
case []uint64:
|
||||||
|
for i, x := range v {
|
||||||
|
order.PutUint64(bs[8*i:], x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := w.Write(bs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to reflect-based encoding.
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(data))
|
||||||
|
size := dataSize(v)
|
||||||
|
if size < 0 {
|
||||||
|
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
|
||||||
|
}
|
||||||
|
buf := make([]byte, size)
|
||||||
|
e := &encoder{order: order, buf: buf}
|
||||||
|
e.value(v)
|
||||||
|
_, err := w.Write(buf)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns how many bytes Write would generate to encode the value v, which
|
||||||
|
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
|
||||||
|
// If v is neither of these, Size returns -1.
|
||||||
|
func Size(v interface{}) int {
|
||||||
|
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
|
||||||
|
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
|
||||||
|
// it returns the length of the slice times the element size and does not count the memory
|
||||||
|
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
|
||||||
|
func dataSize(v reflect.Value) int {
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
if s := sizeof(v.Type().Elem()); s >= 0 {
|
||||||
|
return s * v.Len()
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return sizeof(v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
|
||||||
|
func sizeof(t reflect.Type) int {
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Array:
|
||||||
|
if s := sizeof(t.Elem()); s >= 0 {
|
||||||
|
return s * t.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
sum := 0
|
||||||
|
for i, n := 0, t.NumField(); i < n; i++ {
|
||||||
|
s := sizeof(t.Field(i).Type)
|
||||||
|
if s < 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
sum += s
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||||
|
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
|
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
|
||||||
|
return int(t.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
type coder struct {
|
||||||
|
order ByteOrder
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type decoder coder
|
||||||
|
type encoder coder
|
||||||
|
|
||||||
|
func (d *decoder) uint8() uint8 {
|
||||||
|
x := d.buf[0]
|
||||||
|
d.buf = d.buf[1:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uint8(x uint8) {
|
||||||
|
e.buf[0] = x
|
||||||
|
e.buf = e.buf[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) uint16() uint16 {
|
||||||
|
x := d.order.Uint16(d.buf[0:2])
|
||||||
|
d.buf = d.buf[2:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uint16(x uint16) {
|
||||||
|
e.order.PutUint16(e.buf[0:2], x)
|
||||||
|
e.buf = e.buf[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) uint32() uint32 {
|
||||||
|
x := d.order.Uint32(d.buf[0:4])
|
||||||
|
d.buf = d.buf[4:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uint32(x uint32) {
|
||||||
|
e.order.PutUint32(e.buf[0:4], x)
|
||||||
|
e.buf = e.buf[4:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) uint64() uint64 {
|
||||||
|
x := d.order.Uint64(d.buf[0:8])
|
||||||
|
d.buf = d.buf[8:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uint64(x uint64) {
|
||||||
|
e.order.PutUint64(e.buf[0:8], x)
|
||||||
|
e.buf = e.buf[8:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) int8() int8 { return int8(d.uint8()) }
|
||||||
|
|
||||||
|
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
|
||||||
|
|
||||||
|
func (d *decoder) int16() int16 { return int16(d.uint16()) }
|
||||||
|
|
||||||
|
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
|
||||||
|
|
||||||
|
func (d *decoder) int32() int32 { return int32(d.uint32()) }
|
||||||
|
|
||||||
|
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
|
||||||
|
|
||||||
|
func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
||||||
|
|
||||||
|
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
||||||
|
|
||||||
|
func (d *decoder) value(v reflect.Value) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Array:
|
||||||
|
l := v.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
d.value(v.Index(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
t := v.Type()
|
||||||
|
l := v.NumField()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
// Note: Calling v.CanSet() below is an optimization.
|
||||||
|
// It would be sufficient to check the field name,
|
||||||
|
// but creating the StructField info for each field is
|
||||||
|
// costly (run "go test -bench=ReadStruct" and compare
|
||||||
|
// results when making changes to this code).
|
||||||
|
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
||||||
|
d.value(v)
|
||||||
|
} else {
|
||||||
|
d.skip(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
l := v.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
d.value(v.Index(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Int8:
|
||||||
|
v.SetInt(int64(d.int8()))
|
||||||
|
case reflect.Int16:
|
||||||
|
v.SetInt(int64(d.int16()))
|
||||||
|
case reflect.Int32:
|
||||||
|
v.SetInt(int64(d.int32()))
|
||||||
|
case reflect.Int64:
|
||||||
|
v.SetInt(d.int64())
|
||||||
|
|
||||||
|
case reflect.Uint8:
|
||||||
|
v.SetUint(uint64(d.uint8()))
|
||||||
|
case reflect.Uint16:
|
||||||
|
v.SetUint(uint64(d.uint16()))
|
||||||
|
case reflect.Uint32:
|
||||||
|
v.SetUint(uint64(d.uint32()))
|
||||||
|
case reflect.Uint64:
|
||||||
|
v.SetUint(d.uint64())
|
||||||
|
|
||||||
|
case reflect.Float32:
|
||||||
|
v.SetFloat(float64(math.Float32frombits(d.uint32())))
|
||||||
|
case reflect.Float64:
|
||||||
|
v.SetFloat(math.Float64frombits(d.uint64()))
|
||||||
|
|
||||||
|
case reflect.Complex64:
|
||||||
|
v.SetComplex(complex(
|
||||||
|
float64(math.Float32frombits(d.uint32())),
|
||||||
|
float64(math.Float32frombits(d.uint32())),
|
||||||
|
))
|
||||||
|
case reflect.Complex128:
|
||||||
|
v.SetComplex(complex(
|
||||||
|
math.Float64frombits(d.uint64()),
|
||||||
|
math.Float64frombits(d.uint64()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) value(v reflect.Value) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Array:
|
||||||
|
l := v.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
e.value(v.Index(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
t := v.Type()
|
||||||
|
l := v.NumField()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
// see comment for corresponding code in decoder.value()
|
||||||
|
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
||||||
|
e.value(v)
|
||||||
|
} else {
|
||||||
|
e.skip(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
l := v.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
e.value(v.Index(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int8:
|
||||||
|
e.int8(int8(v.Int()))
|
||||||
|
case reflect.Int16:
|
||||||
|
e.int16(int16(v.Int()))
|
||||||
|
case reflect.Int32:
|
||||||
|
e.int32(int32(v.Int()))
|
||||||
|
case reflect.Int64:
|
||||||
|
e.int64(v.Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Uint8:
|
||||||
|
e.uint8(uint8(v.Uint()))
|
||||||
|
case reflect.Uint16:
|
||||||
|
e.uint16(uint16(v.Uint()))
|
||||||
|
case reflect.Uint32:
|
||||||
|
e.uint32(uint32(v.Uint()))
|
||||||
|
case reflect.Uint64:
|
||||||
|
e.uint64(v.Uint())
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Float32:
|
||||||
|
e.uint32(math.Float32bits(float32(v.Float())))
|
||||||
|
case reflect.Float64:
|
||||||
|
e.uint64(math.Float64bits(v.Float()))
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Complex64:
|
||||||
|
x := v.Complex()
|
||||||
|
e.uint32(math.Float32bits(float32(real(x))))
|
||||||
|
e.uint32(math.Float32bits(float32(imag(x))))
|
||||||
|
case reflect.Complex128:
|
||||||
|
x := v.Complex()
|
||||||
|
e.uint64(math.Float64bits(real(x)))
|
||||||
|
e.uint64(math.Float64bits(imag(x)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) skip(v reflect.Value) {
|
||||||
|
d.buf = d.buf[dataSize(v):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) skip(v reflect.Value) {
|
||||||
|
n := dataSize(v)
|
||||||
|
for i := range e.buf[0:n] {
|
||||||
|
e.buf[i] = 0
|
||||||
|
}
|
||||||
|
e.buf = e.buf[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// intDataSize returns the size of the data required to represent the data when encoded.
|
||||||
|
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
|
||||||
|
func intDataSize(data interface{}) int {
|
||||||
|
switch data := data.(type) {
|
||||||
|
case int8, *int8, *uint8:
|
||||||
|
return 1
|
||||||
|
case []int8:
|
||||||
|
return len(data)
|
||||||
|
case []uint8:
|
||||||
|
return len(data)
|
||||||
|
case int16, *int16, *uint16:
|
||||||
|
return 2
|
||||||
|
case []int16:
|
||||||
|
return 2 * len(data)
|
||||||
|
case []uint16:
|
||||||
|
return 2 * len(data)
|
||||||
|
case int32, *int32, *uint32:
|
||||||
|
return 4
|
||||||
|
case []int32:
|
||||||
|
return 4 * len(data)
|
||||||
|
case []uint32:
|
||||||
|
return 4 * len(data)
|
||||||
|
case int64, *int64, *uint64:
|
||||||
|
return 8
|
||||||
|
case []int64:
|
||||||
|
return 8 * len(data)
|
||||||
|
case []uint64:
|
||||||
|
return 8 * len(data)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiskUsageStat struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Fstype string `json:"fstype"`
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
Free uint64 `json:"free"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
UsedPercent float64 `json:"used_percent"`
|
||||||
|
InodesTotal uint64 `json:"inodes_total"`
|
||||||
|
InodesUsed uint64 `json:"inodes_used"`
|
||||||
|
InodesFree uint64 `json:"inodes_free"`
|
||||||
|
InodesUsedPercent float64 `json:"inodes_used_percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskPartitionStat struct {
|
||||||
|
Device string `json:"device"`
|
||||||
|
Mountpoint string `json:"mountpoint"`
|
||||||
|
Fstype string `json:"fstype"`
|
||||||
|
Opts string `json:"opts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskIOCountersStat struct {
|
||||||
|
ReadCount uint64 `json:"read_count"`
|
||||||
|
WriteCount uint64 `json:"write_count"`
|
||||||
|
ReadBytes uint64 `json:"read_bytes"`
|
||||||
|
WriteBytes uint64 `json:"write_bytes"`
|
||||||
|
ReadTime uint64 `json:"read_time"`
|
||||||
|
WriteTime uint64 `json:"write_time"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
IoTime uint64 `json:"io_time"`
|
||||||
|
SerialNumber string `json:"serial_number"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DiskUsageStat) String() string {
|
||||||
|
s, _ := json.Marshal(d)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DiskPartitionStat) String() string {
|
||||||
|
s, _ := json.Marshal(d)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DiskIOCountersStat) String() string {
|
||||||
|
s, _ := json.Marshal(d)
|
||||||
|
return string(s)
|
||||||
|
}
|
104
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
Normal file
104
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
||||||
|
var ret []DiskPartitionStat
|
||||||
|
|
||||||
|
count, err := Getfsstat(nil, MntWait)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
fs := make([]Statfs_t, count)
|
||||||
|
_, err = Getfsstat(fs, MntWait)
|
||||||
|
for _, stat := range fs {
|
||||||
|
opts := "rw"
|
||||||
|
if stat.Flags&MntReadOnly != 0 {
|
||||||
|
opts = "ro"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntSynchronous != 0 {
|
||||||
|
opts += ",sync"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntNoExec != 0 {
|
||||||
|
opts += ",noexec"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntNoSuid != 0 {
|
||||||
|
opts += ",nosuid"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntUnion != 0 {
|
||||||
|
opts += ",union"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntAsync != 0 {
|
||||||
|
opts += ",async"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntSuidDir != 0 {
|
||||||
|
opts += ",suiddir"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntSoftDep != 0 {
|
||||||
|
opts += ",softdep"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntNoSymFollow != 0 {
|
||||||
|
opts += ",nosymfollow"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntGEOMJournal != 0 {
|
||||||
|
opts += ",gjounalc"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntMultilabel != 0 {
|
||||||
|
opts += ",multilabel"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntACLs != 0 {
|
||||||
|
opts += ",acls"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntNoATime != 0 {
|
||||||
|
opts += ",noattime"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntClusterRead != 0 {
|
||||||
|
opts += ",nocluster"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntClusterWrite != 0 {
|
||||||
|
opts += ",noclusterw"
|
||||||
|
}
|
||||||
|
if stat.Flags&MntNFS4ACLs != 0 {
|
||||||
|
opts += ",nfs4acls"
|
||||||
|
}
|
||||||
|
d := DiskPartitionStat{
|
||||||
|
Device: common.IntToString(stat.Mntfromname[:]),
|
||||||
|
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
||||||
|
Fstype: common.IntToString(stat.Fstypename[:]),
|
||||||
|
Opts: opts,
|
||||||
|
}
|
||||||
|
ret = append(ret, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
||||||
|
return nil, common.NotImplementedError
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
var bufsize uintptr
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFsType(stat syscall.Statfs_t) string {
|
||||||
|
return common.IntToString(stat.Fstypename[:])
|
||||||
|
}
|
58
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
Normal file
58
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// +build darwin
|
||||||
|
// +build amd64
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
const (
|
||||||
|
MntWait = 1
|
||||||
|
MfsNameLen = 15 /* length of fs type name, not inc. nul */
|
||||||
|
MNameLen = 90 /* length of buffer for returned name */
|
||||||
|
|
||||||
|
MFSTYPENAMELEN = 16 /* length of fs type name including null */
|
||||||
|
MAXPATHLEN = 1024
|
||||||
|
MNAMELEN = MAXPATHLEN
|
||||||
|
|
||||||
|
SYS_GETFSSTAT64 = 347
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fsid struct{ val [2]int32 } /* file system id type */
|
||||||
|
type uid_t int32
|
||||||
|
|
||||||
|
// sys/mount.h
|
||||||
|
const (
|
||||||
|
MntReadOnly = 0x00000001 /* read only filesystem */
|
||||||
|
MntSynchronous = 0x00000002 /* filesystem written synchronously */
|
||||||
|
MntNoExec = 0x00000004 /* can't exec from filesystem */
|
||||||
|
MntNoSuid = 0x00000008 /* don't honor setuid bits on fs */
|
||||||
|
MntUnion = 0x00000020 /* union with underlying filesystem */
|
||||||
|
MntAsync = 0x00000040 /* filesystem written asynchronously */
|
||||||
|
MntSuidDir = 0x00100000 /* special handling of SUID on dirs */
|
||||||
|
MntSoftDep = 0x00200000 /* soft updates being done */
|
||||||
|
MntNoSymFollow = 0x00400000 /* do not follow symlinks */
|
||||||
|
MntGEOMJournal = 0x02000000 /* GEOM journal support enabled */
|
||||||
|
MntMultilabel = 0x04000000 /* MAC support for individual objects */
|
||||||
|
MntACLs = 0x08000000 /* ACL support enabled */
|
||||||
|
MntNoATime = 0x10000000 /* disable update of file access time */
|
||||||
|
MntClusterRead = 0x40000000 /* disable cluster read */
|
||||||
|
MntClusterWrite = 0x80000000 /* disable cluster write */
|
||||||
|
MntNFS4ACLs = 0x00000010
|
||||||
|
)
|
||||||
|
|
||||||
|
type Statfs_t struct {
|
||||||
|
Bsize uint32
|
||||||
|
Iosize int32
|
||||||
|
Blocks uint64
|
||||||
|
Bfree uint64
|
||||||
|
Bavail uint64
|
||||||
|
Files uint64
|
||||||
|
Ffree uint64
|
||||||
|
Fsid Fsid
|
||||||
|
Owner uint32
|
||||||
|
Type uint32
|
||||||
|
Flags uint32
|
||||||
|
Fssubtype uint32
|
||||||
|
Fstypename [16]int8
|
||||||
|
Mntonname [1024]int8
|
||||||
|
Mntfromname [1024]int8
|
||||||
|
Reserved [8]uint32
|
||||||
|
}
|
179
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
Normal file
179
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CTLKern = 1
|
||||||
|
// KernDevstat = 773 // for freebsd 8.4
|
||||||
|
// KernDevstatAll = 772 // for freebsd 8.4
|
||||||
|
KernDevstat = 974
|
||||||
|
KernDevstatAll = 975
|
||||||
|
)
|
||||||
|
|
||||||
|
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
||||||
|
var ret []DiskPartitionStat
|
||||||
|
|
||||||
|
// get length
|
||||||
|
count, err := syscall.Getfsstat(nil, MNT_WAIT)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fs := make([]Statfs, count)
|
||||||
|
_, err = Getfsstat(fs, MNT_WAIT)
|
||||||
|
|
||||||
|
for _, stat := range fs {
|
||||||
|
opts := "rw"
|
||||||
|
if stat.Flags&MNT_RDONLY != 0 {
|
||||||
|
opts = "ro"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_SYNCHRONOUS != 0 {
|
||||||
|
opts += ",sync"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOEXEC != 0 {
|
||||||
|
opts += ",noexec"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOSUID != 0 {
|
||||||
|
opts += ",nosuid"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_UNION != 0 {
|
||||||
|
opts += ",union"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_ASYNC != 0 {
|
||||||
|
opts += ",async"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_SUIDDIR != 0 {
|
||||||
|
opts += ",suiddir"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_SOFTDEP != 0 {
|
||||||
|
opts += ",softdep"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOSYMFOLLOW != 0 {
|
||||||
|
opts += ",nosymfollow"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_GJOURNAL != 0 {
|
||||||
|
opts += ",gjounalc"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_MULTILABEL != 0 {
|
||||||
|
opts += ",multilabel"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_ACLS != 0 {
|
||||||
|
opts += ",acls"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOATIME != 0 {
|
||||||
|
opts += ",noattime"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOCLUSTERR != 0 {
|
||||||
|
opts += ",nocluster"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NOCLUSTERW != 0 {
|
||||||
|
opts += ",noclusterw"
|
||||||
|
}
|
||||||
|
if stat.Flags&MNT_NFS4ACLS != 0 {
|
||||||
|
opts += ",nfs4acls"
|
||||||
|
}
|
||||||
|
|
||||||
|
d := DiskPartitionStat{
|
||||||
|
Device: common.IntToString(stat.Mntfromname[:]),
|
||||||
|
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
||||||
|
Fstype: common.IntToString(stat.Fstypename[:]),
|
||||||
|
Opts: opts,
|
||||||
|
}
|
||||||
|
ret = append(ret, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
||||||
|
// statinfo->devinfo->devstat
|
||||||
|
// /usr/include/devinfo.h
|
||||||
|
|
||||||
|
// sysctl.sysctl ('kern.devstat.all', 0)
|
||||||
|
ret := make(map[string]DiskIOCountersStat)
|
||||||
|
mib := []int32{CTLKern, KernDevstat, KernDevstatAll}
|
||||||
|
|
||||||
|
buf, length, err := common.CallSyscall(mib)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ds := Devstat{}
|
||||||
|
devstatLen := int(unsafe.Sizeof(ds))
|
||||||
|
count := int(length / uint64(devstatLen))
|
||||||
|
|
||||||
|
buf = buf[8:] // devstat.all has version in the head.
|
||||||
|
// parse buf to Devstat
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
b := buf[i*devstatLen : i*devstatLen+devstatLen]
|
||||||
|
d, err := parseDevstat(b)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
un := strconv.Itoa(int(d.Unit_number))
|
||||||
|
name := common.IntToString(d.Device_name[:]) + un
|
||||||
|
|
||||||
|
ds := DiskIOCountersStat{
|
||||||
|
ReadCount: d.Operations[DEVSTAT_READ],
|
||||||
|
WriteCount: d.Operations[DEVSTAT_WRITE],
|
||||||
|
ReadBytes: d.Bytes[DEVSTAT_READ],
|
||||||
|
WriteBytes: d.Bytes[DEVSTAT_WRITE],
|
||||||
|
ReadTime: d.Duration[DEVSTAT_READ].Compute(),
|
||||||
|
WriteTime: d.Duration[DEVSTAT_WRITE].Compute(),
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
ret[name] = ds
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bintime) Compute() uint64 {
|
||||||
|
BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20
|
||||||
|
return uint64(b.Sec) + b.Frac*uint64(BINTIME_SCALE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)
|
||||||
|
|
||||||
|
// Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go
|
||||||
|
// change Statfs_t to Statfs in order to get more information
|
||||||
|
func Getfsstat(buf []Statfs, flags int) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
var bufsize uintptr
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
bufsize = unsafe.Sizeof(Statfs{}) * uintptr(len(buf))
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDevstat(buf []byte) (Devstat, error) {
|
||||||
|
var ds Devstat
|
||||||
|
br := bytes.NewReader(buf)
|
||||||
|
// err := binary.Read(br, binary.LittleEndian, &ds)
|
||||||
|
err := Read(br, binary.LittleEndian, &ds)
|
||||||
|
if err != nil {
|
||||||
|
return ds, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFsType(stat syscall.Statfs_t) string {
|
||||||
|
return common.IntToString(stat.Fstypename[:])
|
||||||
|
}
|
111
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
Normal file
111
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs types_freebsd.go
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofPtr = 0x8
|
||||||
|
sizeofShort = 0x2
|
||||||
|
sizeofInt = 0x4
|
||||||
|
sizeofLong = 0x8
|
||||||
|
sizeofLongLong = 0x8
|
||||||
|
sizeofLongDouble = 0x8
|
||||||
|
|
||||||
|
DEVSTAT_NO_DATA = 0x00
|
||||||
|
DEVSTAT_READ = 0x01
|
||||||
|
DEVSTAT_WRITE = 0x02
|
||||||
|
DEVSTAT_FREE = 0x03
|
||||||
|
|
||||||
|
MNT_RDONLY = 0x00000001
|
||||||
|
MNT_SYNCHRONOUS = 0x00000002
|
||||||
|
MNT_NOEXEC = 0x00000004
|
||||||
|
MNT_NOSUID = 0x00000008
|
||||||
|
MNT_UNION = 0x00000020
|
||||||
|
MNT_ASYNC = 0x00000040
|
||||||
|
MNT_SUIDDIR = 0x00100000
|
||||||
|
MNT_SOFTDEP = 0x00200000
|
||||||
|
MNT_NOSYMFOLLOW = 0x00400000
|
||||||
|
MNT_GJOURNAL = 0x02000000
|
||||||
|
MNT_MULTILABEL = 0x04000000
|
||||||
|
MNT_ACLS = 0x08000000
|
||||||
|
MNT_NOATIME = 0x10000000
|
||||||
|
MNT_NOCLUSTERR = 0x40000000
|
||||||
|
MNT_NOCLUSTERW = 0x80000000
|
||||||
|
MNT_NFS4ACLS = 0x00000010
|
||||||
|
|
||||||
|
MNT_WAIT = 1
|
||||||
|
MNT_NOWAIT = 2
|
||||||
|
MNT_LAZY = 3
|
||||||
|
MNT_SUSPEND = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
_C_short int16
|
||||||
|
_C_int int32
|
||||||
|
_C_long int64
|
||||||
|
_C_long_long int64
|
||||||
|
_C_long_double int64
|
||||||
|
)
|
||||||
|
|
||||||
|
type Statfs struct {
|
||||||
|
Version uint32
|
||||||
|
Type uint32
|
||||||
|
Flags uint64
|
||||||
|
Bsize uint64
|
||||||
|
Iosize uint64
|
||||||
|
Blocks uint64
|
||||||
|
Bfree uint64
|
||||||
|
Bavail int64
|
||||||
|
Files uint64
|
||||||
|
Ffree int64
|
||||||
|
Syncwrites uint64
|
||||||
|
Asyncwrites uint64
|
||||||
|
Syncreads uint64
|
||||||
|
Asyncreads uint64
|
||||||
|
Spare [10]uint64
|
||||||
|
Namemax uint32
|
||||||
|
Owner uint32
|
||||||
|
Fsid Fsid
|
||||||
|
Charspare [80]int8
|
||||||
|
Fstypename [16]int8
|
||||||
|
Mntfromname [88]int8
|
||||||
|
Mntonname [88]int8
|
||||||
|
}
|
||||||
|
type Fsid struct {
|
||||||
|
Val [2]int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Devstat struct {
|
||||||
|
Sequence0 uint32
|
||||||
|
Allocated int32
|
||||||
|
Start_count uint32
|
||||||
|
End_count uint32
|
||||||
|
Busy_from Bintime
|
||||||
|
Dev_links _Ctype_struct___0
|
||||||
|
Device_number uint32
|
||||||
|
Device_name [16]int8
|
||||||
|
Unit_number int32
|
||||||
|
Bytes [4]uint64
|
||||||
|
Operations [4]uint64
|
||||||
|
Duration [4]Bintime
|
||||||
|
Busy_time Bintime
|
||||||
|
Creation_time Bintime
|
||||||
|
Block_size uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Tag_types [3]uint64
|
||||||
|
Flags uint32
|
||||||
|
Device_type uint32
|
||||||
|
Priority uint32
|
||||||
|
Pad_cgo_1 [4]byte
|
||||||
|
Id *byte
|
||||||
|
Sequence1 uint32
|
||||||
|
Pad_cgo_2 [4]byte
|
||||||
|
}
|
||||||
|
type Bintime struct {
|
||||||
|
Sec int64
|
||||||
|
Frac uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Ctype_struct___0 struct {
|
||||||
|
Empty uint64
|
||||||
|
}
|
327
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
Normal file
327
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SectorSize = 512
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
// man statfs
|
||||||
|
ADFS_SUPER_MAGIC = 0xadf5
|
||||||
|
AFFS_SUPER_MAGIC = 0xADFF
|
||||||
|
BDEVFS_MAGIC = 0x62646576
|
||||||
|
BEFS_SUPER_MAGIC = 0x42465331
|
||||||
|
BFS_MAGIC = 0x1BADFACE
|
||||||
|
BINFMTFS_MAGIC = 0x42494e4d
|
||||||
|
BTRFS_SUPER_MAGIC = 0x9123683E
|
||||||
|
CGROUP_SUPER_MAGIC = 0x27e0eb
|
||||||
|
CIFS_MAGIC_NUMBER = 0xFF534D42
|
||||||
|
CODA_SUPER_MAGIC = 0x73757245
|
||||||
|
COH_SUPER_MAGIC = 0x012FF7B7
|
||||||
|
CRAMFS_MAGIC = 0x28cd3d45
|
||||||
|
DEBUGFS_MAGIC = 0x64626720
|
||||||
|
DEVFS_SUPER_MAGIC = 0x1373
|
||||||
|
DEVPTS_SUPER_MAGIC = 0x1cd1
|
||||||
|
EFIVARFS_MAGIC = 0xde5e81e4
|
||||||
|
EFS_SUPER_MAGIC = 0x00414A53
|
||||||
|
EXT_SUPER_MAGIC = 0x137D
|
||||||
|
EXT2_OLD_SUPER_MAGIC = 0xEF51
|
||||||
|
EXT2_SUPER_MAGIC = 0xEF53
|
||||||
|
EXT3_SUPER_MAGIC = 0xEF53
|
||||||
|
EXT4_SUPER_MAGIC = 0xEF53
|
||||||
|
FUSE_SUPER_MAGIC = 0x65735546
|
||||||
|
FUTEXFS_SUPER_MAGIC = 0xBAD1DEA
|
||||||
|
HFS_SUPER_MAGIC = 0x4244
|
||||||
|
HOSTFS_SUPER_MAGIC = 0x00c0ffee
|
||||||
|
HPFS_SUPER_MAGIC = 0xF995E849
|
||||||
|
HUGETLBFS_MAGIC = 0x958458f6
|
||||||
|
ISOFS_SUPER_MAGIC = 0x9660
|
||||||
|
JFFS2_SUPER_MAGIC = 0x72b6
|
||||||
|
JFS_SUPER_MAGIC = 0x3153464a
|
||||||
|
MINIX_SUPER_MAGIC = 0x137F /* orig. minix */
|
||||||
|
MINIX_SUPER_MAGIC2 = 0x138F /* 30 char minix */
|
||||||
|
MINIX2_SUPER_MAGIC = 0x2468 /* minix V2 */
|
||||||
|
MINIX2_SUPER_MAGIC2 = 0x2478 /* minix V2, 30 char names */
|
||||||
|
MINIX3_SUPER_MAGIC = 0x4d5a /* minix V3 fs, 60 char names */
|
||||||
|
MQUEUE_MAGIC = 0x19800202
|
||||||
|
MSDOS_SUPER_MAGIC = 0x4d44
|
||||||
|
NCP_SUPER_MAGIC = 0x564c
|
||||||
|
NFS_SUPER_MAGIC = 0x6969
|
||||||
|
NILFS_SUPER_MAGIC = 0x3434
|
||||||
|
NTFS_SB_MAGIC = 0x5346544e
|
||||||
|
OCFS2_SUPER_MAGIC = 0x7461636f
|
||||||
|
OPENPROM_SUPER_MAGIC = 0x9fa1
|
||||||
|
PIPEFS_MAGIC = 0x50495045
|
||||||
|
PROC_SUPER_MAGIC = 0x9fa0
|
||||||
|
PSTOREFS_MAGIC = 0x6165676C
|
||||||
|
QNX4_SUPER_MAGIC = 0x002f
|
||||||
|
QNX6_SUPER_MAGIC = 0x68191122
|
||||||
|
RAMFS_MAGIC = 0x858458f6
|
||||||
|
REISERFS_SUPER_MAGIC = 0x52654973
|
||||||
|
ROMFS_MAGIC = 0x7275
|
||||||
|
SELINUX_MAGIC = 0xf97cff8c
|
||||||
|
SMACK_MAGIC = 0x43415d53
|
||||||
|
SMB_SUPER_MAGIC = 0x517B
|
||||||
|
SOCKFS_MAGIC = 0x534F434B
|
||||||
|
SQUASHFS_MAGIC = 0x73717368
|
||||||
|
SYSFS_MAGIC = 0x62656572
|
||||||
|
SYSV2_SUPER_MAGIC = 0x012FF7B6
|
||||||
|
SYSV4_SUPER_MAGIC = 0x012FF7B5
|
||||||
|
TMPFS_MAGIC = 0x01021994
|
||||||
|
UDF_SUPER_MAGIC = 0x15013346
|
||||||
|
UFS_MAGIC = 0x00011954
|
||||||
|
USBDEVICE_SUPER_MAGIC = 0x9fa2
|
||||||
|
V9FS_MAGIC = 0x01021997
|
||||||
|
VXFS_SUPER_MAGIC = 0xa501FCF5
|
||||||
|
XENFS_SUPER_MAGIC = 0xabba1974
|
||||||
|
XENIX_SUPER_MAGIC = 0x012FF7B4
|
||||||
|
XFS_SUPER_MAGIC = 0x58465342
|
||||||
|
_XIAFS_SUPER_MAGIC = 0x012FD16D
|
||||||
|
|
||||||
|
AFS_SUPER_MAGIC = 0x5346414F
|
||||||
|
AUFS_SUPER_MAGIC = 0x61756673
|
||||||
|
ANON_INODE_FS_SUPER_MAGIC = 0x09041934
|
||||||
|
CEPH_SUPER_MAGIC = 0x00C36400
|
||||||
|
ECRYPTFS_SUPER_MAGIC = 0xF15F
|
||||||
|
FAT_SUPER_MAGIC = 0x4006
|
||||||
|
FHGFS_SUPER_MAGIC = 0x19830326
|
||||||
|
FUSEBLK_SUPER_MAGIC = 0x65735546
|
||||||
|
FUSECTL_SUPER_MAGIC = 0x65735543
|
||||||
|
GFS_SUPER_MAGIC = 0x1161970
|
||||||
|
GPFS_SUPER_MAGIC = 0x47504653
|
||||||
|
MTD_INODE_FS_SUPER_MAGIC = 0x11307854
|
||||||
|
INOTIFYFS_SUPER_MAGIC = 0x2BAD1DEA
|
||||||
|
ISOFS_R_WIN_SUPER_MAGIC = 0x4004
|
||||||
|
ISOFS_WIN_SUPER_MAGIC = 0x4000
|
||||||
|
JFFS_SUPER_MAGIC = 0x07C0
|
||||||
|
KAFS_SUPER_MAGIC = 0x6B414653
|
||||||
|
LUSTRE_SUPER_MAGIC = 0x0BD00BD0
|
||||||
|
NFSD_SUPER_MAGIC = 0x6E667364
|
||||||
|
PANFS_SUPER_MAGIC = 0xAAD7AAEA
|
||||||
|
RPC_PIPEFS_SUPER_MAGIC = 0x67596969
|
||||||
|
SECURITYFS_SUPER_MAGIC = 0x73636673
|
||||||
|
UFS_BYTESWAPPED_SUPER_MAGIC = 0x54190100
|
||||||
|
VMHGFS_SUPER_MAGIC = 0xBACBACBC
|
||||||
|
VZFS_SUPER_MAGIC = 0x565A4653
|
||||||
|
ZFS_SUPER_MAGIC = 0x2FC12FC1
|
||||||
|
)
|
||||||
|
|
||||||
|
// coreutils/src/stat.c
|
||||||
|
var fsTypeMap = map[int64]string{
|
||||||
|
ADFS_SUPER_MAGIC: "adfs", /* 0xADF5 local */
|
||||||
|
AFFS_SUPER_MAGIC: "affs", /* 0xADFF local */
|
||||||
|
AFS_SUPER_MAGIC: "afs", /* 0x5346414F remote */
|
||||||
|
ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */
|
||||||
|
AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */
|
||||||
|
// AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */
|
||||||
|
BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */
|
||||||
|
BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */
|
||||||
|
BFS_MAGIC: "bfs", /* 0x1BADFACE local */
|
||||||
|
BINFMTFS_MAGIC: "binfmt_misc", /* 0x42494E4D local */
|
||||||
|
BTRFS_SUPER_MAGIC: "btrfs", /* 0x9123683E local */
|
||||||
|
CEPH_SUPER_MAGIC: "ceph", /* 0x00C36400 remote */
|
||||||
|
CGROUP_SUPER_MAGIC: "cgroupfs", /* 0x0027E0EB local */
|
||||||
|
CIFS_MAGIC_NUMBER: "cifs", /* 0xFF534D42 remote */
|
||||||
|
CODA_SUPER_MAGIC: "coda", /* 0x73757245 remote */
|
||||||
|
COH_SUPER_MAGIC: "coh", /* 0x012FF7B7 local */
|
||||||
|
CRAMFS_MAGIC: "cramfs", /* 0x28CD3D45 local */
|
||||||
|
DEBUGFS_MAGIC: "debugfs", /* 0x64626720 local */
|
||||||
|
DEVFS_SUPER_MAGIC: "devfs", /* 0x1373 local */
|
||||||
|
DEVPTS_SUPER_MAGIC: "devpts", /* 0x1CD1 local */
|
||||||
|
ECRYPTFS_SUPER_MAGIC: "ecryptfs", /* 0xF15F local */
|
||||||
|
EFS_SUPER_MAGIC: "efs", /* 0x00414A53 local */
|
||||||
|
EXT_SUPER_MAGIC: "ext", /* 0x137D local */
|
||||||
|
EXT2_SUPER_MAGIC: "ext2/ext3", /* 0xEF53 local */
|
||||||
|
EXT2_OLD_SUPER_MAGIC: "ext2", /* 0xEF51 local */
|
||||||
|
FAT_SUPER_MAGIC: "fat", /* 0x4006 local */
|
||||||
|
FHGFS_SUPER_MAGIC: "fhgfs", /* 0x19830326 remote */
|
||||||
|
FUSEBLK_SUPER_MAGIC: "fuseblk", /* 0x65735546 remote */
|
||||||
|
FUSECTL_SUPER_MAGIC: "fusectl", /* 0x65735543 remote */
|
||||||
|
FUTEXFS_SUPER_MAGIC: "futexfs", /* 0x0BAD1DEA local */
|
||||||
|
GFS_SUPER_MAGIC: "gfs/gfs2", /* 0x1161970 remote */
|
||||||
|
GPFS_SUPER_MAGIC: "gpfs", /* 0x47504653 remote */
|
||||||
|
HFS_SUPER_MAGIC: "hfs", /* 0x4244 local */
|
||||||
|
HPFS_SUPER_MAGIC: "hpfs", /* 0xF995E849 local */
|
||||||
|
HUGETLBFS_MAGIC: "hugetlbfs", /* 0x958458F6 local */
|
||||||
|
MTD_INODE_FS_SUPER_MAGIC: "inodefs", /* 0x11307854 local */
|
||||||
|
INOTIFYFS_SUPER_MAGIC: "inotifyfs", /* 0x2BAD1DEA local */
|
||||||
|
ISOFS_SUPER_MAGIC: "isofs", /* 0x9660 local */
|
||||||
|
ISOFS_R_WIN_SUPER_MAGIC: "isofs", /* 0x4004 local */
|
||||||
|
ISOFS_WIN_SUPER_MAGIC: "isofs", /* 0x4000 local */
|
||||||
|
JFFS_SUPER_MAGIC: "jffs", /* 0x07C0 local */
|
||||||
|
JFFS2_SUPER_MAGIC: "jffs2", /* 0x72B6 local */
|
||||||
|
JFS_SUPER_MAGIC: "jfs", /* 0x3153464A local */
|
||||||
|
KAFS_SUPER_MAGIC: "k-afs", /* 0x6B414653 remote */
|
||||||
|
LUSTRE_SUPER_MAGIC: "lustre", /* 0x0BD00BD0 remote */
|
||||||
|
MINIX_SUPER_MAGIC: "minix", /* 0x137F local */
|
||||||
|
MINIX_SUPER_MAGIC2: "minix (30 char.)", /* 0x138F local */
|
||||||
|
MINIX2_SUPER_MAGIC: "minix v2", /* 0x2468 local */
|
||||||
|
MINIX2_SUPER_MAGIC2: "minix v2 (30 char.)", /* 0x2478 local */
|
||||||
|
MINIX3_SUPER_MAGIC: "minix3", /* 0x4D5A local */
|
||||||
|
MQUEUE_MAGIC: "mqueue", /* 0x19800202 local */
|
||||||
|
MSDOS_SUPER_MAGIC: "msdos", /* 0x4D44 local */
|
||||||
|
NCP_SUPER_MAGIC: "novell", /* 0x564C remote */
|
||||||
|
NFS_SUPER_MAGIC: "nfs", /* 0x6969 remote */
|
||||||
|
NFSD_SUPER_MAGIC: "nfsd", /* 0x6E667364 remote */
|
||||||
|
NILFS_SUPER_MAGIC: "nilfs", /* 0x3434 local */
|
||||||
|
NTFS_SB_MAGIC: "ntfs", /* 0x5346544E local */
|
||||||
|
OPENPROM_SUPER_MAGIC: "openprom", /* 0x9FA1 local */
|
||||||
|
OCFS2_SUPER_MAGIC: "ocfs2", /* 0x7461636f remote */
|
||||||
|
PANFS_SUPER_MAGIC: "panfs", /* 0xAAD7AAEA remote */
|
||||||
|
PIPEFS_MAGIC: "pipefs", /* 0x50495045 remote */
|
||||||
|
PROC_SUPER_MAGIC: "proc", /* 0x9FA0 local */
|
||||||
|
PSTOREFS_MAGIC: "pstorefs", /* 0x6165676C local */
|
||||||
|
QNX4_SUPER_MAGIC: "qnx4", /* 0x002F local */
|
||||||
|
QNX6_SUPER_MAGIC: "qnx6", /* 0x68191122 local */
|
||||||
|
RAMFS_MAGIC: "ramfs", /* 0x858458F6 local */
|
||||||
|
REISERFS_SUPER_MAGIC: "reiserfs", /* 0x52654973 local */
|
||||||
|
ROMFS_MAGIC: "romfs", /* 0x7275 local */
|
||||||
|
RPC_PIPEFS_SUPER_MAGIC: "rpc_pipefs", /* 0x67596969 local */
|
||||||
|
SECURITYFS_SUPER_MAGIC: "securityfs", /* 0x73636673 local */
|
||||||
|
SELINUX_MAGIC: "selinux", /* 0xF97CFF8C local */
|
||||||
|
SMB_SUPER_MAGIC: "smb", /* 0x517B remote */
|
||||||
|
SOCKFS_MAGIC: "sockfs", /* 0x534F434B local */
|
||||||
|
SQUASHFS_MAGIC: "squashfs", /* 0x73717368 local */
|
||||||
|
SYSFS_MAGIC: "sysfs", /* 0x62656572 local */
|
||||||
|
SYSV2_SUPER_MAGIC: "sysv2", /* 0x012FF7B6 local */
|
||||||
|
SYSV4_SUPER_MAGIC: "sysv4", /* 0x012FF7B5 local */
|
||||||
|
TMPFS_MAGIC: "tmpfs", /* 0x01021994 local */
|
||||||
|
UDF_SUPER_MAGIC: "udf", /* 0x15013346 local */
|
||||||
|
UFS_MAGIC: "ufs", /* 0x00011954 local */
|
||||||
|
UFS_BYTESWAPPED_SUPER_MAGIC: "ufs", /* 0x54190100 local */
|
||||||
|
USBDEVICE_SUPER_MAGIC: "usbdevfs", /* 0x9FA2 local */
|
||||||
|
V9FS_MAGIC: "v9fs", /* 0x01021997 local */
|
||||||
|
VMHGFS_SUPER_MAGIC: "vmhgfs", /* 0xBACBACBC remote */
|
||||||
|
VXFS_SUPER_MAGIC: "vxfs", /* 0xA501FCF5 local */
|
||||||
|
VZFS_SUPER_MAGIC: "vzfs", /* 0x565A4653 local */
|
||||||
|
XENFS_SUPER_MAGIC: "xenfs", /* 0xABBA1974 local */
|
||||||
|
XENIX_SUPER_MAGIC: "xenix", /* 0x012FF7B4 local */
|
||||||
|
XFS_SUPER_MAGIC: "xfs", /* 0x58465342 local */
|
||||||
|
_XIAFS_SUPER_MAGIC: "xia", /* 0x012FD16D local */
|
||||||
|
ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get disk partitions.
|
||||||
|
// should use setmntent(3) but this implement use /etc/mtab file
|
||||||
|
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
||||||
|
|
||||||
|
filename := "/etc/mtab"
|
||||||
|
lines, err := common.ReadLines(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]DiskPartitionStat, 0, len(lines))
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
d := DiskPartitionStat{
|
||||||
|
Device: fields[0],
|
||||||
|
Mountpoint: fields[1],
|
||||||
|
Fstype: fields[2],
|
||||||
|
Opts: fields[3],
|
||||||
|
}
|
||||||
|
ret = append(ret, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
||||||
|
filename := "/proc/diskstats"
|
||||||
|
lines, err := common.ReadLines(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := make(map[string]DiskIOCountersStat, 0)
|
||||||
|
empty := DiskIOCountersStat{}
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
name := fields[2]
|
||||||
|
reads, err := strconv.ParseUint((fields[3]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
rbytes, err := strconv.ParseUint((fields[5]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
rtime, err := strconv.ParseUint((fields[6]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
writes, err := strconv.ParseUint((fields[7]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
wbytes, err := strconv.ParseUint((fields[9]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
wtime, err := strconv.ParseUint((fields[10]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
iotime, err := strconv.ParseUint((fields[12]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
d := DiskIOCountersStat{
|
||||||
|
ReadBytes: rbytes * SectorSize,
|
||||||
|
WriteBytes: wbytes * SectorSize,
|
||||||
|
ReadCount: reads,
|
||||||
|
WriteCount: writes,
|
||||||
|
ReadTime: rtime,
|
||||||
|
WriteTime: wtime,
|
||||||
|
IoTime: iotime,
|
||||||
|
}
|
||||||
|
if d == empty {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d.Name = name
|
||||||
|
|
||||||
|
d.SerialNumber = GetDiskSerialNumber(name)
|
||||||
|
ret[name] = d
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDiskSerialNumber(name string) string {
|
||||||
|
n := fmt.Sprintf("--name=%s", name)
|
||||||
|
out, err := exec.Command("/sbin/udevadm", "info", "--query=property", n).Output()
|
||||||
|
|
||||||
|
// does not return error, just an empty string
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
values := strings.Split(line, "=")
|
||||||
|
if len(values) < 2 || values[0] != "ID_SERIAL" {
|
||||||
|
// only get ID_SERIAL, not ID_SERIAL_SHORT
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return values[1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFsType(stat syscall.Statfs_t) string {
|
||||||
|
t := stat.Type
|
||||||
|
ret, ok := fsTypeMap[t]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
97
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_test.go
generated
vendored
Normal file
97
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_test.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDisk_usage(t *testing.T) {
|
||||||
|
path := "/"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
path = "C:"
|
||||||
|
}
|
||||||
|
v, err := DiskUsage(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if v.Path != path {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisk_partitions(t *testing.T) {
|
||||||
|
ret, err := DiskPartitions(false)
|
||||||
|
if err != nil || len(ret) == 0 {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
empty := DiskPartitionStat{}
|
||||||
|
for _, disk := range ret {
|
||||||
|
if disk == empty {
|
||||||
|
t.Errorf("Could not get device info %v", disk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisk_io_counters(t *testing.T) {
|
||||||
|
ret, err := DiskIOCounters()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if len(ret) == 0 {
|
||||||
|
t.Errorf("ret is empty, %v", ret)
|
||||||
|
}
|
||||||
|
empty := DiskIOCountersStat{}
|
||||||
|
for part, io := range ret {
|
||||||
|
if io == empty {
|
||||||
|
t.Errorf("io_counter error %v, %v", part, io)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiskUsageStat_String(t *testing.T) {
|
||||||
|
v := DiskUsageStat{
|
||||||
|
Path: "/",
|
||||||
|
Total: 1000,
|
||||||
|
Free: 2000,
|
||||||
|
Used: 3000,
|
||||||
|
UsedPercent: 50.1,
|
||||||
|
InodesTotal: 4000,
|
||||||
|
InodesUsed: 5000,
|
||||||
|
InodesFree: 6000,
|
||||||
|
InodesUsedPercent: 49.1,
|
||||||
|
Fstype: "ext4",
|
||||||
|
}
|
||||||
|
e := `{"path":"/","fstype":"ext4","total":1000,"free":2000,"used":3000,"used_percent":50.1,"inodes_total":4000,"inodes_used":5000,"inodes_free":6000,"inodes_used_percent":49.1}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiskPartitionStat_String(t *testing.T) {
|
||||||
|
v := DiskPartitionStat{
|
||||||
|
Device: "sd01",
|
||||||
|
Mountpoint: "/",
|
||||||
|
Fstype: "ext4",
|
||||||
|
Opts: "ro",
|
||||||
|
}
|
||||||
|
e := `{"device":"sd01","mountpoint":"/","fstype":"ext4","opts":"ro"}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiskIOCountersStat_String(t *testing.T) {
|
||||||
|
v := DiskIOCountersStat{
|
||||||
|
Name: "sd01",
|
||||||
|
ReadCount: 100,
|
||||||
|
WriteCount: 200,
|
||||||
|
ReadBytes: 300,
|
||||||
|
WriteBytes: 400,
|
||||||
|
SerialNumber: "SERIAL",
|
||||||
|
}
|
||||||
|
e := `{"read_count":100,"write_count":200,"read_bytes":300,"write_bytes":400,"read_time":0,"write_time":0,"name":"sd01","io_time":0,"serial_number":"SERIAL"}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
30
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
Normal file
30
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// +build freebsd linux darwin
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func DiskUsage(path string) (*DiskUsageStat, error) {
|
||||||
|
stat := syscall.Statfs_t{}
|
||||||
|
err := syscall.Statfs(path, &stat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bsize := stat.Bsize
|
||||||
|
|
||||||
|
ret := &DiskUsageStat{
|
||||||
|
Path: path,
|
||||||
|
Fstype: getFsType(stat),
|
||||||
|
Total: (uint64(stat.Blocks) * uint64(bsize)),
|
||||||
|
Free: (uint64(stat.Bfree) * uint64(bsize)),
|
||||||
|
InodesTotal: (uint64(stat.Files)),
|
||||||
|
InodesFree: (uint64(stat.Ffree)),
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
|
||||||
|
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
|
||||||
|
ret.Used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize)
|
||||||
|
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
155
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
Normal file
155
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/StackExchange/wmi"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||||
|
procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
|
||||||
|
procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW")
|
||||||
|
provGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
FileFileCompression = int64(16) // 0x00000010
|
||||||
|
FileReadOnlyVolume = int64(524288) // 0x00080000
|
||||||
|
)
|
||||||
|
|
||||||
|
type Win32_PerfFormattedData struct {
|
||||||
|
Name string
|
||||||
|
AvgDiskBytesPerRead uint64
|
||||||
|
AvgDiskBytesPerWrite uint64
|
||||||
|
AvgDiskReadQueueLength uint64
|
||||||
|
AvgDiskWriteQueueLength uint64
|
||||||
|
AvgDisksecPerRead uint64
|
||||||
|
AvgDisksecPerWrite uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
const WaitMSec = 500
|
||||||
|
|
||||||
|
func DiskUsage(path string) (*DiskUsageStat, error) {
|
||||||
|
ret := &DiskUsageStat{}
|
||||||
|
|
||||||
|
lpFreeBytesAvailable := int64(0)
|
||||||
|
lpTotalNumberOfBytes := int64(0)
|
||||||
|
lpTotalNumberOfFreeBytes := int64(0)
|
||||||
|
diskret, _, err := procGetDiskFreeSpaceExW.Call(
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
||||||
|
uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
|
||||||
|
uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
|
||||||
|
uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
|
||||||
|
if diskret == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret = &DiskUsageStat{
|
||||||
|
Path: path,
|
||||||
|
Total: uint64(lpTotalNumberOfBytes),
|
||||||
|
Free: uint64(lpTotalNumberOfFreeBytes),
|
||||||
|
Used: uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes),
|
||||||
|
UsedPercent: (float64(lpTotalNumberOfBytes) - float64(lpTotalNumberOfFreeBytes)) / float64(lpTotalNumberOfBytes) * 100,
|
||||||
|
// InodesTotal: 0,
|
||||||
|
// InodesFree: 0,
|
||||||
|
// InodesUsed: 0,
|
||||||
|
// InodesUsedPercent: 0,
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
||||||
|
var ret []DiskPartitionStat
|
||||||
|
lpBuffer := make([]byte, 254)
|
||||||
|
diskret, _, err := procGetLogicalDriveStringsW.Call(
|
||||||
|
uintptr(len(lpBuffer)),
|
||||||
|
uintptr(unsafe.Pointer(&lpBuffer[0])))
|
||||||
|
if diskret == 0 {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
for _, v := range lpBuffer {
|
||||||
|
if v >= 65 && v <= 90 {
|
||||||
|
path := string(v) + ":"
|
||||||
|
if path == "A:" || path == "B:" { // skip floppy drives
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typepath, _ := syscall.UTF16PtrFromString(path)
|
||||||
|
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
|
||||||
|
if typeret == 0 {
|
||||||
|
return ret, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM
|
||||||
|
|
||||||
|
if typeret == 2 || typeret == 3 || typeret == 5 {
|
||||||
|
lpVolumeNameBuffer := make([]byte, 256)
|
||||||
|
lpVolumeSerialNumber := int64(0)
|
||||||
|
lpMaximumComponentLength := int64(0)
|
||||||
|
lpFileSystemFlags := int64(0)
|
||||||
|
lpFileSystemNameBuffer := make([]byte, 256)
|
||||||
|
volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/")
|
||||||
|
driveret, _, err := provGetVolumeInformation.Call(
|
||||||
|
uintptr(unsafe.Pointer(volpath)),
|
||||||
|
uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
|
||||||
|
uintptr(len(lpVolumeNameBuffer)),
|
||||||
|
uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
|
||||||
|
uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
|
||||||
|
uintptr(unsafe.Pointer(&lpFileSystemFlags)),
|
||||||
|
uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])),
|
||||||
|
uintptr(len(lpFileSystemNameBuffer)))
|
||||||
|
if driveret == 0 {
|
||||||
|
if typeret == 5 {
|
||||||
|
continue //device is not ready will happen if there is no disk in the drive
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
opts := "rw"
|
||||||
|
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
||||||
|
opts = "ro"
|
||||||
|
}
|
||||||
|
if lpFileSystemFlags&FileFileCompression != 0 {
|
||||||
|
opts += ".compress"
|
||||||
|
}
|
||||||
|
|
||||||
|
d := DiskPartitionStat{
|
||||||
|
Mountpoint: path,
|
||||||
|
Device: path,
|
||||||
|
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
|
||||||
|
Opts: opts,
|
||||||
|
}
|
||||||
|
ret = append(ret, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
||||||
|
ret := make(map[string]DiskIOCountersStat, 0)
|
||||||
|
var dst []Win32_PerfFormattedData
|
||||||
|
|
||||||
|
err := wmi.Query("SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk ", &dst)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
for _, d := range dst {
|
||||||
|
if len(d.Name) > 3 { // not get _Total or Harddrive
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret[d.Name] = DiskIOCountersStat{
|
||||||
|
Name: d.Name,
|
||||||
|
ReadCount: uint64(d.AvgDiskReadQueueLength),
|
||||||
|
WriteCount: d.AvgDiskWriteQueueLength,
|
||||||
|
ReadBytes: uint64(d.AvgDiskBytesPerRead),
|
||||||
|
WriteBytes: uint64(d.AvgDiskBytesPerWrite),
|
||||||
|
ReadTime: d.AvgDisksecPerRead,
|
||||||
|
WriteTime: d.AvgDisksecPerWrite,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
85
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/types_freebsd.go
generated
vendored
Normal file
85
Godeps/_workspace/src/github.com/shirou/gopsutil/disk/types_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// +build ignore
|
||||||
|
// Hand writing: _Ctype_struct___0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input to cgo -godefs.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package disk
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <devstat.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sizeofPtr = sizeof(void*),
|
||||||
|
};
|
||||||
|
|
||||||
|
// because statinfo has long double snap_time, redefine with changing long long
|
||||||
|
struct statinfo2 {
|
||||||
|
long cp_time[CPUSTATES];
|
||||||
|
long tk_nin;
|
||||||
|
long tk_nout;
|
||||||
|
struct devinfo *dinfo;
|
||||||
|
long long snap_time;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// Machine characteristics; for internal use.
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofPtr = C.sizeofPtr
|
||||||
|
sizeofShort = C.sizeof_short
|
||||||
|
sizeofInt = C.sizeof_int
|
||||||
|
sizeofLong = C.sizeof_long
|
||||||
|
sizeofLongLong = C.sizeof_longlong
|
||||||
|
sizeofLongDouble = C.sizeof_longlong
|
||||||
|
|
||||||
|
DEVSTAT_NO_DATA = 0x00
|
||||||
|
DEVSTAT_READ = 0x01
|
||||||
|
DEVSTAT_WRITE = 0x02
|
||||||
|
DEVSTAT_FREE = 0x03
|
||||||
|
|
||||||
|
// from sys/mount.h
|
||||||
|
MNT_RDONLY = 0x00000001 /* read only filesystem */
|
||||||
|
MNT_SYNCHRONOUS = 0x00000002 /* filesystem written synchronously */
|
||||||
|
MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */
|
||||||
|
MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */
|
||||||
|
MNT_UNION = 0x00000020 /* union with underlying filesystem */
|
||||||
|
MNT_ASYNC = 0x00000040 /* filesystem written asynchronously */
|
||||||
|
MNT_SUIDDIR = 0x00100000 /* special handling of SUID on dirs */
|
||||||
|
MNT_SOFTDEP = 0x00200000 /* soft updates being done */
|
||||||
|
MNT_NOSYMFOLLOW = 0x00400000 /* do not follow symlinks */
|
||||||
|
MNT_GJOURNAL = 0x02000000 /* GEOM journal support enabled */
|
||||||
|
MNT_MULTILABEL = 0x04000000 /* MAC support for individual objects */
|
||||||
|
MNT_ACLS = 0x08000000 /* ACL support enabled */
|
||||||
|
MNT_NOATIME = 0x10000000 /* disable update of file access time */
|
||||||
|
MNT_NOCLUSTERR = 0x40000000 /* disable cluster read */
|
||||||
|
MNT_NOCLUSTERW = 0x80000000 /* disable cluster write */
|
||||||
|
MNT_NFS4ACLS = 0x00000010
|
||||||
|
|
||||||
|
MNT_WAIT = 1 /* synchronously wait for I/O to complete */
|
||||||
|
MNT_NOWAIT = 2 /* start all I/O, but do not wait for it */
|
||||||
|
MNT_LAZY = 3 /* push data not written by filesystem syncer */
|
||||||
|
MNT_SUSPEND = 4 /* Suspend file system after sync */
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
// Basic types
|
||||||
|
|
||||||
|
type (
|
||||||
|
_C_short C.short
|
||||||
|
_C_int C.int
|
||||||
|
_C_long C.long
|
||||||
|
_C_long_long C.longlong
|
||||||
|
_C_long_double C.longlong
|
||||||
|
)
|
||||||
|
|
||||||
|
type Statfs C.struct_statfs
|
||||||
|
type Fsid C.struct_fsid
|
||||||
|
|
||||||
|
type Devstat C.struct_devstat
|
||||||
|
type Bintime C.struct_bintime
|
|
@ -0,0 +1,37 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var ErrDockerNotAvailable = errors.New("docker not available")
|
||||||
|
var ErrCgroupNotAvailable = errors.New("cgroup not available")
|
||||||
|
|
||||||
|
type CgroupMemStat struct {
|
||||||
|
ContainerID string `json:"container_id"`
|
||||||
|
Cache uint64 `json:"cache"`
|
||||||
|
RSS uint64 `json:"rss"`
|
||||||
|
RSSHuge uint64 `json:"rss_huge"`
|
||||||
|
MappedFile uint64 `json:"mapped_file"`
|
||||||
|
Pgpgin uint64 `json:"pgpgin"`
|
||||||
|
Pgpgout uint64 `json:"pgpgout"`
|
||||||
|
Pgfault uint64 `json:"pgfault"`
|
||||||
|
Pgmajfault uint64 `json:"pgmajfault"`
|
||||||
|
InactiveAnon uint64 `json:"inactive_anon"`
|
||||||
|
ActiveAnon uint64 `json:"active_anon"`
|
||||||
|
InactiveFile uint64 `json:"inactive_file"`
|
||||||
|
ActiveFile uint64 `json:"active_file"`
|
||||||
|
Unevictable uint64 `json:"unevictable"`
|
||||||
|
HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit"`
|
||||||
|
TotalCache uint64 `json:"total_cache"`
|
||||||
|
TotalRSS uint64 `json:"total_rss"`
|
||||||
|
TotalRSSHuge uint64 `json:"total_rss_huge"`
|
||||||
|
TotalMappedFile uint64 `json:"total_mapped_file"`
|
||||||
|
TotalPgpgIn uint64 `json:"total_pgpgin"`
|
||||||
|
TotalPgpgOut uint64 `json:"total_pgpgout"`
|
||||||
|
TotalPgFault uint64 `json:"total_pgfault"`
|
||||||
|
TotalPgMajFault uint64 `json:"total_pgmajfault"`
|
||||||
|
TotalInactiveAnon uint64 `json:"total_inactive_anon"`
|
||||||
|
TotalActiveAnon uint64 `json:"total_active_anon"`
|
||||||
|
TotalInactiveFile uint64 `json:"total_inactive_file"`
|
||||||
|
TotalActiveFile uint64 `json:"total_active_file"`
|
||||||
|
TotalUnevictable uint64 `json:"total_unevictable"`
|
||||||
|
}
|
170
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_linux.go
generated
vendored
Normal file
170
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
cpu "github.com/shirou/gopsutil/cpu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDockerIDList returnes a list of DockerID.
|
||||||
|
// This requires certain permission.
|
||||||
|
func GetDockerIDList() ([]string, error) {
|
||||||
|
path, err := exec.LookPath("docker")
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrDockerNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := exec.Command(path, "ps", "-q", "--no-trunc").Output()
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
ret := make([]string, 0, len(lines))
|
||||||
|
|
||||||
|
for _, l := range lines {
|
||||||
|
if l == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CgroupCPU returnes specified cgroup id CPU status.
|
||||||
|
// containerid is same as docker id if you use docker.
|
||||||
|
// If you use container via systemd.slice, you could use
|
||||||
|
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
||||||
|
func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
|
||||||
|
if len(base) == 0 {
|
||||||
|
base = "/sys/fs/cgroup/cpuacct/docker"
|
||||||
|
}
|
||||||
|
path := path.Join(base, containerid, "cpuacct.stat")
|
||||||
|
|
||||||
|
lines, err := common.ReadLines(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// empty containerid means all cgroup
|
||||||
|
if len(containerid) == 0 {
|
||||||
|
containerid = "all"
|
||||||
|
}
|
||||||
|
ret := &cpu.CPUTimesStat{CPU: containerid}
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Split(line, " ")
|
||||||
|
if fields[0] == "user" {
|
||||||
|
user, err := strconv.ParseFloat(fields[1], 64)
|
||||||
|
if err == nil {
|
||||||
|
ret.User = float64(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fields[0] == "system" {
|
||||||
|
system, err := strconv.ParseFloat(fields[1], 64)
|
||||||
|
if err == nil {
|
||||||
|
ret.System = float64(system)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
|
||||||
|
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
||||||
|
if len(base) == 0 {
|
||||||
|
base = "/sys/fs/cgroup/memory/docker"
|
||||||
|
}
|
||||||
|
path := path.Join(base, containerid, "memory.stat")
|
||||||
|
// empty containerid means all cgroup
|
||||||
|
if len(containerid) == 0 {
|
||||||
|
containerid = "all"
|
||||||
|
}
|
||||||
|
lines, err := common.ReadLines(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := &CgroupMemStat{ContainerID: containerid}
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Split(line, " ")
|
||||||
|
v, err := strconv.ParseUint(fields[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch fields[0] {
|
||||||
|
case "cache":
|
||||||
|
ret.Cache = v
|
||||||
|
case "rss":
|
||||||
|
ret.RSS = v
|
||||||
|
case "rss_huge":
|
||||||
|
ret.RSSHuge = v
|
||||||
|
case "mapped_file":
|
||||||
|
ret.MappedFile = v
|
||||||
|
case "pgpgin":
|
||||||
|
ret.Pgpgin = v
|
||||||
|
case "pgpgout":
|
||||||
|
ret.Pgpgout = v
|
||||||
|
case "pgfault":
|
||||||
|
ret.Pgfault = v
|
||||||
|
case "pgmajfault":
|
||||||
|
ret.Pgmajfault = v
|
||||||
|
case "inactive_anon":
|
||||||
|
ret.InactiveAnon = v
|
||||||
|
case "active_anon":
|
||||||
|
ret.ActiveAnon = v
|
||||||
|
case "inactive_file":
|
||||||
|
ret.InactiveFile = v
|
||||||
|
case "active_file":
|
||||||
|
ret.ActiveFile = v
|
||||||
|
case "unevictable":
|
||||||
|
ret.Unevictable = v
|
||||||
|
case "hierarchical_memory_limit":
|
||||||
|
ret.HierarchicalMemoryLimit = v
|
||||||
|
case "total_cache":
|
||||||
|
ret.TotalCache = v
|
||||||
|
case "total_rss":
|
||||||
|
ret.TotalRSS = v
|
||||||
|
case "total_rss_huge":
|
||||||
|
ret.TotalRSSHuge = v
|
||||||
|
case "total_mapped_file":
|
||||||
|
ret.TotalMappedFile = v
|
||||||
|
case "total_pgpgin":
|
||||||
|
ret.TotalPgpgIn = v
|
||||||
|
case "total_pgpgout":
|
||||||
|
ret.TotalPgpgOut = v
|
||||||
|
case "total_pgfault":
|
||||||
|
ret.TotalPgFault = v
|
||||||
|
case "total_pgmajfault":
|
||||||
|
ret.TotalPgMajFault = v
|
||||||
|
case "total_inactive_anon":
|
||||||
|
ret.TotalInactiveAnon = v
|
||||||
|
case "total_active_anon":
|
||||||
|
ret.TotalActiveAnon = v
|
||||||
|
case "total_inactive_file":
|
||||||
|
ret.TotalInactiveFile = v
|
||||||
|
case "total_active_file":
|
||||||
|
ret.TotalActiveFile = v
|
||||||
|
case "total_unevictable":
|
||||||
|
ret.TotalUnevictable = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
|
||||||
|
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m CgroupMemStat) String() string {
|
||||||
|
s, _ := json.Marshal(m)
|
||||||
|
return string(s)
|
||||||
|
}
|
60
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_linux_test.go
generated
vendored
Normal file
60
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDockerIDList(t *testing.T) {
|
||||||
|
// If there is not docker environment, this test always fail.
|
||||||
|
// not tested here
|
||||||
|
/*
|
||||||
|
_, err := GetDockerIDList()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCgroupCPU(t *testing.T) {
|
||||||
|
v, _ := GetDockerIDList()
|
||||||
|
for _, id := range v {
|
||||||
|
v, err := CgroupCPUDocker(id)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
if v.CPU == "" {
|
||||||
|
t.Errorf("could not get CgroupCPU %v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCgroupCPUInvalidId(t *testing.T) {
|
||||||
|
_, err := CgroupCPUDocker("bad id")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected path does not exist error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCgroupMem(t *testing.T) {
|
||||||
|
v, _ := GetDockerIDList()
|
||||||
|
for _, id := range v {
|
||||||
|
v, err := CgroupMemDocker(id)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
empty := &CgroupMemStat{}
|
||||||
|
if v == empty {
|
||||||
|
t.Errorf("Could not CgroupMemStat %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCgroupMemInvalidId(t *testing.T) {
|
||||||
|
_, err := CgroupMemDocker("bad id")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected path does not exist error")
|
||||||
|
}
|
||||||
|
}
|
40
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_notlinux.go
generated
vendored
Normal file
40
Godeps/_workspace/src/github.com/shirou/gopsutil/docker/docker_notlinux.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/cpu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDockerIDList returnes a list of DockerID.
|
||||||
|
// This requires certain permission.
|
||||||
|
func GetDockerIDList() ([]string, error) {
|
||||||
|
return nil, ErrDockerNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
// CgroupCPU returnes specified cgroup id CPU status.
|
||||||
|
// containerid is same as docker id if you use docker.
|
||||||
|
// If you use container via systemd.slice, you could use
|
||||||
|
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
||||||
|
func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
|
||||||
|
return nil, ErrCgroupNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
|
||||||
|
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
||||||
|
return nil, ErrCgroupNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
|
||||||
|
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m CgroupMemStat) String() string {
|
||||||
|
s, _ := json.Marshal(m)
|
||||||
|
return string(s)
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoadAvgStat struct {
|
||||||
|
Load1 float64 `json:"load1"`
|
||||||
|
Load5 float64 `json:"load5"`
|
||||||
|
Load15 float64 `json:"load15"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LoadAvgStat) String() string {
|
||||||
|
s, _ := json.Marshal(l)
|
||||||
|
return string(s)
|
||||||
|
}
|
37
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_darwin.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadAvg() (*LoadAvgStat, error) {
|
||||||
|
values, err := common.DoSysctrl("vm.loadavg")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
load1, err := strconv.ParseFloat(values[0], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load5, err := strconv.ParseFloat(values[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load15, err := strconv.ParseFloat(values[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &LoadAvgStat{
|
||||||
|
Load1: float64(load1),
|
||||||
|
Load5: float64(load5),
|
||||||
|
Load15: float64(load15),
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
37
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_freebsd.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadAvg() (*LoadAvgStat, error) {
|
||||||
|
values, err := common.DoSysctrl("vm.loadavg")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
load1, err := strconv.ParseFloat(values[0], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load5, err := strconv.ParseFloat(values[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load15, err := strconv.ParseFloat(values[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &LoadAvgStat{
|
||||||
|
Load1: float64(load1),
|
||||||
|
Load5: float64(load5),
|
||||||
|
Load15: float64(load15),
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
40
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go
generated
vendored
Normal file
40
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadAvg() (*LoadAvgStat, error) {
|
||||||
|
filename := "/proc/loadavg"
|
||||||
|
line, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
values := strings.Fields(string(line))
|
||||||
|
|
||||||
|
load1, err := strconv.ParseFloat(values[0], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load5, err := strconv.ParseFloat(values[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
load15, err := strconv.ParseFloat(values[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &LoadAvgStat{
|
||||||
|
Load1: load1,
|
||||||
|
Load5: load5,
|
||||||
|
Load15: load15,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
30
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_test.go
generated
vendored
Normal file
30
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_test.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoad(t *testing.T) {
|
||||||
|
v, err := LoadAvg()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
empty := &LoadAvgStat{}
|
||||||
|
if v == empty {
|
||||||
|
t.Errorf("error load: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadAvgStat_String(t *testing.T) {
|
||||||
|
v := LoadAvgStat{
|
||||||
|
Load1: 10.1,
|
||||||
|
Load5: 20.1,
|
||||||
|
Load15: 30.1,
|
||||||
|
}
|
||||||
|
e := `{"load1":10.1,"load5":20.1,"load15":30.1}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("LoadAvgStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
13
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_windows.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package load
|
||||||
|
|
||||||
|
import (
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadAvg() (*LoadAvgStat, error) {
|
||||||
|
ret := LoadAvgStat{}
|
||||||
|
|
||||||
|
return &ret, common.NotImplementedError
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VirtualMemoryStat struct {
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
Available uint64 `json:"available"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
UsedPercent float64 `json:"used_percent"`
|
||||||
|
Free uint64 `json:"free"`
|
||||||
|
Active uint64 `json:"active"`
|
||||||
|
Inactive uint64 `json:"inactive"`
|
||||||
|
Buffers uint64 `json:"buffers"`
|
||||||
|
Cached uint64 `json:"cached"`
|
||||||
|
Wired uint64 `json:"wired"`
|
||||||
|
Shared uint64 `json:"shared"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SwapMemoryStat struct {
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
Free uint64 `json:"free"`
|
||||||
|
UsedPercent float64 `json:"used_percent"`
|
||||||
|
Sin uint64 `json:"sin"`
|
||||||
|
Sout uint64 `json:"sout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m VirtualMemoryStat) String() string {
|
||||||
|
s, _ := json.Marshal(m)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m SwapMemoryStat) String() string {
|
||||||
|
s, _ := json.Marshal(m)
|
||||||
|
return string(s)
|
||||||
|
}
|
109
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
Normal file
109
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPageSize() (uint64, error) {
|
||||||
|
out, err := exec.Command("pagesize").Output()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
o := strings.TrimSpace(string(out))
|
||||||
|
p, err := strconv.ParseUint(o, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualMemory returns VirtualmemoryStat.
|
||||||
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||||
|
p, err := getPageSize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := common.DoSysctrl("hw.memsize")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
free, err := common.DoSysctrl("vm.page_free_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parsed := make([]uint64, 0, 7)
|
||||||
|
vv := []string{
|
||||||
|
total[0],
|
||||||
|
free[0],
|
||||||
|
}
|
||||||
|
for _, target := range vv {
|
||||||
|
t, err := strconv.ParseUint(target, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parsed = append(parsed, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &VirtualMemoryStat{
|
||||||
|
Total: parsed[0],
|
||||||
|
Free: parsed[1] * p,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: platform independent (worked freebsd?)
|
||||||
|
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||||
|
|
||||||
|
ret.Used = ret.Total - ret.Free
|
||||||
|
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwapMemory returns swapinfo.
|
||||||
|
func SwapMemory() (*SwapMemoryStat, error) {
|
||||||
|
var ret *SwapMemoryStat
|
||||||
|
|
||||||
|
swapUsage, err := common.DoSysctrl("vm.swapusage")
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
total := strings.Replace(swapUsage[2], "M", "", 1)
|
||||||
|
used := strings.Replace(swapUsage[5], "M", "", 1)
|
||||||
|
free := strings.Replace(swapUsage[8], "M", "", 1)
|
||||||
|
|
||||||
|
total_v, err := strconv.ParseFloat(total, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
used_v, err := strconv.ParseFloat(used, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
free_v, err := strconv.ParseFloat(free, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u := float64(0)
|
||||||
|
if total_v != 0 {
|
||||||
|
u = ((total_v - free_v) / total_v) * 100.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// vm.swapusage shows "M", multiply 1000
|
||||||
|
ret = &SwapMemoryStat{
|
||||||
|
Total: uint64(total_v * 1000),
|
||||||
|
Used: uint64(used_v * 1000),
|
||||||
|
Free: uint64(free_v * 1000),
|
||||||
|
UsedPercent: u,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
131
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
Normal file
131
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||||
|
pageSize, err := common.DoSysctrl("vm.stats.vm.v_page_size")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p, err := strconv.ParseUint(pageSize[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pageCount, err := common.DoSysctrl("vm.stats.vm.v_page_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
free, err := common.DoSysctrl("vm.stats.vm.v_free_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
active, err := common.DoSysctrl("vm.stats.vm.v_active_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inactive, err := common.DoSysctrl("vm.stats.vm.v_inactive_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cache, err := common.DoSysctrl("vm.stats.vm.v_cache_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buffer, err := common.DoSysctrl("vfs.bufspace")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
wired, err := common.DoSysctrl("vm.stats.vm.v_wire_count")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed := make([]uint64, 0, 7)
|
||||||
|
vv := []string{
|
||||||
|
pageCount[0],
|
||||||
|
free[0],
|
||||||
|
active[0],
|
||||||
|
inactive[0],
|
||||||
|
cache[0],
|
||||||
|
buffer[0],
|
||||||
|
wired[0],
|
||||||
|
}
|
||||||
|
for _, target := range vv {
|
||||||
|
t, err := strconv.ParseUint(target, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parsed = append(parsed, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &VirtualMemoryStat{
|
||||||
|
Total: parsed[0] * p,
|
||||||
|
Free: parsed[1] * p,
|
||||||
|
Active: parsed[2] * p,
|
||||||
|
Inactive: parsed[3] * p,
|
||||||
|
Cached: parsed[4] * p,
|
||||||
|
Buffers: parsed[5],
|
||||||
|
Wired: parsed[6] * p,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: platform independent (worked freebsd?)
|
||||||
|
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||||
|
|
||||||
|
ret.Used = ret.Total - ret.Free
|
||||||
|
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return swapinfo
|
||||||
|
// FreeBSD can have multiple swap devices. but use only first device
|
||||||
|
func SwapMemory() (*SwapMemoryStat, error) {
|
||||||
|
out, err := exec.Command("swapinfo").Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var ret *SwapMemoryStat
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = &SwapMemoryStat{
|
||||||
|
Total: total_v,
|
||||||
|
Used: used_v,
|
||||||
|
Free: free_v,
|
||||||
|
UsedPercent: up_v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||||
|
filename := "/proc/meminfo"
|
||||||
|
lines, _ := common.ReadLines(filename)
|
||||||
|
|
||||||
|
ret := &VirtualMemoryStat{}
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Split(line, ":")
|
||||||
|
if len(fields) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key := strings.TrimSpace(fields[0])
|
||||||
|
value := strings.TrimSpace(fields[1])
|
||||||
|
value = strings.Replace(value, " kB", "", -1)
|
||||||
|
|
||||||
|
t, err := strconv.ParseUint(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
switch key {
|
||||||
|
case "MemTotal":
|
||||||
|
ret.Total = t * 1024
|
||||||
|
case "MemFree":
|
||||||
|
ret.Free = t * 1024
|
||||||
|
case "Buffers":
|
||||||
|
ret.Buffers = t * 1024
|
||||||
|
case "Cached":
|
||||||
|
ret.Cached = t * 1024
|
||||||
|
case "Active":
|
||||||
|
ret.Active = t * 1024
|
||||||
|
case "Inactive":
|
||||||
|
ret.Inactive = t * 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||||
|
ret.Used = ret.Total - ret.Free
|
||||||
|
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapMemory() (*SwapMemoryStat, error) {
|
||||||
|
sysinfo := &syscall.Sysinfo_t{}
|
||||||
|
|
||||||
|
if err := syscall.Sysinfo(sysinfo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := &SwapMemoryStat{
|
||||||
|
Total: uint64(sysinfo.Totalswap),
|
||||||
|
Free: uint64(sysinfo.Freeswap),
|
||||||
|
}
|
||||||
|
ret.Used = ret.Total - ret.Free
|
||||||
|
//check Infinity
|
||||||
|
if ret.Total != 0 {
|
||||||
|
ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
|
||||||
|
} else {
|
||||||
|
ret.UsedPercent = 0
|
||||||
|
}
|
||||||
|
lines, _ := common.ReadLines("/proc/vmstat")
|
||||||
|
for _, l := range lines {
|
||||||
|
fields := strings.Fields(l)
|
||||||
|
if len(fields) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch fields[0] {
|
||||||
|
case "pswpin":
|
||||||
|
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret.Sin = value * 4 * 1024
|
||||||
|
case "pswpout":
|
||||||
|
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret.Sout = value * 4 * 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVirtual_memory(t *testing.T) {
|
||||||
|
v, err := VirtualMemory()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
empty := &VirtualMemoryStat{}
|
||||||
|
if v == empty {
|
||||||
|
t.Errorf("error %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSwap_memory(t *testing.T) {
|
||||||
|
v, err := SwapMemory()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
empty := &SwapMemoryStat{}
|
||||||
|
if v == empty {
|
||||||
|
t.Errorf("error %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVirtualMemoryStat_String(t *testing.T) {
|
||||||
|
v := VirtualMemoryStat{
|
||||||
|
Total: 10,
|
||||||
|
Available: 20,
|
||||||
|
Used: 30,
|
||||||
|
UsedPercent: 30.1,
|
||||||
|
Free: 40,
|
||||||
|
}
|
||||||
|
e := `{"total":10,"available":20,"used":30,"used_percent":30.1,"free":40,"active":0,"inactive":0,"buffers":0,"cached":0,"wired":0,"shared":0}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSwapMemoryStat_String(t *testing.T) {
|
||||||
|
v := SwapMemoryStat{
|
||||||
|
Total: 10,
|
||||||
|
Used: 30,
|
||||||
|
Free: 40,
|
||||||
|
UsedPercent: 30.1,
|
||||||
|
}
|
||||||
|
e := `{"total":10,"used":30,"free":40,"used_percent":30.1,"sin":0,"sout":0}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("SwapMemoryStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
50
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
Normal file
50
Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
procGlobalMemoryStatusEx = common.Modkernel32.NewProc("GlobalMemoryStatusEx")
|
||||||
|
)
|
||||||
|
|
||||||
|
type MEMORYSTATUSEX struct {
|
||||||
|
cbSize uint32
|
||||||
|
dwMemoryLoad uint32
|
||||||
|
ullTotalPhys uint64 // in bytes
|
||||||
|
ullAvailPhys uint64
|
||||||
|
ullTotalPageFile uint64
|
||||||
|
ullAvailPageFile uint64
|
||||||
|
ullTotalVirtual uint64
|
||||||
|
ullAvailVirtual uint64
|
||||||
|
ullAvailExtendedVirtual uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||||
|
var memInfo MEMORYSTATUSEX
|
||||||
|
memInfo.cbSize = uint32(unsafe.Sizeof(memInfo))
|
||||||
|
mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
|
||||||
|
if mem == 0 {
|
||||||
|
return nil, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &VirtualMemoryStat{
|
||||||
|
Total: memInfo.ullTotalPhys,
|
||||||
|
Available: memInfo.ullAvailPhys,
|
||||||
|
UsedPercent: float64(memInfo.dwMemoryLoad),
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Used = ret.Total - ret.Available
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapMemory() (*SwapMemoryStat, error) {
|
||||||
|
ret := &SwapMemoryStat{}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var invoke common.Invoker
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
invoke = common.Invoke{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetIOCountersStat struct {
|
||||||
|
Name string `json:"name"` // interface name
|
||||||
|
BytesSent uint64 `json:"bytes_sent"` // number of bytes sent
|
||||||
|
BytesRecv uint64 `json:"bytes_recv"` // number of bytes received
|
||||||
|
PacketsSent uint64 `json:"packets_sent"` // number of packets sent
|
||||||
|
PacketsRecv uint64 `json:"packets_recv"` // number of packets received
|
||||||
|
Errin uint64 `json:"errin"` // total number of errors while receiving
|
||||||
|
Errout uint64 `json:"errout"` // total number of errors while sending
|
||||||
|
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
||||||
|
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr is implemented compatibility to psutil
|
||||||
|
type Addr struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Port uint32 `json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetConnectionStat struct {
|
||||||
|
Fd uint32 `json:"fd"`
|
||||||
|
Family uint32 `json:"family"`
|
||||||
|
Type uint32 `json:"type"`
|
||||||
|
Laddr Addr `json:"localaddr"`
|
||||||
|
Raddr Addr `json:"remoteaddr"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Pid int32 `json:"pid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetInterfaceAddr is designed for represent interface addresses
|
||||||
|
type NetInterfaceAddr struct {
|
||||||
|
Addr string `json:"addr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetInterfaceStat struct {
|
||||||
|
MTU int `json:"mtu"` // maximum transmission unit
|
||||||
|
Name string `json:"name"` // e.g., "en0", "lo0", "eth0.100"
|
||||||
|
HardwareAddr string `json:"hardwareaddr"` // IEEE MAC-48, EUI-48 and EUI-64 form
|
||||||
|
Flags []string `json:"flags"` // e.g., FlagUp, FlagLoopback, FlagMulticast
|
||||||
|
Addrs []NetInterfaceAddr `json:"addrs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var constMap = map[string]int{
|
||||||
|
"TCP": syscall.SOCK_STREAM,
|
||||||
|
"UDP": syscall.SOCK_DGRAM,
|
||||||
|
"IPv4": syscall.AF_INET,
|
||||||
|
"IPv6": syscall.AF_INET6,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NetIOCountersStat) String() string {
|
||||||
|
s, _ := json.Marshal(n)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NetConnectionStat) String() string {
|
||||||
|
s, _ := json.Marshal(n)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Addr) String() string {
|
||||||
|
s, _ := json.Marshal(a)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NetInterfaceStat) String() string {
|
||||||
|
s, _ := json.Marshal(n)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NetInterfaceAddr) String() string {
|
||||||
|
s, _ := json.Marshal(n)
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NetInterfaces() ([]NetInterfaceStat, error) {
|
||||||
|
is, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := make([]NetInterfaceStat, 0, len(is))
|
||||||
|
for _, ifi := range is {
|
||||||
|
|
||||||
|
var flags []string
|
||||||
|
if ifi.Flags&net.FlagUp != 0 {
|
||||||
|
flags = append(flags, "up")
|
||||||
|
}
|
||||||
|
if ifi.Flags&net.FlagBroadcast != 0 {
|
||||||
|
flags = append(flags, "broadcast")
|
||||||
|
}
|
||||||
|
if ifi.Flags&net.FlagLoopback != 0 {
|
||||||
|
flags = append(flags, "loopback")
|
||||||
|
}
|
||||||
|
if ifi.Flags&net.FlagPointToPoint != 0 {
|
||||||
|
flags = append(flags, "pointtopoint")
|
||||||
|
}
|
||||||
|
if ifi.Flags&net.FlagMulticast != 0 {
|
||||||
|
flags = append(flags, "multicast")
|
||||||
|
}
|
||||||
|
|
||||||
|
r := NetInterfaceStat{
|
||||||
|
Name: ifi.Name,
|
||||||
|
MTU: ifi.MTU,
|
||||||
|
HardwareAddr: ifi.HardwareAddr.String(),
|
||||||
|
Flags: flags,
|
||||||
|
}
|
||||||
|
addrs, err := ifi.Addrs()
|
||||||
|
if err == nil {
|
||||||
|
r.Addrs = make([]NetInterfaceAddr, 0, len(addrs))
|
||||||
|
for _, addr := range addrs {
|
||||||
|
r.Addrs = append(r.Addrs, NetInterfaceAddr{
|
||||||
|
Addr: addr.String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ret = append(ret, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetIOCountersAll(n []NetIOCountersStat) ([]NetIOCountersStat, error) {
|
||||||
|
r := NetIOCountersStat{
|
||||||
|
Name: "all",
|
||||||
|
}
|
||||||
|
for _, nic := range n {
|
||||||
|
r.BytesRecv += nic.BytesRecv
|
||||||
|
r.PacketsRecv += nic.PacketsRecv
|
||||||
|
r.Errin += nic.Errin
|
||||||
|
r.Dropin += nic.Dropin
|
||||||
|
r.BytesSent += nic.BytesSent
|
||||||
|
r.PacketsSent += nic.PacketsSent
|
||||||
|
r.Errout += nic.Errout
|
||||||
|
r.Dropout += nic.Dropout
|
||||||
|
}
|
||||||
|
|
||||||
|
return []NetIOCountersStat{r}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNetLine(line string) (NetConnectionStat, error) {
|
||||||
|
f := strings.Fields(line)
|
||||||
|
if len(f) < 9 {
|
||||||
|
return NetConnectionStat{}, fmt.Errorf("wrong line,%s", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
pid, err := strconv.Atoi(f[1])
|
||||||
|
if err != nil {
|
||||||
|
return NetConnectionStat{}, err
|
||||||
|
}
|
||||||
|
fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
|
||||||
|
if err != nil {
|
||||||
|
return NetConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
|
||||||
|
}
|
||||||
|
netFamily, ok := constMap[f[4]]
|
||||||
|
if !ok {
|
||||||
|
return NetConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
|
||||||
|
}
|
||||||
|
netType, ok := constMap[f[7]]
|
||||||
|
if !ok {
|
||||||
|
return NetConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
|
||||||
|
}
|
||||||
|
|
||||||
|
laddr, raddr, err := parseNetAddr(f[8])
|
||||||
|
if err != nil {
|
||||||
|
return NetConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
|
||||||
|
}
|
||||||
|
|
||||||
|
n := NetConnectionStat{
|
||||||
|
Fd: uint32(fd),
|
||||||
|
Family: uint32(netFamily),
|
||||||
|
Type: uint32(netType),
|
||||||
|
Laddr: laddr,
|
||||||
|
Raddr: raddr,
|
||||||
|
Pid: int32(pid),
|
||||||
|
}
|
||||||
|
if len(f) == 10 {
|
||||||
|
n.Status = strings.Trim(f[9], "()")
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
|
||||||
|
parse := func(l string) (Addr, error) {
|
||||||
|
host, port, err := net.SplitHostPort(l)
|
||||||
|
if err != nil {
|
||||||
|
return Addr{}, fmt.Errorf("wrong addr, %s", l)
|
||||||
|
}
|
||||||
|
lport, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
return Addr{}, err
|
||||||
|
}
|
||||||
|
return Addr{IP: host, Port: uint32(lport)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs := strings.Split(line, "->")
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
|
||||||
|
}
|
||||||
|
laddr, err = parse(addrs[0])
|
||||||
|
if len(addrs) == 2 { // remote addr exists
|
||||||
|
raddr, err = parse(addrs[1])
|
||||||
|
if err != nil {
|
||||||
|
return laddr, raddr, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return laddr, raddr, err
|
||||||
|
}
|
147
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
Normal file
147
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// example of netstat -idbn output on yosemite
|
||||||
|
// Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop
|
||||||
|
// lo0 16384 <Link#1> 869107 0 169411755 869107 0 169411755 0 0
|
||||||
|
// lo0 16384 ::1/128 ::1 869107 - 169411755 869107 - 169411755 - -
|
||||||
|
// lo0 16384 127 127.0.0.1 869107 - 169411755 869107 - 169411755 - -
|
||||||
|
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
|
out, err := exec.Command("/usr/sbin/netstat", "-ibdn").Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
ret := make([]NetIOCountersStat, 0, len(lines)-1)
|
||||||
|
exists := make([]string, 0, len(ret))
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
values := strings.Fields(line)
|
||||||
|
if len(values) < 1 || values[0] == "Name" {
|
||||||
|
// skip first line
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if common.StringsHas(exists, values[0]) {
|
||||||
|
// skip if already get
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
exists = append(exists, values[0])
|
||||||
|
|
||||||
|
base := 1
|
||||||
|
// sometimes Address is ommitted
|
||||||
|
if len(values) < 11 {
|
||||||
|
base = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed := make([]uint64, 0, 7)
|
||||||
|
vv := []string{
|
||||||
|
values[base+3], // Ipkts == PacketsRecv
|
||||||
|
values[base+4], // Ierrs == Errin
|
||||||
|
values[base+5], // Ibytes == BytesRecv
|
||||||
|
values[base+6], // Opkts == PacketsSent
|
||||||
|
values[base+7], // Oerrs == Errout
|
||||||
|
values[base+8], // Obytes == BytesSent
|
||||||
|
}
|
||||||
|
if len(values) == 12 {
|
||||||
|
vv = append(vv, values[base+10])
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, target := range vv {
|
||||||
|
if target == "-" {
|
||||||
|
parsed = append(parsed, 0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := strconv.ParseUint(target, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parsed = append(parsed, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := NetIOCountersStat{
|
||||||
|
Name: values[0],
|
||||||
|
PacketsRecv: parsed[0],
|
||||||
|
Errin: parsed[1],
|
||||||
|
BytesRecv: parsed[2],
|
||||||
|
PacketsSent: parsed[3],
|
||||||
|
Errout: parsed[4],
|
||||||
|
BytesSent: parsed[5],
|
||||||
|
}
|
||||||
|
if len(parsed) == 7 {
|
||||||
|
n.Dropout = parsed[6]
|
||||||
|
}
|
||||||
|
ret = append(ret, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pernic == false {
|
||||||
|
return getNetIOCountersAll(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of network connections opened by a process
|
||||||
|
func NetConnections(kind string) ([]NetConnectionStat, error) {
|
||||||
|
var ret []NetConnectionStat
|
||||||
|
|
||||||
|
args := []string{"-i"}
|
||||||
|
switch strings.ToLower(kind) {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case "":
|
||||||
|
fallthrough
|
||||||
|
case "all":
|
||||||
|
fallthrough
|
||||||
|
case "inet":
|
||||||
|
args = append(args, "tcp")
|
||||||
|
case "inet4":
|
||||||
|
args = append(args, "4")
|
||||||
|
case "inet6":
|
||||||
|
args = append(args, "6")
|
||||||
|
case "tcp":
|
||||||
|
args = append(args, "tcp")
|
||||||
|
case "tcp4":
|
||||||
|
args = append(args, "4tcp")
|
||||||
|
case "tcp6":
|
||||||
|
args = append(args, "6tcp")
|
||||||
|
case "udp":
|
||||||
|
args = append(args, "udp")
|
||||||
|
case "udp4":
|
||||||
|
args = append(args, "6udp")
|
||||||
|
case "udp6":
|
||||||
|
args = append(args, "6udp")
|
||||||
|
case "unix":
|
||||||
|
return ret, common.NotImplementedError
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can not use -F filter to get all of required information at once.
|
||||||
|
r, err := common.CallLsof(invoke, 0, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, rr := range r {
|
||||||
|
if strings.HasPrefix(rr, "COMMAND") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n, err := parseNetLine(rr)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println(err) // TODO: should debug print?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
89
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
Normal file
89
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
|
out, err := exec.Command("/usr/bin/netstat", "-ibdn").Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(out), "\n")
|
||||||
|
ret := make([]NetIOCountersStat, 0, len(lines)-1)
|
||||||
|
exists := make([]string, 0, len(ret))
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
values := strings.Fields(line)
|
||||||
|
if len(values) < 1 || values[0] == "Name" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if common.StringsHas(exists, values[0]) {
|
||||||
|
// skip if already get
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
exists = append(exists, values[0])
|
||||||
|
|
||||||
|
base := 1
|
||||||
|
// sometimes Address is ommitted
|
||||||
|
if len(values) < 13 {
|
||||||
|
base = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed := make([]uint64, 0, 8)
|
||||||
|
vv := []string{
|
||||||
|
values[base+3], // PacketsRecv
|
||||||
|
values[base+4], // Errin
|
||||||
|
values[base+5], // Dropin
|
||||||
|
values[base+6], // BytesRecvn
|
||||||
|
values[base+7], // PacketSent
|
||||||
|
values[base+8], // Errout
|
||||||
|
values[base+9], // BytesSent
|
||||||
|
values[base+11], // Dropout
|
||||||
|
}
|
||||||
|
for _, target := range vv {
|
||||||
|
if target == "-" {
|
||||||
|
parsed = append(parsed, 0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := strconv.ParseUint(target, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parsed = append(parsed, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := NetIOCountersStat{
|
||||||
|
Name: values[0],
|
||||||
|
PacketsRecv: parsed[0],
|
||||||
|
Errin: parsed[1],
|
||||||
|
Dropin: parsed[2],
|
||||||
|
BytesRecv: parsed[3],
|
||||||
|
PacketsSent: parsed[4],
|
||||||
|
Errout: parsed[5],
|
||||||
|
BytesSent: parsed[6],
|
||||||
|
Dropout: parsed[7],
|
||||||
|
}
|
||||||
|
ret = append(ret, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pernic == false {
|
||||||
|
return getNetIOCountersAll(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NetConnections(kind string) ([]NetConnectionStat, error) {
|
||||||
|
var ret []NetConnectionStat
|
||||||
|
|
||||||
|
return ret, common.NotImplementedError
|
||||||
|
}
|
145
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
Normal file
145
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NetIOCounters returnes network I/O statistics for every network
|
||||||
|
// interface installed on the system. If pernic argument is false,
|
||||||
|
// return only sum of all information (which name is 'all'). If true,
|
||||||
|
// every network interface installed on the system is returned
|
||||||
|
// separately.
|
||||||
|
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
|
filename := "/proc/net/dev"
|
||||||
|
lines, err := common.ReadLines(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
statlen := len(lines) - 1
|
||||||
|
|
||||||
|
ret := make([]NetIOCountersStat, 0, statlen)
|
||||||
|
|
||||||
|
for _, line := range lines[2:] {
|
||||||
|
parts := strings.SplitN(line, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
interfaceName := strings.TrimSpace(parts[0])
|
||||||
|
if interfaceName == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.Fields(strings.TrimSpace(parts[1]))
|
||||||
|
bytesRecv, err := strconv.ParseUint(fields[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
packetsRecv, err := strconv.ParseUint(fields[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
errIn, err := strconv.ParseUint(fields[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
dropIn, err := strconv.ParseUint(fields[3], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
bytesSent, err := strconv.ParseUint(fields[8], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
packetsSent, err := strconv.ParseUint(fields[9], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
errOut, err := strconv.ParseUint(fields[10], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
dropOut, err := strconv.ParseUint(fields[13], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := NetIOCountersStat{
|
||||||
|
Name: interfaceName,
|
||||||
|
BytesRecv: bytesRecv,
|
||||||
|
PacketsRecv: packetsRecv,
|
||||||
|
Errin: errIn,
|
||||||
|
Dropin: dropIn,
|
||||||
|
BytesSent: bytesSent,
|
||||||
|
PacketsSent: packetsSent,
|
||||||
|
Errout: errOut,
|
||||||
|
Dropout: dropOut,
|
||||||
|
}
|
||||||
|
ret = append(ret, nic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pernic == false {
|
||||||
|
return getNetIOCountersAll(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NetConnections(kind string) ([]NetConnectionStat, error) {
|
||||||
|
var ret []NetConnectionStat
|
||||||
|
|
||||||
|
args := []string{"-i"}
|
||||||
|
switch strings.ToLower(kind) {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case "":
|
||||||
|
fallthrough
|
||||||
|
case "all":
|
||||||
|
fallthrough
|
||||||
|
case "inet":
|
||||||
|
args = append(args, "tcp")
|
||||||
|
case "inet4":
|
||||||
|
args = append(args, "4")
|
||||||
|
case "inet6":
|
||||||
|
args = append(args, "6")
|
||||||
|
case "tcp":
|
||||||
|
args = append(args, "tcp")
|
||||||
|
case "tcp4":
|
||||||
|
args = append(args, "4tcp")
|
||||||
|
case "tcp6":
|
||||||
|
args = append(args, "6tcp")
|
||||||
|
case "udp":
|
||||||
|
args = append(args, "udp")
|
||||||
|
case "udp4":
|
||||||
|
args = append(args, "6udp")
|
||||||
|
case "udp6":
|
||||||
|
args = append(args, "6udp")
|
||||||
|
case "unix":
|
||||||
|
return ret, common.NotImplementedError
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can not use -F filter to get all of required information at once.
|
||||||
|
r, err := common.CallLsof(invoke, 0, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, rr := range r {
|
||||||
|
if strings.HasPrefix(rr, "COMMAND") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n, err := parseNetLine(rr)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println(err) // TODO: should debug print?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddrString(t *testing.T) {
|
||||||
|
v := Addr{IP: "192.168.0.1", Port: 8000}
|
||||||
|
|
||||||
|
s := fmt.Sprintf("%v", v)
|
||||||
|
if s != "{\"ip\":\"192.168.0.1\",\"port\":8000}" {
|
||||||
|
t.Errorf("Addr string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetIOCountersStatString(t *testing.T) {
|
||||||
|
v := NetIOCountersStat{
|
||||||
|
Name: "test",
|
||||||
|
BytesSent: 100,
|
||||||
|
}
|
||||||
|
e := `{"name":"test","bytes_sent":100,"bytes_recv":0,"packets_sent":0,"packets_recv":0,"errin":0,"errout":0,"dropin":0,"dropout":0}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("NetIOCountersStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetConnectionStatString(t *testing.T) {
|
||||||
|
v := NetConnectionStat{
|
||||||
|
Fd: 10,
|
||||||
|
Family: 10,
|
||||||
|
Type: 10,
|
||||||
|
}
|
||||||
|
e := `{"fd":10,"family":10,"type":10,"localaddr":{"ip":"","port":0},"remoteaddr":{"ip":"","port":0},"status":"","pid":0}`
|
||||||
|
if e != fmt.Sprintf("%v", v) {
|
||||||
|
t.Errorf("NetConnectionStat string is invalid: %v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetIOCountersAll(t *testing.T) {
|
||||||
|
v, err := NetIOCounters(false)
|
||||||
|
per, err := NetIOCounters(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Could not get NetIOCounters: %v", err)
|
||||||
|
}
|
||||||
|
if len(v) != 1 {
|
||||||
|
t.Errorf("Could not get NetIOCounters: %v", v)
|
||||||
|
}
|
||||||
|
if v[0].Name != "all" {
|
||||||
|
t.Errorf("Invalid NetIOCounters: %v", v)
|
||||||
|
}
|
||||||
|
var pr uint64
|
||||||
|
for _, p := range per {
|
||||||
|
pr += p.PacketsRecv
|
||||||
|
}
|
||||||
|
if v[0].PacketsRecv != pr {
|
||||||
|
t.Errorf("invalid sum value: %v, %v", v[0].PacketsRecv, pr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetIOCountersPerNic(t *testing.T) {
|
||||||
|
v, err := NetIOCounters(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Could not get NetIOCounters: %v", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
t.Errorf("Could not get NetIOCounters: %v", v)
|
||||||
|
}
|
||||||
|
for _, vv := range v {
|
||||||
|
if vv.Name == "" {
|
||||||
|
t.Errorf("Invalid NetIOCounters: %v", vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_getNetIOCountersAll(t *testing.T) {
|
||||||
|
n := []NetIOCountersStat{
|
||||||
|
NetIOCountersStat{
|
||||||
|
Name: "a",
|
||||||
|
BytesRecv: 10,
|
||||||
|
PacketsRecv: 10,
|
||||||
|
},
|
||||||
|
NetIOCountersStat{
|
||||||
|
Name: "b",
|
||||||
|
BytesRecv: 10,
|
||||||
|
PacketsRecv: 10,
|
||||||
|
Errin: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ret, err := getNetIOCountersAll(n)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(ret) != 1 {
|
||||||
|
t.Errorf("invalid return count")
|
||||||
|
}
|
||||||
|
if ret[0].Name != "all" {
|
||||||
|
t.Errorf("invalid return name")
|
||||||
|
}
|
||||||
|
if ret[0].BytesRecv != 20 {
|
||||||
|
t.Errorf("invalid count bytesrecv")
|
||||||
|
}
|
||||||
|
if ret[0].Errin != 10 {
|
||||||
|
t.Errorf("invalid count errin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetInterfaces(t *testing.T) {
|
||||||
|
v, err := NetInterfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
||||||
|
}
|
||||||
|
for _, vv := range v {
|
||||||
|
if vv.Name == "" {
|
||||||
|
t.Errorf("Invalid NetInterface: %v", vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetConnections(t *testing.T) {
|
||||||
|
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := NetConnections("inet")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("could not get NetConnections: %v", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
t.Errorf("could not get NetConnections: %v", v)
|
||||||
|
}
|
||||||
|
for _, vv := range v {
|
||||||
|
if vv.Family == 0 {
|
||||||
|
t.Errorf("invalid NetConnections: %v", vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
98
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
Normal file
98
Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
common "github.com/shirou/gopsutil/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
|
||||||
|
procGetExtendedTcpTable = modiphlpapi.NewProc("GetExtendedTcpTable")
|
||||||
|
procGetExtendedUdpTable = modiphlpapi.NewProc("GetExtendedUdpTable")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCPTableBasicListener = iota
|
||||||
|
TCPTableBasicConnections
|
||||||
|
TCPTableBasicAll
|
||||||
|
TCPTableOwnerPIDListener
|
||||||
|
TCPTableOwnerPIDConnections
|
||||||
|
TCPTableOwnerPIDAll
|
||||||
|
TCPTableOwnerModuleListener
|
||||||
|
TCPTableOwnerModuleConnections
|
||||||
|
TCPTableOwnerModuleAll
|
||||||
|
)
|
||||||
|
|
||||||
|
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
|
ifs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ai, err := getAdapterList()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var ret []NetIOCountersStat
|
||||||
|
|
||||||
|
for _, ifi := range ifs {
|
||||||
|
name := ifi.Name
|
||||||
|
for ; ai != nil; ai = ai.Next {
|
||||||
|
name = common.BytePtrToString(&ai.Description[0])
|
||||||
|
c := NetIOCountersStat{
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
|
||||||
|
row := syscall.MibIfRow{Index: ai.Index}
|
||||||
|
e := syscall.GetIfEntry(&row)
|
||||||
|
if e != nil {
|
||||||
|
return nil, os.NewSyscallError("GetIfEntry", e)
|
||||||
|
}
|
||||||
|
c.BytesSent = uint64(row.OutOctets)
|
||||||
|
c.BytesRecv = uint64(row.InOctets)
|
||||||
|
c.PacketsSent = uint64(row.OutUcastPkts)
|
||||||
|
c.PacketsRecv = uint64(row.InUcastPkts)
|
||||||
|
c.Errin = uint64(row.InErrors)
|
||||||
|
c.Errout = uint64(row.OutErrors)
|
||||||
|
c.Dropin = uint64(row.InDiscards)
|
||||||
|
c.Dropout = uint64(row.OutDiscards)
|
||||||
|
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pernic == false {
|
||||||
|
return getNetIOCountersAll(ret)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of network connections opened by a process
|
||||||
|
func NetConnections(kind string) ([]NetConnectionStat, error) {
|
||||||
|
var ret []NetConnectionStat
|
||||||
|
|
||||||
|
return ret, common.NotImplementedError
|
||||||
|
}
|
||||||
|
|
||||||
|
// borrowed from src/pkg/net/interface_windows.go
|
||||||
|
func getAdapterList() (*syscall.IpAdapterInfo, error) {
|
||||||
|
b := make([]byte, 1000)
|
||||||
|
l := uint32(len(b))
|
||||||
|
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
||||||
|
err := syscall.GetAdaptersInfo(a, &l)
|
||||||
|
if err == syscall.ERROR_BUFFER_OVERFLOW {
|
||||||
|
b = make([]byte, l)
|
||||||
|
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
||||||
|
err = syscall.GetAdaptersInfo(a, &l)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, os.NewSyscallError("GetAdaptersInfo", err)
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
|
}
|
Loading…
Reference in New Issue