mirror of
https://github.com/opencontainers/runc.git
synced 2025-10-05 23:46:57 +08:00
libct/cg/sd/v2: support cpuset.* / Allowed*
* cpuset.cpus -> AllowedCPUs * cpuset.mems -> AllowedMemoryNodes No test for cgroup v2 resources.unified override, as this requires a separate test case, and all the unified resources are handled uniformly so there's little sense to test all parameters. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
1
go.mod
1
go.mod
@@ -22,5 +22,6 @@ require (
|
|||||||
// NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
// NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||||
github.com/urfave/cli v1.22.1
|
github.com/urfave/cli v1.22.1
|
||||||
github.com/vishvananda/netlink v1.1.0
|
github.com/vishvananda/netlink v1.1.0
|
||||||
|
github.com/willf/bitset v1.1.11
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@@ -62,6 +62,8 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7Zo
|
|||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
|
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
|
||||||
|
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
67
libcontainer/cgroups/systemd/cpuset.go
Normal file
67
libcontainer/cgroups/systemd/cpuset.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package systemd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/willf/bitset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rangeToBits converts a text representation of a CPU mask (as written to
|
||||||
|
// or read from cgroups' cpuset.* files, e.g. "1,3-5") to a slice of bytes
|
||||||
|
// with the corresponding bits set (as consumed by systemd over dbus as
|
||||||
|
// AllowedCPUs/AllowedMemoryNodes unit property value).
|
||||||
|
func rangeToBits(str string) ([]byte, error) {
|
||||||
|
bits := &bitset.BitSet{}
|
||||||
|
|
||||||
|
for _, r := range strings.Split(str, ",") {
|
||||||
|
// allow extra spaces around
|
||||||
|
r = strings.TrimSpace(r)
|
||||||
|
// allow empty elements (extra commas)
|
||||||
|
if r == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ranges := strings.SplitN(r, "-", 2)
|
||||||
|
if len(ranges) > 1 {
|
||||||
|
start, err := strconv.ParseUint(ranges[0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
end, err := strconv.ParseUint(ranges[1], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if start > end {
|
||||||
|
return nil, errors.New("invalid range: " + r)
|
||||||
|
}
|
||||||
|
for i := uint(start); i <= uint(end); i++ {
|
||||||
|
bits.Set(i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val, err := strconv.ParseUint(ranges[0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bits.Set(uint(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val := bits.Bytes()
|
||||||
|
if len(val) == 0 {
|
||||||
|
// do not allow empty values
|
||||||
|
return nil, errors.New("empty value")
|
||||||
|
}
|
||||||
|
ret := make([]byte, len(val)*8)
|
||||||
|
for i := range val {
|
||||||
|
// bitset uses BigEndian internally
|
||||||
|
binary.BigEndian.PutUint64(ret[i*8:], val[len(val)-1-i])
|
||||||
|
}
|
||||||
|
// remove upper all-zero bytes
|
||||||
|
for ret[0] == 0 {
|
||||||
|
ret = ret[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
58
libcontainer/cgroups/systemd/cpuset_test.go
Normal file
58
libcontainer/cgroups/systemd/cpuset_test.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package systemd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRangeToBits(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
in string
|
||||||
|
out []byte
|
||||||
|
isErr bool
|
||||||
|
}{
|
||||||
|
{in: "", isErr: true},
|
||||||
|
{in: "0", out: []byte{1}},
|
||||||
|
{in: "1", out: []byte{2}},
|
||||||
|
{in: "0-1", out: []byte{3}},
|
||||||
|
{in: "0,1", out: []byte{3}},
|
||||||
|
{in: ",0,1,", out: []byte{3}},
|
||||||
|
{in: "0-3", out: []byte{0x0f}},
|
||||||
|
{in: "0,1,2-3", out: []byte{0x0f}},
|
||||||
|
{in: "4-7", out: []byte{0xf0}},
|
||||||
|
{in: "0-7", out: []byte{0xff}},
|
||||||
|
{in: "0-15", out: []byte{0xff, 0xff}},
|
||||||
|
{in: "16", out: []byte{1, 0, 0}},
|
||||||
|
{in: "0-3,32-33", out: []byte{3, 0, 0, 0, 0x0f}},
|
||||||
|
// extra spaces and tabs are ok
|
||||||
|
{in: "1, 2, 1-2", out: []byte{6}},
|
||||||
|
{in: " , 1 , 3 , 5-7, ", out: []byte{0xea}},
|
||||||
|
// somewhat large values
|
||||||
|
{in: "128-130,1", out: []byte{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}},
|
||||||
|
|
||||||
|
{in: "-", isErr: true},
|
||||||
|
{in: "1-", isErr: true},
|
||||||
|
{in: "-3", isErr: true},
|
||||||
|
// bad range (start > end)
|
||||||
|
{in: "54-53", isErr: true},
|
||||||
|
// kernel does not allow extra spaces inside a range
|
||||||
|
{in: "1 - 2", isErr: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Logf("case: %q", tc.in)
|
||||||
|
out, err := rangeToBits(tc.in)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf(" got error: %s", err)
|
||||||
|
if !tc.isErr {
|
||||||
|
t.Error(" ^^^ unexpected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Logf(" expected %v, got %v", tc.out, out)
|
||||||
|
if !bytes.Equal(out, tc.out) {
|
||||||
|
t.Error(" ^^^ unexpected result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -93,6 +93,18 @@ func unifiedResToSystemdProps(conn *systemdDbus.Conn, res map[string]string) (pr
|
|||||||
props = append(props,
|
props = append(props,
|
||||||
newProp("CPUWeight", num))
|
newProp("CPUWeight", num))
|
||||||
|
|
||||||
|
case "cpuset.cpus", "cpuset.mems":
|
||||||
|
bits, err := rangeToBits(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unified resource %q=%q conversion error: %w", k, v, err)
|
||||||
|
}
|
||||||
|
m := map[string]string{
|
||||||
|
"cpuset.cpus": "AllowedCPUs",
|
||||||
|
"cpuset.mems": "AllowedMemoryNodes",
|
||||||
|
}
|
||||||
|
props = append(props,
|
||||||
|
newProp(m[k], bits))
|
||||||
|
|
||||||
case "pids.max":
|
case "pids.max":
|
||||||
num := uint64(math.MaxUint64)
|
num := uint64(math.MaxUint64)
|
||||||
if v != "max" {
|
if v != "max" {
|
||||||
|
@@ -357,6 +357,12 @@ function requires() {
|
|||||||
skip_me=1
|
skip_me=1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
smp)
|
||||||
|
local cpu_count=$(grep -c '^processor' /proc/cpuinfo)
|
||||||
|
if [ "$cpu_count" -lt 2 ]; then
|
||||||
|
skip_me=1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
systemd)
|
systemd)
|
||||||
if [ -z "${RUNC_USE_SYSTEMD}" ]; then
|
if [ -z "${RUNC_USE_SYSTEMD}" ]; then
|
||||||
skip_me=1
|
skip_me=1
|
||||||
|
@@ -392,6 +392,53 @@ EOF
|
|||||||
check_systemd_value "TasksMax" 10
|
check_systemd_value "TasksMax" 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "update cpuset parameters via v2 unified map" {
|
||||||
|
[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
|
||||||
|
requires cgroups_v2 smp
|
||||||
|
|
||||||
|
update_config ' .linux.resources.unified |= {
|
||||||
|
"cpuset.cpus": "0",
|
||||||
|
"cpuset.mems": "0"
|
||||||
|
}' "${BUSYBOX_BUNDLE}"
|
||||||
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
|
# check that initial values were properly set
|
||||||
|
check_systemd_value "AllowedCPUs" 0
|
||||||
|
check_systemd_value "AllowedMemoryNodes" 0
|
||||||
|
|
||||||
|
runc update -r - test_update <<EOF
|
||||||
|
{
|
||||||
|
"unified": {
|
||||||
|
"cpuset.cpus": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
|
# check the updated systemd unit properties
|
||||||
|
check_systemd_value "AllowedCPUs" 1
|
||||||
|
|
||||||
|
# More than 1 numa memory node is required to test this
|
||||||
|
file="/sys/fs/cgroup/cpuset.mems.effective"
|
||||||
|
if ! test -r $file || grep -q '^0$' $file; then
|
||||||
|
# skip the rest of it
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
runc update -r - test_update <<EOF
|
||||||
|
{
|
||||||
|
"unified": {
|
||||||
|
"cpuset.mems": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
|
# check the updated systemd unit properties
|
||||||
|
check_systemd_value "AllowedMemoryNodes" 1
|
||||||
|
}
|
||||||
|
|
||||||
@test "update rt period and runtime" {
|
@test "update rt period and runtime" {
|
||||||
[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
|
[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
|
||||||
requires cgroups_v1 cgroups_rt no_systemd
|
requires cgroups_v1 cgroups_rt no_systemd
|
||||||
|
191
vendor/github.com/willf/bitset/Makefile
generated
vendored
191
vendor/github.com/willf/bitset/Makefile
generated
vendored
@@ -1,191 +0,0 @@
|
|||||||
# MAKEFILE
|
|
||||||
#
|
|
||||||
# @author Nicola Asuni <info@tecnick.com>
|
|
||||||
# @link https://github.com/willf/bitset
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# List special make targets that are not associated with files
|
|
||||||
.PHONY: help all test format fmtcheck vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple astscan qa deps clean nuke
|
|
||||||
|
|
||||||
# Use bash as shell (Note: Ubuntu now uses dash which doesn't support PIPESTATUS).
|
|
||||||
SHELL=/bin/bash
|
|
||||||
|
|
||||||
# CVS path (path to the parent dir containing the project)
|
|
||||||
CVSPATH=github.com/willf
|
|
||||||
|
|
||||||
# Project owner
|
|
||||||
OWNER=willf
|
|
||||||
|
|
||||||
# Project vendor
|
|
||||||
VENDOR=willf
|
|
||||||
|
|
||||||
# Project name
|
|
||||||
PROJECT=bitset
|
|
||||||
|
|
||||||
# Project version
|
|
||||||
VERSION=$(shell cat VERSION)
|
|
||||||
|
|
||||||
# Name of RPM or DEB package
|
|
||||||
PKGNAME=${VENDOR}-${PROJECT}
|
|
||||||
|
|
||||||
# Current directory
|
|
||||||
CURRENTDIR=$(shell pwd)
|
|
||||||
|
|
||||||
# GO lang path
|
|
||||||
ifneq ($(GOPATH),)
|
|
||||||
ifeq ($(findstring $(GOPATH),$(CURRENTDIR)),)
|
|
||||||
# the defined GOPATH is not valid
|
|
||||||
GOPATH=
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
ifeq ($(GOPATH),)
|
|
||||||
# extract the GOPATH
|
|
||||||
GOPATH=$(firstword $(subst /src/, ,$(CURRENTDIR)))
|
|
||||||
endif
|
|
||||||
|
|
||||||
# --- MAKE TARGETS ---
|
|
||||||
|
|
||||||
# Display general help about this command
|
|
||||||
help:
|
|
||||||
@echo ""
|
|
||||||
@echo "$(PROJECT) Makefile."
|
|
||||||
@echo "GOPATH=$(GOPATH)"
|
|
||||||
@echo "The following commands are available:"
|
|
||||||
@echo ""
|
|
||||||
@echo " make qa : Run all the tests"
|
|
||||||
@echo " make test : Run the unit tests"
|
|
||||||
@echo ""
|
|
||||||
@echo " make format : Format the source code"
|
|
||||||
@echo " make fmtcheck : Check if the source code has been formatted"
|
|
||||||
@echo " make vet : Check for suspicious constructs"
|
|
||||||
@echo " make lint : Check for style errors"
|
|
||||||
@echo " make coverage : Generate the coverage report"
|
|
||||||
@echo " make cyclo : Generate the cyclomatic complexity report"
|
|
||||||
@echo " make ineffassign : Detect ineffectual assignments"
|
|
||||||
@echo " make misspell : Detect commonly misspelled words in source files"
|
|
||||||
@echo " make structcheck : Find unused struct fields"
|
|
||||||
@echo " make varcheck : Find unused global variables and constants"
|
|
||||||
@echo " make errcheck : Check that error return values are used"
|
|
||||||
@echo " make gosimple : Suggest code simplifications"
|
|
||||||
@echo " make astscan : GO AST scanner"
|
|
||||||
@echo ""
|
|
||||||
@echo " make docs : Generate source code documentation"
|
|
||||||
@echo ""
|
|
||||||
@echo " make deps : Get the dependencies"
|
|
||||||
@echo " make clean : Remove any build artifact"
|
|
||||||
@echo " make nuke : Deletes any intermediate file"
|
|
||||||
@echo ""
|
|
||||||
|
|
||||||
# Alias for help target
|
|
||||||
all: help
|
|
||||||
|
|
||||||
# Run the unit tests
|
|
||||||
test:
|
|
||||||
@mkdir -p target/test
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) \
|
|
||||||
go test \
|
|
||||||
-covermode=atomic \
|
|
||||||
-bench=. \
|
|
||||||
-race \
|
|
||||||
-cpuprofile=target/report/cpu.out \
|
|
||||||
-memprofile=target/report/mem.out \
|
|
||||||
-mutexprofile=target/report/mutex.out \
|
|
||||||
-coverprofile=target/report/coverage.out \
|
|
||||||
-v ./... | \
|
|
||||||
tee >(PATH=$(GOPATH)/bin:$(PATH) go-junit-report > target/test/report.xml); \
|
|
||||||
test $${PIPESTATUS[0]} -eq 0
|
|
||||||
|
|
||||||
# Format the source code
|
|
||||||
format:
|
|
||||||
@find . -type f -name "*.go" -exec gofmt -s -w {} \;
|
|
||||||
|
|
||||||
# Check if the source code has been formatted
|
|
||||||
fmtcheck:
|
|
||||||
@mkdir -p target
|
|
||||||
@find . -type f -name "*.go" -exec gofmt -s -d {} \; | tee target/format.diff
|
|
||||||
@test ! -s target/format.diff || { echo "ERROR: the source code has not been formatted - please use 'make format' or 'gofmt'"; exit 1; }
|
|
||||||
|
|
||||||
# Check for syntax errors
|
|
||||||
vet:
|
|
||||||
GOPATH=$(GOPATH) go vet .
|
|
||||||
|
|
||||||
# Check for style errors
|
|
||||||
lint:
|
|
||||||
GOPATH=$(GOPATH) PATH=$(GOPATH)/bin:$(PATH) golint .
|
|
||||||
|
|
||||||
# Generate the coverage report
|
|
||||||
coverage:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) \
|
|
||||||
go tool cover -html=target/report/coverage.out -o target/report/coverage.html
|
|
||||||
|
|
||||||
# Report cyclomatic complexity
|
|
||||||
cyclo:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) gocyclo -avg ./ | tee target/report/cyclo.txt ; test $${PIPESTATUS[0]} -eq 0
|
|
||||||
|
|
||||||
# Detect ineffectual assignments
|
|
||||||
ineffassign:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) ineffassign ./ | tee target/report/ineffassign.txt ; test $${PIPESTATUS[0]} -eq 0
|
|
||||||
|
|
||||||
# Detect commonly misspelled words in source files
|
|
||||||
misspell:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) misspell -error ./ | tee target/report/misspell.txt ; test $${PIPESTATUS[0]} -eq 0
|
|
||||||
|
|
||||||
# Find unused struct fields
|
|
||||||
structcheck:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) structcheck -a ./ | tee target/report/structcheck.txt
|
|
||||||
|
|
||||||
# Find unused global variables and constants
|
|
||||||
varcheck:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) varcheck -e ./ | tee target/report/varcheck.txt
|
|
||||||
|
|
||||||
# Check that error return values are used
|
|
||||||
errcheck:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) errcheck ./ | tee target/report/errcheck.txt
|
|
||||||
|
|
||||||
# AST scanner
|
|
||||||
astscan:
|
|
||||||
@mkdir -p target/report
|
|
||||||
GOPATH=$(GOPATH) gosec . | tee target/report/astscan.txt ; test $${PIPESTATUS[0]} -eq 0 || true
|
|
||||||
|
|
||||||
# Generate source docs
|
|
||||||
docs:
|
|
||||||
@mkdir -p target/docs
|
|
||||||
nohup sh -c 'GOPATH=$(GOPATH) godoc -http=127.0.0.1:6060' > target/godoc_server.log 2>&1 &
|
|
||||||
wget --directory-prefix=target/docs/ --execute robots=off --retry-connrefused --recursive --no-parent --adjust-extension --page-requisites --convert-links http://127.0.0.1:6060/pkg/github.com/${VENDOR}/${PROJECT}/ ; kill -9 `lsof -ti :6060`
|
|
||||||
@echo '<html><head><meta http-equiv="refresh" content="0;./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html"/></head><a href="./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html">'${PKGNAME}' Documentation ...</a></html>' > target/docs/index.html
|
|
||||||
|
|
||||||
# Alias to run all quality-assurance checks
|
|
||||||
qa: fmtcheck test vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple astscan
|
|
||||||
|
|
||||||
# --- INSTALL ---
|
|
||||||
|
|
||||||
# Get the dependencies
|
|
||||||
deps:
|
|
||||||
GOPATH=$(GOPATH) go get ./...
|
|
||||||
GOPATH=$(GOPATH) go get golang.org/x/lint/golint
|
|
||||||
GOPATH=$(GOPATH) go get github.com/jstemmer/go-junit-report
|
|
||||||
GOPATH=$(GOPATH) go get github.com/axw/gocov/gocov
|
|
||||||
GOPATH=$(GOPATH) go get github.com/fzipp/gocyclo
|
|
||||||
GOPATH=$(GOPATH) go get github.com/gordonklaus/ineffassign
|
|
||||||
GOPATH=$(GOPATH) go get github.com/client9/misspell/cmd/misspell
|
|
||||||
GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/structcheck
|
|
||||||
GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/varcheck
|
|
||||||
GOPATH=$(GOPATH) go get github.com/kisielk/errcheck
|
|
||||||
GOPATH=$(GOPATH) go get github.com/securego/gosec/cmd/gosec/...
|
|
||||||
|
|
||||||
# Remove any build artifact
|
|
||||||
clean:
|
|
||||||
GOPATH=$(GOPATH) go clean ./...
|
|
||||||
|
|
||||||
# Deletes any intermediate file
|
|
||||||
nuke:
|
|
||||||
rm -rf ./target
|
|
||||||
GOPATH=$(GOPATH) go clean -i ./...
|
|
20
vendor/github.com/willf/bitset/README.md
generated
vendored
20
vendor/github.com/willf/bitset/README.md
generated
vendored
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
*Go language library to map between non-negative integers and boolean values*
|
*Go language library to map between non-negative integers and boolean values*
|
||||||
|
|
||||||
[](https://travis-ci.org/willf/bitset?branch=master)
|
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||||
[](https://coveralls.io/github/willf/bitset?branch=master)
|
[](https://coveralls.io/github/willf/bitset?branch=master)
|
||||||
[](https://goreportcard.com/report/github.com/willf/bitset)
|
[](https://goreportcard.com/report/github.com/willf/bitset)
|
||||||
[](http://godoc.org/github.com/willf/bitset)
|
[](https://pkg.go.dev/github.com/willf/bitset?tab=doc)
|
||||||
|
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
@@ -63,8 +63,11 @@ func main() {
|
|||||||
|
|
||||||
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
||||||
|
|
||||||
Godoc documentation is at: https://godoc.org/github.com/willf/bitset
|
Package documentation is at: https://pkg.go.dev/github.com/willf/bitset?tab=doc
|
||||||
|
|
||||||
|
## Memory Usage
|
||||||
|
|
||||||
|
The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
|
||||||
|
|
||||||
## Implementation Note
|
## Implementation Note
|
||||||
|
|
||||||
@@ -82,15 +85,10 @@ go get github.com/willf/bitset
|
|||||||
|
|
||||||
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
||||||
|
|
||||||
This project include a Makefile that allows you to test and build the project with simple commands.
|
|
||||||
To see all available options:
|
|
||||||
```bash
|
|
||||||
make help
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running all tests
|
## Running all tests
|
||||||
|
|
||||||
Before committing the code, please check if it passes all tests using (note: this will install some dependencies):
|
Before committing the code, please check if it passes tests, has adequate coverage, etc.
|
||||||
```bash
|
```bash
|
||||||
make qa
|
go test
|
||||||
|
go test -cover
|
||||||
```
|
```
|
||||||
|
72
vendor/github.com/willf/bitset/bitset.go
generated
vendored
72
vendor/github.com/willf/bitset/bitset.go
generated
vendored
@@ -138,6 +138,9 @@ func (b *BitSet) Len() uint {
|
|||||||
// extendSetMaybe adds additional words to incorporate new bits if needed
|
// extendSetMaybe adds additional words to incorporate new bits if needed
|
||||||
func (b *BitSet) extendSetMaybe(i uint) {
|
func (b *BitSet) extendSetMaybe(i uint) {
|
||||||
if i >= b.length { // if we need more bits, make 'em
|
if i >= b.length { // if we need more bits, make 'em
|
||||||
|
if i >= Cap() {
|
||||||
|
panic("You are exceeding the capacity")
|
||||||
|
}
|
||||||
nsize := wordsNeeded(i + 1)
|
nsize := wordsNeeded(i + 1)
|
||||||
if b.set == nil {
|
if b.set == nil {
|
||||||
b.set = make([]uint64, nsize)
|
b.set = make([]uint64, nsize)
|
||||||
@@ -160,7 +163,12 @@ func (b *BitSet) Test(i uint) bool {
|
|||||||
return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
|
return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set bit i to 1
|
// Set bit i to 1, the capacity of the bitset is automatically
|
||||||
|
// increased accordingly.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
func (b *BitSet) Set(i uint) *BitSet {
|
func (b *BitSet) Set(i uint) *BitSet {
|
||||||
b.extendSetMaybe(i)
|
b.extendSetMaybe(i)
|
||||||
b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
|
b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
|
||||||
@@ -176,7 +184,11 @@ func (b *BitSet) Clear(i uint) *BitSet {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo sets bit i to value
|
// SetTo sets bit i to value.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
||||||
if value {
|
if value {
|
||||||
return b.Set(i)
|
return b.Set(i)
|
||||||
@@ -184,7 +196,11 @@ func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
|||||||
return b.Clear(i)
|
return b.Clear(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip bit at i
|
// Flip bit at i.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
func (b *BitSet) Flip(i uint) *BitSet {
|
func (b *BitSet) Flip(i uint) *BitSet {
|
||||||
if i >= b.length {
|
if i >= b.length {
|
||||||
return b.Set(i)
|
return b.Set(i)
|
||||||
@@ -193,26 +209,51 @@ func (b *BitSet) Flip(i uint) *BitSet {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shrink shrinks BitSet to desired length in bits. It clears all bits > length
|
// Shrink shrinks BitSet so that the provided value is the last possible
|
||||||
// and reduces the size and length of the set.
|
// set value. It clears all bits > the provided index and reduces the size
|
||||||
|
// and length of the set.
|
||||||
|
//
|
||||||
|
// Note that the parameter value is not the new length in bits: it is the
|
||||||
|
// maximal value that can be stored in the bitset after the function call.
|
||||||
|
// The new length in bits is the parameter value + 1. Thus it is not possible
|
||||||
|
// to use this function to set the length to 0, the minimal value of the length
|
||||||
|
// after this function call is 1.
|
||||||
//
|
//
|
||||||
// A new slice is allocated to store the new bits, so you may see an increase in
|
// A new slice is allocated to store the new bits, so you may see an increase in
|
||||||
// memory usage until the GC runs. Normally this should not be a problem, but if you
|
// memory usage until the GC runs. Normally this should not be a problem, but if you
|
||||||
// have an extremely large BitSet its important to understand that the old BitSet will
|
// have an extremely large BitSet its important to understand that the old BitSet will
|
||||||
// remain in memory until the GC frees it.
|
// remain in memory until the GC frees it.
|
||||||
func (b *BitSet) Shrink(length uint) *BitSet {
|
func (b *BitSet) Shrink(lastbitindex uint) *BitSet {
|
||||||
idx := wordsNeeded(length + 1)
|
length := lastbitindex + 1
|
||||||
|
idx := wordsNeeded(length)
|
||||||
if idx > len(b.set) {
|
if idx > len(b.set) {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
shrunk := make([]uint64, idx)
|
shrunk := make([]uint64, idx)
|
||||||
copy(shrunk, b.set[:idx])
|
copy(shrunk, b.set[:idx])
|
||||||
b.set = shrunk
|
b.set = shrunk
|
||||||
b.length = length + 1
|
b.length = length
|
||||||
b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1)) - 1))
|
b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1))))
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compact shrinks BitSet to so that we preserve all set bits, while minimizing
|
||||||
|
// memory usage. Compact calls Shrink.
|
||||||
|
func (b *BitSet) Compact() *BitSet {
|
||||||
|
idx := len(b.set) - 1
|
||||||
|
for ; idx >= 0 && b.set[idx] == 0; idx-- {
|
||||||
|
}
|
||||||
|
newlength := uint((idx + 1) << log2WordSize)
|
||||||
|
if newlength >= b.length {
|
||||||
|
return b // nothing to do
|
||||||
|
}
|
||||||
|
if newlength > 0 {
|
||||||
|
return b.Shrink(newlength - 1)
|
||||||
|
}
|
||||||
|
// We preserve one word
|
||||||
|
return b.Shrink(63)
|
||||||
|
}
|
||||||
|
|
||||||
// InsertAt takes an index which indicates where a bit should be
|
// InsertAt takes an index which indicates where a bit should be
|
||||||
// inserted. Then it shifts all the bits in the set to the left by 1, starting
|
// inserted. Then it shifts all the bits in the set to the left by 1, starting
|
||||||
// from the given index position, and sets the index position to 0.
|
// from the given index position, and sets the index position to 0.
|
||||||
@@ -323,6 +364,9 @@ func (b *BitSet) DeleteAt(i uint) *BitSet {
|
|||||||
// including possibly the current index
|
// including possibly the current index
|
||||||
// along with an error code (true = valid, false = no set bit found)
|
// along with an error code (true = valid, false = no set bit found)
|
||||||
// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
|
// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
|
||||||
|
//
|
||||||
|
// Users concerned with performance may want to use NextSetMany to
|
||||||
|
// retrieve several values at once.
|
||||||
func (b *BitSet) NextSet(i uint) (uint, bool) {
|
func (b *BitSet) NextSet(i uint) (uint, bool) {
|
||||||
x := int(i >> log2WordSize)
|
x := int(i >> log2WordSize)
|
||||||
if x >= len(b.set) {
|
if x >= len(b.set) {
|
||||||
@@ -358,6 +402,14 @@ func (b *BitSet) NextSet(i uint) (uint, bool) {
|
|||||||
// j += 1
|
// j += 1
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
// It is possible to retrieve all set bits as follow:
|
||||||
|
//
|
||||||
|
// indices := make([]uint, bitmap.Count())
|
||||||
|
// bitmap.NextSetMany(0, indices)
|
||||||
|
//
|
||||||
|
// However if bitmap.Count() is large, it might be preferable to
|
||||||
|
// use several calls to NextSetMany, for performance reasons.
|
||||||
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
|
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
|
||||||
myanswer := buffer
|
myanswer := buffer
|
||||||
capacity := cap(buffer)
|
capacity := cap(buffer)
|
||||||
@@ -809,7 +861,7 @@ func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {
|
|||||||
newset := New(uint(length))
|
newset := New(uint(length))
|
||||||
|
|
||||||
if uint64(newset.length) != length {
|
if uint64(newset.length) != length {
|
||||||
return 0, errors.New("Unmarshalling error: type mismatch")
|
return 0, errors.New("unmarshalling error: type mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read remaining bytes as set
|
// Read remaining bytes as set
|
||||||
|
3
vendor/github.com/willf/bitset/go.mod
generated
vendored
Normal file
3
vendor/github.com/willf/bitset/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/willf/bitset
|
||||||
|
|
||||||
|
go 1.14
|
0
vendor/github.com/willf/bitset/go.sum
generated
vendored
Normal file
0
vendor/github.com/willf/bitset/go.sum
generated
vendored
Normal file
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@@ -69,7 +69,8 @@ github.com/vishvananda/netlink
|
|||||||
github.com/vishvananda/netlink/nl
|
github.com/vishvananda/netlink/nl
|
||||||
# github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
|
# github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
|
||||||
github.com/vishvananda/netns
|
github.com/vishvananda/netns
|
||||||
# github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243
|
# github.com/willf/bitset v1.1.11
|
||||||
|
## explicit
|
||||||
github.com/willf/bitset
|
github.com/willf/bitset
|
||||||
# golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
|
# golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
|
||||||
## explicit
|
## explicit
|
||||||
|
Reference in New Issue
Block a user