Downgrade the version of github.com/prometheus/client_golang to 1.7.1 to avoid the compile error in mac

The version 1.8.0 of "github.com/prometheus/client_golang" bumps up lib "golang.org/x/sys" which referenced by "github.com/docker/docker@1.4.2". The changes of "golang.org/x/sys" causes the compile error in mac

Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
Wenkai Yin 2020-11-09 21:25:46 +08:00
parent 9152521b11
commit 69ddb9c2a8
200 changed files with 12315 additions and 8881 deletions

View File

@ -55,9 +55,10 @@ require (
github.com/olekukonko/tablewriter v0.0.1 github.com/olekukonko/tablewriter v0.0.1
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec v1.0.1
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v1.8.0 github.com/prometheus/client_golang v1.7.1
github.com/robfig/cron v1.0.0 github.com/robfig/cron v1.0.0
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
github.com/spf13/viper v1.4.0 // indirect github.com/spf13/viper v1.4.0 // indirect

View File

@ -414,6 +414,7 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@ -714,6 +715,8 @@ github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKw
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
@ -749,6 +752,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
@ -768,6 +772,7 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4= github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
@ -779,6 +784,7 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@ -1056,6 +1062,7 @@ golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=

View File

@ -7,9 +7,6 @@ wmiller848 (bitwise operators)
prashantv (optimization of bools) prashantv (optimization of bools)
dpaolella (exposure of variables used in an expression) dpaolella (exposure of variables used in an expression)
benpaxton (fix for missing type checks during literal elide process) benpaxton (fix for missing type checks during literal elide process)
abrander (panic-finding testing tool, float32 conversions) abrander (panic-finding testing tool)
xfennec (fix for dates being parsed in the current Location) xfennec (fix for dates being parsed in the current Location)
bgaifullin (lifting restriction on complex/struct types) bgaifullin (lifting restriction on complex/struct types)
gautambt (hexadecimal literals)
felixonmars (fix multiple typos in test names)
sambonfire (automatic type conversion for accessor function calls)

View File

@ -133,7 +133,6 @@ func (this EvaluableExpression) Evaluate(parameters map[string]interface{}) (int
if parameters == nil { if parameters == nil {
return this.Eval(nil) return this.Eval(nil)
} }
return this.Eval(MapParameters(parameters)) return this.Eval(MapParameters(parameters))
} }
@ -156,10 +155,7 @@ func (this EvaluableExpression) Eval(parameters Parameters) (interface{}, error)
if parameters != nil { if parameters != nil {
parameters = &sanitizedParameters{parameters} parameters = &sanitizedParameters{parameters}
} else {
parameters = DUMMY_PARAMETERS
} }
return this.evaluateStage(this.evaluationStages, parameters) return this.evaluateStage(this.evaluationStages, parameters)
} }
@ -177,27 +173,27 @@ func (this EvaluableExpression) evaluateStage(stage *evaluationStage, parameters
if stage.isShortCircuitable() { if stage.isShortCircuitable() {
switch stage.symbol { switch stage.symbol {
case AND: case AND:
if left == false { if left == false {
return false, nil return false, nil
} }
case OR: case OR:
if left == true { if left == true {
return true, nil return true, nil
} }
case COALESCE: case COALESCE:
if left != nil { if left != nil {
return left, nil return left, nil
} }
case TERNARY_TRUE: case TERNARY_TRUE:
if left == false { if left == false {
right = shortCircuitHolder right = shortCircuitHolder
} }
case TERNARY_FALSE: case TERNARY_FALSE:
if left != nil { if left != nil {
right = shortCircuitHolder right = shortCircuitHolder
} }
} }
} }

View File

@ -44,7 +44,6 @@ const (
COALESCE COALESCE
FUNCTIONAL FUNCTIONAL
ACCESS
SEPARATE SEPARATE
) )
@ -130,8 +129,6 @@ func findOperatorPrecedenceForSymbol(symbol OperatorSymbol) operatorPrecedence {
fallthrough fallthrough
case TERNARY_FALSE: case TERNARY_FALSE:
return ternaryPrecedence return ternaryPrecedence
case ACCESS:
fallthrough
case FUNCTIONAL: case FUNCTIONAL:
return functionalPrecedence return functionalPrecedence
case SEPARATE: case SEPARATE:

View File

@ -2,9 +2,8 @@ govaluate
==== ====
[![Build Status](https://travis-ci.org/Knetic/govaluate.svg?branch=master)](https://travis-ci.org/Knetic/govaluate) [![Build Status](https://travis-ci.org/Knetic/govaluate.svg?branch=master)](https://travis-ci.org/Knetic/govaluate)
[![Godoc](https://img.shields.io/badge/godoc-reference-5272B4.svg)](https://godoc.org/github.com/Knetic/govaluate) [![Godoc](https://godoc.org/github.com/Knetic/govaluate?status.png)](https://godoc.org/github.com/Knetic/govaluate)
[![Go Report Card](https://goreportcard.com/badge/github.com/Knetic/govaluate)](https://goreportcard.com/report/github.com/Knetic/govaluate)
[![Gocover](https://gocover.io/_badge/github.com/Knetic/govaluate)](https://gocover.io/github.com/Knetic/govaluate)
Provides support for evaluating arbitrary C-like artithmetic/string expressions. Provides support for evaluating arbitrary C-like artithmetic/string expressions.
@ -151,28 +150,6 @@ Functions can accept any number of arguments, correctly handles nested functions
Functions cannot be passed as parameters, they must be known at the time when the expression is parsed, and are unchangeable after parsing. Functions cannot be passed as parameters, they must be known at the time when the expression is parsed, and are unchangeable after parsing.
Accessors
--
If you have structs in your parameters, you can access their fields and methods in the usual way. For instance, given a struct that has a method "Echo", present in the parameters as `foo`, the following is valid:
"foo.Echo('hello world')"
Fields are accessed in a similar way. Assuming `foo` has a field called "Length":
"foo.Length > 9000"
Accessors can be nested to any depth, like the following
"foo.Bar.Baz.SomeFunction()"
However it is not _currently_ supported to access values in `map`s. So the following will not work
"foo.SomeMap['key']"
This may be convenient, but note that using accessors involves a _lot_ of reflection. This makes the expression about four times slower than just using a parameter (consult the benchmarks for more precise measurements on your system).
If at all reasonable, the author recommends extracting the values you care about into a parameter map beforehand, or defining a struct that implements the `Parameters` interface, and which grabs fields as required. If there are functions you want to use, it's better to pass them as expression functions (see the above section). These approaches use no reflection, and are designed to be fast and clean.
What operators and types does this support? What operators and types does this support?
-- --
@ -223,7 +200,7 @@ ok
API Breaks API Breaks
-- --
While this library has very few cases which will ever result in an API break, it can (and [has](https://github.com/Knetic/govaluate/releases/tag/v2.0.0)) happened. If you are using this in production, vendor the commit you've tested against, or use gopkg.in to redirect your import (e.g., `import "gopkg.in/Knetic/govaluate.v2"`). Master branch (while infrequent) _may_ at some point contain API breaking changes, and the author will have no way to communicate these to downstreams, other than creating a new major release. While this library has very few cases which will ever result in an API break, it can (and [has](https://github.com/Knetic/govaluate/releases/tag/2.0.0)) happened. If you are using this in production, vendor the commit you've tested against, or use gopkg.in to redirect your import (e.g., `import "gopkg.in/Knetic/govaluate.v2"`). Master branch (while infrequent) _may_ at some point contain API breaking changes, and the author will have no way to communicate these to downstreams, other than creating a new major release.
Releases will explicitly state when an API break happens, and if they do not specify an API break it should be safe to upgrade. Releases will explicitly state when an API break happens, and if they do not specify an API break it should be safe to upgrade.

View File

@ -17,7 +17,6 @@ const (
VARIABLE VARIABLE
FUNCTION FUNCTION
SEPARATOR SEPARATOR
ACCESSOR
COMPARATOR COMPARATOR
LOGICALOP LOGICALOP
@ -67,8 +66,6 @@ func (kind TokenKind) String() string {
return "CLAUSE_CLOSE" return "CLAUSE_CLOSE"
case TERNARY: case TERNARY:
return "TERNARY" return "TERNARY"
case ACCESSOR:
return "ACCESSOR"
} }
return "UNKNOWN" return "UNKNOWN"

View File

@ -4,9 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"math" "math"
"reflect"
"regexp" "regexp"
"strings" "reflect"
) )
const ( const (
@ -67,16 +66,16 @@ func (this *evaluationStage) setToNonStage(other evaluationStage) {
func (this *evaluationStage) isShortCircuitable() bool { func (this *evaluationStage) isShortCircuitable() bool {
switch this.symbol { switch this.symbol {
case AND: case AND:
fallthrough fallthrough
case OR: case OR:
fallthrough fallthrough
case TERNARY_TRUE: case TERNARY_TRUE:
fallthrough fallthrough
case TERNARY_FALSE: case TERNARY_FALSE:
fallthrough fallthrough
case COALESCE: case COALESCE:
return true return true
} }
return false return false
@ -244,163 +243,7 @@ func makeFunctionStage(function ExpressionFunction) evaluationOperator {
default: default:
return function(right) return function(right)
} }
}
}
func typeConvertParam(p reflect.Value, t reflect.Type) (ret reflect.Value, err error) {
defer func() {
if r := recover(); r != nil {
errorMsg := fmt.Sprintf("Argument type conversion failed: failed to convert '%s' to '%s'", p.Kind().String(), t.Kind().String())
err = errors.New(errorMsg)
ret = p
}
}()
return p.Convert(t), nil
}
func typeConvertParams(method reflect.Value, params []reflect.Value) ([]reflect.Value, error) {
methodType := method.Type()
numIn := methodType.NumIn()
numParams := len(params)
if numIn != numParams {
if numIn > numParams {
return nil, fmt.Errorf("Too few arguments to parameter call: got %d arguments, expected %d", len(params), numIn)
}
return nil, fmt.Errorf("Too many arguments to parameter call: got %d arguments, expected %d", len(params), numIn)
}
for i := 0; i < numIn; i++ {
t := methodType.In(i)
p := params[i]
pt := p.Type()
if t.Kind() != pt.Kind() {
np, err := typeConvertParam(p, t)
if err != nil {
return nil, err
}
params[i] = np
}
}
return params, nil
}
func makeAccessorStage(pair []string) evaluationOperator {
reconstructed := strings.Join(pair, ".")
return func(left interface{}, right interface{}, parameters Parameters) (ret interface{}, err error) {
var params []reflect.Value
value, err := parameters.Get(pair[0])
if err != nil {
return nil, err
}
// while this library generally tries to handle panic-inducing cases on its own,
// accessors are a sticky case which have a lot of possible ways to fail.
// therefore every call to an accessor sets up a defer that tries to recover from panics, converting them to errors.
defer func() {
if r := recover(); r != nil {
errorMsg := fmt.Sprintf("Failed to access '%s': %v", reconstructed, r.(string))
err = errors.New(errorMsg)
ret = nil
}
}()
for i := 1; i < len(pair); i++ {
coreValue := reflect.ValueOf(value)
var corePtrVal reflect.Value
// if this is a pointer, resolve it.
if coreValue.Kind() == reflect.Ptr {
corePtrVal = coreValue
coreValue = coreValue.Elem()
}
if coreValue.Kind() != reflect.Struct {
return nil, errors.New("Unable to access '" + pair[i] + "', '" + pair[i-1] + "' is not a struct")
}
field := coreValue.FieldByName(pair[i])
if field != (reflect.Value{}) {
value = field.Interface()
continue
}
method := coreValue.MethodByName(pair[i])
if method == (reflect.Value{}) {
if corePtrVal.IsValid() {
method = corePtrVal.MethodByName(pair[i])
}
if method == (reflect.Value{}) {
return nil, errors.New("No method or field '" + pair[i] + "' present on parameter '" + pair[i-1] + "'")
}
}
switch right.(type) {
case []interface{}:
givenParams := right.([]interface{})
params = make([]reflect.Value, len(givenParams))
for idx, _ := range givenParams {
params[idx] = reflect.ValueOf(givenParams[idx])
}
default:
if right == nil {
params = []reflect.Value{}
break
}
params = []reflect.Value{reflect.ValueOf(right.(interface{}))}
}
params, err = typeConvertParams(method, params)
if err != nil {
return nil, errors.New("Method call failed - '" + pair[0] + "." + pair[1] + "': " + err.Error())
}
returned := method.Call(params)
retLength := len(returned)
if retLength == 0 {
return nil, errors.New("Method call '" + pair[i-1] + "." + pair[i] + "' did not return any values.")
}
if retLength == 1 {
value = returned[0].Interface()
continue
}
if retLength == 2 {
errIface := returned[1].Interface()
err, validType := errIface.(error)
if validType && errIface != nil {
return returned[0].Interface(), err
}
value = returned[0].Interface()
continue
}
return nil, errors.New("Method call '" + pair[0] + "." + pair[1] + "' did not return either one value, or a value and an error. Cannot interpret meaning.")
}
value = castToFloat64(value)
return value, nil
} }
} }

View File

@ -17,8 +17,8 @@ type lexerState struct {
var validLexerStates = []lexerState{ var validLexerStates = []lexerState{
lexerState{ lexerState{
kind: UNKNOWN, kind: UNKNOWN,
isEOF: false, isEOF: false,
isNullable: true, isNullable: true,
validNextKinds: []TokenKind{ validNextKinds: []TokenKind{
@ -28,7 +28,6 @@ var validLexerStates = []lexerState{
VARIABLE, VARIABLE,
PATTERN, PATTERN,
FUNCTION, FUNCTION,
ACCESSOR,
STRING, STRING,
TIME, TIME,
CLAUSE, CLAUSE,
@ -48,7 +47,6 @@ var validLexerStates = []lexerState{
VARIABLE, VARIABLE,
PATTERN, PATTERN,
FUNCTION, FUNCTION,
ACCESSOR,
STRING, STRING,
TIME, TIME,
CLAUSE, CLAUSE,
@ -178,7 +176,6 @@ var validLexerStates = []lexerState{
NUMERIC, NUMERIC,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
STRING, STRING,
BOOLEAN, BOOLEAN,
CLAUSE, CLAUSE,
@ -197,7 +194,6 @@ var validLexerStates = []lexerState{
BOOLEAN, BOOLEAN,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
STRING, STRING,
TIME, TIME,
CLAUSE, CLAUSE,
@ -217,7 +213,6 @@ var validLexerStates = []lexerState{
BOOLEAN, BOOLEAN,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
STRING, STRING,
TIME, TIME,
CLAUSE, CLAUSE,
@ -235,7 +230,6 @@ var validLexerStates = []lexerState{
BOOLEAN, BOOLEAN,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
CLAUSE, CLAUSE,
CLAUSE_CLOSE, CLAUSE_CLOSE,
}, },
@ -255,7 +249,6 @@ var validLexerStates = []lexerState{
TIME, TIME,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
CLAUSE, CLAUSE,
SEPARATOR, SEPARATOR,
}, },
@ -269,21 +262,6 @@ var validLexerStates = []lexerState{
CLAUSE, CLAUSE,
}, },
}, },
lexerState{
kind: ACCESSOR,
isEOF: true,
isNullable: false,
validNextKinds: []TokenKind{
CLAUSE,
MODIFIER,
COMPARATOR,
LOGICALOP,
CLAUSE_CLOSE,
TERNARY,
SEPARATOR,
},
},
lexerState{ lexerState{
kind: SEPARATOR, kind: SEPARATOR,
@ -298,7 +276,6 @@ var validLexerStates = []lexerState{
TIME, TIME,
VARIABLE, VARIABLE,
FUNCTION, FUNCTION,
ACCESSOR,
CLAUSE, CLAUSE,
}, },
}, },

View File

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"strconv" "strconv"
"strings"
"time" "time"
"unicode" "unicode"
) )
@ -65,7 +64,7 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
var completed bool var completed bool
var err error var err error
// numeric is 0-9, or . or 0x followed by digits // numeric is 0-9, or .
// string starts with ' // string starts with '
// variable is alphanumeric, always starts with a letter // variable is alphanumeric, always starts with a letter
// bracket always means variable // bracket always means variable
@ -84,26 +83,6 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
// numeric constant // numeric constant
if isNumeric(character) { if isNumeric(character) {
if stream.canRead() && character == '0' {
character = stream.readCharacter()
if stream.canRead() && character == 'x' {
tokenString, _ = readUntilFalse(stream, false, true, true, isHexDigit)
tokenValueInt, err := strconv.ParseUint(tokenString, 16, 64)
if err != nil {
errorMsg := fmt.Sprintf("Unable to parse hex value '%v' to uint64\n", tokenString)
return ExpressionToken{}, errors.New(errorMsg), false
}
kind = NUMERIC
tokenValue = float64(tokenValueInt)
break
} else {
stream.rewind(1)
}
}
tokenString = readTokenUntilFalse(stream, isNumeric) tokenString = readTokenUntilFalse(stream, isNumeric)
tokenValue, err = strconv.ParseFloat(tokenString, 64) tokenValue, err = strconv.ParseFloat(tokenString, 64)
@ -174,32 +153,6 @@ func readToken(stream *lexerStream, state lexerState, functions map[string]Expre
kind = FUNCTION kind = FUNCTION
tokenValue = function tokenValue = function
} }
// accessor?
accessorIndex := strings.Index(tokenString, ".")
if accessorIndex > 0 {
// check that it doesn't end with a hanging period
if tokenString[len(tokenString)-1] == '.' {
errorMsg := fmt.Sprintf("Hanging accessor on token '%s'", tokenString)
return ExpressionToken{}, errors.New(errorMsg), false
}
kind = ACCESSOR
splits := strings.Split(tokenString, ".")
tokenValue = splits
// check that none of them are unexported
for i := 1; i < len(splits); i++ {
firstCharacter := getFirstRune(splits[i])
if unicode.ToUpper(firstCharacter) != firstCharacter {
errorMsg := fmt.Sprintf("Unable to access unexported field '%s' in token '%s'", splits[i], tokenString)
return ExpressionToken{}, errors.New(errorMsg), false
}
}
}
break break
} }
@ -414,23 +367,6 @@ func checkBalance(tokens []ExpressionToken) error {
return nil return nil
} }
func isDigit(character rune) bool {
return unicode.IsDigit(character)
}
func isHexDigit(character rune) bool {
character = unicode.ToLower(character)
return unicode.IsDigit(character) ||
character == 'a' ||
character == 'b' ||
character == 'c' ||
character == 'd' ||
character == 'e' ||
character == 'f'
}
func isNumeric(character rune) bool { func isNumeric(character rune) bool {
return unicode.IsDigit(character) || character == '.' return unicode.IsDigit(character) || character == '.'
@ -447,8 +383,6 @@ func isNotAlphanumeric(character rune) bool {
unicode.IsLetter(character) || unicode.IsLetter(character) ||
character == '(' || character == '(' ||
character == ')' || character == ')' ||
character == '[' ||
character == ']' || // starting to feel like there needs to be an `isOperation` func (#59)
!isNotQuote(character)) !isNotQuote(character))
} }
@ -456,8 +390,7 @@ func isVariableName(character rune) bool {
return unicode.IsLetter(character) || return unicode.IsLetter(character) ||
unicode.IsDigit(character) || unicode.IsDigit(character) ||
character == '_' || character == '_'
character == '.'
} }
func isNotClosingBracket(character rune) bool { func isNotClosingBracket(character rune) bool {
@ -515,12 +448,3 @@ func tryParseExactTime(candidate string, format string) (time.Time, bool) {
return ret, true return ret, true
} }
func getFirstRune(candidate string) rune {
for _, character := range candidate {
return character
}
return 0
}

View File

@ -12,10 +12,40 @@ func (p sanitizedParameters) Get(key string) (interface{}, error) {
return nil, err return nil, err
} }
return castToFloat64(value), nil // should be converted to fixed point?
if isFixedPoint(value) {
return castFixedPoint(value), nil
}
return value, nil
} }
func castToFloat64(value interface{}) interface{} { func isFixedPoint(value interface{}) bool {
switch value.(type) {
case uint8:
return true
case uint16:
return true
case uint32:
return true
case uint64:
return true
case int8:
return true
case int16:
return true
case int32:
return true
case int64:
return true
case int:
return true
}
return false
}
func castFixedPoint(value interface{}) float64 {
switch value.(type) { switch value.(type) {
case uint8: case uint8:
return float64(value.(uint8)) return float64(value.(uint8))
@ -35,9 +65,7 @@ func castToFloat64(value interface{}) interface{} {
return float64(value.(int64)) return float64(value.(int64))
case int: case int:
return float64(value.(int)) return float64(value.(int))
case float32:
return float64(value.(float32))
} }
return value return 0.0
} }

View File

@ -2,8 +2,8 @@ package govaluate
import ( import (
"errors" "errors"
"fmt"
"time" "time"
"fmt"
) )
var stageSymbolMap = map[OperatorSymbol]evaluationOperator{ var stageSymbolMap = map[OperatorSymbol]evaluationOperator{
@ -302,10 +302,10 @@ func planFunction(stream *tokenStream) (*evaluationStage, error) {
if token.Kind != FUNCTION { if token.Kind != FUNCTION {
stream.rewind() stream.rewind()
return planAccessor(stream) return planValue(stream)
} }
rightStage, err = planAccessor(stream) rightStage, err = planValue(stream)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -319,51 +319,6 @@ func planFunction(stream *tokenStream) (*evaluationStage, error) {
}, nil }, nil
} }
func planAccessor(stream *tokenStream) (*evaluationStage, error) {
var token, otherToken ExpressionToken
var rightStage *evaluationStage
var err error
if !stream.hasNext() {
return nil, nil
}
token = stream.next()
if token.Kind != ACCESSOR {
stream.rewind()
return planValue(stream)
}
// check if this is meant to be a function or a field.
// fields have a clause next to them, functions do not.
// if it's a function, parse the arguments. Otherwise leave the right stage null.
if stream.hasNext() {
otherToken = stream.next()
if otherToken.Kind == CLAUSE {
stream.rewind()
rightStage, err = planTokens(stream)
if err != nil {
return nil, err
}
} else {
stream.rewind()
}
}
return &evaluationStage{
symbol: ACCESS,
rightStage: rightStage,
operator: makeAccessorStage(token.Value.([]string)),
typeErrorFormat: "Unable to access parameter field or method '%v': %v",
}, nil
}
/* /*
A truly special precedence function, this handles all the "lowest-case" errata of the process, including literals, parmeters, A truly special precedence function, this handles all the "lowest-case" errata of the process, including literals, parmeters,
clauses, and prefixes. clauses, and prefixes.
@ -376,10 +331,6 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
var operator evaluationOperator var operator evaluationOperator
var err error var err error
if !stream.hasNext() {
return nil, nil
}
token = stream.next() token = stream.next()
switch token.Kind { switch token.Kind {
@ -397,10 +348,10 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
// the stage we got represents all of the logic contained within the parens // the stage we got represents all of the logic contained within the parens
// but for technical reasons, we need to wrap this stage in a "noop" stage which breaks long chains of precedence. // but for technical reasons, we need to wrap this stage in a "noop" stage which breaks long chains of precedence.
// see github #33. // see github #33.
ret = &evaluationStage{ ret = &evaluationStage {
rightStage: ret, rightStage: ret,
operator: noopStageRight, operator: noopStageRight,
symbol: NOOP, symbol: NOOP,
} }
return ret, nil return ret, nil
@ -439,7 +390,7 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
} }
return &evaluationStage{ return &evaluationStage{
symbol: symbol, symbol: symbol,
operator: operator, operator: operator,
}, nil }, nil
} }
@ -717,8 +668,8 @@ func elideStage(root *evaluationStage) *evaluationStage {
return root return root
} }
return &evaluationStage{ return &evaluationStage {
symbol: LITERAL, symbol: LITERAL,
operator: makeLiteralStage(result), operator: makeLiteralStage(result),
} }
} }

View File

@ -18,7 +18,7 @@ pushd "${TEMPORARY_PATH}/src/govaluate"
# run the actual tests. # run the actual tests.
export GOVALUATE_TORTURE_TEST="true" export GOVALUATE_TORTURE_TEST="true"
go test -bench=. -benchmem #-coverprofile coverage.out go test -bench=. -benchmem -coverprofile coverage.out
status=$? status=$?
if [ "${status}" != 0 ]; if [ "${status}" != 0 ];
@ -27,7 +27,6 @@ then
fi fi
# coverage # coverage
# disabled because travis go1.4 seems not to support it suddenly? go tool cover -func=coverage.out
#go tool cover -func=coverage.out
popd popd

View File

@ -765,7 +765,7 @@ func unescape(s string) (ch string, tail string, err error) {
if i > utf8.MaxRune { if i > utf8.MaxRune {
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
} }
return string(rune(i)), s, nil return string(i), s, nil
} }
return "", "", fmt.Errorf(`unknown escape \%c`, r) return "", "", fmt.Errorf(`unknown escape \%c`, r)
} }

View File

@ -27,7 +27,6 @@ We thank all the authors who provided code to this library:
* Felix Kollmann * Felix Kollmann
* Nicolas Perraut * Nicolas Perraut
* @dirty49374
## License ## License

View File

@ -4,6 +4,7 @@ package sequences
import ( import (
"syscall" "syscall"
"unsafe"
) )
var ( var (
@ -26,7 +27,7 @@ func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING
} }
ret, _, err := setConsoleMode.Call(uintptr(stream), uintptr(mode)) ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode))
if ret == 0 { if ret == 0 {
return err return err
} }

View File

@ -2,8 +2,8 @@ language: go
matrix: matrix:
include: include:
- go: "1.11.x" - go: "1.13.x"
- go: "1.12.x" - go: "1.14.x"
- go: "tip" - go: "tip"
env: env:
- LINT=true - LINT=true

View File

@ -1,6 +1,23 @@
Changes by Version Changes by Version
================== ==================
1.2.0 (2020-07-01)
-------------------
* Restore the ability to reset the current span in context to nil (#231) -- Yuri Shkuro
* Use error.object per OpenTracing Semantic Conventions (#179) -- Rahman Syed
* Convert nil pointer log field value to string "nil" (#230) -- Cyril Tovena
* Add Go module support (#215) -- Zaba505
* Make SetTag helper types in ext public (#229) -- Blake Edwards
* Add log/fields helpers for keys from specification (#226) -- Dmitry Monakhov
* Improve noop impementation (#223) -- chanxuehong
* Add an extension to Tracer interface for custom go context creation (#220) -- Krzesimir Nowak
* Fix typo in comments (#222) -- meteorlxy
* Improve documentation for log.Object() to emphasize the requirement to pass immutable arguments (#219) -- 疯狂的小企鹅
* [mock] Return ErrInvalidSpanContext if span context is not MockSpanContext (#216) -- Milad Irannejad
1.1.0 (2019-03-23) 1.1.0 (2019-03-23)
------------------- -------------------

View File

@ -0,0 +1,24 @@
package opentracing
import (
"context"
)
// TracerContextWithSpanExtension is an extension interface that the
// implementation of the Tracer interface may want to implement. It
// allows to have some control over the go context when the
// ContextWithSpan is invoked.
//
// The primary purpose of this extension are adapters from opentracing
// API to some other tracing API.
type TracerContextWithSpanExtension interface {
// ContextWithSpanHook gets called by the ContextWithSpan
// function, when the Tracer implementation also implements
// this interface. It allows to put extra information into the
// context and make it available to the callers of the
// ContextWithSpan.
//
// This hook is invoked before the ContextWithSpan function
// actually puts the span into the context.
ContextWithSpanHook(ctx context.Context, span Span) context.Context
}

View File

@ -0,0 +1,5 @@
module github.com/opentracing/opentracing-go
go 1.14
require github.com/stretchr/testify v1.3.0

View File

@ -0,0 +1,7 @@
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/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=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@ -7,8 +7,13 @@ type contextKey struct{}
var activeSpanKey = contextKey{} var activeSpanKey = contextKey{}
// ContextWithSpan returns a new `context.Context` that holds a reference to // ContextWithSpan returns a new `context.Context` that holds a reference to
// `span`'s SpanContext. // the span. If span is nil, a new context without an active span is returned.
func ContextWithSpan(ctx context.Context, span Span) context.Context { func ContextWithSpan(ctx context.Context, span Span) context.Context {
if span != nil {
if tracerWithHook, ok := span.Tracer().(TracerContextWithSpanExtension); ok {
ctx = tracerWithHook.ContextWithSpanHook(ctx, span)
}
}
return context.WithValue(ctx, activeSpanKey, span) return context.WithValue(ctx, activeSpanKey, span)
} }

View File

@ -122,16 +122,19 @@ func Float64(key string, val float64) Field {
} }
} }
// Error adds an error with the key "error" to a Span.LogFields() record // Error adds an error with the key "error.object" to a Span.LogFields() record
func Error(err error) Field { func Error(err error) Field {
return Field{ return Field{
key: "error", key: "error.object",
fieldType: errorType, fieldType: errorType,
interfaceVal: err, interfaceVal: err,
} }
} }
// Object adds an object-valued key:value pair to a Span.LogFields() record // Object adds an object-valued key:value pair to a Span.LogFields() record
// Please pass in an immutable object, otherwise there may be concurrency issues.
// Such as passing in the map, log.Object may result in "fatal error: concurrent map iteration and map write".
// Because span is sent asynchronously, it is possible that this map will also be modified.
func Object(key string, obj interface{}) Field { func Object(key string, obj interface{}) Field {
return Field{ return Field{
key: key, key: key,
@ -140,6 +143,16 @@ func Object(key string, obj interface{}) Field {
} }
} }
// Event creates a string-valued Field for span logs with key="event" and value=val.
func Event(val string) Field {
return String("event", val)
}
// Message creates a string-valued Field for span logs with key="message" and value=val.
func Message(val string) Field {
return String("message", val)
}
// LazyLogger allows for user-defined, late-bound logging of arbitrary data // LazyLogger allows for user-defined, late-bound logging of arbitrary data
type LazyLogger func(fv Encoder) type LazyLogger func(fv Encoder)

View File

@ -1,6 +1,9 @@
package log package log
import "fmt" import (
"fmt"
"reflect"
)
// InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice // InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice
// a la Span.LogFields(). // a la Span.LogFields().
@ -46,6 +49,10 @@ func InterleavedKVToFields(keyValues ...interface{}) ([]Field, error) {
case float64: case float64:
fields[i] = Float64(key, typedVal) fields[i] = Float64(key, typedVal)
default: default:
if typedVal == nil || (reflect.ValueOf(typedVal).Kind() == reflect.Ptr && reflect.ValueOf(typedVal).IsNil()) {
fields[i] = String(key, "nil")
continue
}
// When in doubt, coerce to a string // When in doubt, coerce to a string
fields[i] = String(key, fmt.Sprint(typedVal)) fields[i] = String(key, fmt.Sprint(typedVal))
} }

View File

@ -21,9 +21,9 @@ type noopSpan struct{}
type noopSpanContext struct{} type noopSpanContext struct{}
var ( var (
defaultNoopSpanContext = noopSpanContext{} defaultNoopSpanContext SpanContext = noopSpanContext{}
defaultNoopSpan = noopSpan{} defaultNoopSpan Span = noopSpan{}
defaultNoopTracer = NoopTracer{} defaultNoopTracer Tracer = NoopTracer{}
) )
const ( const (
@ -35,7 +35,7 @@ func (n noopSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
// noopSpan: // noopSpan:
func (n noopSpan) Context() SpanContext { return defaultNoopSpanContext } func (n noopSpan) Context() SpanContext { return defaultNoopSpanContext }
func (n noopSpan) SetBaggageItem(key, val string) Span { return defaultNoopSpan } func (n noopSpan) SetBaggageItem(key, val string) Span { return n }
func (n noopSpan) BaggageItem(key string) string { return emptyString } func (n noopSpan) BaggageItem(key string) string { return emptyString }
func (n noopSpan) SetTag(key string, value interface{}) Span { return n } func (n noopSpan) SetTag(key string, value interface{}) Span { return n }
func (n noopSpan) LogFields(fields ...log.Field) {} func (n noopSpan) LogFields(fields ...log.Field) {}

View File

@ -163,7 +163,7 @@ func (c *counter) updateExemplar(v float64, l Labels) {
// (e.g. number of HTTP requests, partitioned by response code and // (e.g. number of HTTP requests, partitioned by response code and
// method). Create instances with NewCounterVec. // method). Create instances with NewCounterVec.
type CounterVec struct { type CounterVec struct {
*MetricVec *metricVec
} }
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and // NewCounterVec creates a new CounterVec based on the provided CounterOpts and
@ -176,11 +176,11 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
opts.ConstLabels, opts.ConstLabels,
) )
return &CounterVec{ return &CounterVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { metricVec: newMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) { if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
} }
result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now} result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs), now: time.Now}
result.init(result) // Init self-collection. result.init(result) // Init self-collection.
return result return result
}), }),
@ -188,7 +188,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
} }
// GetMetricWithLabelValues returns the Counter for the given slice of label // GetMetricWithLabelValues returns the Counter for the given slice of label
// values (same order as the variable labels in Desc). If that combination of // values (same order as the VariableLabels in Desc). If that combination of
// label values is accessed for the first time, a new Counter is created. // label values is accessed for the first time, a new Counter is created.
// //
// It is possible to call this method without using the returned Counter to only // It is possible to call this method without using the returned Counter to only
@ -202,7 +202,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
// Counter with the same label values is created later. // Counter with the same label values is created later.
// //
// An error is returned if the number of label values is not the same as the // An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels). // number of VariableLabels in Desc (minus any curried labels).
// //
// Note that for more than one label value, this method is prone to mistakes // Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -211,7 +211,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
// with a performance overhead (for creating and processing the Labels map). // with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example. // See also the GaugeVec example.
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) { func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...) metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
if metric != nil { if metric != nil {
return metric.(Counter), err return metric.(Counter), err
} }
@ -219,19 +219,19 @@ func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
} }
// GetMetricWith returns the Counter for the given Labels map (the label names // GetMetricWith returns the Counter for the given Labels map (the label names
// must match those of the variable labels in Desc). If that label map is // must match those of the VariableLabels in Desc). If that label map is
// accessed for the first time, a new Counter is created. Implications of // accessed for the first time, a new Counter is created. Implications of
// creating a Counter without using it and keeping the Counter for later use are // creating a Counter without using it and keeping the Counter for later use are
// the same as for GetMetricWithLabelValues. // the same as for GetMetricWithLabelValues.
// //
// An error is returned if the number and names of the Labels are inconsistent // An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels). // with those of the VariableLabels in Desc (minus any curried labels).
// //
// This method is used for the same purpose as // This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two // GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods. // methods.
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) { func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
metric, err := v.MetricVec.GetMetricWith(labels) metric, err := v.metricVec.getMetricWith(labels)
if metric != nil { if metric != nil {
return metric.(Counter), err return metric.(Counter), err
} }
@ -275,7 +275,7 @@ func (v *CounterVec) With(labels Labels) Counter {
// registered with a given registry (usually the uncurried version). The Reset // registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector. // method deletes all metrics, even if called on a curried vector.
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) { func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
vec, err := v.MetricVec.CurryWith(labels) vec, err := v.curryWith(labels)
if vec != nil { if vec != nil {
return &CounterVec{vec}, err return &CounterVec{vec}, err
} }

View File

@ -51,7 +51,7 @@ type Desc struct {
// constLabelPairs contains precalculated DTO label pairs based on // constLabelPairs contains precalculated DTO label pairs based on
// the constant labels. // the constant labels.
constLabelPairs []*dto.LabelPair constLabelPairs []*dto.LabelPair
// variableLabels contains names of labels for which the metric // VariableLabels contains names of labels for which the metric
// maintains variable values. // maintains variable values.
variableLabels []string variableLabels []string
// id is a hash of the values of the ConstLabels and fqName. This // id is a hash of the values of the ConstLabels and fqName. This

View File

@ -132,7 +132,7 @@ func (g *gauge) Write(out *dto.Metric) error {
// (e.g. number of operations queued, partitioned by user and operation // (e.g. number of operations queued, partitioned by user and operation
// type). Create instances with NewGaugeVec. // type). Create instances with NewGaugeVec.
type GaugeVec struct { type GaugeVec struct {
*MetricVec *metricVec
} }
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
@ -145,11 +145,11 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
opts.ConstLabels, opts.ConstLabels,
) )
return &GaugeVec{ return &GaugeVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { metricVec: newMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) { if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
} }
result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)} result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
result.init(result) // Init self-collection. result.init(result) // Init self-collection.
return result return result
}), }),
@ -157,7 +157,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
} }
// GetMetricWithLabelValues returns the Gauge for the given slice of label // GetMetricWithLabelValues returns the Gauge for the given slice of label
// values (same order as the variable labels in Desc). If that combination of // values (same order as the VariableLabels in Desc). If that combination of
// label values is accessed for the first time, a new Gauge is created. // label values is accessed for the first time, a new Gauge is created.
// //
// It is possible to call this method without using the returned Gauge to only // It is possible to call this method without using the returned Gauge to only
@ -172,7 +172,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
// example. // example.
// //
// An error is returned if the number of label values is not the same as the // An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels). // number of VariableLabels in Desc (minus any curried labels).
// //
// Note that for more than one label value, this method is prone to mistakes // Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -180,7 +180,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes // latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map). // with a performance overhead (for creating and processing the Labels map).
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...) metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
if metric != nil { if metric != nil {
return metric.(Gauge), err return metric.(Gauge), err
} }
@ -188,19 +188,19 @@ func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
} }
// GetMetricWith returns the Gauge for the given Labels map (the label names // GetMetricWith returns the Gauge for the given Labels map (the label names
// must match those of the variable labels in Desc). If that label map is // must match those of the VariableLabels in Desc). If that label map is
// accessed for the first time, a new Gauge is created. Implications of // accessed for the first time, a new Gauge is created. Implications of
// creating a Gauge without using it and keeping the Gauge for later use are // creating a Gauge without using it and keeping the Gauge for later use are
// the same as for GetMetricWithLabelValues. // the same as for GetMetricWithLabelValues.
// //
// An error is returned if the number and names of the Labels are inconsistent // An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels). // with those of the VariableLabels in Desc (minus any curried labels).
// //
// This method is used for the same purpose as // This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two // GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods. // methods.
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
metric, err := v.MetricVec.GetMetricWith(labels) metric, err := v.metricVec.getMetricWith(labels)
if metric != nil { if metric != nil {
return metric.(Gauge), err return metric.(Gauge), err
} }
@ -244,7 +244,7 @@ func (v *GaugeVec) With(labels Labels) Gauge {
// registered with a given registry (usually the uncurried version). The Reset // registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector. // method deletes all metrics, even if called on a curried vector.
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) { func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
vec, err := v.MetricVec.CurryWith(labels) vec, err := v.curryWith(labels)
if vec != nil { if vec != nil {
return &GaugeVec{vec}, err return &GaugeVec{vec}, err
} }

View File

@ -58,10 +58,9 @@ type goCollector struct {
// collector will use the memstats from a previous collection if // collector will use the memstats from a previous collection if
// runtime.ReadMemStats takes more than 1s. However, if there are no previously // runtime.ReadMemStats takes more than 1s. However, if there are no previously
// collected memstats, or their collection is more than 5m ago, the collection // collected memstats, or their collection is more than 5m ago, the collection
// will block until runtime.ReadMemStats succeeds. // will block until runtime.ReadMemStats succeeds. (The problem might be solved
// // in Go1.13, see https://github.com/golang/go/issues/19812 for the related Go
// NOTE: The problem is solved in Go 1.15, see // issue.)
// https://github.com/golang/go/issues/19812 for the related Go issue.
func NewGoCollector() Collector { func NewGoCollector() Collector {
return &goCollector{ return &goCollector{
goroutinesDesc: NewDesc( goroutinesDesc: NewDesc(

View File

@ -192,7 +192,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
h := &histogram{ h := &histogram{
desc: desc, desc: desc,
upperBounds: opts.Buckets, upperBounds: opts.Buckets,
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
counts: [2]*histogramCounts{{}, {}}, counts: [2]*histogramCounts{{}, {}},
now: time.Now, now: time.Now,
} }
@ -409,7 +409,7 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
// (e.g. HTTP request latencies, partitioned by status code and method). Create // (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewHistogramVec. // instances with NewHistogramVec.
type HistogramVec struct { type HistogramVec struct {
*MetricVec *metricVec
} }
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and // NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
@ -422,14 +422,14 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
opts.ConstLabels, opts.ConstLabels,
) )
return &HistogramVec{ return &HistogramVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { metricVec: newMetricVec(desc, func(lvs ...string) Metric {
return newHistogram(desc, opts, lvs...) return newHistogram(desc, opts, lvs...)
}), }),
} }
} }
// GetMetricWithLabelValues returns the Histogram for the given slice of label // GetMetricWithLabelValues returns the Histogram for the given slice of label
// values (same order as the variable labels in Desc). If that combination of // values (same order as the VariableLabels in Desc). If that combination of
// label values is accessed for the first time, a new Histogram is created. // label values is accessed for the first time, a new Histogram is created.
// //
// It is possible to call this method without using the returned Histogram to only // It is possible to call this method without using the returned Histogram to only
@ -444,7 +444,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
// example. // example.
// //
// An error is returned if the number of label values is not the same as the // An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels). // number of VariableLabels in Desc (minus any curried labels).
// //
// Note that for more than one label value, this method is prone to mistakes // Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -453,7 +453,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
// with a performance overhead (for creating and processing the Labels map). // with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example. // See also the GaugeVec example.
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...) metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
if metric != nil { if metric != nil {
return metric.(Observer), err return metric.(Observer), err
} }
@ -461,19 +461,19 @@ func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error)
} }
// GetMetricWith returns the Histogram for the given Labels map (the label names // GetMetricWith returns the Histogram for the given Labels map (the label names
// must match those of the variable labels in Desc). If that label map is // must match those of the VariableLabels in Desc). If that label map is
// accessed for the first time, a new Histogram is created. Implications of // accessed for the first time, a new Histogram is created. Implications of
// creating a Histogram without using it and keeping the Histogram for later use // creating a Histogram without using it and keeping the Histogram for later use
// are the same as for GetMetricWithLabelValues. // are the same as for GetMetricWithLabelValues.
// //
// An error is returned if the number and names of the Labels are inconsistent // An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels). // with those of the VariableLabels in Desc (minus any curried labels).
// //
// This method is used for the same purpose as // This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two // GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods. // methods.
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
metric, err := v.MetricVec.GetMetricWith(labels) metric, err := v.metricVec.getMetricWith(labels)
if metric != nil { if metric != nil {
return metric.(Observer), err return metric.(Observer), err
} }
@ -517,7 +517,7 @@ func (v *HistogramVec) With(labels Labels) Observer {
// registered with a given registry (usually the uncurried version). The Reset // registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector. // method deletes all metrics, even if called on a curried vector.
func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) { func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
vec, err := v.MetricVec.CurryWith(labels) vec, err := v.curryWith(labels)
if vec != nil { if vec != nil {
return &HistogramVec{vec}, err return &HistogramVec{vec}, err
} }
@ -602,7 +602,7 @@ func NewConstHistogram(
count: count, count: count,
sum: sum, sum: sum,
buckets: buckets, buckets: buckets,
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
}, nil }, nil
} }

View File

@ -89,7 +89,7 @@ type Opts struct {
// better covered by target labels set by the scraping Prometheus // better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a // server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also // machine_role metric). See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
ConstLabels Labels ConstLabels Labels
} }

View File

@ -110,7 +110,7 @@ type SummaryOpts struct {
// better covered by target labels set by the scraping Prometheus // better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a // server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also // machine_role metric). See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
ConstLabels Labels ConstLabels Labels
// Objectives defines the quantile rank estimates with their respective // Objectives defines the quantile rank estimates with their respective
@ -208,7 +208,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
// Use the lock-free implementation of a Summary without objectives. // Use the lock-free implementation of a Summary without objectives.
s := &noObjectivesSummary{ s := &noObjectivesSummary{
desc: desc, desc: desc,
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
counts: [2]*summaryCounts{{}, {}}, counts: [2]*summaryCounts{{}, {}},
} }
s.init(s) // Init self-collection. s.init(s) // Init self-collection.
@ -221,7 +221,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
objectives: opts.Objectives, objectives: opts.Objectives,
sortedObjectives: make([]float64, 0, len(opts.Objectives)), sortedObjectives: make([]float64, 0, len(opts.Objectives)),
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
hotBuf: make([]float64, 0, opts.BufCap), hotBuf: make([]float64, 0, opts.BufCap),
coldBuf: make([]float64, 0, opts.BufCap), coldBuf: make([]float64, 0, opts.BufCap),
@ -513,7 +513,7 @@ func (s quantSort) Less(i, j int) bool {
// (e.g. HTTP request latencies, partitioned by status code and method). Create // (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewSummaryVec. // instances with NewSummaryVec.
type SummaryVec struct { type SummaryVec struct {
*MetricVec *metricVec
} }
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and // NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
@ -535,14 +535,14 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
opts.ConstLabels, opts.ConstLabels,
) )
return &SummaryVec{ return &SummaryVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { metricVec: newMetricVec(desc, func(lvs ...string) Metric {
return newSummary(desc, opts, lvs...) return newSummary(desc, opts, lvs...)
}), }),
} }
} }
// GetMetricWithLabelValues returns the Summary for the given slice of label // GetMetricWithLabelValues returns the Summary for the given slice of label
// values (same order as the variable labels in Desc). If that combination of // values (same order as the VariableLabels in Desc). If that combination of
// label values is accessed for the first time, a new Summary is created. // label values is accessed for the first time, a new Summary is created.
// //
// It is possible to call this method without using the returned Summary to only // It is possible to call this method without using the returned Summary to only
@ -557,7 +557,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
// example. // example.
// //
// An error is returned if the number of label values is not the same as the // An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels). // number of VariableLabels in Desc (minus any curried labels).
// //
// Note that for more than one label value, this method is prone to mistakes // Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@ -566,7 +566,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
// with a performance overhead (for creating and processing the Labels map). // with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example. // See also the GaugeVec example.
func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...) metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
if metric != nil { if metric != nil {
return metric.(Observer), err return metric.(Observer), err
} }
@ -574,19 +574,19 @@ func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
} }
// GetMetricWith returns the Summary for the given Labels map (the label names // GetMetricWith returns the Summary for the given Labels map (the label names
// must match those of the variable labels in Desc). If that label map is // must match those of the VariableLabels in Desc). If that label map is
// accessed for the first time, a new Summary is created. Implications of // accessed for the first time, a new Summary is created. Implications of
// creating a Summary without using it and keeping the Summary for later use are // creating a Summary without using it and keeping the Summary for later use are
// the same as for GetMetricWithLabelValues. // the same as for GetMetricWithLabelValues.
// //
// An error is returned if the number and names of the Labels are inconsistent // An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels). // with those of the VariableLabels in Desc (minus any curried labels).
// //
// This method is used for the same purpose as // This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two // GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods. // methods.
func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
metric, err := v.MetricVec.GetMetricWith(labels) metric, err := v.metricVec.getMetricWith(labels)
if metric != nil { if metric != nil {
return metric.(Observer), err return metric.(Observer), err
} }
@ -630,7 +630,7 @@ func (v *SummaryVec) With(labels Labels) Observer {
// registered with a given registry (usually the uncurried version). The Reset // registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector. // method deletes all metrics, even if called on a curried vector.
func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) { func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
vec, err := v.MetricVec.CurryWith(labels) vec, err := v.curryWith(labels)
if vec != nil { if vec != nil {
return &SummaryVec{vec}, err return &SummaryVec{vec}, err
} }
@ -716,7 +716,7 @@ func NewConstSummary(
count: count, count: count,
sum: sum, sum: sum,
quantiles: quantiles, quantiles: quantiles,
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
}, nil }, nil
} }

View File

@ -63,7 +63,7 @@ func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *val
desc: desc, desc: desc,
valType: valueType, valType: valueType,
function: function, function: function,
labelPairs: MakeLabelPairs(desc, nil), labelPairs: makeLabelPairs(desc, nil),
} }
result.init(result) result.init(result)
return result return result
@ -95,7 +95,7 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues
desc: desc, desc: desc,
valType: valueType, valType: valueType,
val: value, val: value,
labelPairs: MakeLabelPairs(desc, labelValues), labelPairs: makeLabelPairs(desc, labelValues),
}, nil }, nil
} }
@ -145,14 +145,7 @@ func populateMetric(
return nil return nil
} }
// MakeLabelPairs is a helper function to create protobuf LabelPairs from the func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
// variable and constant labels in the provided Desc. The values for the
// variable labels are defined by the labelValues slice, which must be in the
// same order as the corresponding variable labels in the Desc.
//
// This function is only needed for custom Metric implementations. See MetricVec
// example.
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
totalLen := len(desc.variableLabels) + len(desc.constLabelPairs) totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
if totalLen == 0 { if totalLen == 0 {
// Super fast path. // Super fast path.

View File

@ -20,20 +20,12 @@ import (
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
) )
// MetricVec is a Collector to bundle metrics of the same name that differ in // metricVec is a Collector to bundle metrics of the same name that differ in
// their label values. MetricVec is not used directly but as a building block // their label values. metricVec is not used directly (and therefore
// for implementations of vectors of a given metric type, like GaugeVec, // unexported). It is used as a building block for implementations of vectors of
// CounterVec, SummaryVec, and HistogramVec. It is exported so that it can be // a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
// used for custom Metric implementations. // It also handles label currying.
// type metricVec struct {
// To create a FooVec for custom Metric Foo, embed a pointer to MetricVec in
// FooVec and initialize it with NewMetricVec. Implement wrappers for
// GetMetricWithLabelValues and GetMetricWith that return (Foo, error) rather
// than (Metric, error). Similarly, create a wrapper for CurryWith that returns
// (*FooVec, error) rather than (*MetricVec, error). It is recommended to also
// add the convenience methods WithLabelValues, With, and MustCurryWith, which
// panic instead of returning errors. See also the MetricVec example.
type MetricVec struct {
*metricMap *metricMap
curry []curriedLabelValue curry []curriedLabelValue
@ -43,9 +35,9 @@ type MetricVec struct {
hashAddByte func(h uint64, b byte) uint64 hashAddByte func(h uint64, b byte) uint64
} }
// NewMetricVec returns an initialized metricVec. // newMetricVec returns an initialized metricVec.
func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec { func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
return &MetricVec{ return &metricVec{
metricMap: &metricMap{ metricMap: &metricMap{
metrics: map[uint64][]metricWithLabelValues{}, metrics: map[uint64][]metricWithLabelValues{},
desc: desc, desc: desc,
@ -71,7 +63,7 @@ func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes // latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map). // with a performance overhead (for creating and processing the Labels map).
// See also the CounterVec example. // See also the CounterVec example.
func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
h, err := m.hashLabelValues(lvs) h, err := m.hashLabelValues(lvs)
if err != nil { if err != nil {
return false return false
@ -90,7 +82,7 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
// //
// This method is used for the same purpose as DeleteLabelValues(...string). See // This method is used for the same purpose as DeleteLabelValues(...string). See
// there for pros and cons of the two methods. // there for pros and cons of the two methods.
func (m *MetricVec) Delete(labels Labels) bool { func (m *metricVec) Delete(labels Labels) bool {
h, err := m.hashLabels(labels) h, err := m.hashLabels(labels)
if err != nil { if err != nil {
return false return false
@ -103,32 +95,15 @@ func (m *MetricVec) Delete(labels Labels) bool {
// show up in GoDoc. // show up in GoDoc.
// Describe implements Collector. // Describe implements Collector.
func (m *MetricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) } func (m *metricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
// Collect implements Collector. // Collect implements Collector.
func (m *MetricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) } func (m *metricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
// Reset deletes all metrics in this vector. // Reset deletes all metrics in this vector.
func (m *MetricVec) Reset() { m.metricMap.Reset() } func (m *metricVec) Reset() { m.metricMap.Reset() }
// CurryWith returns a vector curried with the provided labels, i.e. the func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
// returned vector has those labels pre-set for all labeled operations performed
// on it. The cardinality of the curried vector is reduced accordingly. The
// order of the remaining labels stays the same (just with the curried labels
// taken out of the sequence which is relevant for the
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
// vector, but only with labels not yet used for currying before.
//
// The metrics contained in the MetricVec are shared between the curried and
// uncurried vectors. They are just accessed differently. Curried and uncurried
// vectors behave identically in terms of collection. Only one must be
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
//
// Note that CurryWith is usually not called directly but through a wrapper
// around MetricVec, implementing a vector for a specific Metric
// implementation, for example GaugeVec.
func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
var ( var (
newCurry []curriedLabelValue newCurry []curriedLabelValue
oldCurry = m.curry oldCurry = m.curry
@ -153,7 +128,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
return nil, fmt.Errorf("%d unknown label(s) found during currying", l) return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
} }
return &MetricVec{ return &metricVec{
metricMap: m.metricMap, metricMap: m.metricMap,
curry: newCurry, curry: newCurry,
hashAdd: m.hashAdd, hashAdd: m.hashAdd,
@ -161,34 +136,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
}, nil }, nil
} }
// GetMetricWithLabelValues returns the Metric for the given slice of label func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Metric is created (by
// calling the newMetric function provided during construction of the
// MetricVec).
//
// It is possible to call this method without using the returned Metry to only
// create the new Metric but leave it in its intitial state.
//
// Keeping the Metric for later use is possible (and should be considered if
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
// Delete can be used to delete the Metric from the MetricVec. In that case, the
// Metric will still exist, but it will not be exported anymore, even if a
// Metric with the same label values is created later.
//
// An error is returned if the number of label values is not the same as the
// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
// an alternative to avoid that type of mistake. For higher label numbers, the
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
//
// Note that GetMetricWithLabelValues is usually not called directly but through
// a wrapper around MetricVec, implementing a vector for a specific Metric
// implementation, for example GaugeVec.
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
h, err := m.hashLabelValues(lvs) h, err := m.hashLabelValues(lvs)
if err != nil { if err != nil {
return nil, err return nil, err
@ -197,23 +145,7 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
} }
// GetMetricWith returns the Metric for the given Labels map (the label names func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Metric is created. Implications of
// creating a Metric without using it and keeping the Metric for later use
// are the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
//
// Note that GetMetricWith is usually not called directly but through a wrapper
// around MetricVec, implementing a vector for a specific Metric implementation,
// for example GaugeVec.
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
h, err := m.hashLabels(labels) h, err := m.hashLabels(labels)
if err != nil { if err != nil {
return nil, err return nil, err
@ -222,7 +154,7 @@ func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
} }
func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil { if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err return 0, err
} }
@ -245,7 +177,7 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
return h, nil return h, nil
} }
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) { func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil { if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err return 0, err
} }
@ -344,9 +276,7 @@ func (m *metricMap) deleteByHashWithLabelValues(
} }
if len(metrics) > 1 { if len(metrics) > 1 {
old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...) m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
old[len(old)-1] = metricWithLabelValues{}
} else { } else {
delete(m.metrics, h) delete(m.metrics, h)
} }
@ -372,9 +302,7 @@ func (m *metricMap) deleteByHashWithLabels(
} }
if len(metrics) > 1 { if len(metrics) > 1 {
old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...) m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
old[len(old)-1] = metricWithLabelValues{}
} else { } else {
delete(m.metrics, h) delete(m.metrics, h)
} }

View File

@ -32,9 +32,7 @@ import (
// in a no-op Registerer. // in a no-op Registerer.
// //
// WrapRegistererWith provides a way to add fixed labels to a subset of // WrapRegistererWith provides a way to add fixed labels to a subset of
// Collectors. It should not be used to add fixed labels to all metrics // Collectors. It should not be used to add fixed labels to all metrics exposed.
// exposed. See also
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
// //
// Conflicts between Collectors registered through the original Registerer with // Conflicts between Collectors registered through the original Registerer with
// Collectors registered through the wrapping Registerer will still be // Collectors registered through the wrapping Registerer will still be

View File

@ -164,7 +164,7 @@ func (sd *SampleDecoder) Decode(s *model.Vector) error {
} }
// ExtractSamples builds a slice of samples from the provided metric // ExtractSamples builds a slice of samples from the provided metric
// families. If an error occurs during sample extraction, it continues to // families. If an error occurrs during sample extraction, it continues to
// extract from the remaining metric families. The returned error is the last // extract from the remaining metric families. The returned error is the last
// error that has occurred. // error that has occurred.
func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) { func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) {

View File

@ -20,7 +20,7 @@ const (
prime64 = 1099511628211 prime64 = 1099511628211
) )
// hashNew initializes a new fnv64a hash value. // hashNew initializies a new fnv64a hash value.
func hashNew() uint64 { func hashNew() uint64 {
return offset64 return offset64
} }

View File

@ -181,77 +181,77 @@ func (d *Duration) Type() string {
return "duration" return "duration"
} }
var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$") var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
// ParseDuration parses a string into a time.Duration, assuming that a year // ParseDuration parses a string into a time.Duration, assuming that a year
// always has 365d, a week always has 7d, and a day always has 24h. // always has 365d, a week always has 7d, and a day always has 24h.
func ParseDuration(durationStr string) (Duration, error) { func ParseDuration(durationStr string) (Duration, error) {
switch durationStr { // Allow 0 without a unit.
case "0": if durationStr == "0" {
// Allow 0 without a unit.
return 0, nil return 0, nil
case "":
return 0, fmt.Errorf("empty duration string")
} }
matches := durationRE.FindStringSubmatch(durationStr) matches := durationRE.FindStringSubmatch(durationStr)
if matches == nil { if len(matches) != 3 {
return 0, fmt.Errorf("not a valid duration string: %q", durationStr) return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
} }
var dur time.Duration var (
n, _ = strconv.Atoi(matches[1])
// Parse the match at pos `pos` in the regex and use `mult` to turn that dur = time.Duration(n) * time.Millisecond
// into ms, then add that value to the total parsed duration. )
m := func(pos int, mult time.Duration) { switch unit := matches[2]; unit {
if matches[pos] == "" { case "y":
return dur *= 1000 * 60 * 60 * 24 * 365
} case "w":
n, _ := strconv.Atoi(matches[pos]) dur *= 1000 * 60 * 60 * 24 * 7
d := time.Duration(n) * time.Millisecond case "d":
dur += d * mult dur *= 1000 * 60 * 60 * 24
case "h":
dur *= 1000 * 60 * 60
case "m":
dur *= 1000 * 60
case "s":
dur *= 1000
case "ms":
// Value already correct
default:
return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
} }
m(2, 1000*60*60*24*365) // y
m(4, 1000*60*60*24*7) // w
m(6, 1000*60*60*24) // d
m(8, 1000*60*60) // h
m(10, 1000*60) // m
m(12, 1000) // s
m(14, 1) // ms
return Duration(dur), nil return Duration(dur), nil
} }
func (d Duration) String() string { func (d Duration) String() string {
var ( var (
ms = int64(time.Duration(d) / time.Millisecond) ms = int64(time.Duration(d) / time.Millisecond)
r = "" unit = "ms"
) )
if ms == 0 { if ms == 0 {
return "0s" return "0s"
} }
factors := map[string]int64{
f := func(unit string, mult int64, exact bool) { "y": 1000 * 60 * 60 * 24 * 365,
if exact && ms%mult != 0 { "w": 1000 * 60 * 60 * 24 * 7,
return "d": 1000 * 60 * 60 * 24,
} "h": 1000 * 60 * 60,
if v := ms / mult; v > 0 { "m": 1000 * 60,
r += fmt.Sprintf("%d%s", v, unit) "s": 1000,
ms -= v * mult "ms": 1,
}
} }
// Only format years and weeks if the remainder is zero, as it is often switch int64(0) {
// easier to read 90d than 12w6d. case ms % factors["y"]:
f("y", 1000*60*60*24*365, true) unit = "y"
f("w", 1000*60*60*24*7, true) case ms % factors["w"]:
unit = "w"
f("d", 1000*60*60*24, false) case ms % factors["d"]:
f("h", 1000*60*60, false) unit = "d"
f("m", 1000*60, false) case ms % factors["h"]:
f("s", 1000, false) unit = "h"
f("ms", 1, false) case ms % factors["m"]:
unit = "m"
return r case ms % factors["s"]:
unit = "s"
}
return fmt.Sprintf("%v%v", ms/factors[unit], unit)
} }
// MarshalYAML implements the yaml.Marshaler interface. // MarshalYAML implements the yaml.Marshaler interface.

View File

@ -1,3 +0,0 @@
## Prometheus Community Code of Conduct
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

View File

@ -407,50 +407,6 @@ func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
return cpuinfo, nil return cpuinfo, nil
} }
func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) {
scanner := bufio.NewScanner(bytes.NewReader(info))
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
v, err := strconv.ParseUint(field[1], 0, 32)
if err != nil {
return nil, err
}
firstcpu := CPUInfo{Processor: uint(v)}
cpuinfo := []CPUInfo{firstcpu}
i := 0
for scanner.Scan() {
line := scanner.Text()
if !strings.Contains(line, ":") {
continue
}
field := strings.SplitN(line, ": ", 2)
switch strings.TrimSpace(field[0]) {
case "processor":
v, err := strconv.ParseUint(field[1], 0, 32)
if err != nil {
return nil, err
}
i = int(v)
cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor
cpuinfo[i].Processor = uint(v)
case "hart":
cpuinfo[i].CoreID = field[1]
case "isa":
cpuinfo[i].ModelName = field[1]
}
}
return cpuinfo, nil
}
func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode
return nil, errors.New("not implemented")
}
// firstNonEmptyLine advances the scanner to the first non-empty line // firstNonEmptyLine advances the scanner to the first non-empty line
// and returns the contents of that line // and returns the contents of that line
func firstNonEmptyLine(scanner *bufio.Scanner) string { func firstNonEmptyLine(scanner *bufio.Scanner) string {

View File

@ -12,7 +12,6 @@
// limitations under the License. // limitations under the License.
// +build linux // +build linux
// +build arm arm64
package procfs package procfs

View File

@ -12,8 +12,8 @@
// limitations under the License. // limitations under the License.
// +build linux // +build linux
// +build !386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x // +build arm64
package procfs package procfs
var parseCPUInfo = parseCPUInfoDummy var parseCPUInfo = parseCPUInfoARM

View File

@ -12,7 +12,6 @@
// limitations under the License. // limitations under the License.
// +build linux // +build linux
// +build mips mipsle mips64 mips64le
package procfs package procfs

View File

@ -0,0 +1,18 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build linux
package procfs
var parseCPUInfo = parseCPUInfoMips

View File

@ -0,0 +1,18 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build linux
package procfs
var parseCPUInfo = parseCPUInfoMips

View File

@ -0,0 +1,18 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build linux
package procfs
var parseCPUInfo = parseCPUInfoMips

View File

@ -12,7 +12,6 @@
// limitations under the License. // limitations under the License.
// +build linux // +build linux
// +build ppc64 ppc64le
package procfs package procfs

View File

@ -0,0 +1,18 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build linux
package procfs
var parseCPUInfo = parseCPUInfoPPC

View File

@ -467,7 +467,7 @@ Pid: 26231
PPid: 1 PPid: 1
TracerPid: 0 TracerPid: 0
Uid: 1000 1000 1000 0 Uid: 1000 1000 1000 0
Gid: 1001 1001 1001 0 Gid: 0 0 0 0
FDSize: 128 FDSize: 128
Groups: Groups:
NStgid: 1 NStgid: 1
@ -1966,7 +1966,7 @@ Lines: 1
Mode: 444 Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/mdstat Path: fixtures/proc/mdstat
Lines: 60 Lines: 56
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S) md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S)
@ -1989,10 +1989,6 @@ md8 : active raid1 sdb1[1] sda1[0] sdc[2](S) sde[3](S)
195310144 blocks [2/2] [UU] 195310144 blocks [2/2] [UU]
[=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec
md201 : active raid1 sda3[0] sdb3[1]
1993728 blocks super 1.2 [2/2] [UU]
[=>...................] check = 5.7% (114176/1993728) finish=0.2min speed=114176K/sec
md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F) md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F)
7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU]
bitmap: 0/30 pages [0KB], 65536KB chunk bitmap: 0/30 pages [0KB], 65536KB chunk
@ -3758,73 +3754,6 @@ Path: fixtures/sys/class/powercap/intel-rapl:0:0/uevent
Lines: 0 Lines: 0
Mode: 644 Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/class/powercap/intel-rapl:a
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_max_power_uw
Lines: 1
95000000
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_name
Lines: 1
long_term
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_power_limit_uw
Lines: 1
4090000000
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_time_window_us
Lines: 1
999424
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_max_power_uw
Lines: 1
0
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_name
Lines: 1
short_term
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_power_limit_uw
Lines: 1
4090000000
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_time_window_us
Lines: 1
2440
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/enabled
Lines: 1
1
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/energy_uj
Lines: 1
240422366267
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/max_energy_range_uj
Lines: 1
262143328850
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/name
Lines: 1
package-10
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/powercap/intel-rapl:a/uevent
Lines: 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/class/thermal Directory: fixtures/sys/class/thermal
Mode: 775 Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -25,7 +25,7 @@ import (
type KernelRandom struct { type KernelRandom struct {
// EntropyAvaliable gives the available entropy, in bits. // EntropyAvaliable gives the available entropy, in bits.
EntropyAvaliable *uint64 EntropyAvaliable *uint64
// PoolSize gives the size of the entropy pool, in bits. // PoolSize gives the size of the entropy pool, in bytes.
PoolSize *uint64 PoolSize *uint64
// URandomMinReseedSeconds is the number of seconds after which the DRNG will be reseeded. // URandomMinReseedSeconds is the number of seconds after which the DRNG will be reseeded.
URandomMinReseedSeconds *uint64 URandomMinReseedSeconds *uint64

View File

@ -107,14 +107,11 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
syncedBlocks := size syncedBlocks := size
recovering := strings.Contains(lines[syncLineIdx], "recovery") recovering := strings.Contains(lines[syncLineIdx], "recovery")
resyncing := strings.Contains(lines[syncLineIdx], "resync") resyncing := strings.Contains(lines[syncLineIdx], "resync")
checking := strings.Contains(lines[syncLineIdx], "check")
// Append recovery and resyncing state info. // Append recovery and resyncing state info.
if recovering || resyncing || checking { if recovering || resyncing {
if recovering { if recovering {
state = "recovering" state = "recovering"
} else if checking {
state = "checking"
} else { } else {
state = "resyncing" state = "resyncing"
} }

View File

@ -72,10 +72,8 @@ type ProcStatus struct {
// Number of involuntary context switches. // Number of involuntary context switches.
NonVoluntaryCtxtSwitches uint64 NonVoluntaryCtxtSwitches uint64
// UIDs of the process (Real, effective, saved set, and filesystem UIDs) // UIDs of the process (Real, effective, saved set, and filesystem UIDs (GIDs))
UIDs [4]string UIDs [4]string
// GIDs of the process (Real, effective, saved set, and filesystem GIDs)
GIDs [4]string
} }
// NewStatus returns the current status information of the process. // NewStatus returns the current status information of the process.
@ -121,8 +119,6 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
s.Name = vString s.Name = vString
case "Uid": case "Uid":
copy(s.UIDs[:], strings.Split(vString, "\t")) copy(s.UIDs[:], strings.Split(vString, "\t"))
case "Gid":
copy(s.GIDs[:], strings.Split(vString, "\t"))
case "VmPeak": case "VmPeak":
s.VmPeak = vUintBytes s.VmPeak = vUintBytes
case "VmSize": case "VmSize":

View File

@ -1,40 +0,0 @@
run:
# do not run on test files yet
tests: false
# all available settings of specific linters
linters-settings:
errcheck:
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: false
lll:
line-length: 100
tab-width: 4
prealloc:
simple: false
range-loops: false
for-loops: false
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
linters:
enable:
- megacheck
- govet
disable:
- maligned
- prealloc
disable-all: false
presets:
- bugs
- unused
fast: false

View File

@ -4,13 +4,21 @@ git:
depth: 1 depth: 1
env: env:
- GO111MODULE=on - GO111MODULE=on
go: [1.13.x, 1.14.x] - GO111MODULE=off
os: [linux, osx] go: [ 1.11.x, 1.12.x ]
os: [ linux, osx ]
matrix:
exclude:
- go: 1.12.x
env: GO111MODULE=off
- go: 1.11.x
os: osx
install: install:
- ./travis/install.sh - ./travis/install.sh
- if [[ "$GO111MODULE" == "on" ]]; then go mod download; fi
- if [[ "$GO111MODULE" == "off" ]]; then go get github.com/stretchr/testify/assert golang.org/x/sys/unix github.com/konsorten/go-windows-terminal-sequences; fi
script: script:
- ./travis/cross_build.sh - ./travis/cross_build.sh
- ./travis/lint.sh
- export GOMAXPROCS=4 - export GOMAXPROCS=4
- export GORACE=halt_on_error=1 - export GORACE=halt_on_error=1
- go test -race -v ./... - go test -race -v ./...

View File

@ -1,32 +1,9 @@
# 1.6.0
Fixes:
* end of line cleanup
* revert the entry concurrency bug fix whic leads to deadlock under some circumstances
* update dependency on go-windows-terminal-sequences to fix a crash with go 1.14
Features:
* add an option to the `TextFormatter` to completely disable fields quoting
# 1.5.0
Code quality:
* add golangci linter run on travis
Fixes:
* add mutex for hooks concurrent access on `Entry` data
* caller function field for go1.14
* fix build issue for gopherjs target
Feature:
* add an hooks/writer sub-package whose goal is to split output on different stream depending on the trace level
* add a `DisableHTMLEscape` option in the `JSONFormatter`
* add `ForceQuote` and `PadLevelText` options in the `TextFormatter`
# 1.4.2 # 1.4.2
* Fixes build break for plan9, nacl, solaris * Fixes build break for plan9, nacl, solaris
# 1.4.1 # 1.4.1
This new release introduces: This new release introduces:
* Enhance TextFormatter to not print caller information when they are empty (#944) * Enhance TextFormatter to not print caller information when they are empty (#944)
* Remove dependency on golang.org/x/crypto (#932, #943) * Remove dependency on golang.org/x/crypto (#932, #943)
Fixes: Fixes:
* Fix Entry.WithContext method to return a copy of the initial entry (#941) * Fix Entry.WithContext method to return a copy of the initial entry (#941)
@ -34,7 +11,7 @@ Fixes:
# 1.4.0 # 1.4.0
This new release introduces: This new release introduces:
* Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848). * Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
* Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter` (#909, #911) * Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter (#909, #911)
* Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919). * Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
Fixes: Fixes:

View File

@ -1,28 +1,8 @@
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) # Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus)&nbsp;[![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
Logrus is a structured logger for Go (golang), completely API compatible with Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger. the standard library logger.
**Logrus is in maintenance-mode.** We will not be introducing new features. It's
simply too hard to do in a way that won't break many people's projects, which is
the last thing you want from your Logging library (again...).
This does not mean Logrus is dead. Logrus will continue to be maintained for
security, (backwards compatible) bug fixes, and performance (where we are
limited by the interface).
I believe Logrus' biggest contribution is to have played a part in today's
widespread use of structured logging in Golang. There doesn't seem to be a
reason to do a major, breaking iteration into Logrus V2, since the fantastic Go
community has built those independently. Many fantastic alternatives have sprung
up. Logrus would look like those, had it been re-designed with what we know
about structured logging in Go today. Check out, for example,
[Zerolog][zerolog], [Zap][zap], and [Apex][apex].
[zerolog]: https://github.com/rs/zerolog
[zap]: https://github.com/uber-go/zap
[apex]: https://github.com/apex/log
**Seeing weird case-sensitive problems?** It's in the past been possible to **Seeing weird case-sensitive problems?** It's in the past been possible to
import Logrus as both upper- and lower-case. Due to the Go package environment, import Logrus as both upper- and lower-case. Due to the Go package environment,
this caused issues in the community and we needed a standard. Some environments this caused issues in the community and we needed a standard. Some environments
@ -35,6 +15,11 @@ comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
For an in-depth explanation of the casing issue, see [this For an in-depth explanation of the casing issue, see [this
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
**Are you interested in assisting in maintaining Logrus?** Currently I have a
lot of obligations, and I am unable to provide Logrus with the maintainership it
needs. If you'd like to help, please reach out to me at `simon at author's
username dot com`.
Nicely color-coded in development (when a TTY is attached, otherwise just Nicely color-coded in development (when a TTY is attached, otherwise just
plain text): plain text):
@ -202,7 +187,7 @@ func main() {
log.Out = os.Stdout log.Out = os.Stdout
// You could set this to any `io.Writer` such as a file // You could set this to any `io.Writer` such as a file
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
// if err == nil { // if err == nil {
// log.Out = file // log.Out = file
// } else { // } else {
@ -287,7 +272,7 @@ func init() {
``` ```
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
#### Level logging #### Level logging
@ -369,7 +354,6 @@ The built-in logging formatters are:
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
* When colors are enabled, levels are truncated to 4 characters by default. To disable * When colors are enabled, levels are truncated to 4 characters by default. To disable
truncation set the `DisableLevelTruncation` field to `true`. truncation set the `DisableLevelTruncation` field to `true`.
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
* `logrus.JSONFormatter`. Logs fields as JSON. * `logrus.JSONFormatter`. Logs fields as JSON.
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
@ -380,10 +364,8 @@ Third party logging formatters:
* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html). * [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html).
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. * [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. * [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the Power of Zalgo. * [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure. * [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Sava log to files.
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added.
You can define your formatter by implementing the `Formatter` interface, You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
@ -448,14 +430,14 @@ entries. It should not be a feature of the application-level logger.
| Tool | Description | | Tool | Description |
| ---- | ----------- | | ---- | ----------- |
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments.| |[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | |[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
#### Testing #### Testing
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just adds the `test` hook * decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): * a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
```go ```go
@ -483,7 +465,7 @@ func TestSomething(t*testing.T){
Logrus can register one or more functions that will be called when any `fatal` Logrus can register one or more functions that will be called when any `fatal`
level message is logged. The registered handlers will be executed before level message is logged. The registered handlers will be executed before
logrus performs an `os.Exit(1)`. This behavior may be helpful if callers need logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
``` ```
@ -508,6 +490,6 @@ Situation when locking is not needed includes:
1) logger.Out is protected by locks. 1) logger.Out is protected by locks.
2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing) 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)

View File

@ -1,14 +1,14 @@
version: "{build}" version: "{build}"
platform: x64 platform: x64
clone_folder: c:\gopath\src\github.com\sirupsen\logrus clone_folder: c:\gopath\src\github.com\sirupsen\logrus
environment: environment:
GOPATH: c:\gopath GOPATH: c:\gopath
branches: branches:
only: only:
- master - master
install: install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH% - set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- go version - go version
build_script: build_script:
- go get -t - go get -t
- go test - go test

View File

@ -85,15 +85,10 @@ func NewEntry(logger *Logger) *Entry {
} }
} }
// Returns the bytes representation of this entry from the formatter.
func (entry *Entry) Bytes() ([]byte, error) {
return entry.Logger.Formatter.Format(entry)
}
// Returns the string representation from the reader and ultimately the // Returns the string representation from the reader and ultimately the
// formatter. // formatter.
func (entry *Entry) String() (string, error) { func (entry *Entry) String() (string, error) {
serialized, err := entry.Bytes() serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -108,11 +103,7 @@ func (entry *Entry) WithError(err error) *Entry {
// Add a context to the Entry. // Add a context to the Entry.
func (entry *Entry) WithContext(ctx context.Context) *Entry { func (entry *Entry) WithContext(ctx context.Context) *Entry {
dataCopy := make(Fields, len(entry.Data)) return &Entry{Logger: entry.Logger, Data: entry.Data, Time: entry.Time, err: entry.err, Context: ctx}
for k, v := range entry.Data {
dataCopy[k] = v
}
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx}
} }
// Add a single field to the Entry. // Add a single field to the Entry.
@ -153,11 +144,7 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
// Overrides the time of the Entry. // Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry { func (entry *Entry) WithTime(t time.Time) *Entry {
dataCopy := make(Fields, len(entry.Data)) return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context}
for k, v := range entry.Data {
dataCopy[k] = v
}
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context}
} }
// getPackageName reduces a fully qualified function name to the package name // getPackageName reduces a fully qualified function name to the package name
@ -178,20 +165,15 @@ func getPackageName(f string) string {
// getCaller retrieves the name of the first non-logrus calling function // getCaller retrieves the name of the first non-logrus calling function
func getCaller() *runtime.Frame { func getCaller() *runtime.Frame {
// cache this package's fully-qualified name // cache this package's fully-qualified name
callerInitOnce.Do(func() { callerInitOnce.Do(func() {
pcs := make([]uintptr, maximumCallerDepth) pcs := make([]uintptr, 2)
_ = runtime.Callers(0, pcs) _ = runtime.Callers(0, pcs)
logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name())
// dynamic get the package name and the minimum caller depth // now that we have the cache, we can skip a minimum count of known-logrus functions
for i := 0; i < maximumCallerDepth; i++ { // XXX this is dubious, the number of frames may vary
funcName := runtime.FuncForPC(pcs[i]).Name()
if strings.Contains(funcName, "getCaller") {
logrusPackage = getPackageName(funcName)
break
}
}
minimumCallerDepth = knownLogrusFrames minimumCallerDepth = knownLogrusFrames
}) })
@ -205,7 +187,7 @@ func getCaller() *runtime.Frame {
// If the caller isn't part of this package, we're done // If the caller isn't part of this package, we're done
if pkg != logrusPackage { if pkg != logrusPackage {
return &f //nolint:scopelint return &f
} }
} }
@ -235,11 +217,9 @@ func (entry Entry) log(level Level, msg string) {
entry.Level = level entry.Level = level
entry.Message = msg entry.Message = msg
entry.Logger.mu.Lock()
if entry.Logger.ReportCaller { if entry.Logger.ReportCaller {
entry.Caller = getCaller() entry.Caller = getCaller()
} }
entry.Logger.mu.Unlock()
entry.fireHooks() entry.fireHooks()
@ -275,10 +255,11 @@ func (entry *Entry) write() {
serialized, err := entry.Logger.Formatter.Format(entry) serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
return } else {
} _, err = entry.Logger.Out.Write(serialized)
if _, err = entry.Logger.Out.Write(serialized); err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
}
} }
} }

View File

@ -80,7 +80,7 @@ func WithFields(fields Fields) *Entry {
return std.WithFields(fields) return std.WithFields(fields)
} }
// WithTime creates an entry from the standard logger and overrides the time of // WithTime creats an entry from the standard logger and overrides the time of
// logs generated with it. // logs generated with it.
// //
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal

View File

@ -2,10 +2,9 @@ module github.com/sirupsen/logrus
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.3 github.com/konsorten/go-windows-terminal-sequences v1.0.1
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.2.2 github.com/stretchr/testify v1.2.2
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 golang.org/x/sys v0.0.0-20190422165155-953cdadca894
) )
go 1.13

View File

@ -1,12 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -28,9 +28,6 @@ type JSONFormatter struct {
// DisableTimestamp allows disabling automatic timestamps in output // DisableTimestamp allows disabling automatic timestamps in output
DisableTimestamp bool DisableTimestamp bool
// DisableHTMLEscape allows disabling html escaping in output
DisableHTMLEscape bool
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key. // DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
DataKey string DataKey string
@ -113,7 +110,6 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
} }
encoder := json.NewEncoder(b) encoder := json.NewEncoder(b)
encoder.SetEscapeHTML(!f.DisableHTMLEscape)
if f.PrettyPrint { if f.PrettyPrint {
encoder.SetIndent("", " ") encoder.SetIndent("", " ")
} }

View File

@ -68,10 +68,10 @@ func (mw *MutexWrap) Disable() {
// `Out` and `Hooks` directly on the default logger instance. You can also just // `Out` and `Hooks` directly on the default logger instance. You can also just
// instantiate your own: // instantiate your own:
// //
// var log = &logrus.Logger{ // var log = &Logger{
// Out: os.Stderr, // Out: os.Stderr,
// Formatter: new(logrus.JSONFormatter), // Formatter: new(JSONFormatter),
// Hooks: make(logrus.LevelHooks), // Hooks: make(LevelHooks),
// Level: logrus.DebugLevel, // Level: logrus.DebugLevel,
// } // }
// //
@ -100,9 +100,8 @@ func (logger *Logger) releaseEntry(entry *Entry) {
logger.entryPool.Put(entry) logger.entryPool.Put(entry)
} }
// WithField allocates a new entry and adds a field to it. // Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to // Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry.
// this new returned entry.
// If you want multiple fields, use `WithFields`. // If you want multiple fields, use `WithFields`.
func (logger *Logger) WithField(key string, value interface{}) *Entry { func (logger *Logger) WithField(key string, value interface{}) *Entry {
entry := logger.newEntry() entry := logger.newEntry()

View File

@ -51,7 +51,7 @@ func (level *Level) UnmarshalText(text []byte) error {
return err return err
} }
*level = l *level = Level(l)
return nil return nil
} }

View File

@ -1,5 +1,4 @@
// +build darwin dragonfly freebsd netbsd openbsd // +build darwin dragonfly freebsd netbsd openbsd
// +build !js
package logrus package logrus
@ -11,3 +10,4 @@ func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios) _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil return err == nil
} }

View File

@ -1,7 +0,0 @@
// +build js
package logrus
func isTerminal(fd int) bool {
return false
}

View File

@ -1,5 +1,4 @@
// +build linux aix // +build linux aix
// +build !js
package logrus package logrus
@ -11,3 +10,4 @@ func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios) _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil return err == nil
} }

View File

@ -6,11 +6,9 @@ import (
"os" "os"
"runtime" "runtime"
"sort" "sort"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"unicode/utf8"
) )
const ( const (
@ -34,14 +32,6 @@ type TextFormatter struct {
// Force disabling colors. // Force disabling colors.
DisableColors bool DisableColors bool
// Force quoting of all values
ForceQuote bool
// DisableQuote disables quoting for all values.
// DisableQuote will have a lower priority than ForceQuote.
// If both of them are set to true, quote will be forced on all values.
DisableQuote bool
// Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/ // Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
EnvironmentOverrideColors bool EnvironmentOverrideColors bool
@ -67,10 +57,6 @@ type TextFormatter struct {
// Disables the truncation of the level text to 4 characters. // Disables the truncation of the level text to 4 characters.
DisableLevelTruncation bool DisableLevelTruncation bool
// PadLevelText Adds padding the level text so that all the levels output at the same length
// PadLevelText is a superset of the DisableLevelTruncation option
PadLevelText bool
// QuoteEmptyFields will wrap empty fields in quotes if true // QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool QuoteEmptyFields bool
@ -93,32 +79,23 @@ type TextFormatter struct {
CallerPrettyfier func(*runtime.Frame) (function string, file string) CallerPrettyfier func(*runtime.Frame) (function string, file string)
terminalInitOnce sync.Once terminalInitOnce sync.Once
// The max length of the level text, generated dynamically on init
levelTextMaxLength int
} }
func (f *TextFormatter) init(entry *Entry) { func (f *TextFormatter) init(entry *Entry) {
if entry.Logger != nil { if entry.Logger != nil {
f.isTerminal = checkIfTerminal(entry.Logger.Out) f.isTerminal = checkIfTerminal(entry.Logger.Out)
} }
// Get the max length of the level text
for _, level := range AllLevels {
levelTextLength := utf8.RuneCount([]byte(level.String()))
if levelTextLength > f.levelTextMaxLength {
f.levelTextMaxLength = levelTextLength
}
}
} }
func (f *TextFormatter) isColored() bool { func (f *TextFormatter) isColored() bool {
isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows")) isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
if f.EnvironmentOverrideColors { if f.EnvironmentOverrideColors {
switch force, ok := os.LookupEnv("CLICOLOR_FORCE"); { if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" {
case ok && force != "0":
isColored = true isColored = true
case ok && force == "0", os.Getenv("CLICOLOR") == "0": } else if ok && force == "0" {
isColored = false
} else if os.Getenv("CLICOLOR") == "0" {
isColored = false isColored = false
} }
} }
@ -240,18 +217,9 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
} }
levelText := strings.ToUpper(entry.Level.String()) levelText := strings.ToUpper(entry.Level.String())
if !f.DisableLevelTruncation && !f.PadLevelText { if !f.DisableLevelTruncation {
levelText = levelText[0:4] levelText = levelText[0:4]
} }
if f.PadLevelText {
// Generates the format string used in the next line, for example "%-6s" or "%-7s".
// Based on the max level text length.
formatString := "%-" + strconv.Itoa(f.levelTextMaxLength) + "s"
// Formats the level text by appending spaces up to the max length, for example:
// - "INFO "
// - "WARNING"
levelText = fmt.Sprintf(formatString, levelText)
}
// Remove a single newline if it already exists in the message to keep // Remove a single newline if it already exists in the message to keep
// the behavior of logrus text_formatter the same as the stdlib log package // the behavior of logrus text_formatter the same as the stdlib log package
@ -275,12 +243,11 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
} }
} }
switch { if f.DisableTimestamp {
case f.DisableTimestamp:
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message) fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message)
case !f.FullTimestamp: } else if !f.FullTimestamp {
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message) fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
default: } else {
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message) fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
} }
for _, k := range keys { for _, k := range keys {
@ -291,15 +258,9 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
} }
func (f *TextFormatter) needsQuoting(text string) bool { func (f *TextFormatter) needsQuoting(text string) bool {
if f.ForceQuote {
return true
}
if f.QuoteEmptyFields && len(text) == 0 { if f.QuoteEmptyFields && len(text) == 0 {
return true return true
} }
if f.DisableQuote {
return false
}
for _, ch := range text { for _, ch := range text {
if !((ch >= 'a' && ch <= 'z') || if !((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') || (ch >= 'A' && ch <= 'Z') ||

View File

@ -6,16 +6,10 @@ import (
"runtime" "runtime"
) )
// Writer at INFO level. See WriterLevel for details.
func (logger *Logger) Writer() *io.PipeWriter { func (logger *Logger) Writer() *io.PipeWriter {
return logger.WriterLevel(InfoLevel) return logger.WriterLevel(InfoLevel)
} }
// WriterLevel returns an io.Writer that can be used to write arbitrary text to
// the logger at the given log level. Each line written to the writer will be
// printed in the usual way using formatters and hooks. The writer is part of an
// io.Pipe and it is the callers responsibility to close the writer when done.
// This can be used to override the standard library logger easily.
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
return NewEntry(logger).WriterLevel(level) return NewEntry(logger).WriterLevel(level)
} }

View File

@ -1,29 +0,0 @@
// Copyright 2019 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for mips64, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

View File

@ -16,9 +16,3 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk)))) _, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk))))
return err return err
} }
// FcntlFstore performs a fcntl syscall for the F_PREALLOCATE command.
func FcntlFstore(fd uintptr, cmd int, fstore *Fstore_t) error {
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(fstore))))
return err
}

View File

@ -1,9 +1,9 @@
// +build linux,386 linux,arm linux,mips linux,mipsle
// Copyright 2014 The Go Authors. All rights reserved. // Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux,386 linux,arm linux,mips linux,mipsle
package unix package unix
func init() { func init() {

View File

@ -12,8 +12,10 @@ import "syscall"
// We can't use the gc-syntax .s files for gccgo. On the plus side // We can't use the gc-syntax .s files for gccgo. On the plus side
// much of the functionality can be written directly in Go. // much of the functionality can be written directly in Go.
//extern gccgoRealSyscallNoError
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr) func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
//extern gccgoRealSyscall
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr) func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) { func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {

View File

@ -21,9 +21,6 @@ struct ret {
uintptr_t err; uintptr_t err;
}; };
struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscall");
struct ret struct ret
gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
{ {
@ -35,9 +32,6 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
return r; return r;
} }
uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscallNoError");
uintptr_t uintptr_t
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
{ {

View File

@ -20,15 +20,6 @@ func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value)) return ioctl(fd, req, uintptr(value))
} }
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
// To change fd's window size, the req argument should be TIOCSWINSZ. // To change fd's window size, the req argument should be TIOCSWINSZ.

View File

@ -73,22 +73,26 @@ aix_ppc64)
darwin_386) darwin_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32" mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_amd64) darwin_amd64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_arm) darwin_arm)
mkerrors="$mkerrors" mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32" mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_arm64) darwin_arm64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
@ -180,15 +184,6 @@ openbsd_arm64)
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
openbsd_mips64)
mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd"
mksysctl="go run mksysctl_openbsd.go"
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
# Let the type of C char be signed for making the bare syscall
# API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
solaris_amd64) solaris_amd64)
mksyscall="go run mksyscall_solaris.go" mksyscall="go run mksyscall_solaris.go"
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
@ -222,6 +217,8 @@ esac
# aix/ppc64 script generates files instead of writing to stdin. # aix/ppc64 script generates files instead of writing to stdin.
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
elif [ "$GOOS" == "darwin" ]; then elif [ "$GOOS" == "darwin" ]; then
# pre-1.12, direct syscalls
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
# 1.12 and later, syscalls via libSystem # 1.12 and later, syscalls via libSystem
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
# 1.13 and later, syscalls via libSystem (including syscallPtr) # 1.13 and later, syscalls via libSystem (including syscallPtr)

View File

@ -58,7 +58,6 @@ includes_Darwin='
#define _DARWIN_USE_64_BIT_INODE #define _DARWIN_USE_64_BIT_INODE
#include <stdint.h> #include <stdint.h>
#include <sys/attr.h> #include <sys/attr.h>
#include <sys/clonefile.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
@ -94,7 +93,6 @@ includes_DragonFly='
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <net/bpf.h> #include <net/bpf.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_clone.h>
#include <net/if_types.h> #include <net/if_types.h>
#include <net/route.h> #include <net/route.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -109,7 +107,6 @@ includes_FreeBSD='
#include <sys/types.h> #include <sys/types.h>
#include <sys/disk.h> #include <sys/disk.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/sched.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
@ -195,12 +192,9 @@ struct ltchars {
#include <sys/xattr.h> #include <sys/xattr.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cryptouser.h> #include <linux/cryptouser.h>
#include <linux/devlink.h> #include <linux/devlink.h>
#include <linux/dm-ioctl.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/fanotify.h> #include <linux/fanotify.h>
@ -303,7 +297,6 @@ includes_NetBSD='
#include <sys/extattr.h> #include <sys/extattr.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/sched.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
@ -332,7 +325,6 @@ includes_OpenBSD='
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/sched.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -373,7 +365,6 @@ includes_SunOS='
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/stream.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -498,7 +489,6 @@ ccflags="$@"
$2 !~ "NLA_TYPE_MASK" && $2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^FIORDCHK$/ ||
$2 ~ /^SIOC/ || $2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ || $2 ~ /^TIOC/ ||
$2 ~ /^TCGET/ || $2 ~ /^TCGET/ ||
@ -517,20 +507,16 @@ ccflags="$@"
$2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ || $2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ || $2 ~ /^CAP_/ ||
$2 ~ /^CP_/ ||
$2 ~ /^CPUSTATES$/ ||
$2 ~ /^ALG_/ || $2 ~ /^ALG_/ ||
$2 ~ /^FI(CLONE|DEDUPERANGE)/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ || $2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|GETFLAGS)/ ||
$2 ~ /^FS_VERITY_/ || $2 ~ /^FS_VERITY_/ ||
$2 ~ /^FSCRYPT_/ || $2 ~ /^FSCRYPT_/ ||
$2 ~ /^DM_/ ||
$2 ~ /^GRND_/ || $2 ~ /^GRND_/ ||
$2 ~ /^RND/ || $2 ~ /^RND/ ||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
$2 ~ /^KEYCTL_/ || $2 ~ /^KEYCTL_/ ||
$2 ~ /^PERF_/ || $2 ~ /^PERF_EVENT_IOC_/ ||
$2 ~ /^SECCOMP_MODE_/ || $2 ~ /^SECCOMP_MODE_/ ||
$2 ~ /^SPLICE_/ || $2 ~ /^SPLICE_/ ||
$2 ~ /^SYNC_FILE_RANGE_/ || $2 ~ /^SYNC_FILE_RANGE_/ ||
@ -549,7 +535,7 @@ ccflags="$@"
$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
$2 ~ /^FSOPT_/ || $2 ~ /^FSOPT_/ ||
$2 ~ /^WDIO[CFS]_/ || $2 ~ /^WDIOC_/ ||
$2 ~ /^NFN/ || $2 ~ /^NFN/ ||
$2 ~ /^XDP_/ || $2 ~ /^XDP_/ ||
$2 ~ /^RWF_/ || $2 ~ /^RWF_/ ||

View File

@ -20,7 +20,7 @@ func cmsgAlignOf(salen int) int {
case "aix": case "aix":
// There is no alignment on AIX. // There is no alignment on AIX.
salign = 1 salign = 1
case "darwin", "ios", "illumos", "solaris": case "darwin", "illumos", "solaris":
// NOTE: It seems like 64-bit Darwin, Illumos and Solaris // NOTE: It seems like 64-bit Darwin, Illumos and Solaris
// kernels still require 32-bit aligned access to network // kernels still require 32-bit aligned access to network
// subsystem. // subsystem.
@ -32,10 +32,6 @@ func cmsgAlignOf(salen int) int {
if runtime.GOARCH == "arm" { if runtime.GOARCH == "arm" {
salign = 8 salign = 8
} }
// NetBSD aarch64 requires 128-bit alignment.
if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
salign = 16
}
} }
return (salen + salign - 1) & ^(salign - 1) return (salen + salign - 1) & ^(salign - 1)

View File

@ -18,21 +18,6 @@ import (
"unsafe" "unsafe"
) )
const ImplementsGetwd = true
func Getwd() (string, error) {
var buf [PathMax]byte
_, err := Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
/* /*
* Wrapped * Wrapped
*/ */
@ -287,7 +272,7 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
if err != nil { if err != nil {
return return
} }
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && len == 0 { if runtime.GOOS == "darwin" && len == 0 {
// Accepted socket has no address. // Accepted socket has no address.
// This is likely due to a bug in xnu kernels, // This is likely due to a bug in xnu kernels,
// where instead of ECONNABORTED error socket // where instead of ECONNABORTED error socket
@ -542,23 +527,6 @@ func SysctlClockinfo(name string) (*Clockinfo, error) {
return &ci, nil return &ci, nil
} }
func SysctlTimeval(name string) (*Timeval, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
var tv Timeval
n := uintptr(unsafe.Sizeof(tv))
if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
return nil, err
}
if n != unsafe.Sizeof(tv) {
return nil, EIO
}
return &tv, nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error) //sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error { func Utimes(path string, tv []Timeval) error {

View File

@ -10,8 +10,6 @@ import (
"unsafe" "unsafe"
) )
const _SYS_GETDIRENTRIES64 = 344
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// To implement this using libSystem we'd need syscall_syscallPtr for // To implement this using libSystem we'd need syscall_syscallPtr for
// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall // fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
@ -22,7 +20,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
} else { } else {
p = unsafe.Pointer(&_zero) p = unsafe.Pointer(&_zero)
} }
r0, _, e1 := Syscall6(_SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {
return n, errnoErr(e1) return n, errnoErr(e1)

View File

@ -13,10 +13,29 @@
package unix package unix
import ( import (
"errors"
"syscall" "syscall"
"unsafe" "unsafe"
) )
const ImplementsGetwd = true
func Getwd() (string, error) {
buf := make([]byte, 2048)
attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0)
if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 {
wd := string(attrs[0])
// Sanity check that it's an absolute path and ends
// in a null byte, which we then strip.
if wd[0] == '/' && wd[len(wd)-1] == 0 {
return wd[:len(wd)-1], nil
}
}
// If pkg/os/getwd.go gets ENOTSUP, it will fall back to the
// slow algorithm.
return "", ENOTSUP
}
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
type SockaddrDatalink struct { type SockaddrDatalink struct {
Len uint8 Len uint8
@ -30,11 +49,6 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink raw RawSockaddrDatalink
} }
// Some external packages rely on SYS___SYSCTL being defined to implement their
// own sysctl wrappers. Provide it here, even though direct syscalls are no
// longer supported on darwin.
const SYS___SYSCTL = 202
// Translate "kern.hostname" to []_C_int{0,1,2,3}. // Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, err error) { func nametomib(name string) (mib []_C_int, err error) {
const siz = unsafe.Sizeof(mib[0]) const siz = unsafe.Sizeof(mib[0])
@ -78,6 +92,11 @@ func direntNamlen(buf []byte) (uint64, bool) {
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
const (
attrBitMapCount = 5
attrCmnFullpath = 0x08000000
)
type attrList struct { type attrList struct {
bitmapCount uint16 bitmapCount uint16
_ uint16 _ uint16
@ -88,6 +107,54 @@ type attrList struct {
Forkattr uint32 Forkattr uint32
} }
func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) {
if len(attrBuf) < 4 {
return nil, errors.New("attrBuf too small")
}
attrList.bitmapCount = attrBitMapCount
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return nil, err
}
if err := getattrlist(_p0, unsafe.Pointer(&attrList), unsafe.Pointer(&attrBuf[0]), uintptr(len(attrBuf)), int(options)); err != nil {
return nil, err
}
size := *(*uint32)(unsafe.Pointer(&attrBuf[0]))
// dat is the section of attrBuf that contains valid data,
// without the 4 byte length header. All attribute offsets
// are relative to dat.
dat := attrBuf
if int(size) < len(attrBuf) {
dat = dat[:size]
}
dat = dat[4:] // remove length prefix
for i := uint32(0); int(i) < len(dat); {
header := dat[i:]
if len(header) < 8 {
return attrs, errors.New("truncated attribute header")
}
datOff := *(*int32)(unsafe.Pointer(&header[0]))
attrLen := *(*uint32)(unsafe.Pointer(&header[4]))
if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) {
return attrs, errors.New("truncated results; attrBuf too small")
}
end := uint32(datOff) + attrLen
attrs = append(attrs, dat[datOff:end])
i = end
if r := i % 4; r != 0 {
i += (4 - r)
}
}
return
}
//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
//sysnb pipe() (r int, w int, err error) //sysnb pipe() (r int, w int, err error)
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
@ -329,8 +396,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Chroot(path string) (err error) //sys Chroot(path string) (err error)
//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys ClockGettime(clockid int32, time *Timespec) (err error)
//sys Close(fd int) (err error) //sys Close(fd int) (err error)
//sys Clonefile(src string, dst string, flags int) (err error)
//sys Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error)
//sys Dup(fd int) (nfd int, err error) //sys Dup(fd int) (nfd int, err error)
//sys Dup2(from int, to int) (err error) //sys Dup2(from int, to int) (err error)
//sys Exchangedata(path1 string, path2 string, options int) (err error) //sys Exchangedata(path1 string, path2 string, options int) (err error)
@ -342,12 +407,10 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
//sys Flock(fd int, how int) (err error) //sys Flock(fd int, how int) (err error)
//sys Fpathconf(fd int, name int) (val int, err error) //sys Fpathconf(fd int, name int) (val int, err error)
//sys Fsync(fd int) (err error) //sys Fsync(fd int) (err error)
//sys Ftruncate(fd int, length int64) (err error) //sys Ftruncate(fd int, length int64) (err error)
//sys Getcwd(buf []byte) (n int, err error)
//sys Getdtablesize() (size int) //sys Getdtablesize() (size int)
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
//sysnb Geteuid() (uid int) //sysnb Geteuid() (uid int)

View File

@ -0,0 +1,9 @@
// Copyright 2019 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.
// +build darwin,386,!go1.12
package unix
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64

View File

@ -44,6 +44,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/386 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64

View File

@ -0,0 +1,9 @@
// Copyright 2019 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.
// +build darwin,amd64,!go1.12
package unix
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64

View File

@ -44,6 +44,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/amd64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64

View File

@ -0,0 +1,11 @@
// Copyright 2019 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.
// +build darwin,arm,!go1.12
package unix
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

View File

@ -44,6 +44,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error)

View File

@ -0,0 +1,11 @@
// Copyright 2019 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.
// +build darwin,arm64,!go1.12
package unix
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

View File

@ -46,6 +46,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error)

View File

@ -129,8 +129,23 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
return return
} }
const ImplementsGetwd = true
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
func Getwd() (string, error) {
var buf [PathMax]byte
_, err := Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
var bufsize uintptr var bufsize uintptr

View File

@ -140,8 +140,23 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
return return
} }
const ImplementsGetwd = true
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
func Getwd() (string, error) {
var buf [PathMax]byte
_, err := Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
var ( var (
_p0 unsafe.Pointer _p0 unsafe.Pointer

View File

@ -24,7 +24,7 @@ func bytes2iovec(bs [][]byte) []Iovec {
return iovecs return iovecs
} }
//sys readv(fd int, iovs []Iovec) (n int, err error) //sys readv(fd int, iovs []Iovec) (n int, err error)
func Readv(fd int, iovs [][]byte) (n int, err error) { func Readv(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs) iovecs := bytes2iovec(iovs)
@ -32,7 +32,7 @@ func Readv(fd int, iovs [][]byte) (n int, err error) {
return n, err return n, err
} }
//sys preadv(fd int, iovs []Iovec, off int64) (n int, err error) //sys preadv(fd int, iovs []Iovec, off int64) (n int, err error)
func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) { func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs) iovecs := bytes2iovec(iovs)
@ -40,7 +40,7 @@ func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) {
return n, err return n, err
} }
//sys writev(fd int, iovs []Iovec) (n int, err error) //sys writev(fd int, iovs []Iovec) (n int, err error)
func Writev(fd int, iovs [][]byte) (n int, err error) { func Writev(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs) iovecs := bytes2iovec(iovs)
@ -48,43 +48,10 @@ func Writev(fd int, iovs [][]byte) (n int, err error) {
return n, err return n, err
} }
//sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error) //sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error)
func Pwritev(fd int, iovs [][]byte, off int64) (n int, err error) { func Pwritev(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs) iovecs := bytes2iovec(iovs)
n, err = pwritev(fd, iovecs, off) n, err = pwritev(fd, iovecs, off)
return n, err return n, err
} }
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4
func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
nfd, err = accept4(fd, &rsa, &len, flags)
if err != nil {
return
}
if len > SizeofSockaddrAny {
panic("RawSockaddrAny too small")
}
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0
}
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) error {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return err
}

