From 0eae055018e6c32c003e7b2a80bdb94b1ef36891 Mon Sep 17 00:00:00 2001 From: lufia Date: Sat, 9 Oct 2021 07:07:03 +0900 Subject: [PATCH] [v3][mem] add plan9 support --- README.md | 42 +++++++-------- v3/Makefile | 4 ++ v3/go.mod | 1 + v3/go.sum | 6 +++ v3/mem/mem_fallback.go | 2 +- v3/mem/mem_plan9.go | 67 +++++++++++++++++++++++ v3/mem/mem_plan9_test.go | 79 ++++++++++++++++++++++++++++ v3/mem/testdata/plan9/virtualmemory/dev/swap | 7 +++ v3/process/process.go | 3 +- v3/process/process_fallback.go | 3 +- v3/process/process_plan9.go | 9 ++++ v3/process/process_posix.go | 2 + v3/process/process_windows.go | 2 + 13 files changed, 201 insertions(+), 26 deletions(-) create mode 100644 v3/mem/mem_plan9.go create mode 100644 v3/mem/mem_plan9_test.go create mode 100644 v3/mem/testdata/plan9/virtualmemory/dev/swap create mode 100644 v3/process/process_plan9.go diff --git a/README.md b/README.md index 183d8b7..4786cfa 100644 --- a/README.md +++ b/README.md @@ -155,27 +155,27 @@ Some code is ported from Ohai. many thanks. - x: works - b: almost works, but something is broken -|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris | -|----------------------|-------|---------|---------|--------|---------|---------| -|cpu\_times |x |x |x |x |x | | -|cpu\_count |x |x |x |x |x | | -|cpu\_percent |x |x |x |x |x | | -|cpu\_times\_percent |x |x |x |x |x | | -|virtual\_memory |x |x |x |x |x | b | -|swap\_memory |x |x |x |x | | | -|disk\_partitions |x |x |x |x |x | | -|disk\_io\_counters |x |x |x | | | | -|disk\_usage |x |x |x |x |x | | -|net\_io\_counters |x |x |x |b |x | | -|boot\_time |x |x |x |x |x | | -|users |x |x |x |x |x | | -|pids |x |x |x |x |x | | -|pid\_exists |x |x |x |x |x | | -|net\_connections |x | |x |x | | | -|net\_protocols |x | | | | | | -|net\_if\_addrs | | | | | | | -|net\_if\_stats | | | | | | | -|netfilter\_conntrack |x | | | | | | +|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |Plan 9 | +|----------------------|-------|---------|---------|--------|---------|---------|---------| +|cpu\_times |x |x |x |x |x | | | +|cpu\_count |x |x |x |x |x | | | +|cpu\_percent |x |x |x |x |x | | | +|cpu\_times\_percent |x |x |x |x |x | | | +|virtual\_memory |x |x |x |x |x | b |x | +|swap\_memory |x |x |x |x | | |x | +|disk\_partitions |x |x |x |x |x | | | +|disk\_io\_counters |x |x |x | | | | | +|disk\_usage |x |x |x |x |x | | | +|net\_io\_counters |x |x |x |b |x | | | +|boot\_time |x |x |x |x |x | | | +|users |x |x |x |x |x | | | +|pids |x |x |x |x |x | | | +|pid\_exists |x |x |x |x |x | | | +|net\_connections |x | |x |x | | | | +|net\_protocols |x | | | | | | | +|net\_if\_addrs | | | | | | | | +|net\_if\_stats | | | | | | | | +|netfilter\_conntrack |x | | | | | | | ### Process class diff --git a/v3/Makefile b/v3/Makefile index 7a540a9..71bf943 100644 --- a/v3/Makefile +++ b/v3/Makefile @@ -28,6 +28,7 @@ build_test: ## test only buildable GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN) # cross build to OpenBSD not worked since process has "C" # GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN) + GOOS=plan9 go test ./... | $(BUILD_FAIL_PATTERN) ifeq ($(shell uname -s), Darwin) CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) @@ -63,6 +64,9 @@ vet: GOOS=windows GOARCH=amd64 go vet ./... GOOS=windows GOARCH=386 go vet ./... + GOOS=plan9 GOARCH=amd64 go vet ./... + GOOS=plan9 GOARCH=386 go vet ./... + macos_test: CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) diff --git a/v3/go.mod b/v3/go.mod index 0bb64a7..de49de4 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -4,6 +4,7 @@ go 1.15 require ( github.com/StackExchange/wmi v1.2.1 + github.com/lufia/plan9stats v0.0.0-20211008203909-9b7c2b47d7c3 github.com/stretchr/testify v1.7.0 github.com/tklauser/go-sysconf v0.3.9 golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 diff --git a/v3/go.sum b/v3/go.sum index 83b329b..c9a43f1 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -4,6 +4,10 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/lufia/plan9stats v0.0.0-20211008203909-9b7c2b47d7c3 h1:zvvlSubuP3jgjD69jAfrprCEKZkjn0D9FpZ168E1rDc= +github.com/lufia/plan9stats v0.0.0-20211008203909-9b7c2b47d7c3/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -16,6 +20,8 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/v3/mem/mem_fallback.go b/v3/mem/mem_fallback.go index 5cce2c0..e6c8c09 100644 --- a/v3/mem/mem_fallback.go +++ b/v3/mem/mem_fallback.go @@ -1,4 +1,4 @@ -// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows +// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!plan9 package mem diff --git a/v3/mem/mem_plan9.go b/v3/mem/mem_plan9.go new file mode 100644 index 0000000..8e7c433 --- /dev/null +++ b/v3/mem/mem_plan9.go @@ -0,0 +1,67 @@ +// +build plan9 + +package mem + +import ( + "context" + "os" + + stats "github.com/lufia/plan9stats" + "github.com/shirou/gopsutil/v3/internal/common" +) + +func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { + root := os.Getenv("HOST_ROOT") + m, err := stats.ReadMemStats(ctx, stats.WithRootDir(root)) + if err != nil { + return nil, err + } + u := 0.0 + if m.SwapPages.Avail != 0 { + u = float64(m.SwapPages.Used) / float64(m.SwapPages.Avail) * 100.0 + } + return &SwapMemoryStat{ + Total: uint64(m.SwapPages.Avail * m.PageSize), + Used: uint64(m.SwapPages.Used * m.PageSize), + Free: uint64(m.SwapPages.Free() * m.PageSize), + UsedPercent: u, + }, nil +} + +func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { + root := os.Getenv("HOST_ROOT") + m, err := stats.ReadMemStats(ctx, stats.WithRootDir(root)) + if err != nil { + return nil, err + } + u := 0.0 + if m.UserPages.Avail != 0 { + u = float64(m.UserPages.Used) / float64(m.UserPages.Avail) * 100.0 + } + return &VirtualMemoryStat{ + Total: uint64(m.Total), + Available: uint64(m.UserPages.Free() * m.PageSize), + Used: uint64(m.UserPages.Used * m.PageSize), + UsedPercent: u, + Free: uint64(m.UserPages.Free() * m.PageSize), + + SwapTotal: uint64(m.SwapPages.Avail * m.PageSize), + SwapFree: uint64(m.SwapPages.Free() * m.PageSize), + }, nil +} + +func SwapDevices() ([]*SwapDevice, error) { + return SwapDevicesWithContext(context.Background()) +} + +func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) { + return nil, common.ErrNotImplementedError +} diff --git a/v3/mem/mem_plan9_test.go b/v3/mem/mem_plan9_test.go new file mode 100644 index 0000000..94097bd --- /dev/null +++ b/v3/mem/mem_plan9_test.go @@ -0,0 +1,79 @@ +// +build plan9 + +package mem + +import ( + "os" + "reflect" + "testing" +) + +var virtualMemoryTests = []struct { + mockedRootFS string + stat *VirtualMemoryStat +}{ + {"swap", &VirtualMemoryStat{ + Total: 1071185920, + Available: 808370176, + Used: 11436032, + UsedPercent: 1.3949677238843257, + Free: 808370176, + SwapTotal: 655360000, + SwapFree: 655360000}, + }, +} + +func TestVirtualMemoryPlan9(t *testing.T) { + origProc := os.Getenv("HOST_ROOT") + t.Cleanup(func() { + os.Setenv("HOST_ROOT", origProc) + }) + + for _, tt := range virtualMemoryTests { + t.Run(tt.mockedRootFS, func(t *testing.T) { + os.Setenv("HOST_ROOT", "testdata/plan9/virtualmemory/") + + stat, err := VirtualMemory() + skipIfNotImplementedErr(t, err) + if err != nil { + t.Errorf("error %v", err) + } + if !reflect.DeepEqual(stat, tt.stat) { + t.Errorf("got: %+v\nwant: %+v", stat, tt.stat) + } + }) + } +} + +var swapMemoryTests = []struct { + mockedRootFS string + swap *SwapMemoryStat +}{ + {"swap", &SwapMemoryStat{ + Total: 655360000, + Used: 0, + Free: 655360000}, + }, +} + +func TestSwapMemoryPlan9(t *testing.T) { + origProc := os.Getenv("HOST_ROOT") + t.Cleanup(func() { + os.Setenv("HOST_ROOT", origProc) + }) + + for _, tt := range swapMemoryTests { + t.Run(tt.mockedRootFS, func(t *testing.T) { + os.Setenv("HOST_ROOT", "testdata/plan9/virtualmemory/") + + swap, err := SwapMemory() + skipIfNotImplementedErr(t, err) + if err != nil { + t.Errorf("error %v", err) + } + if !reflect.DeepEqual(swap, tt.swap) { + t.Errorf("got: %+v\nwant: %+v", swap, tt.swap) + } + }) + } +} diff --git a/v3/mem/testdata/plan9/virtualmemory/dev/swap b/v3/mem/testdata/plan9/virtualmemory/dev/swap new file mode 100644 index 0000000..a04b957 --- /dev/null +++ b/v3/mem/testdata/plan9/virtualmemory/dev/swap @@ -0,0 +1,7 @@ +1071185920 memory +4096 pagesize +61372 kernel +2792/200148 user +0/160000 swap +9046176/219352384 kernel malloc +0/16777216 kernel draw diff --git a/v3/process/process.go b/v3/process/process.go index 9f2852b..9c57310 100644 --- a/v3/process/process.go +++ b/v3/process/process.go @@ -7,7 +7,6 @@ import ( "runtime" "sort" "sync" - "syscall" "time" "github.com/shirou/gopsutil/v3/cpu" @@ -520,7 +519,7 @@ func (p *Process) Tgid() (int32, error) { } // SendSignal sends a unix.Signal to the process. -func (p *Process) SendSignal(sig syscall.Signal) error { +func (p *Process) SendSignal(sig Signal) error { return p.SendSignalWithContext(context.Background(), sig) } diff --git a/v3/process/process_fallback.go b/v3/process/process_fallback.go index d5e134e..ee35306 100644 --- a/v3/process/process_fallback.go +++ b/v3/process/process_fallback.go @@ -4,7 +4,6 @@ package process import ( "context" - "syscall" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/internal/common" @@ -176,7 +175,7 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M return nil, common.ErrNotImplementedError } -func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error { +func (p *Process) SendSignalWithContext(ctx context.Context, sig Signal) error { return common.ErrNotImplementedError } diff --git a/v3/process/process_plan9.go b/v3/process/process_plan9.go new file mode 100644 index 0000000..53a0291 --- /dev/null +++ b/v3/process/process_plan9.go @@ -0,0 +1,9 @@ +// +build plan9 + +package process + +import ( + "syscall" +) + +type Signal = syscall.Note diff --git a/v3/process/process_posix.go b/v3/process/process_posix.go index 2a53934..fa38759 100644 --- a/v3/process/process_posix.go +++ b/v3/process/process_posix.go @@ -16,6 +16,8 @@ import ( "golang.org/x/sys/unix" ) +type Signal = syscall.Signal + // POSIX func getTerminalMap() (map[uint64]string, error) { ret := make(map[uint64]string) diff --git a/v3/process/process_windows.go b/v3/process/process_windows.go index 6183c0c..dca0645 100644 --- a/v3/process/process_windows.go +++ b/v3/process/process_windows.go @@ -19,6 +19,8 @@ import ( "golang.org/x/sys/windows" ) +type Signal = syscall.Signal + var ( modntdll = windows.NewLazySystemDLL("ntdll.dll") procNtResumeProcess = modntdll.NewProc("NtResumeProcess")