Move to typical go project layout, fix golangci-lint warnings, update deps

This commit is contained in:
eleksir
2024-10-06 22:10:19 +03:00
parent 0b573aa169
commit 83970650b5
115 changed files with 9402 additions and 4920 deletions

View File

@@ -193,17 +193,28 @@ func main() {
### Pool Configuration Options
- **MinWorkers**: Specifies the minimum number of worker goroutines that must be running at any given time. These goroutines are started when the pool is created. The default value is 0. Example:
#### MinWorkers
Specifies the minimum number of worker goroutines that must be running at any given time. These goroutines are started when the pool is created. The default value is 0. Example:
``` go
// This will create a pool with 5 running worker goroutines
pool := pond.New(10, 1000, pond.MinWorkers(5))
```
- **IdleTimeout**: Defines how long to wait before removing idle worker goroutines from the pool. The default value is 5 seconds. Example:
#### IdleTimeout
Defines how long to wait before removing idle worker goroutines from the pool. The default value is 5 seconds. Example:
``` go
// This will create a pool that will remove workers 100ms after they become idle
pool := pond.New(10, 1000, pond.IdleTimeout(100 * time.Millisecond))
```
- **PanicHandler**: Allows to configure a custom function to handle panics thrown by tasks submitted to the pool. The default handler just writes a message to standard output using `fmt.Printf` with the following contents: `Worker exits from a panic: [panic] \n Stack trace: [stack trace]`). Example:
#### PanicHandler
Allows to configure a custom function to handle panics thrown by tasks submitted to the pool. The default handler just writes a message to standard output using `fmt.Printf` with the following contents: `Worker exits from a panic: [panic] \n Stack trace: [stack trace]`). Example:
```go
// Custom panic handler function
panicHandler := func(p interface{}) {
@@ -213,17 +224,26 @@ panicHandler := func(p interface{}) {
// This will create a pool that will handle panics using a custom panic handler
pool := pond.New(10, 1000, pond.PanicHandler(panicHandler)))
```
- **Strategy**: Configures the strategy used to resize the pool when backpressure is detected. You can create a custom strategy by implementing the `pond.ResizingStrategy` interface or choose one of the 3 presets:
- **Eager**: maximizes responsiveness at the expense of higher resource usage, which can reduce throughput under certain conditions. This strategy is meant for worker pools that will operate at a small percentage of their capacity most of the time and may occasionally receive bursts of tasks. This is the default strategy.
- **Balanced**: tries to find a balance between responsiveness and throughput. It's suitable for general purpose worker pools or those that will operate close to 50% of their capacity most of the time.
- **Lazy**: maximizes throughput at the expense of responsiveness. This strategy is meant for worker pools that will operate close to their max. capacity most of the time.
#### Strategy
Configures the strategy used to resize the pool when backpressure is detected. You can create a custom strategy by implementing the `pond.ResizingStrategy` interface or choose one of the 3 presets:
- **Eager**: maximizes responsiveness at the expense of higher resource usage, which can reduce throughput under certain conditions. This strategy is meant for worker pools that will operate at a small percentage of their capacity most of the time and may occasionally receive bursts of tasks. This is the default strategy.
- **Balanced**: tries to find a balance between responsiveness and throughput. It's suitable for general purpose worker pools or those that will operate close to 50% of their capacity most of the time.
- **Lazy**: maximizes throughput at the expense of responsiveness. This strategy is meant for worker pools that will operate close to their max. capacity most of the time.
``` go
// Example: create pools with different resizing strategies
eagerPool := pond.New(10, 1000, pond.Strategy(pond.Eager()))
balancedPool := pond.New(10, 1000, pond.Strategy(pond.Balanced()))
lazyPool := pond.New(10, 1000, pond.Strategy(pond.Lazy()))
```
- **Context**: Configures a parent context on this pool to stop all workers when it is cancelled. The default value `context.Background()`. Example:
#### Context
Configures a parent context on this pool to stop all workers when it is cancelled. The default value `context.Background()`. Example:
``` go
// This creates a pool that is stopped when myCtx is cancelled
pool := pond.New(10, 1000, pond.Context(myCtx))

8
vendor/github.com/alitto/pond/codecov.yml generated vendored Normal file
View File

@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 90%
patch:
default:
target: 90%

View File

@@ -318,8 +318,14 @@ func (p *WorkerPool) SubmitBefore(task func(), deadline time.Duration) {
// Stop causes this pool to stop accepting new tasks and signals all workers to exit.
// Tasks being executed by workers will continue until completion (unless the process is terminated).
// Tasks in the queue will not be executed.
func (p *WorkerPool) Stop() {
go p.stop(false)
// This method returns a context object that is cancelled when the pool has stopped completely.
func (p *WorkerPool) Stop() context.Context {
ctx, cancel := context.WithCancel(context.Background())
go func() {
p.stop(false)
cancel()
}()
return ctx
}
// StopAndWait causes this pool to stop accepting new tasks and then waits for all tasks in the queue
@@ -371,6 +377,7 @@ func (p *WorkerPool) stop(waitForQueuedTasksToComplete bool) {
p.tasksCloseOnce.Do(func() {
close(p.tasks)
})
}
// purge represents the work done by the purger goroutine
@@ -420,7 +427,7 @@ func (p *WorkerPool) maybeStartWorker(firstTask func()) bool {
}
// Launch worker goroutine
go worker(p.context, &p.workersWaitGroup, firstTask, p.tasks, p.executeTask)
go worker(p.context, &p.workersWaitGroup, firstTask, p.tasks, p.executeTask, &p.tasksWaitGroup)
return true
}

View File

@@ -6,7 +6,7 @@ import (
)
// worker represents a worker goroutine
func worker(context context.Context, waitGroup *sync.WaitGroup, firstTask func(), tasks <-chan func(), taskExecutor func(func(), bool)) {
func worker(context context.Context, waitGroup *sync.WaitGroup, firstTask func(), tasks <-chan func(), taskExecutor func(func(), bool), taskWaitGroup *sync.WaitGroup) {
// If provided, execute the first task immediately, before listening to the tasks channel
if firstTask != nil {
@@ -20,16 +20,43 @@ func worker(context context.Context, waitGroup *sync.WaitGroup, firstTask func()
for {
select {
case <-context.Done():
// Pool context was cancelled, exit
// Pool context was cancelled, empty tasks channel and exit
drainTasks(tasks, taskWaitGroup)
return
case task, ok := <-tasks:
if task == nil || !ok {
// We have received a signal to exit
// Prioritize context.Done statement (https://stackoverflow.com/questions/46200343/force-priority-of-go-select-statement)
select {
case <-context.Done():
if task != nil && ok {
// We have received a task, ignore it
taskWaitGroup.Done()
}
// Pool context was cancelled, empty tasks channel and exit
drainTasks(tasks, taskWaitGroup)
return
}
default:
if task == nil || !ok {
// We have received a signal to exit
return
}
// We have received a task, execute it
taskExecutor(task, false)
// We have received a task, execute it
taskExecutor(task, false)
}
}
}
}
// drainPendingTasks discards queued tasks and decrements the corresponding wait group
func drainTasks(tasks <-chan func(), tasksWaitGroup *sync.WaitGroup) {
for {
select {
case task, ok := <-tasks:
if task != nil && ok {
tasksWaitGroup.Done()
}
default:
return
}
}
}

View File

@@ -1,13 +0,0 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/go-ole/go-ole/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.

View File

@@ -6,29 +6,7 @@
version: "1.3.0.{build}-alpha-{branch}"
os: Visual Studio 2019
build: off
skip_tags: true
clone_folder: c:\gopath\src\github.com\go-ole\go-ole
environment:
GOPATH: c:\gopath
GOROOT: c:\go
DOWNLOADPLATFORM: "x64"
before_test:
# - Download COM Server
- ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip"
- 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL
- c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat
test_script:
- go test -v -cover ./...
# go vet has false positives on unsafe.Pointer with windows/sys. Disabling since it is recommended to use go test instead.
# - go vet ./...
os: Windows Server 2012 R2
branches:
only:
@@ -37,19 +15,26 @@ branches:
- v1.1
- v1.0
matrix:
allow_failures:
- environment:
GOROOT: C:\go-x86
DOWNLOADPLATFORM: "x86"
- environment:
GOROOT: C:\go118
DOWNLOADPLATFORM: "x64"
- environment:
GOROOT: C:\go118-x86
DOWNLOADPLATFORM: "x86"
skip_tags: true
clone_folder: c:\gopath\src\github.com\go-ole\go-ole
environment:
GOPATH: c:\gopath
matrix:
- GOARCH: amd64
GOVERSION: 1.5
GOROOT: c:\go
DOWNLOADPLATFORM: "x64"
install:
- choco install mingw
- SET PATH=c:\tools\mingw64\bin;%PATH%
# - Download COM Server
- ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip"
- 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL
- c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat
# - set
- go version
- go env
- go get -u golang.org/x/tools/cmd/cover
@@ -60,9 +45,10 @@ build_script:
- cd c:\gopath\src\github.com\go-ole\go-ole
- go get -v -t ./...
- go build
- go test -v -cover ./...
# disable automatic tests
test: on
test: off
# disable deployment
deploy: off

View File

@@ -11,7 +11,6 @@ import (
var (
procCoInitialize = modole32.NewProc("CoInitialize")
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
procCoInitializeSecurity = modole32.NewProc("CoInitializeSecurity")
procCoUninitialize = modole32.NewProc("CoUninitialize")
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
@@ -38,9 +37,6 @@ var (
procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
)
// This is to enable calling COM Security initialization multiple times
var bSecurityInit bool = false
// coInitialize initializes COM library on current thread.
//
// MSDN documentation suggests that this function should not be called. Call
@@ -72,35 +68,6 @@ func coInitializeEx(coinit uint32) (err error) {
return
}
// coInitializeSecurity: Registers security and sets the default security values
// for the process.
func coInitializeSecurity(cAuthSvc int32,
dwAuthnLevel uint32,
dwImpLevel uint32,
dwCapabilities uint32) (err error) {
// Check COM Security initialization has done previously
if !bSecurityInit {
// https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializesecurity
hr, _, _ := procCoInitializeSecurity.Call(
uintptr(0), // Allow *all* VSS writers to communicate back!
uintptr(cAuthSvc), // Default COM authentication service
uintptr(0), // Default COM authorization service
uintptr(0), // Reserved parameter
uintptr(dwAuthnLevel), // Strongest COM authentication level
uintptr(dwImpLevel), // Minimal impersonation abilities
uintptr(0), // Default COM authentication settings
uintptr(dwCapabilities), // Cloaking
uintptr(0)) // eserved parameter
if hr != 0 {
err = NewError(hr)
} else {
// COM Security initialization done make global flag true.
bSecurityInit = true
}
}
return
}
// CoInitialize initializes COM library on current thread.
//
// MSDN documentation suggests that this function should not be called. Call
@@ -129,15 +96,6 @@ func CoUninitialize() {
procCoUninitialize.Call()
}
// CoInitializeSecurity: Registers security and sets the default security values
// for the process.
func CoInitializeSecurity(cAuthSvc int32,
dwAuthnLevel uint32,
dwImpLevel uint32,
dwCapabilities uint32) (err error) {
return coInitializeSecurity(cAuthSvc, dwAuthnLevel, dwImpLevel, dwCapabilities)
}
// CoTaskMemFree frees memory pointer.
func CoTaskMemFree(memptr uintptr) {
procCoTaskMemFree.Call(memptr)

View File

@@ -1,4 +1,3 @@
//go:build windows
// +build windows
package ole
@@ -93,7 +92,7 @@ func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}
case int8:
vargs[n] = NewVariant(VT_I1, int64(v.(int8)))
case *int8:
vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int8)))))
vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
case int16:
vargs[n] = NewVariant(VT_I2, int64(v.(int16)))
case *int16:

View File

@@ -99,7 +99,7 @@ func (v *VARIANT) Value() interface{} {
case VT_DISPATCH:
return v.ToIDispatch()
case VT_BOOL:
return (v.Val & 0xffff) != 0
return v.Val != 0
}
return nil
}

View File

@@ -1,13 +1,2 @@
# plan9stats
A module for retrieving statistics of Plan 9
[![GoDev][godev-image]][godev-url]
[![Actions Status][actions-image]][actions-url]
[![Coverage Status][coveralls-image]][coveralls-url]
[godev-image]: https://pkg.go.dev/badge/github.com/lufia/plan9stats
[godev-url]: https://pkg.go.dev/github.com/lufia/plan9stats
[actions-image]: https://github.com/lufia/plan9stats/workflows/Test/badge.svg?branch=main
[actions-url]: https://github.com/lufia/plan9stats/actions?workflow=Test
[coveralls-image]: https://coveralls.io/repos/github/lufia/plan9stats/badge.svg
[coveralls-url]: https://coveralls.io/github/lufia/plan9stats

View File

@@ -178,12 +178,9 @@ func ReadCPUStats(ctx context.Context, opts ...Option) (*CPUStats, error) {
var up uint32parser
pids := make([]uint32, len(names))
for i, s := range names {
if s == "trace" {
continue
}
pids[i] = up.Parse(s)
}
if err := up.err; err != nil {
if up.err != nil {
return nil, err
}
sort.Slice(pids, func(i, j int) bool {

View File

@@ -1,116 +0,0 @@
package stats
import (
"bufio"
"bytes"
"context"
"os"
"path/filepath"
"strings"
)
// Storage represents /dev/sdXX/ctl.
type Storage struct {
Name string
Model string
Capacity int64
Partitions []*Partition
}
// Partition represents a part of /dev/sdXX/ctl.
type Partition struct {
Name string
Start uint64
End uint64
}
func ReadStorages(ctx context.Context, opts ...Option) ([]*Storage, error) {
cfg := newConfig(opts...)
sdctl := filepath.Join(cfg.rootdir, "/dev/sdctl")
f, err := os.Open(sdctl)
if err != nil {
return nil, err
}
defer f.Close()
var a []*Storage
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fields := bytes.Split(scanner.Bytes(), delim)
if len(fields) == 0 {
continue
}
exp := string(fields[0]) + "*"
if !strings.HasPrefix(exp, "sd") {
continue
}
dir := filepath.Join(cfg.rootdir, "/dev", exp)
m, err := filepath.Glob(dir)
if err != nil {
return nil, err
}
for _, dir := range m {
s, err := readStorage(dir)
if err != nil {
return nil, err
}
a = append(a, s)
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return a, nil
}
func readStorage(dir string) (*Storage, error) {
ctl := filepath.Join(dir, "ctl")
f, err := os.Open(ctl)
if err != nil {
return nil, err
}
defer f.Close()
var s Storage
s.Name = filepath.Base(dir)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Bytes()
switch {
case bytes.HasPrefix(line, []byte("inquiry ")):
s.Model = string(bytes.TrimSpace(line[7:]))
case bytes.HasPrefix(line, []byte("geometry ")):
fields := bytes.Split(line, delim)
if len(fields) < 3 {
continue
}
var p intParser
sec := p.ParseInt64(string(fields[1]), 10)
size := p.ParseInt64(string(fields[2]), 10)
if err := p.Err(); err != nil {
return nil, err
}
s.Capacity = sec * size
case bytes.HasPrefix(line, []byte("part ")):
fields := bytes.Split(line, delim)
if len(fields) < 4 {
continue
}
var p intParser
start := p.ParseUint64(string(fields[2]), 10)
end := p.ParseUint64(string(fields[3]), 10)
if err := p.Err(); err != nil {
return nil, err
}
s.Partitions = append(s.Partitions, &Partition{
Name: string(fields[1]),
Start: start,
End: end,
})
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return &s, nil
}

View File

@@ -109,6 +109,12 @@ func parseGauge(s string, r *Gauge) error {
return nil
}
type Storage struct {
Name string
Model string
Capacity int64
}
type Interface struct {
Name string
Addr string
@@ -171,7 +177,7 @@ func ReadHost(ctx context.Context, opts ...Option) (*Host, error) {
}
h.Sysname = name
a, err := ReadStorages(ctx, opts...)
a, err := readStorages(cfg.rootdir)
if err != nil {
return nil, err
}
@@ -197,6 +203,80 @@ func readSysname(rootdir string) (string, error) {
return string(bytes.TrimSpace(b)), nil
}
func readStorages(rootdir string) ([]*Storage, error) {
sdctl := filepath.Join(rootdir, "/dev/sdctl")
f, err := os.Open(sdctl)
if err != nil {
return nil, err
}
defer f.Close()
var a []*Storage
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fields := bytes.Split(scanner.Bytes(), delim)
if len(fields) == 0 {
continue
}
exp := string(fields[0]) + "*"
if !strings.HasPrefix(exp, "sd") {
continue
}
dir := filepath.Join(rootdir, "/dev", exp)
m, err := filepath.Glob(dir)
if err != nil {
return nil, err
}
for _, dir := range m {
s, err := readStorage(dir)
if err != nil {
return nil, err
}
a = append(a, s)
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return a, nil
}
func readStorage(dir string) (*Storage, error) {
ctl := filepath.Join(dir, "ctl")
f, err := os.Open(ctl)
if err != nil {
return nil, err
}
defer f.Close()
var s Storage
s.Name = filepath.Base(dir)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Bytes()
switch {
case bytes.HasPrefix(line, []byte("inquiry")):
s.Model = string(bytes.TrimSpace(line[7:]))
case bytes.HasPrefix(line, []byte("geometry")):
fields := bytes.Split(line, delim)
if len(fields) < 3 {
continue
}
var p intParser
sec := p.ParseInt64(string(fields[1]), 10)
size := p.ParseInt64(string(fields[2]), 10)
if err := p.Err(); err != nil {
return nil, err
}
s.Capacity = sec * size
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return &s, nil
}
type IPStats struct {
ID int // number of interface in ipifc dir
Device string // associated physical device

View File

@@ -26,15 +26,6 @@ func (p *intParser) ParseInt64(s string, base int) int64 {
return n
}
func (p *intParser) ParseUint64(s string, base int) uint64 {
if p.err != nil {
return 0
}
var n uint64
n, p.err = strconv.ParseUint(s, base, 64)
return n
}
func (p *intParser) Err() error {
return p.err
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat
@@ -21,13 +20,6 @@ import (
"unsafe"
)
var old_cpu_total_stat *C.perfstat_cpu_total_t
func init() {
old_cpu_total_stat = (*C.perfstat_cpu_total_t)(C.malloc(C.sizeof_perfstat_cpu_total_t))
C.perfstat_cpu_total(nil, old_cpu_total_stat, C.sizeof_perfstat_cpu_total_t, 1)
}
func CpuStat() ([]CPU, error) {
var cpustat *C.perfstat_cpu_t
var cpu C.perfstat_id_t
@@ -104,35 +96,3 @@ func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) {
u := perfstatcpuutil2cpuutil(cpuutil)
return &u, nil
}
func CpuUtilTotalStat() (*CPUUtil, error) {
var cpuutil *C.perfstat_cpu_util_t
var new_cpu_total_stat *C.perfstat_cpu_total_t
var data C.perfstat_rawdata_t
new_cpu_total_stat = (*C.perfstat_cpu_total_t)(C.malloc(C.sizeof_perfstat_cpu_total_t))
cpuutil = (*C.perfstat_cpu_util_t)(C.malloc(C.sizeof_perfstat_cpu_util_t))
defer C.free(unsafe.Pointer(cpuutil))
r := C.perfstat_cpu_total(nil, new_cpu_total_stat, C.sizeof_perfstat_cpu_total_t, 1)
if r <= 0 {
C.free(unsafe.Pointer(new_cpu_total_stat))
return nil, fmt.Errorf("error perfstat_cpu_total()")
}
data._type = C.UTIL_CPU_TOTAL
data.curstat = unsafe.Pointer(new_cpu_total_stat)
data.prevstat = unsafe.Pointer(old_cpu_total_stat)
data.sizeof_data = C.sizeof_perfstat_cpu_total_t
data.cur_elems = 1
data.prev_elems = 1
r = C.perfstat_cpu_util(&data, cpuutil, C.sizeof_perfstat_cpu_util_t, 1)
C.free(unsafe.Pointer(old_cpu_total_stat))
old_cpu_total_stat = new_cpu_total_stat
if r <= 0 {
return nil, fmt.Errorf("error perfstat_cpu_util()")
}
u := perfstatcpuutil2cpuutil(cpuutil)
return &u, nil
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build !aix
// +build !aix
// Copyright 2020 Power-Devops.com. All rights reserved.
@@ -37,24 +36,24 @@ func DisableLVMStat() {}
// CpuStat() returns array of CPU structures with information about
// logical CPUs on the system.
// IBM documentation:
// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html
// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html
func CpuStat() ([]CPU, error) {
return nil, fmt.Errorf("not implemented")
}
// CpuTotalStat() returns general information about CPUs on the system.
// IBM documentation:
// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html
// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html
func CpuTotalStat() (*CPUTotal, error) {
return nil, fmt.Errorf("not implemented")
}
// CpuUtilStat() calculates CPU utilization.
// IBM documentation:
// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html
// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html
func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) {
return nil, fmt.Errorf("not implemented")
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat
@@ -8,7 +7,6 @@ package perfstat
#include <libperfstat.h>
#include <sys/proc.h>
#include <sys/dr.h>
#include "c_helpers.h"
*/
@@ -756,7 +754,7 @@ func fsinfo2filesystem(n *C.struct_fsinfo) FileSystem {
i.Device = C.GoString(n.devname)
i.MountPoint = C.GoString(n.fsname)
i.FSType = int(n.fstype)
i.Flags = uint(n.flags)
i.Flags = int(n.flags)
i.TotalBlocks = int64(n.totalblks)
i.FreeBlocks = int64(n.freeblks)
i.TotalInodes = int64(n.totalinodes)
@@ -764,56 +762,3 @@ func fsinfo2filesystem(n *C.struct_fsinfo) FileSystem {
return i
}
func lparinfo2partinfo(n C.lpar_info_format2_t) PartitionInfo {
var i PartitionInfo
i.Version = int(n.version)
i.OnlineMemory = uint64(n.online_memory)
i.TotalDispatchTime = uint64(n.tot_dispatch_time)
i.PoolIdleTime = uint64(n.pool_idle_time)
i.DispatchLatency = uint64(n.dispatch_latency)
i.LparFlags = uint(n.lpar_flags)
i.PCpusInSys = uint(n.pcpus_in_sys)
i.OnlineVCpus = uint(n.online_vcpus)
i.OnlineLCpus = uint(n.online_lcpus)
i.PCpusInPool = uint(n.pcpus_in_pool)
i.UnallocCapacity = uint(n.unalloc_capacity)
i.EntitledCapacity = uint(n.entitled_capacity)
i.VariableWeight = uint(n.variable_weight)
i.UnallocWeight = uint(n.unalloc_weight)
i.MinReqVCpuCapacity = uint(n.min_req_vcpu_capacity)
i.GroupId = uint8(n.group_id)
i.PoolId = uint8(n.pool_id)
i.ShCpusInSys = uint(n.shcpus_in_sys)
i.MaxPoolCapacity = uint(n.max_pool_capacity)
i.EntitledPoolCapacity = uint(n.entitled_pool_capacity)
i.PoolMaxTime = uint64(n.pool_max_time)
i.PoolBusyTime = uint64(n.pool_busy_time)
i.PoolScaledBusyTime = uint64(n.pool_scaled_busy_time)
i.ShCpuTotalTime = uint64(n.shcpu_tot_time)
i.ShCpuBusyTime = uint64(n.shcpu_busy_time)
i.ShCpuScaledBusyTime = uint64(n.shcpu_scaled_busy_time)
i.EntMemCapacity = uint64(n.ent_mem_capacity)
i.PhysMem = uint64(n.phys_mem)
i.VrmPoolPhysMem = uint64(n.vrm_pool_physmem)
i.HypPageSize = uint(n.hyp_pagesize)
i.VrmPoolId = int(n.vrm_pool_id)
i.VrmGroupId = int(n.vrm_group_id)
i.VarMemWeight = int(n.var_mem_weight)
i.UnallocVarMemWeight = int(n.unalloc_var_mem_weight)
i.UnallocEntMemCapacity = uint64(n.unalloc_ent_mem_capacity)
i.TrueOnlineMemory = uint64(n.true_online_memory)
i.AmeOnlineMemory = uint64(n.ame_online_memory)
i.AmeType = uint8(n.ame_type)
i.SpecExecMode = uint8(n.spec_exec_mode)
i.AmeFactor = uint(n.ame_factor)
i.EmPartMajorCode = uint(n.em_part_major_code)
i.EmPartMinorCode = uint(n.em_part_minor_code)
i.BytesCoalesced = uint64(n.bytes_coalesced)
i.BytesCoalescedMemPool = uint64(n.bytes_coalesced_mempool)
i.PurrCoalescing = uint64(n.purr_coalescing)
i.SpurrCoalescing = uint64(n.spurr_coalescing)
return i
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat
@@ -7,13 +6,11 @@ package perfstat
#cgo LDFLAGS: -lperfstat
#include <libperfstat.h>
#include <sys/dr.h>
*/
import "C"
import (
"fmt"
"unsafe"
)
func PartitionStat() (*PartitionConfig, error) {
@@ -27,14 +24,3 @@ func PartitionStat() (*PartitionConfig, error) {
return &p, nil
}
func LparInfo() (*PartitionInfo, error) {
var pinfo C.lpar_info_format2_t
rc := C.lpar_get_info(C.LPAR_INFO_FORMAT2, unsafe.Pointer(&pinfo), C.sizeof_lpar_info_format2_t)
if rc != 0 {
return nil, fmt.Errorf("lpar_get_info() error")
}
p := lparinfo2partinfo(pinfo)
return &p, nil
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat
@@ -71,7 +70,6 @@ const (
SC_TM_VER = 59 /* Transaction Memory version, 0 - not capable */
SC_NX_CAP = 60 /* NX GZIP capable */
SC_PKS_STATE = 61 /* Platform KeyStore */
SC_MMA_VER = 62
)
/* kernel attributes */
@@ -121,7 +119,6 @@ const (
IMPL_POWER7 = 0x8000 /* 7 class CPU */
IMPL_POWER8 = 0x10000 /* 8 class CPU */
IMPL_POWER9 = 0x20000 /* 9 class CPU */
IMPL_POWER10 = 0x20000 /* 10 class CPU */
)
// Values for implementation field for IA64 Architectures
@@ -154,13 +151,11 @@ const (
PV_7 = 0x200000 /* Power PC 7 */
PV_8 = 0x300000 /* Power PC 8 */
PV_9 = 0x400000 /* Power PC 9 */
PV_10 = 0x500000 /* Power PC 10 */
PV_5_Compat = 0x0F8000 /* Power PC 5 */
PV_6_Compat = 0x108000 /* Power PC 6 */
PV_7_Compat = 0x208000 /* Power PC 7 */
PV_8_Compat = 0x308000 /* Power PC 8 */
PV_9_Compat = 0x408000 /* Power PC 9 */
PV_10_Compat = 0x508000 /* Power PC 10 */
PV_RESERVED_2 = 0x0A0000 /* source compatability */
PV_RESERVED_3 = 0x0B0000 /* source compatability */
PV_RS2 = 0x040000 /* Power RS2 */
@@ -186,21 +181,19 @@ const (
// Macros for identifying physical processor
const (
PPI4_1 = 0x35
PPI4_2 = 0x38
PPI4_3 = 0x39
PPI4_4 = 0x3C
PPI4_5 = 0x44
PPI5_1 = 0x3A
PPI5_2 = 0x3B
PPI6_1 = 0x3E
PPI7_1 = 0x3F
PPI7_2 = 0x4A
PPI8_1 = 0x4B
PPI8_2 = 0x4D
PPI9 = 0x4E
PPI9_1 = 0x4E
PPI10_1 = 0x80
PPI4_1 = 0x35
PPI4_2 = 0x38
PPI4_3 = 0x39
PPI4_4 = 0x3C
PPI4_5 = 0x44
PPI5_1 = 0x3A
PPI5_2 = 0x3B
PPI6_1 = 0x3E
PPI7_1 = 0x3F
PPI7_2 = 0x4A
PPI8_1 = 0x4B
PPI8_2 = 0x4D
PPI9 = 0x4E
)
// Macros for kernel attributes
@@ -298,32 +291,14 @@ func GetCPUImplementation() string {
return "POWER8"
case impl&IMPL_POWER9 != 0:
return "POWER9"
case impl&IMPL_POWER10 != 0:
return "Power10"
default:
return "Unknown"
}
}
func POWER10OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 {
return true
}
return false
}
func POWER10() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 {
return true
}
return false
}
func POWER9OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 {
if impl&IMPL_POWER9 != 0 {
return true
}
return false
@@ -339,7 +314,7 @@ func POWER9() bool {
func POWER8OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 {
if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 {
return true
}
return false
@@ -355,7 +330,7 @@ func POWER8() bool {
func POWER7OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 {
if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 {
return true
}
return false
@@ -444,8 +419,6 @@ func PksEnabled() bool {
func CPUMode() string {
impl := unix.Getsystemcfg(SC_VERS)
switch impl {
case PV_10, PV_10_Compat:
return "Power10"
case PV_9, PV_9_Compat:
return "POWER9"
case PV_8, PV_8_Compat:

View File

@@ -29,8 +29,8 @@ type DiskTotal struct {
// Disk Adapter Types
const (
DA_SCSI = 0 /* 0 ==> SCSI, SAS, other legacy adapter types */
DA_VSCSI = 1 /* 1 ==> Virtual SCSI/SAS Adapter */
DA_FCA = 2 /* 2 ==> Fiber Channel Adapter */
DA_VSCSI /* 1 ==> Virtual SCSI/SAS Adapter */
DA_FCA /* 2 ==> Fiber Channel Adapter */
)
type DiskAdapter struct {

View File

@@ -8,7 +8,7 @@ type FileSystem struct {
Device string /* name of the mounted device */
MountPoint string /* where the device is mounted */
FSType int /* File system type, see the constants below */
Flags uint /* Flags of the file system */
Flags int /* Flags of the file system */
TotalBlocks int64 /* number of 512 bytes blocks in the filesystem */
FreeBlocks int64 /* number of free 512 bytes block in the filesystem */
TotalInodes int64 /* total number of inodes in the filesystem */

View File

@@ -66,64 +66,3 @@ type PartitionConfig struct {
TargetMemExpSize int64 /* Expanded Memory Size in MB */
SubProcessorMode int32 /* Split core mode, its value can be 0,1,2 or 4. 0 for unsupported, 1 for capable but not enabled, 2 or 4 for enabled*/
}
const (
AME_TYPE_V1 = 0x1
AME_TYPE_V2 = 0x2
LPAR_INFO_CAPPED = 0x01 /* Parition Capped */
LPAR_INFO_AUTH_PIC = 0x02 /* Authority granted for poolidle*/
LPAR_INFO_SMT_ENABLED = 0x04 /* SMT Enabled */
LPAR_INFO_WPAR_ACTIVE = 0x08 /* Process Running Within a WPAR */
LPAR_INFO_EXTENDED = 0x10 /* Extended shared processor pool information */
LPAR_INFO_AME_ENABLED = 0x20 /* Active Mem. Expansion (AME) enabled*/
LPAR_INFO_SEM_ENABLED = 0x40 /* Speculative Execution Mode enabled */
)
type PartitionInfo struct {
Version int /* version for this structure */
OnlineMemory uint64 /* MB of currently online memory */
TotalDispatchTime uint64 /* Total lpar dispatch time in nsecs */
PoolIdleTime uint64 /* Idle time of shared CPU pool nsecs*/
DispatchLatency uint64 /* Max latency inbetween dispatches of this LPAR on physCPUS in nsecs */
LparFlags uint /* LPAR flags */
PCpusInSys uint /* # of active licensed physical CPUs in system */
OnlineVCpus uint /* # of current online virtual CPUs */
OnlineLCpus uint /* # of current online logical CPUs */
PCpusInPool uint /* # physical CPUs in shared pool */
UnallocCapacity uint /* Unallocated Capacity available in shared pool */
EntitledCapacity uint /* Entitled Processor Capacity for this partition */
VariableWeight uint /* Variable Processor Capacity Weight */
UnallocWeight uint /* Unallocated Variable Weight available for this partition */
MinReqVCpuCapacity uint /* OS minimum required virtual processor capacity. */
GroupId uint8 /* ID of a LPAR group/aggregation */
PoolId uint8 /* ID of a shared pool */
ShCpusInSys uint /* # of physical processors allocated for shared processor use */
MaxPoolCapacity uint /* Maximum processor capacity of partition's pool */
EntitledPoolCapacity uint /* Entitled processor capacity of partition's pool */
PoolMaxTime uint64 /* Summation of maximum time that could be consumed by the pool, in nanoseconds */
PoolBusyTime uint64 /* Summation of busy time accumulated across all partitions in the pool, in nanoseconds */
PoolScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all partitions in the pool, in nanoseconds */
ShCpuTotalTime uint64 /* Summation of total time across all physical processors allocated for shared processor use, in nanoseconds */
ShCpuBusyTime uint64 /* Summation of busy time accumulated across all shared processor partitions, in nanoseconds */
ShCpuScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all shared processor partitions, in nanoseconds */
EntMemCapacity uint64 /* Partition's current entitlement memory capacity setting */
PhysMem uint64 /* Amount of physical memory, in bytes, currently backing the partition's logical memory */
VrmPoolPhysMem uint64 /* Total amount of physical memory in the VRM pool */
HypPageSize uint /* Page size hypervisor is using to virtualize partition's memory */
VrmPoolId int /* ID of VRM pool */
VrmGroupId int /* eWLM VRM group to which partition belongs */
VarMemWeight int /* Partition's current variable memory capacity weighting setting */
UnallocVarMemWeight int /* Amount of unallocated variable memory capacity weight available to LPAR's group */
UnallocEntMemCapacity uint64 /* Amount of unallocated I/O memory entitlement available to LPAR's group */
TrueOnlineMemory uint64 /* true MB of currently online memory */
AmeOnlineMemory uint64 /* AME MB of currently online memory */
AmeType uint8
SpecExecMode uint8 /* Speculative Execution Mode */
AmeFactor uint /* memory expansion factor for LPAR */
EmPartMajorCode uint /* Major and minor codes for our */
EmPartMinorCode uint /* current energy management mode */
BytesCoalesced uint64 /* The number of bytes of the calling partition.s logical real memory coalesced because they contained duplicated data */
BytesCoalescedMemPool uint64 /* If the calling partition is authorized to see pool wide statistics then the number of bytes of logical real memory coalesced because they contained duplicated data in the calling partition.s memory pool else set to zero.*/
PurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then PURR cycles consumed to coalesce data else set to zero.*/
SpurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then SPURR cycles consumed to coalesce data else set to zero.*/
}

View File

@@ -1,4 +1,3 @@
//go:build aix
// +build aix
package perfstat

View File

@@ -12,8 +12,57 @@ import (
)
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
var ret []TimesStat
if percpu {
return []TimesStat{}, common.ErrNotImplementedError
per_out, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
if err != nil {
return nil, err
}
lines := strings.Split(string(per_out), "\n")
if len(lines) < 6 {
return []TimesStat{}, common.ErrNotImplementedError
}
hp := strings.Fields(lines[5]) // headers
for l := 6; l < len(lines)-1; l++ {
ct := &TimesStat{}
v := strings.Fields(lines[l]) // values
for i, header := range hp {
// We're done in any of these use cases
if i >= len(v) || v[0] == "-" {
break
}
// Position variable for v
pos := i
// There is a missing field at the beginning of all but the first line
// so adjust the position
if l > 6 {
pos = i - 1
}
// We don't want invalid positions
if pos < 0 {
continue
}
if t, err := strconv.ParseFloat(v[pos], 64); err == nil {
switch header {
case `cpu`:
ct.CPU = strconv.FormatFloat(t, 'f', -1, 64)
case `%usr`:
ct.User = t
case `%sys`:
ct.System = t
case `%wio`:
ct.Iowait = t
case `%idle`:
ct.Idle = t
}
}
}
// Valid CPU data, so append it
ret = append(ret, *ct)
}
} else {
out, err := invoke.CommandWithContext(ctx, "sar", "-u", "10", "1")
if err != nil {
@@ -24,26 +73,28 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return []TimesStat{}, common.ErrNotImplementedError
}
ret := TimesStat{CPU: "cpu-total"}
ct := &TimesStat{CPU: "cpu-total"}
h := strings.Fields(lines[len(lines)-3]) // headers
v := strings.Fields(lines[len(lines)-2]) // values
for i, header := range h {
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
switch header {
case `%usr`:
ret.User = t
ct.User = t
case `%sys`:
ret.System = t
ct.System = t
case `%wio`:
ret.Iowait = t
ct.Iowait = t
case `%idle`:
ret.Idle = t
ct.Idle = t
}
}
}
return []TimesStat{ret}, nil
ret = append(ret, *ct)
}
return ret, nil
}
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
@@ -78,6 +129,20 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
}
}
break
} else if strings.HasPrefix(line, "System Model:") {
p := strings.Split(string(line), ":")
if p != nil {
ret.VendorID = strings.TrimSpace(p[1])
}
} else if strings.HasPrefix(line, "Processor Type:") {
p := strings.Split(string(line), ":")
if p != nil {
c := strings.Split(string(p[1]), "_")
if c != nil {
ret.Family = strings.TrimSpace(c[0])
ret.Model = strings.TrimSpace(c[1])
}
}
}
}
return []InfoStat{ret}, nil

View File

@@ -6,7 +6,7 @@ import (
)
// Sleep awaits for provided interval.
// Can be interrupted by context cancelation.
// Can be interrupted by context cancellation.
func Sleep(ctx context.Context, interval time.Duration) error {
timer := time.NewTimer(interval)
select {

View File

@@ -12,7 +12,7 @@ import (
)
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
vmem, swap, err := callSVMon(ctx)
vmem, swap, err := callSVMon(ctx, true)
if err != nil {
return nil, err
}
@@ -25,7 +25,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
}
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
_, swap, err := callSVMon(ctx)
_, swap, err := callSVMon(ctx, false)
if err != nil {
return nil, err
}
@@ -35,7 +35,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
return swap, nil
}
func callSVMon(ctx context.Context) (*VirtualMemoryStat, *SwapMemoryStat, error) {
func callSVMon(ctx context.Context, virt bool) (*VirtualMemoryStat, *SwapMemoryStat, error) {
out, err := invoke.CommandWithContext(ctx, "svmon", "-G")
if err != nil {
return nil, nil, err
@@ -45,7 +45,7 @@ func callSVMon(ctx context.Context) (*VirtualMemoryStat, *SwapMemoryStat, error)
vmem := &VirtualMemoryStat{}
swap := &SwapMemoryStat{}
for _, line := range strings.Split(string(out), "\n") {
if strings.HasPrefix(line, "memory") {
if virt && strings.HasPrefix(line, "memory") {
p := strings.Fields(line)
if len(p) > 2 {
if t, err := strconv.ParseUint(p[1], 10, 64); err == nil {

View File

@@ -471,7 +471,7 @@ func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
}
}
if err != nil {
return nil, fmt.Errorf("cound not get pid(s), %d: %w", pid, err)
return nil, fmt.Errorf("could not get pid(s), %d: %w", pid, err)
}
return statsFromInodesWithContext(ctx, root, pid, tmap, inodes, skipUids)
}

View File

@@ -23,9 +23,9 @@ func ParseNetstat(output string, mode string,
exists := make([]string, 0, len(lines)-1)
columns := 6
if mode == "ind" {
columns = 10
columns := 9
if mode == "inb" {
columns = 6
}
for _, line := range lines {
values := strings.Fields(line)
@@ -48,18 +48,23 @@ func ParseNetstat(output string, mode string,
parsed := make([]uint64, 0, 8)
var vv []string
if mode == "inb" {
switch mode {
case "inb":
vv = []string{
values[base+3], // BytesRecv
values[base+4], // BytesSent
}
} else {
case "ind":
vv = []string{
values[base+3], // Ipkts
values[base+4], // Ierrs
values[base+4], // Idrop
values[base+5], // Opkts
values[base+6], // Odrops
}
case "ine":
vv = []string{
values[base+4], // Ierrs
values[base+6], // Oerrs
values[base+8], // Drops
}
}
for _, target := range vv {
@@ -80,16 +85,19 @@ func ParseNetstat(output string, mode string,
if !present {
n = IOCountersStat{Name: values[0]}
}
if mode == "inb" {
switch mode {
case "inb":
n.BytesRecv = parsed[0]
n.BytesSent = parsed[1]
} else {
case "ind":
n.PacketsRecv = parsed[0]
n.Errin = parsed[1]
n.Dropin = parsed[1]
n.PacketsSent = parsed[2]
n.Errout = parsed[3]
n.Dropin = parsed[4]
n.Dropout = parsed[4]
n.Dropout = parsed[3]
case "ine":
n.Errin = parsed[0]
n.Errout = parsed[1]
}
iocs[n.Name] = n
@@ -114,6 +122,10 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
if err != nil {
return nil, err
}
out3, err := invoke.CommandWithContext(ctx, netstat, "-ine")
if err != nil {
return nil, err
}
iocs := make(map[string]IOCountersStat)
lines := strings.Split(string(out), "\n")
@@ -127,6 +139,10 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
if err != nil {
return nil, err
}
err = ParseNetstat(string(out3), "ine", iocs)
if err != nil {
return nil, err
}
for _, ioc := range iocs {
ret = append(ret, ioc)

View File

@@ -24,14 +24,21 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
}
txtFound := 0
lines := strings.Split(string(out), "\n")
fallback := ""
for i := 1; i < len(lines); i++ {
if lines[i] == "ftxt" {
txtFound++
if txtFound == 1 {
fallback = lines[i-1][1:]
}
if txtFound == 2 {
return lines[i-1][1:], nil
}
}
}
if fallback != "" {
return fallback, nil
}
return "", fmt.Errorf("missing txt data returned by lsof")
}

View File

@@ -68,7 +68,12 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
}
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
mib := []int32{CTLKern, KernProcCwd, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return "", err
}
return common.ByteToString(buf), nil
}
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {

View File

@@ -14,6 +14,7 @@ const (
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcCwd = 78
KernProcArgv = 1
KernProcEnv = 3
)

View File

@@ -11,6 +11,7 @@ const (
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcCwd = 78
KernProcArgv = 1
KernProcEnv = 3
)

View File

@@ -14,6 +14,7 @@ const (
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcCwd = 78
KernProcArgv = 1
KernProcEnv = 3
)

View File

@@ -14,6 +14,7 @@ const (
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcCwd = 78
KernProcArgv = 1
KernProcEnv = 3
)

View File

@@ -14,6 +14,7 @@ const (
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcCwd = 78
KernProcArgv = 1
KernProcEnv = 3
)

View File

@@ -1,6 +1,6 @@
env:
CIRRUS_CLONE_DEPTH: 1
GO_VERSION: go1.21.3
GO_VERSION: go1.20
freebsd_12_task:
freebsd_instance:

View File

@@ -6,6 +6,7 @@ package sysconf
import (
"bufio"
"io/ioutil"
"os"
"runtime"
"strconv"
@@ -25,7 +26,7 @@ const (
)
func readProcFsInt64(path string, fallback int64) int64 {
data, err := os.ReadFile(path)
data, err := ioutil.ReadFile(path)
if err != nil {
return fallback
}
@@ -85,16 +86,10 @@ func getNprocsProcStat() (int64, error) {
s := bufio.NewScanner(f)
for s.Scan() {
if line := strings.TrimSpace(s.Text()); strings.HasPrefix(line, "cpu") {
cpu, _, found := strings.Cut(line, " ")
if found {
// skip first line with accumulated values
if cpu == "cpu" {
continue
}
_, err := strconv.ParseInt(cpu[len("cpu"):], 10, 64)
if err == nil {
count++
}
l := strings.SplitN(line, " ", 2)
_, err := strconv.ParseInt(l[0][3:], 10, 64)
if err == nil {
count++
}
} else {
// The current format of /proc/stat has all the
@@ -103,9 +98,6 @@ func getNprocsProcStat() (int64, error) {
break
}
}
if err := s.Err(); err != nil {
return -1, err
}
return count, nil
}

View File

@@ -25,10 +25,10 @@ const (
_POSIX2_UPE = -1
)
var clktck struct {
sync.Once
v int64
}
var (
clktck int64
clktckOnce sync.Once
)
func sysconfPOSIX(name int) (int64, error) {
// NetBSD does not define all _POSIX_* values used in sysconf_posix.go
@@ -42,6 +42,7 @@ func sysconf(name int) (int64, error) {
// Duplicate the relevant values here.
switch name {
// 1003.1
case SC_ARG_MAX:
return sysctl32("kern.argmax"), nil
@@ -54,14 +55,13 @@ func sysconf(name int) (int64, error) {
}
return -1, nil
case SC_CLK_TCK:
// TODO: use sync.OnceValue once Go 1.21 is the minimal supported version
clktck.Do(func() {
clktck.v = -1
clktckOnce.Do(func() {
clktck = -1
if ci, err := unix.SysctlClockinfo("kern.clockrate"); err == nil {
clktck.v = int64(ci.Hz)
clktck = int64(ci.Hz)
}
})
return clktck.v, nil
return clktck, nil
case SC_NGROUPS_MAX:
return sysctl32("kern.ngroups"), nil
case SC_JOB_CONTROL:

View File

@@ -1,6 +1,6 @@
env:
CIRRUS_CLONE_DEPTH: 1
GO_VERSION: go1.21.3
GO_VERSION: go1.20
freebsd_12_task:
freebsd_instance:

View File

@@ -15,6 +15,7 @@
package numcpus
import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -34,7 +35,7 @@ func getFromCPUAffinity() (int, error) {
}
func readCPURange(file string) (int, error) {
buf, err := os.ReadFile(filepath.Join(sysfsCPUBasePath, file))
buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, file))
if err != nil {
return 0, err
}
@@ -47,16 +48,16 @@ func parseCPURange(cpus string) (int, error) {
if len(cpuRange) == 0 {
continue
}
from, to, found := strings.Cut(cpuRange, "-")
first, err := strconv.ParseUint(from, 10, 32)
rangeOp := strings.SplitN(cpuRange, "-", 2)
first, err := strconv.ParseUint(rangeOp[0], 10, 32)
if err != nil {
return 0, err
}
if !found {
if len(rangeOp) == 1 {
n++
continue
}
last, err := strconv.ParseUint(to, 10, 32)
last, err := strconv.ParseUint(rangeOp[1], 10, 32)
if err != nil {
return 0, err
}
@@ -88,7 +89,7 @@ func getConfigured() (int, error) {
}
func getKernelMax() (int, error) {
buf, err := os.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
if err != nil {
return 0, err
}