View File

@ -82,6 +82,15 @@ func IoctlRetInt(fd int, req uint) (int, error) {
return int(ret), nil return int(ret), nil
} }
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}
func IoctlSetRTCTime(fd int, value *RTCTime) error { func IoctlSetRTCTime(fd int, value *RTCTime) error {
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value) runtime.KeepAlive(value)
@ -106,53 +115,12 @@ func IoctlGetRTCTime(fd int) (*RTCTime, error) {
return &value, err return &value, err
} }
// IoctlGetWatchdogInfo fetches information about a watchdog device from the
// Linux watchdog API. For more information, see:
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
var value WatchdogInfo
err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value))) err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
return &value, err return &value, err
} }
// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the
// range of data conveyed in value to the file associated with the file
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value)
return err
}
// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
// associated with the file description srcFd to the file associated with the
// file descriptor destFd. See the ioctl_ficlone(2) man page for details.
func IoctlFileClone(destFd, srcFd int) error {
return ioctl(destFd, FICLONE, uintptr(srcFd))
}
// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the
// range of data conveyed in value with the file associated with the file
// descriptor destFd. See the ioctl_fideduperange(2) man page for details.
func IoctlFileDedupeRange(destFd int, value *FileDedupeRange) error {
err := ioctl(destFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value)
return err
}
// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For
// more information, see:
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlWatchdogKeepalive(fd int) error {
return ioctl(fd, WDIOC_KEEPALIVE, 0)
}
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Link(oldpath string, newpath string) (err error) { func Link(oldpath string, newpath string) (err error) {
@ -177,12 +145,6 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
return openat(dirfd, path, flags|O_LARGEFILE, mode) return openat(dirfd, path, flags|O_LARGEFILE, mode)
} }
//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error)
func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
return openat2(dirfd, path, how, SizeofOpenHow)
}
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
@ -923,35 +885,6 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
} }
// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets.
type SockaddrIUCV struct {
UserID string
Name string
raw RawSockaddrIUCV
}
func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_IUCV
// These are EBCDIC encoded by the kernel, but we still need to pad them
// with blanks. Initializing with blanks allows the caller to feed in either
// a padded or an unpadded string.
for i := 0; i < 8; i++ {
sa.raw.Nodeid[i] = ' '
sa.raw.User_id[i] = ' '
sa.raw.Name[i] = ' '
}
if len(sa.UserID) > 8 || len(sa.Name) > 8 {
return nil, 0, EINVAL
}
for i, b := range []byte(sa.UserID[:]) {
sa.raw.User_id[i] = int8(b)
}
for i, b := range []byte(sa.Name[:]) {
sa.raw.Name[i] = int8(b)
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
}
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_NETLINK: case AF_NETLINK:
@ -1132,38 +1065,6 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
} }
return sa, nil return sa, nil
case AF_IUCV:
pp := (*RawSockaddrIUCV)(unsafe.Pointer(rsa))
var user [8]byte
var name [8]byte
for i := 0; i < 8; i++ {
user[i] = byte(pp.User_id[i])
name[i] = byte(pp.Name[i])
}
sa := &SockaddrIUCV{
UserID: string(user[:]),
Name: string(name[:]),
}
return sa, nil
case AF_CAN:
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
sa := &SockaddrCAN{
Ifindex: int(pp.Ifindex),
}
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
for i := 0; i < 4; i++ {
rx[i] = pp.Addr[i]
}
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
for i := 0; i < 4; i++ {
tx[i] = pp.Addr[i+4]
}
return sa, nil
} }
return nil, EAFNOSUPPORT return nil, EAFNOSUPPORT
} }
@ -2049,30 +1950,11 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
return int(n), nil return int(n), nil
} }
func isGroupMember(gid int) bool {
groups, err := Getgroups()
if err != nil {
return false
}
for _, g := range groups {
if g == gid {
return true
}
}
return false
}
//sys faccessat(dirfd int, path string, mode uint32) (err error) //sys faccessat(dirfd int, path string, mode uint32) (err error)
//sys Faccessat2(dirfd int, path string, mode uint32, flags int) (err error)
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
if flags == 0 { if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return faccessat(dirfd, path, mode) return EINVAL
}
if err := Faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM {
return err
} }
// The Linux kernel faccessat system call does not take any flags. // The Linux kernel faccessat system call does not take any flags.
@ -2081,8 +1963,8 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
// Because people naturally expect syscall.Faccessat to act // Because people naturally expect syscall.Faccessat to act
// like C faccessat, we do the same. // like C faccessat, we do the same.
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 { if flags == 0 {
return EINVAL return faccessat(dirfd, path, mode)
} }
var st Stat_t var st Stat_t
@ -2125,7 +2007,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
gid = Getgid() gid = Getgid()
} }
if uint32(gid) == st.Gid || isGroupMember(gid) { if uint32(gid) == st.Gid {
fmode = (st.Mode >> 3) & 7 fmode = (st.Mode >> 3) & 7
} else { } else {
fmode = st.Mode & 7 fmode = st.Mode & 7
@ -2226,18 +2108,6 @@ func Klogset(typ int, arg int) (err error) {
return nil return nil
} }
// RemoteIovec is Iovec with the pointer replaced with an integer.
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
// refers to a location in a different process' address space, which
// would confuse the Go garbage collector.
type RemoteIovec struct {
Base uintptr
Len int
}
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
/* /*
* Unimplemented * Unimplemented
*/ */

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
// +build 386,linux // +build 386,linux
package unix package unix

View File

@ -7,6 +7,7 @@
package unix package unix
import ( import (
"syscall"
"unsafe" "unsafe"
) )
@ -48,6 +49,10 @@ func Pipe2(p []int, flags int) (err error) {
return return
} }
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, errno := seek(fd, offset, whence) newoffset, errno := seek(fd, offset, whence)
if errno != 0 { if errno != 0 {

View File

@ -1,13 +0,0 @@
// 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.
// +build arm,!gccgo,linux
package unix
import "syscall"
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)

View File

@ -141,8 +141,23 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return return
} }
const ImplementsGetwd = true
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
func Getwd() (string, error) {
var buf [PathMax]byte
_, err := Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
// TODO // TODO
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
return -1, ENOSYS return -1, ENOSYS

View File

@ -114,8 +114,23 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return return
} }
const ImplementsGetwd = true
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
func Getwd() (string, error) {
var buf [PathMax]byte
_, err := Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
if raceenabled { if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync)) raceReleaseMerge(unsafe.Pointer(&ioSync))

View File

@ -1,35 +0,0 @@
// Copyright 2019 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 unix
func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec}
}
func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: usec}
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of OpenBSD the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL

Some files were not shown because too many files have changed in this diff Show More