rebase: bump google.golang.org/grpc from 1.52.3 to 1.53.0

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.52.3 to 1.53.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.52.3...v1.53.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2023-02-13 21:00:11 +00:00 committed by mergify[bot]
parent db8320ce51
commit d09eae2efa
43 changed files with 971 additions and 623 deletions

8
go.mod
View File

@ -30,7 +30,7 @@ require (
golang.org/x/crypto v0.5.0 golang.org/x/crypto v0.5.0
golang.org/x/net v0.5.0 golang.org/x/net v0.5.0
golang.org/x/sys v0.4.0 golang.org/x/sys v0.4.0
google.golang.org/grpc v1.52.3 google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1 google.golang.org/protobuf v1.28.1
k8s.io/api v0.26.1 k8s.io/api v0.26.1
k8s.io/apimachinery v0.26.1 k8s.io/apimachinery v0.26.1
@ -61,7 +61,7 @@ require (
github.com/blang/semver/v4 v4.0.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect
@ -150,13 +150,13 @@ require (
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.24.0 // indirect go.uber.org/zap v1.24.0 // indirect
golang.org/x/oauth2 v0.2.0 // indirect golang.org/x/oauth2 v0.4.0 // indirect
golang.org/x/term v0.4.0 // indirect golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect golang.org/x/text v0.6.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

15
go.sum
View File

@ -178,8 +178,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q= github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@ -1248,8 +1249,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU= golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1567,8 +1568,8 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220208230804-65c12eb4c068/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220208230804-65c12eb4c068/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@ -1606,8 +1607,8 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View File

@ -3,8 +3,7 @@
[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) [![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2)
[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) [![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml)
xxhash is a Go implementation of the 64-bit xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a
[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
high-quality hashing algorithm that is much faster than anything in the Go high-quality hashing algorithm that is much faster than anything in the Go
standard library. standard library.
@ -25,8 +24,11 @@ func (*Digest) WriteString(string) (int, error)
func (*Digest) Sum64() uint64 func (*Digest) Sum64() uint64
``` ```
This implementation provides a fast pure-Go implementation and an even faster The package is written with optimized pure Go and also contains even faster
assembly implementation for amd64. assembly implementations for amd64 and arm64. If desired, the `purego` build tag
opts into using the Go code even on those architectures.
[xxHash]: http://cyan4973.github.io/xxHash/
## Compatibility ## Compatibility
@ -46,18 +48,19 @@ Here are some quick benchmarks comparing the pure-Go and assembly
implementations of Sum64. implementations of Sum64.
| input size | purego | asm | | input size | purego | asm |
| --- | --- | --- | | ---------- | --------- | --------- |
| 5 B | 979.66 MB/s | 1291.17 MB/s | | 4 B | 1.3 GB/s | 1.2 GB/s |
| 100 B | 7475.26 MB/s | 7973.40 MB/s | | 16 B | 2.9 GB/s | 3.5 GB/s |
| 4 KB | 17573.46 MB/s | 17602.65 MB/s | | 100 B | 6.9 GB/s | 8.1 GB/s |
| 10 MB | 17131.46 MB/s | 17142.16 MB/s | | 4 KB | 11.7 GB/s | 16.7 GB/s |
| 10 MB | 12.0 GB/s | 17.3 GB/s |
These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C
the following commands under Go 1.11.2: CPU using the following commands under Go 1.19.2:
``` ```
$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes' benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$')
$ go test -benchtime 10s -bench '/xxhash,direct,bytes' benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
``` ```
## Projects using this package ## Projects using this package

10
vendor/github.com/cespare/xxhash/v2/testall.sh generated vendored Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
set -eu -o pipefail
# Small convenience script for running the tests with various combinations of
# arch/tags. This assumes we're running on amd64 and have qemu available.
go test ./...
go test -tags purego ./...
GOARCH=arm64 go test
GOARCH=arm64 go test -tags purego

View File

@ -16,19 +16,11 @@ const (
prime5 uint64 = 2870177450012600261 prime5 uint64 = 2870177450012600261
) )
// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where // Store the primes in an array as well.
// possible in the Go code is worth a small (but measurable) performance boost //
// by avoiding some MOVQs. Vars are needed for the asm and also are useful for // The consts are used when possible in Go code to avoid MOVs but we need a
// convenience in the Go code in a few places where we need to intentionally // contiguous array of the assembly code.
// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5}
// result overflows a uint64).
var (
prime1v = prime1
prime2v = prime2
prime3v = prime3
prime4v = prime4
prime5v = prime5
)
// Digest implements hash.Hash64. // Digest implements hash.Hash64.
type Digest struct { type Digest struct {
@ -50,10 +42,10 @@ func New() *Digest {
// Reset clears the Digest's state so that it can be reused. // Reset clears the Digest's state so that it can be reused.
func (d *Digest) Reset() { func (d *Digest) Reset() {
d.v1 = prime1v + prime2 d.v1 = primes[0] + prime2
d.v2 = prime2 d.v2 = prime2
d.v3 = 0 d.v3 = 0
d.v4 = -prime1v d.v4 = -primes[0]
d.total = 0 d.total = 0
d.n = 0 d.n = 0
} }
@ -69,21 +61,23 @@ func (d *Digest) Write(b []byte) (n int, err error) {
n = len(b) n = len(b)
d.total += uint64(n) d.total += uint64(n)
memleft := d.mem[d.n&(len(d.mem)-1):]
if d.n+n < 32 { if d.n+n < 32 {
// This new data doesn't even fill the current block. // This new data doesn't even fill the current block.
copy(d.mem[d.n:], b) copy(memleft, b)
d.n += n d.n += n
return return
} }
if d.n > 0 { if d.n > 0 {
// Finish off the partial block. // Finish off the partial block.
copy(d.mem[d.n:], b) c := copy(memleft, b)
d.v1 = round(d.v1, u64(d.mem[0:8])) d.v1 = round(d.v1, u64(d.mem[0:8]))
d.v2 = round(d.v2, u64(d.mem[8:16])) d.v2 = round(d.v2, u64(d.mem[8:16]))
d.v3 = round(d.v3, u64(d.mem[16:24])) d.v3 = round(d.v3, u64(d.mem[16:24]))
d.v4 = round(d.v4, u64(d.mem[24:32])) d.v4 = round(d.v4, u64(d.mem[24:32]))
b = b[32-d.n:] b = b[c:]
d.n = 0 d.n = 0
} }
@ -133,21 +127,20 @@ func (d *Digest) Sum64() uint64 {
h += d.total h += d.total
i, end := 0, d.n b := d.mem[:d.n&(len(d.mem)-1)]
for ; i+8 <= end; i += 8 { for ; len(b) >= 8; b = b[8:] {
k1 := round(0, u64(d.mem[i:i+8])) k1 := round(0, u64(b[:8]))
h ^= k1 h ^= k1
h = rol27(h)*prime1 + prime4 h = rol27(h)*prime1 + prime4
} }
if i+4 <= end { if len(b) >= 4 {
h ^= uint64(u32(d.mem[i:i+4])) * prime1 h ^= uint64(u32(b[:4])) * prime1
h = rol23(h)*prime2 + prime3 h = rol23(h)*prime2 + prime3
i += 4 b = b[4:]
} }
for i < end { for ; len(b) > 0; b = b[1:] {
h ^= uint64(d.mem[i]) * prime5 h ^= uint64(b[0]) * prime5
h = rol11(h) * prime1 h = rol11(h) * prime1
i++
} }
h ^= h >> 33 h ^= h >> 33

View File

@ -1,215 +1,209 @@
//go:build !appengine && gc && !purego
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !purego // +build !purego
#include "textflag.h" #include "textflag.h"
// Register allocation: // Registers:
// AX h #define h AX
// SI pointer to advance through b #define d AX
// DX n #define p SI // pointer to advance through b
// BX loop end #define n DX
// R8 v1, k1 #define end BX // loop end
// R9 v2 #define v1 R8
// R10 v3 #define v2 R9
// R11 v4 #define v3 R10
// R12 tmp #define v4 R11
// R13 prime1v #define x R12
// R14 prime2v #define prime1 R13
// DI prime4v #define prime2 R14
#define prime4 DI
// round reads from and advances the buffer pointer in SI. #define round(acc, x) \
// It assumes that R13 has prime1v and R14 has prime2v. IMULQ prime2, x \
#define round(r) \ ADDQ x, acc \
MOVQ (SI), R12 \ ROLQ $31, acc \
ADDQ $8, SI \ IMULQ prime1, acc
IMULQ R14, R12 \
ADDQ R12, r \
ROLQ $31, r \
IMULQ R13, r
// mergeRound applies a merge round on the two registers acc and val. // round0 performs the operation x = round(0, x).
// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v. #define round0(x) \
#define mergeRound(acc, val) \ IMULQ prime2, x \
IMULQ R14, val \ ROLQ $31, x \
ROLQ $31, val \ IMULQ prime1, x
IMULQ R13, val \
XORQ val, acc \ // mergeRound applies a merge round on the two registers acc and x.
IMULQ R13, acc \ // It assumes that prime1, prime2, and prime4 have been loaded.
ADDQ DI, acc #define mergeRound(acc, x) \
round0(x) \
XORQ x, acc \
IMULQ prime1, acc \
ADDQ prime4, acc
// blockLoop processes as many 32-byte blocks as possible,
// updating v1, v2, v3, and v4. It assumes that there is at least one block
// to process.
#define blockLoop() \
loop: \
MOVQ +0(p), x \
round(v1, x) \
MOVQ +8(p), x \
round(v2, x) \
MOVQ +16(p), x \
round(v3, x) \
MOVQ +24(p), x \
round(v4, x) \
ADDQ $32, p \
CMPQ p, end \
JLE loop
// func Sum64(b []byte) uint64 // func Sum64(b []byte) uint64
TEXT ·Sum64(SB), NOSPLIT, $0-32 TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
// Load fixed primes. // Load fixed primes.
MOVQ ·prime1v(SB), R13 MOVQ ·primes+0(SB), prime1
MOVQ ·prime2v(SB), R14 MOVQ ·primes+8(SB), prime2
MOVQ ·prime4v(SB), DI MOVQ ·primes+24(SB), prime4
// Load slice. // Load slice.
MOVQ b_base+0(FP), SI MOVQ b_base+0(FP), p
MOVQ b_len+8(FP), DX MOVQ b_len+8(FP), n
LEAQ (SI)(DX*1), BX LEAQ (p)(n*1), end
// The first loop limit will be len(b)-32. // The first loop limit will be len(b)-32.
SUBQ $32, BX SUBQ $32, end
// Check whether we have at least one block. // Check whether we have at least one block.
CMPQ DX, $32 CMPQ n, $32
JLT noBlocks JLT noBlocks
// Set up initial state (v1, v2, v3, v4). // Set up initial state (v1, v2, v3, v4).
MOVQ R13, R8 MOVQ prime1, v1
ADDQ R14, R8 ADDQ prime2, v1
MOVQ R14, R9 MOVQ prime2, v2
XORQ R10, R10 XORQ v3, v3
XORQ R11, R11 XORQ v4, v4
SUBQ R13, R11 SUBQ prime1, v4
// Loop until SI > BX. blockLoop()
blockLoop:
round(R8)
round(R9)
round(R10)
round(R11)
CMPQ SI, BX MOVQ v1, h
JLE blockLoop ROLQ $1, h
MOVQ v2, x
ROLQ $7, x
ADDQ x, h
MOVQ v3, x
ROLQ $12, x
ADDQ x, h
MOVQ v4, x
ROLQ $18, x
ADDQ x, h
MOVQ R8, AX mergeRound(h, v1)
ROLQ $1, AX mergeRound(h, v2)
MOVQ R9, R12 mergeRound(h, v3)
ROLQ $7, R12 mergeRound(h, v4)
ADDQ R12, AX
MOVQ R10, R12
ROLQ $12, R12
ADDQ R12, AX
MOVQ R11, R12
ROLQ $18, R12
ADDQ R12, AX
mergeRound(AX, R8)
mergeRound(AX, R9)
mergeRound(AX, R10)
mergeRound(AX, R11)
JMP afterBlocks JMP afterBlocks
noBlocks: noBlocks:
MOVQ ·prime5v(SB), AX MOVQ ·primes+32(SB), h
afterBlocks: afterBlocks:
ADDQ DX, AX ADDQ n, h
// Right now BX has len(b)-32, and we want to loop until SI > len(b)-8. ADDQ $24, end
ADDQ $24, BX CMPQ p, end
JG try4
CMPQ SI, BX loop8:
JG fourByte MOVQ (p), x
ADDQ $8, p
round0(x)
XORQ x, h
ROLQ $27, h
IMULQ prime1, h
ADDQ prime4, h
wordLoop: CMPQ p, end
// Calculate k1. JLE loop8
MOVQ (SI), R8
ADDQ $8, SI
IMULQ R14, R8
ROLQ $31, R8
IMULQ R13, R8
XORQ R8, AX try4:
ROLQ $27, AX ADDQ $4, end
IMULQ R13, AX CMPQ p, end
ADDQ DI, AX JG try1
CMPQ SI, BX MOVL (p), x
JLE wordLoop ADDQ $4, p
IMULQ prime1, x
XORQ x, h
fourByte: ROLQ $23, h
ADDQ $4, BX IMULQ prime2, h
CMPQ SI, BX ADDQ ·primes+16(SB), h
JG singles
MOVL (SI), R8 try1:
ADDQ $4, SI ADDQ $4, end
IMULQ R13, R8 CMPQ p, end
XORQ R8, AX
ROLQ $23, AX
IMULQ R14, AX
ADDQ ·prime3v(SB), AX
singles:
ADDQ $4, BX
CMPQ SI, BX
JGE finalize JGE finalize
singlesLoop: loop1:
MOVBQZX (SI), R12 MOVBQZX (p), x
ADDQ $1, SI ADDQ $1, p
IMULQ ·prime5v(SB), R12 IMULQ ·primes+32(SB), x
XORQ R12, AX XORQ x, h
ROLQ $11, h
IMULQ prime1, h
ROLQ $11, AX CMPQ p, end
IMULQ R13, AX JL loop1
CMPQ SI, BX
JL singlesLoop
finalize: finalize:
MOVQ AX, R12 MOVQ h, x
SHRQ $33, R12 SHRQ $33, x
XORQ R12, AX XORQ x, h
IMULQ R14, AX IMULQ prime2, h
MOVQ AX, R12 MOVQ h, x
SHRQ $29, R12 SHRQ $29, x
XORQ R12, AX XORQ x, h
IMULQ ·prime3v(SB), AX IMULQ ·primes+16(SB), h
MOVQ AX, R12 MOVQ h, x
SHRQ $32, R12 SHRQ $32, x
XORQ R12, AX XORQ x, h
MOVQ AX, ret+24(FP) MOVQ h, ret+24(FP)
RET RET
// writeBlocks uses the same registers as above except that it uses AX to store
// the d pointer.
// func writeBlocks(d *Digest, b []byte) int // func writeBlocks(d *Digest, b []byte) int
TEXT ·writeBlocks(SB), NOSPLIT, $0-40 TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
// Load fixed primes needed for round. // Load fixed primes needed for round.
MOVQ ·prime1v(SB), R13 MOVQ ·primes+0(SB), prime1
MOVQ ·prime2v(SB), R14 MOVQ ·primes+8(SB), prime2
// Load slice. // Load slice.
MOVQ b_base+8(FP), SI MOVQ b_base+8(FP), p
MOVQ b_len+16(FP), DX MOVQ b_len+16(FP), n
LEAQ (SI)(DX*1), BX LEAQ (p)(n*1), end
SUBQ $32, BX SUBQ $32, end
// Load vN from d. // Load vN from d.
MOVQ d+0(FP), AX MOVQ s+0(FP), d
MOVQ 0(AX), R8 // v1 MOVQ 0(d), v1
MOVQ 8(AX), R9 // v2 MOVQ 8(d), v2
MOVQ 16(AX), R10 // v3 MOVQ 16(d), v3
MOVQ 24(AX), R11 // v4 MOVQ 24(d), v4
// We don't need to check the loop condition here; this function is // We don't need to check the loop condition here; this function is
// always called with at least one block of data to process. // always called with at least one block of data to process.
blockLoop: blockLoop()
round(R8)
round(R9)
round(R10)
round(R11)
CMPQ SI, BX
JLE blockLoop
// Copy vN back to d. // Copy vN back to d.
MOVQ R8, 0(AX) MOVQ v1, 0(d)
MOVQ R9, 8(AX) MOVQ v2, 8(d)
MOVQ R10, 16(AX) MOVQ v3, 16(d)
MOVQ R11, 24(AX) MOVQ v4, 24(d)
// The number of bytes written is SI minus the old base pointer. // The number of bytes written is p minus the old base pointer.
SUBQ b_base+8(FP), SI SUBQ b_base+8(FP), p
MOVQ SI, ret+32(FP) MOVQ p, ret+32(FP)
RET RET

183
vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s generated vendored Normal file
View File

@ -0,0 +1,183 @@
//go:build !appengine && gc && !purego
// +build !appengine
// +build gc
// +build !purego
#include "textflag.h"
// Registers:
#define digest R1
#define h R2 // return value
#define p R3 // input pointer
#define n R4 // input length
#define nblocks R5 // n / 32
#define prime1 R7
#define prime2 R8
#define prime3 R9
#define prime4 R10
#define prime5 R11
#define v1 R12
#define v2 R13
#define v3 R14
#define v4 R15
#define x1 R20
#define x2 R21
#define x3 R22
#define x4 R23
#define round(acc, x) \
MADD prime2, acc, x, acc \
ROR $64-31, acc \
MUL prime1, acc
// round0 performs the operation x = round(0, x).
#define round0(x) \
MUL prime2, x \
ROR $64-31, x \
MUL prime1, x
#define mergeRound(acc, x) \
round0(x) \
EOR x, acc \
MADD acc, prime4, prime1, acc
// blockLoop processes as many 32-byte blocks as possible,
// updating v1, v2, v3, and v4. It assumes that n >= 32.
#define blockLoop() \
LSR $5, n, nblocks \
PCALIGN $16 \
loop: \
LDP.P 16(p), (x1, x2) \
LDP.P 16(p), (x3, x4) \
round(v1, x1) \
round(v2, x2) \
round(v3, x3) \
round(v4, x4) \
SUB $1, nblocks \
CBNZ nblocks, loop
// func Sum64(b []byte) uint64
TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
LDP b_base+0(FP), (p, n)
LDP ·primes+0(SB), (prime1, prime2)
LDP ·primes+16(SB), (prime3, prime4)
MOVD ·primes+32(SB), prime5
CMP $32, n
CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 }
BLT afterLoop
ADD prime1, prime2, v1
MOVD prime2, v2
MOVD $0, v3
NEG prime1, v4
blockLoop()
ROR $64-1, v1, x1
ROR $64-7, v2, x2
ADD x1, x2
ROR $64-12, v3, x3
ROR $64-18, v4, x4
ADD x3, x4
ADD x2, x4, h
mergeRound(h, v1)
mergeRound(h, v2)
mergeRound(h, v3)
mergeRound(h, v4)
afterLoop:
ADD n, h
TBZ $4, n, try8
LDP.P 16(p), (x1, x2)
round0(x1)
// NOTE: here and below, sequencing the EOR after the ROR (using a
// rotated register) is worth a small but measurable speedup for small
// inputs.
ROR $64-27, h
EOR x1 @> 64-27, h, h
MADD h, prime4, prime1, h
round0(x2)
ROR $64-27, h
EOR x2 @> 64-27, h, h
MADD h, prime4, prime1, h
try8:
TBZ $3, n, try4
MOVD.P 8(p), x1
round0(x1)
ROR $64-27, h
EOR x1 @> 64-27, h, h
MADD h, prime4, prime1, h
try4:
TBZ $2, n, try2
MOVWU.P 4(p), x2
MUL prime1, x2
ROR $64-23, h
EOR x2 @> 64-23, h, h
MADD h, prime3, prime2, h
try2:
TBZ $1, n, try1
MOVHU.P 2(p), x3
AND $255, x3, x1
LSR $8, x3, x2
MUL prime5, x1
ROR $64-11, h
EOR x1 @> 64-11, h, h
MUL prime1, h
MUL prime5, x2
ROR $64-11, h
EOR x2 @> 64-11, h, h
MUL prime1, h
try1:
TBZ $0, n, finalize
MOVBU (p), x4
MUL prime5, x4
ROR $64-11, h
EOR x4 @> 64-11, h, h
MUL prime1, h
finalize:
EOR h >> 33, h
MUL prime2, h
EOR h >> 29, h
MUL prime3, h
EOR h >> 32, h
MOVD h, ret+24(FP)
RET
// func writeBlocks(d *Digest, b []byte) int
TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
LDP ·primes+0(SB), (prime1, prime2)
// Load state. Assume v[1-4] are stored contiguously.
MOVD d+0(FP), digest
LDP 0(digest), (v1, v2)
LDP 16(digest), (v3, v4)
LDP b_base+8(FP), (p, n)
blockLoop()
// Store updated state.
STP (v1, v2), 0(digest)
STP (v3, v4), 16(digest)
BIC $31, n
MOVD n, ret+32(FP)
RET

View File

@ -1,3 +1,5 @@
//go:build (amd64 || arm64) && !appengine && gc && !purego
// +build amd64 arm64
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !purego // +build !purego

View File

@ -1,4 +1,5 @@
// +build !amd64 appengine !gc purego //go:build (!amd64 && !arm64) || appengine || !gc || purego
// +build !amd64,!arm64 appengine !gc purego
package xxhash package xxhash
@ -14,10 +15,10 @@ func Sum64(b []byte) uint64 {
var h uint64 var h uint64
if n >= 32 { if n >= 32 {
v1 := prime1v + prime2 v1 := primes[0] + prime2
v2 := prime2 v2 := prime2
v3 := uint64(0) v3 := uint64(0)
v4 := -prime1v v4 := -primes[0]
for len(b) >= 32 { for len(b) >= 32 {
v1 = round(v1, u64(b[0:8:len(b)])) v1 = round(v1, u64(b[0:8:len(b)]))
v2 = round(v2, u64(b[8:16:len(b)])) v2 = round(v2, u64(b[8:16:len(b)]))
@ -36,19 +37,18 @@ func Sum64(b []byte) uint64 {
h += uint64(n) h += uint64(n)
i, end := 0, len(b) for ; len(b) >= 8; b = b[8:] {
for ; i+8 <= end; i += 8 { k1 := round(0, u64(b[:8]))
k1 := round(0, u64(b[i:i+8:len(b)]))
h ^= k1 h ^= k1
h = rol27(h)*prime1 + prime4 h = rol27(h)*prime1 + prime4
} }
if i+4 <= end { if len(b) >= 4 {
h ^= uint64(u32(b[i:i+4:len(b)])) * prime1 h ^= uint64(u32(b[:4])) * prime1
h = rol23(h)*prime2 + prime3 h = rol23(h)*prime2 + prime3
i += 4 b = b[4:]
} }
for ; i < end; i++ { for ; len(b) > 0; b = b[1:] {
h ^= uint64(b[i]) * prime5 h ^= uint64(b[0]) * prime5
h = rol11(h) * prime1 h = rol11(h) * prime1
} }

View File

@ -1,3 +1,4 @@
//go:build appengine
// +build appengine // +build appengine
// This file contains the safe implementations of otherwise unsafe-using code. // This file contains the safe implementations of otherwise unsafe-using code.

View File

@ -1,3 +1,4 @@
//go:build !appengine
// +build !appengine // +build !appengine
// This file encapsulates usage of unsafe. // This file encapsulates usage of unsafe.
@ -11,7 +12,7 @@ import (
// In the future it's possible that compiler optimizations will make these // In the future it's possible that compiler optimizations will make these
// XxxString functions unnecessary by realizing that calls such as // XxxString functions unnecessary by realizing that calls such as
// Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205. // Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205.
// If that happens, even if we keep these functions they can be replaced with // If that happens, even if we keep these functions they can be replaced with
// the trivial safe code. // the trivial safe code.

View File

@ -1,4 +1,4 @@
// Copyright 2020 Google LLC // Copyright 2022 Google LLC
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.12.2 // protoc v3.21.9
// source: google/rpc/error_details.proto // source: google/rpc/error_details.proto
package errdetails package errdetails
@ -36,6 +36,112 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
// Describes the cause of the error with structured details.
//
// Example of an error when contacting the "pubsub.googleapis.com" API when it
// is not enabled:
//
// { "reason": "API_DISABLED"
// "domain": "googleapis.com"
// "metadata": {
// "resource": "projects/123",
// "service": "pubsub.googleapis.com"
// }
// }
//
// This response indicates that the pubsub.googleapis.com API is not enabled.
//
// Example of an error that is returned when attempting to create a Spanner
// instance in a region that is out of stock:
//
// { "reason": "STOCKOUT"
// "domain": "spanner.googleapis.com",
// "metadata": {
// "availableRegions": "us-central1,us-east2"
// }
// }
type ErrorInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The reason of the error. This is a constant value that identifies the
// proximate cause of the error. Error reasons are unique within a particular
// domain of errors. This should be at most 63 characters and match a
// regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, which represents
// UPPER_SNAKE_CASE.
Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"`
// The logical grouping to which the "reason" belongs. The error domain
// is typically the registered service name of the tool or product that
// generates the error. Example: "pubsub.googleapis.com". If the error is
// generated by some common infrastructure, the error domain must be a
// globally unique value that identifies the infrastructure. For Google API
// infrastructure, the error domain is "googleapis.com".
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
// Additional structured details about this error.
//
// Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in
// length. When identifying the current value of an exceeded limit, the units
// should be contained in the key, not the value. For example, rather than
// {"instanceLimit": "100/request"}, should be returned as,
// {"instanceLimitPerRequest": "100"}, if the client exceeds the number of
// instances that can be created in a single (batch) request.
Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *ErrorInfo) Reset() {
*x = ErrorInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ErrorInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ErrorInfo) ProtoMessage() {}
func (x *ErrorInfo) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead.
func (*ErrorInfo) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{0}
}
func (x *ErrorInfo) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
func (x *ErrorInfo) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (x *ErrorInfo) GetMetadata() map[string]string {
if x != nil {
return x.Metadata
}
return nil
}
// Describes when the clients can retry a failed request. Clients could ignore // Describes when the clients can retry a failed request. Clients could ignore
// the recommendation here or retry when this information is missing from error // the recommendation here or retry when this information is missing from error
// responses. // responses.
@ -61,7 +167,7 @@ type RetryInfo struct {
func (x *RetryInfo) Reset() { func (x *RetryInfo) Reset() {
*x = RetryInfo{} *x = RetryInfo{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[0] mi := &file_google_rpc_error_details_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -74,7 +180,7 @@ func (x *RetryInfo) String() string {
func (*RetryInfo) ProtoMessage() {} func (*RetryInfo) ProtoMessage() {}
func (x *RetryInfo) ProtoReflect() protoreflect.Message { func (x *RetryInfo) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[0] mi := &file_google_rpc_error_details_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -87,7 +193,7 @@ func (x *RetryInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use RetryInfo.ProtoReflect.Descriptor instead. // Deprecated: Use RetryInfo.ProtoReflect.Descriptor instead.
func (*RetryInfo) Descriptor() ([]byte, []int) { func (*RetryInfo) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{0} return file_google_rpc_error_details_proto_rawDescGZIP(), []int{1}
} }
func (x *RetryInfo) GetRetryDelay() *durationpb.Duration { func (x *RetryInfo) GetRetryDelay() *durationpb.Duration {
@ -112,7 +218,7 @@ type DebugInfo struct {
func (x *DebugInfo) Reset() { func (x *DebugInfo) Reset() {
*x = DebugInfo{} *x = DebugInfo{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[1] mi := &file_google_rpc_error_details_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -125,7 +231,7 @@ func (x *DebugInfo) String() string {
func (*DebugInfo) ProtoMessage() {} func (*DebugInfo) ProtoMessage() {}
func (x *DebugInfo) ProtoReflect() protoreflect.Message { func (x *DebugInfo) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[1] mi := &file_google_rpc_error_details_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -138,7 +244,7 @@ func (x *DebugInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use DebugInfo.ProtoReflect.Descriptor instead. // Deprecated: Use DebugInfo.ProtoReflect.Descriptor instead.
func (*DebugInfo) Descriptor() ([]byte, []int) { func (*DebugInfo) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{1} return file_google_rpc_error_details_proto_rawDescGZIP(), []int{2}
} }
func (x *DebugInfo) GetStackEntries() []string { func (x *DebugInfo) GetStackEntries() []string {
@ -178,7 +284,7 @@ type QuotaFailure struct {
func (x *QuotaFailure) Reset() { func (x *QuotaFailure) Reset() {
*x = QuotaFailure{} *x = QuotaFailure{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[2] mi := &file_google_rpc_error_details_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -191,7 +297,7 @@ func (x *QuotaFailure) String() string {
func (*QuotaFailure) ProtoMessage() {} func (*QuotaFailure) ProtoMessage() {}
func (x *QuotaFailure) ProtoReflect() protoreflect.Message { func (x *QuotaFailure) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[2] mi := &file_google_rpc_error_details_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -204,7 +310,7 @@ func (x *QuotaFailure) ProtoReflect() protoreflect.Message {
// Deprecated: Use QuotaFailure.ProtoReflect.Descriptor instead. // Deprecated: Use QuotaFailure.ProtoReflect.Descriptor instead.
func (*QuotaFailure) Descriptor() ([]byte, []int) { func (*QuotaFailure) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{2} return file_google_rpc_error_details_proto_rawDescGZIP(), []int{3}
} }
func (x *QuotaFailure) GetViolations() []*QuotaFailure_Violation { func (x *QuotaFailure) GetViolations() []*QuotaFailure_Violation {
@ -214,111 +320,6 @@ func (x *QuotaFailure) GetViolations() []*QuotaFailure_Violation {
return nil return nil
} }
// Describes the cause of the error with structured details.
//
// Example of an error when contacting the "pubsub.googleapis.com" API when it
// is not enabled:
//
// { "reason": "API_DISABLED"
// "domain": "googleapis.com"
// "metadata": {
// "resource": "projects/123",
// "service": "pubsub.googleapis.com"
// }
// }
//
// This response indicates that the pubsub.googleapis.com API is not enabled.
//
// Example of an error that is returned when attempting to create a Spanner
// instance in a region that is out of stock:
//
// { "reason": "STOCKOUT"
// "domain": "spanner.googleapis.com",
// "metadata": {
// "availableRegions": "us-central1,us-east2"
// }
// }
type ErrorInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The reason of the error. This is a constant value that identifies the
// proximate cause of the error. Error reasons are unique within a particular
// domain of errors. This should be at most 63 characters and match
// /[A-Z0-9_]+/.
Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"`
// The logical grouping to which the "reason" belongs. The error domain
// is typically the registered service name of the tool or product that
// generates the error. Example: "pubsub.googleapis.com". If the error is
// generated by some common infrastructure, the error domain must be a
// globally unique value that identifies the infrastructure. For Google API
// infrastructure, the error domain is "googleapis.com".
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
// Additional structured details about this error.
//
// Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in
// length. When identifying the current value of an exceeded limit, the units
// should be contained in the key, not the value. For example, rather than
// {"instanceLimit": "100/request"}, should be returned as,
// {"instanceLimitPerRequest": "100"}, if the client exceeds the number of
// instances that can be created in a single (batch) request.
Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *ErrorInfo) Reset() {
*x = ErrorInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ErrorInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ErrorInfo) ProtoMessage() {}
func (x *ErrorInfo) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead.
func (*ErrorInfo) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{3}
}
func (x *ErrorInfo) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
func (x *ErrorInfo) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (x *ErrorInfo) GetMetadata() map[string]string {
if x != nil {
return x.Metadata
}
return nil
}
// Describes what preconditions have failed. // Describes what preconditions have failed.
// //
// For example, if an RPC failed because it required the Terms of Service to be // For example, if an RPC failed because it required the Terms of Service to be
@ -495,7 +496,8 @@ type ResourceInfo struct {
ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"`
// The name of the resource being accessed. For example, a shared calendar // The name of the resource being accessed. For example, a shared calendar
// name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
// error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. // error is
// [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
ResourceName string `protobuf:"bytes,2,opt,name=resource_name,json=resourceName,proto3" json:"resource_name,omitempty"` ResourceName string `protobuf:"bytes,2,opt,name=resource_name,json=resourceName,proto3" json:"resource_name,omitempty"`
// The owner of the resource (optional). // The owner of the resource (optional).
// For example, "user:<owner email>" or "project:<Google developer project // For example, "user:<owner email>" or "project:<Google developer project
@ -628,7 +630,7 @@ type LocalizedMessage struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// The locale used following the specification defined at // The locale used following the specification defined at
// http://www.rfc-editor.org/rfc/bcp/bcp47.txt. // https://www.rfc-editor.org/rfc/bcp/bcp47.txt.
// Examples are: "en-US", "fr-CH", "es-MX" // Examples are: "en-US", "fr-CH", "es-MX"
Locale string `protobuf:"bytes,1,opt,name=locale,proto3" json:"locale,omitempty"` Locale string `protobuf:"bytes,1,opt,name=locale,proto3" json:"locale,omitempty"`
// The localized error message in the above locale. // The localized error message in the above locale.
@ -705,7 +707,7 @@ type QuotaFailure_Violation struct {
func (x *QuotaFailure_Violation) Reset() { func (x *QuotaFailure_Violation) Reset() {
*x = QuotaFailure_Violation{} *x = QuotaFailure_Violation{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_google_rpc_error_details_proto_msgTypes[10] mi := &file_google_rpc_error_details_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -718,7 +720,7 @@ func (x *QuotaFailure_Violation) String() string {
func (*QuotaFailure_Violation) ProtoMessage() {} func (*QuotaFailure_Violation) ProtoMessage() {}
func (x *QuotaFailure_Violation) ProtoReflect() protoreflect.Message { func (x *QuotaFailure_Violation) ProtoReflect() protoreflect.Message {
mi := &file_google_rpc_error_details_proto_msgTypes[10] mi := &file_google_rpc_error_details_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -731,7 +733,7 @@ func (x *QuotaFailure_Violation) ProtoReflect() protoreflect.Message {
// Deprecated: Use QuotaFailure_Violation.ProtoReflect.Descriptor instead. // Deprecated: Use QuotaFailure_Violation.ProtoReflect.Descriptor instead.
func (*QuotaFailure_Violation) Descriptor() ([]byte, []int) { func (*QuotaFailure_Violation) Descriptor() ([]byte, []int) {
return file_google_rpc_error_details_proto_rawDescGZIP(), []int{2, 0} return file_google_rpc_error_details_proto_rawDescGZIP(), []int{3, 0}
} }
func (x *QuotaFailure_Violation) GetSubject() string { func (x *QuotaFailure_Violation) GetSubject() string {
@ -828,9 +830,43 @@ type BadRequest_FieldViolation struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// A path leading to a field in the request body. The value will be a // A path that leads to a field in the request body. The value will be a
// sequence of dot-separated identifiers that identify a protocol buffer // sequence of dot-separated identifiers that identify a protocol buffer
// field. E.g., "field_violations.field" would identify this field. // field.
//
// Consider the following:
//
// message CreateContactRequest {
// message EmailAddress {
// enum Type {
// TYPE_UNSPECIFIED = 0;
// HOME = 1;
// WORK = 2;
// }
//
// optional string email = 1;
// repeated EmailType type = 2;
// }
//
// string full_name = 1;
// repeated EmailAddress email_addresses = 2;
// }
//
// In this example, in proto `field` could take one of the following values:
//
// - `full_name` for a violation in the `full_name` value
// - `email_addresses[1].email` for a violation in the `email` field of the
// first `email_addresses` message
// - `email_addresses[3].type[2]` for a violation in the second `type`
// value in the third `email_addresses` message.
//
// In JSON, the same values are represented as:
//
// - `fullName` for a violation in the `fullName` value
// - `emailAddresses[1].email` for a violation in the `email` field of the
// first `emailAddresses` message
// - `emailAddresses[3].type[2]` for a violation in the second `type`
// value in the third `emailAddresses` message.
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"` Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
// A description of why the request element is bad. // A description of why the request element is bad.
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
@ -947,38 +983,38 @@ var file_google_rpc_error_details_proto_rawDesc = []byte{
0x6f, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x1a, 0x1e, 0x67, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x1a, 0x1e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x47, 0x0a, 0x09, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a,
0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3a, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65,
0x72, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x6d, 0x65,
0x44, 0x65, 0x6c, 0x61, 0x79, 0x22, 0x48, 0x0a, 0x09, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67,
0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49,
0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72,
0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d,
0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x9b, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
0x12, 0x42, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72,
0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3a, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64,
0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x47, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61,
0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x79, 0x22, 0x48, 0x0a, 0x09, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18,
0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x01, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x45, 0x6e, 0x74, 0x72,
0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x69, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20,
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x9b, 0x01, 0x0a, 0x0c,
0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x0a,
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x6d, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61,
0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x1a, 0x47, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a,
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbd, 0x01, 0x0a, 0x13, 0x50, 0x72, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xbd, 0x01, 0x0a, 0x13, 0x50, 0x72,
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72,
0x65, 0x12, 0x49, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72,
@ -1051,27 +1087,27 @@ func file_google_rpc_error_details_proto_rawDescGZIP() []byte {
var file_google_rpc_error_details_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_google_rpc_error_details_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
var file_google_rpc_error_details_proto_goTypes = []interface{}{ var file_google_rpc_error_details_proto_goTypes = []interface{}{
(*RetryInfo)(nil), // 0: google.rpc.RetryInfo (*ErrorInfo)(nil), // 0: google.rpc.ErrorInfo
(*DebugInfo)(nil), // 1: google.rpc.DebugInfo (*RetryInfo)(nil), // 1: google.rpc.RetryInfo
(*QuotaFailure)(nil), // 2: google.rpc.QuotaFailure (*DebugInfo)(nil), // 2: google.rpc.DebugInfo
(*ErrorInfo)(nil), // 3: google.rpc.ErrorInfo (*QuotaFailure)(nil), // 3: google.rpc.QuotaFailure
(*PreconditionFailure)(nil), // 4: google.rpc.PreconditionFailure (*PreconditionFailure)(nil), // 4: google.rpc.PreconditionFailure
(*BadRequest)(nil), // 5: google.rpc.BadRequest (*BadRequest)(nil), // 5: google.rpc.BadRequest
(*RequestInfo)(nil), // 6: google.rpc.RequestInfo (*RequestInfo)(nil), // 6: google.rpc.RequestInfo
(*ResourceInfo)(nil), // 7: google.rpc.ResourceInfo (*ResourceInfo)(nil), // 7: google.rpc.ResourceInfo
(*Help)(nil), // 8: google.rpc.Help (*Help)(nil), // 8: google.rpc.Help
(*LocalizedMessage)(nil), // 9: google.rpc.LocalizedMessage (*LocalizedMessage)(nil), // 9: google.rpc.LocalizedMessage
(*QuotaFailure_Violation)(nil), // 10: google.rpc.QuotaFailure.Violation nil, // 10: google.rpc.ErrorInfo.MetadataEntry
nil, // 11: google.rpc.ErrorInfo.MetadataEntry (*QuotaFailure_Violation)(nil), // 11: google.rpc.QuotaFailure.Violation
(*PreconditionFailure_Violation)(nil), // 12: google.rpc.PreconditionFailure.Violation (*PreconditionFailure_Violation)(nil), // 12: google.rpc.PreconditionFailure.Violation
(*BadRequest_FieldViolation)(nil), // 13: google.rpc.BadRequest.FieldViolation (*BadRequest_FieldViolation)(nil), // 13: google.rpc.BadRequest.FieldViolation
(*Help_Link)(nil), // 14: google.rpc.Help.Link (*Help_Link)(nil), // 14: google.rpc.Help.Link
(*durationpb.Duration)(nil), // 15: google.protobuf.Duration (*durationpb.Duration)(nil), // 15: google.protobuf.Duration
} }
var file_google_rpc_error_details_proto_depIdxs = []int32{ var file_google_rpc_error_details_proto_depIdxs = []int32{
15, // 0: google.rpc.RetryInfo.retry_delay:type_name -> google.protobuf.Duration 10, // 0: google.rpc.ErrorInfo.metadata:type_name -> google.rpc.ErrorInfo.MetadataEntry
10, // 1: google.rpc.QuotaFailure.violations:type_name -> google.rpc.QuotaFailure.Violation 15, // 1: google.rpc.RetryInfo.retry_delay:type_name -> google.protobuf.Duration
11, // 2: google.rpc.ErrorInfo.metadata:type_name -> google.rpc.ErrorInfo.MetadataEntry 11, // 2: google.rpc.QuotaFailure.violations:type_name -> google.rpc.QuotaFailure.Violation
12, // 3: google.rpc.PreconditionFailure.violations:type_name -> google.rpc.PreconditionFailure.Violation 12, // 3: google.rpc.PreconditionFailure.violations:type_name -> google.rpc.PreconditionFailure.Violation
13, // 4: google.rpc.BadRequest.field_violations:type_name -> google.rpc.BadRequest.FieldViolation 13, // 4: google.rpc.BadRequest.field_violations:type_name -> google.rpc.BadRequest.FieldViolation
14, // 5: google.rpc.Help.links:type_name -> google.rpc.Help.Link 14, // 5: google.rpc.Help.links:type_name -> google.rpc.Help.Link
@ -1089,7 +1125,7 @@ func file_google_rpc_error_details_proto_init() {
} }
if !protoimpl.UnsafeEnabled { if !protoimpl.UnsafeEnabled {
file_google_rpc_error_details_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { file_google_rpc_error_details_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RetryInfo); i { switch v := v.(*ErrorInfo); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1101,7 +1137,7 @@ func file_google_rpc_error_details_proto_init() {
} }
} }
file_google_rpc_error_details_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { file_google_rpc_error_details_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DebugInfo); i { switch v := v.(*RetryInfo); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1113,7 +1149,7 @@ func file_google_rpc_error_details_proto_init() {
} }
} }
file_google_rpc_error_details_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { file_google_rpc_error_details_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QuotaFailure); i { switch v := v.(*DebugInfo); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1125,7 +1161,7 @@ func file_google_rpc_error_details_proto_init() {
} }
} }
file_google_rpc_error_details_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { file_google_rpc_error_details_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ErrorInfo); i { switch v := v.(*QuotaFailure); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1208,7 +1244,7 @@ func file_google_rpc_error_details_proto_init() {
return nil return nil
} }
} }
file_google_rpc_error_details_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { file_google_rpc_error_details_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QuotaFailure_Violation); i { switch v := v.(*QuotaFailure_Violation); i {
case 0: case 0:
return &v.state return &v.state

View File

@ -1,4 +1,4 @@
// Copyright 2020 Google LLC // Copyright 2022 Google LLC
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.12.2 // protoc v3.21.9
// source: google/rpc/status.proto // source: google/rpc/status.proto
package status package status
@ -48,11 +48,13 @@ type Status struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. // The status code, which should be an enum value of
// [google.rpc.Code][google.rpc.Code].
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
// A developer-facing error message, which should be in English. Any // A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the // user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. // [google.rpc.Status.details][google.rpc.Status.details] field, or localized
// by the client.
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// A list of messages that carry the error details. There is a common set of // A list of messages that carry the error details. There is a common set of
// message types for APIs to use. // message types for APIs to use.

View File

@ -279,6 +279,14 @@ type PickResult struct {
// type, Done may not be called. May be nil if the balancer does not wish // type, Done may not be called. May be nil if the balancer does not wish
// to be notified when the RPC completes. // to be notified when the RPC completes.
Done func(DoneInfo) Done func(DoneInfo)
// Metadata provides a way for LB policies to inject arbitrary per-call
// metadata. Any metadata returned here will be merged with existing
// metadata added by the client application.
//
// LB policies with child policies are responsible for propagating metadata
// injected by their children to the ClientConn, as part of Pick().
Metatada metadata.MD
} }
// TransientFailureError returns e. It exists for backward compatibility and // TransientFailureError returns e. It exists for backward compatibility and

View File

@ -256,7 +256,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
if err != nil { if err != nil {
return nil, err return nil, err
} }
cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint, cc.target, cc.dopts) cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint(), cc.target, cc.dopts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -934,7 +934,7 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
return cc.sc.healthCheckConfig return cc.sc.healthCheckConfig
} }
func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) { func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
return cc.blockingpicker.pick(ctx, failfast, balancer.PickInfo{ return cc.blockingpicker.pick(ctx, failfast, balancer.PickInfo{
Ctx: ctx, Ctx: ctx,
FullMethodName: method, FullMethodName: method,
@ -1237,9 +1237,11 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
addr.ServerName = ac.cc.getServerName(addr) addr.ServerName = ac.cc.getServerName(addr)
hctx, hcancel := context.WithCancel(ac.ctx) hctx, hcancel := context.WithCancel(ac.ctx)
onClose := grpcsync.OnceFunc(func() { onClose := func(r transport.GoAwayReason) {
ac.mu.Lock() ac.mu.Lock()
defer ac.mu.Unlock() defer ac.mu.Unlock()
// adjust params based on GoAwayReason
ac.adjustParams(r)
if ac.state == connectivity.Shutdown { if ac.state == connectivity.Shutdown {
// Already shut down. tearDown() already cleared the transport and // Already shut down. tearDown() already cleared the transport and
// canceled hctx via ac.ctx, and we expected this connection to be // canceled hctx via ac.ctx, and we expected this connection to be
@ -1260,19 +1262,13 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
// Always go idle and wait for the LB policy to initiate a new // Always go idle and wait for the LB policy to initiate a new
// connection attempt. // connection attempt.
ac.updateConnectivityState(connectivity.Idle, nil) ac.updateConnectivityState(connectivity.Idle, nil)
})
onGoAway := func(r transport.GoAwayReason) {
ac.mu.Lock()
ac.adjustParams(r)
ac.mu.Unlock()
onClose()
} }
connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline) connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline)
defer cancel() defer cancel()
copts.ChannelzParentID = ac.channelzID copts.ChannelzParentID = ac.channelzID
newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, addr, copts, onGoAway, onClose) newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, addr, copts, onClose)
if err != nil { if err != nil {
if logger.V(2) { if logger.V(2) {
logger.Infof("Creating new client transport to %q: %v", addr, err) logger.Infof("Creating new client transport to %q: %v", addr, err)
@ -1380,7 +1376,7 @@ func (ac *addrConn) startHealthCheck(ctx context.Context) {
if status.Code(err) == codes.Unimplemented { if status.Code(err) == codes.Unimplemented {
channelz.Error(logger, ac.channelzID, "Subchannel health check is unimplemented at server side, thus health check is disabled") channelz.Error(logger, ac.channelzID, "Subchannel health check is unimplemented at server side, thus health check is disabled")
} else { } else {
channelz.Errorf(logger, ac.channelzID, "HealthCheckFunc exits with unexpected error %v", err) channelz.Errorf(logger, ac.channelzID, "Health checking failed: %v", err)
} }
} }
}() }()
@ -1591,30 +1587,17 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) {
} }
// parseTarget uses RFC 3986 semantics to parse the given target into a // parseTarget uses RFC 3986 semantics to parse the given target into a
// resolver.Target struct containing scheme, authority and endpoint. Query // resolver.Target struct containing scheme, authority and url. Query
// params are stripped from the endpoint. // params are stripped from the endpoint.
func parseTarget(target string) (resolver.Target, error) { func parseTarget(target string) (resolver.Target, error) {
u, err := url.Parse(target) u, err := url.Parse(target)
if err != nil { if err != nil {
return resolver.Target{}, err return resolver.Target{}, err
} }
// For targets of the form "[scheme]://[authority]/endpoint, the endpoint
// value returned from url.Parse() contains a leading "/". Although this is
// in accordance with RFC 3986, we do not want to break existing resolver
// implementations which expect the endpoint without the leading "/". So, we
// end up stripping the leading "/" here. But this will result in an
// incorrect parsing for something like "unix:///path/to/socket". Since we
// own the "unix" resolver, we can workaround in the unix resolver by using
// the `URL` field instead of the `Endpoint` field.
endpoint := u.Path
if endpoint == "" {
endpoint = u.Opaque
}
endpoint = strings.TrimPrefix(endpoint, "/")
return resolver.Target{ return resolver.Target{
Scheme: u.Scheme, Scheme: u.Scheme,
Authority: u.Host, Authority: u.Host,
Endpoint: endpoint,
URL: *u, URL: *u,
}, nil }, nil
} }

View File

@ -23,9 +23,9 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"net/url" "net/url"
"os"
credinternal "google.golang.org/grpc/internal/credentials" credinternal "google.golang.org/grpc/internal/credentials"
) )
@ -166,7 +166,7 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
// it will override the virtual host name of authority (e.g. :authority header // it will override the virtual host name of authority (e.g. :authority header
// field) in requests. // field) in requests.
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) { func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
b, err := ioutil.ReadFile(certFile) b, err := os.ReadFile(certFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -44,6 +44,7 @@ func init() {
extraDialOptions = nil extraDialOptions = nil
} }
internal.WithBinaryLogger = withBinaryLogger internal.WithBinaryLogger = withBinaryLogger
internal.JoinDialOptions = newJoinDialOption
} }
// dialOptions configure a Dial call. dialOptions are set by the DialOption // dialOptions configure a Dial call. dialOptions are set by the DialOption
@ -111,6 +112,20 @@ func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
} }
} }
type joinDialOption struct {
opts []DialOption
}
func (jdo *joinDialOption) apply(do *dialOptions) {
for _, opt := range jdo.opts {
opt.apply(do)
}
}
func newJoinDialOption(opts ...DialOption) DialOption {
return &joinDialOption{opts: opts}
}
// WithWriteBufferSize determines how much data can be batched before doing a // WithWriteBufferSize determines how much data can be batched before doing a
// write on the wire. The corresponding memory allocation for this buffer will // write on the wire. The corresponding memory allocation for this buffer will
// be twice the size to keep syscalls low. The default value for this buffer is // be twice the size to keep syscalls low. The default value for this buffer is

View File

@ -75,8 +75,10 @@ var registeredCompressor = make(map[string]Compressor)
// registered with the same name, the one registered last will take effect. // registered with the same name, the one registered last will take effect.
func RegisterCompressor(c Compressor) { func RegisterCompressor(c Compressor) {
registeredCompressor[c.Name()] = c registeredCompressor[c.Name()] = c
if !grpcutil.IsCompressorNameRegistered(c.Name()) {
grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name()) grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name())
} }
}
// GetCompressor returns Compressor for the given compressor name. // GetCompressor returns Compressor for the given compressor name.
func GetCompressor(name string) Compressor { func GetCompressor(name string) Compressor {

View File

@ -30,7 +30,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"sync" "sync"
"google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding"
@ -42,7 +41,7 @@ const Name = "gzip"
func init() { func init() {
c := &compressor{} c := &compressor{}
c.poolCompressor.New = func() interface{} { c.poolCompressor.New = func() interface{} {
return &writer{Writer: gzip.NewWriter(ioutil.Discard), pool: &c.poolCompressor} return &writer{Writer: gzip.NewWriter(io.Discard), pool: &c.poolCompressor}
} }
encoding.RegisterCompressor(c) encoding.RegisterCompressor(c)
} }
@ -63,7 +62,7 @@ func SetLevel(level int) error {
} }
c := encoding.GetCompressor(Name).(*compressor) c := encoding.GetCompressor(Name).(*compressor)
c.poolCompressor.New = func() interface{} { c.poolCompressor.New = func() interface{} {
w, err := gzip.NewWriterLevel(ioutil.Discard, level) w, err := gzip.NewWriterLevel(io.Discard, level)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -22,7 +22,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"os" "os"
"strconv" "strconv"
@ -140,9 +139,9 @@ func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config)
// newLoggerV2 creates a loggerV2 to be used as default logger. // newLoggerV2 creates a loggerV2 to be used as default logger.
// All logs are written to stderr. // All logs are written to stderr.
func newLoggerV2() LoggerV2 { func newLoggerV2() LoggerV2 {
errorW := ioutil.Discard errorW := io.Discard
warningW := ioutil.Discard warningW := io.Discard
infoW := ioutil.Discard infoW := io.Discard
logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
switch logLevel { switch logLevel {

View File

@ -26,7 +26,7 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes"
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
@ -79,7 +79,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
// Build is an internal only method for building the proto message out of the // Build is an internal only method for building the proto message out of the
// input event. It's made public to enable other library to reuse as much logic // input event. It's made public to enable other library to reuse as much logic
// in TruncatingMethodLogger as possible. // in TruncatingMethodLogger as possible.
func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry { func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry {
m := c.toProto() m := c.toProto()
timestamp, _ := ptypes.TimestampProto(time.Now()) timestamp, _ := ptypes.TimestampProto(time.Now())
m.Timestamp = timestamp m.Timestamp = timestamp
@ -87,11 +87,11 @@ func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
m.SequenceIdWithinCall = ml.idWithinCallGen.next() m.SequenceIdWithinCall = ml.idWithinCallGen.next()
switch pay := m.Payload.(type) { switch pay := m.Payload.(type) {
case *pb.GrpcLogEntry_ClientHeader: case *binlogpb.GrpcLogEntry_ClientHeader:
m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata()) m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
case *pb.GrpcLogEntry_ServerHeader: case *binlogpb.GrpcLogEntry_ServerHeader:
m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata()) m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
case *pb.GrpcLogEntry_Message: case *binlogpb.GrpcLogEntry_Message:
m.PayloadTruncated = ml.truncateMessage(pay.Message) m.PayloadTruncated = ml.truncateMessage(pay.Message)
} }
return m return m
@ -102,7 +102,7 @@ func (ml *TruncatingMethodLogger) Log(c LogEntryConfig) {
ml.sink.Write(ml.Build(c)) ml.sink.Write(ml.Build(c))
} }
func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) { func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *binlogpb.Metadata) (truncated bool) {
if ml.headerMaxLen == maxUInt { if ml.headerMaxLen == maxUInt {
return false return false
} }
@ -132,7 +132,7 @@ func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated
return truncated return truncated
} }
func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) { func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (truncated bool) {
if ml.messageMaxLen == maxUInt { if ml.messageMaxLen == maxUInt {
return false return false
} }
@ -145,7 +145,7 @@ func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated
// LogEntryConfig represents the configuration for binary log entry. // LogEntryConfig represents the configuration for binary log entry.
type LogEntryConfig interface { type LogEntryConfig interface {
toProto() *pb.GrpcLogEntry toProto() *binlogpb.GrpcLogEntry
} }
// ClientHeader configs the binary log entry to be a ClientHeader entry. // ClientHeader configs the binary log entry to be a ClientHeader entry.
@ -159,10 +159,10 @@ type ClientHeader struct {
PeerAddr net.Addr PeerAddr net.Addr
} }
func (c *ClientHeader) toProto() *pb.GrpcLogEntry { func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry {
// This function doesn't need to set all the fields (e.g. seq ID). The Log // This function doesn't need to set all the fields (e.g. seq ID). The Log
// function will set the fields when necessary. // function will set the fields when necessary.
clientHeader := &pb.ClientHeader{ clientHeader := &binlogpb.ClientHeader{
Metadata: mdToMetadataProto(c.Header), Metadata: mdToMetadataProto(c.Header),
MethodName: c.MethodName, MethodName: c.MethodName,
Authority: c.Authority, Authority: c.Authority,
@ -170,16 +170,16 @@ func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
if c.Timeout > 0 { if c.Timeout > 0 {
clientHeader.Timeout = ptypes.DurationProto(c.Timeout) clientHeader.Timeout = ptypes.DurationProto(c.Timeout)
} }
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
Payload: &pb.GrpcLogEntry_ClientHeader{ Payload: &binlogpb.GrpcLogEntry_ClientHeader{
ClientHeader: clientHeader, ClientHeader: clientHeader,
}, },
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
if c.PeerAddr != nil { if c.PeerAddr != nil {
ret.Peer = addrToProto(c.PeerAddr) ret.Peer = addrToProto(c.PeerAddr)
@ -195,19 +195,19 @@ type ServerHeader struct {
PeerAddr net.Addr PeerAddr net.Addr
} }
func (c *ServerHeader) toProto() *pb.GrpcLogEntry { func (c *ServerHeader) toProto() *binlogpb.GrpcLogEntry {
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
Payload: &pb.GrpcLogEntry_ServerHeader{ Payload: &binlogpb.GrpcLogEntry_ServerHeader{
ServerHeader: &pb.ServerHeader{ ServerHeader: &binlogpb.ServerHeader{
Metadata: mdToMetadataProto(c.Header), Metadata: mdToMetadataProto(c.Header),
}, },
}, },
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
if c.PeerAddr != nil { if c.PeerAddr != nil {
ret.Peer = addrToProto(c.PeerAddr) ret.Peer = addrToProto(c.PeerAddr)
@ -223,7 +223,7 @@ type ClientMessage struct {
Message interface{} Message interface{}
} }
func (c *ClientMessage) toProto() *pb.GrpcLogEntry { func (c *ClientMessage) toProto() *binlogpb.GrpcLogEntry {
var ( var (
data []byte data []byte
err error err error
@ -238,19 +238,19 @@ func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
} else { } else {
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte") grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
} }
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
Payload: &pb.GrpcLogEntry_Message{ Payload: &binlogpb.GrpcLogEntry_Message{
Message: &pb.Message{ Message: &binlogpb.Message{
Length: uint32(len(data)), Length: uint32(len(data)),
Data: data, Data: data,
}, },
}, },
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
return ret return ret
} }
@ -263,7 +263,7 @@ type ServerMessage struct {
Message interface{} Message interface{}
} }
func (c *ServerMessage) toProto() *pb.GrpcLogEntry { func (c *ServerMessage) toProto() *binlogpb.GrpcLogEntry {
var ( var (
data []byte data []byte
err error err error
@ -278,19 +278,19 @@ func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
} else { } else {
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte") grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
} }
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
Payload: &pb.GrpcLogEntry_Message{ Payload: &binlogpb.GrpcLogEntry_Message{
Message: &pb.Message{ Message: &binlogpb.Message{
Length: uint32(len(data)), Length: uint32(len(data)),
Data: data, Data: data,
}, },
}, },
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
return ret return ret
} }
@ -300,15 +300,15 @@ type ClientHalfClose struct {
OnClientSide bool OnClientSide bool
} }
func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry { func (c *ClientHalfClose) toProto() *binlogpb.GrpcLogEntry {
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
Payload: nil, // No payload here. Payload: nil, // No payload here.
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
return ret return ret
} }
@ -324,7 +324,7 @@ type ServerTrailer struct {
PeerAddr net.Addr PeerAddr net.Addr
} }
func (c *ServerTrailer) toProto() *pb.GrpcLogEntry { func (c *ServerTrailer) toProto() *binlogpb.GrpcLogEntry {
st, ok := status.FromError(c.Err) st, ok := status.FromError(c.Err)
if !ok { if !ok {
grpclogLogger.Info("binarylogging: error in trailer is not a status error") grpclogLogger.Info("binarylogging: error in trailer is not a status error")
@ -340,10 +340,10 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
grpclogLogger.Infof("binarylogging: failed to marshal status proto: %v", err) grpclogLogger.Infof("binarylogging: failed to marshal status proto: %v", err)
} }
} }
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
Payload: &pb.GrpcLogEntry_Trailer{ Payload: &binlogpb.GrpcLogEntry_Trailer{
Trailer: &pb.Trailer{ Trailer: &binlogpb.Trailer{
Metadata: mdToMetadataProto(c.Trailer), Metadata: mdToMetadataProto(c.Trailer),
StatusCode: uint32(st.Code()), StatusCode: uint32(st.Code()),
StatusMessage: st.Message(), StatusMessage: st.Message(),
@ -352,9 +352,9 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
}, },
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
if c.PeerAddr != nil { if c.PeerAddr != nil {
ret.Peer = addrToProto(c.PeerAddr) ret.Peer = addrToProto(c.PeerAddr)
@ -367,15 +367,15 @@ type Cancel struct {
OnClientSide bool OnClientSide bool
} }
func (c *Cancel) toProto() *pb.GrpcLogEntry { func (c *Cancel) toProto() *binlogpb.GrpcLogEntry {
ret := &pb.GrpcLogEntry{ ret := &binlogpb.GrpcLogEntry{
Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL, Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CANCEL,
Payload: nil, Payload: nil,
} }
if c.OnClientSide { if c.OnClientSide {
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
} else { } else {
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
} }
return ret return ret
} }
@ -392,15 +392,15 @@ func metadataKeyOmit(key string) bool {
return strings.HasPrefix(key, "grpc-") return strings.HasPrefix(key, "grpc-")
} }
func mdToMetadataProto(md metadata.MD) *pb.Metadata { func mdToMetadataProto(md metadata.MD) *binlogpb.Metadata {
ret := &pb.Metadata{} ret := &binlogpb.Metadata{}
for k, vv := range md { for k, vv := range md {
if metadataKeyOmit(k) { if metadataKeyOmit(k) {
continue continue
} }
for _, v := range vv { for _, v := range vv {
ret.Entry = append(ret.Entry, ret.Entry = append(ret.Entry,
&pb.MetadataEntry{ &binlogpb.MetadataEntry{
Key: k, Key: k,
Value: []byte(v), Value: []byte(v),
}, },
@ -410,26 +410,26 @@ func mdToMetadataProto(md metadata.MD) *pb.Metadata {
return ret return ret
} }
func addrToProto(addr net.Addr) *pb.Address { func addrToProto(addr net.Addr) *binlogpb.Address {
ret := &pb.Address{} ret := &binlogpb.Address{}
switch a := addr.(type) { switch a := addr.(type) {
case *net.TCPAddr: case *net.TCPAddr:
if a.IP.To4() != nil { if a.IP.To4() != nil {
ret.Type = pb.Address_TYPE_IPV4 ret.Type = binlogpb.Address_TYPE_IPV4
} else if a.IP.To16() != nil { } else if a.IP.To16() != nil {
ret.Type = pb.Address_TYPE_IPV6 ret.Type = binlogpb.Address_TYPE_IPV6
} else { } else {
ret.Type = pb.Address_TYPE_UNKNOWN ret.Type = binlogpb.Address_TYPE_UNKNOWN
// Do not set address and port fields. // Do not set address and port fields.
break break
} }
ret.Address = a.IP.String() ret.Address = a.IP.String()
ret.IpPort = uint32(a.Port) ret.IpPort = uint32(a.Port)
case *net.UnixAddr: case *net.UnixAddr:
ret.Type = pb.Address_TYPE_UNIX ret.Type = binlogpb.Address_TYPE_UNIX
ret.Address = a.String() ret.Address = a.String()
default: default:
ret.Type = pb.Address_TYPE_UNKNOWN ret.Type = binlogpb.Address_TYPE_UNKNOWN
} }
return ret return ret
} }

View File

@ -26,7 +26,7 @@ import (
"time" "time"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
) )
var ( var (
@ -42,14 +42,14 @@ type Sink interface {
// Write will be called to write the log entry into the sink. // Write will be called to write the log entry into the sink.
// //
// It should be thread-safe so it can be called in parallel. // It should be thread-safe so it can be called in parallel.
Write(*pb.GrpcLogEntry) error Write(*binlogpb.GrpcLogEntry) error
// Close will be called when the Sink is replaced by a new Sink. // Close will be called when the Sink is replaced by a new Sink.
Close() error Close() error
} }
type noopSink struct{} type noopSink struct{}
func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil } func (ns *noopSink) Write(*binlogpb.GrpcLogEntry) error { return nil }
func (ns *noopSink) Close() error { return nil } func (ns *noopSink) Close() error { return nil }
// newWriterSink creates a binary log sink with the given writer. // newWriterSink creates a binary log sink with the given writer.
@ -66,7 +66,7 @@ type writerSink struct {
out io.Writer out io.Writer
} }
func (ws *writerSink) Write(e *pb.GrpcLogEntry) error { func (ws *writerSink) Write(e *binlogpb.GrpcLogEntry) error {
b, err := proto.Marshal(e) b, err := proto.Marshal(e)
if err != nil { if err != nil {
grpclogLogger.Errorf("binary logging: failed to marshal proto message: %v", err) grpclogLogger.Errorf("binary logging: failed to marshal proto message: %v", err)
@ -96,7 +96,7 @@ type bufferedSink struct {
done chan struct{} done chan struct{}
} }
func (fs *bufferedSink) Write(e *pb.GrpcLogEntry) error { func (fs *bufferedSink) Write(e *binlogpb.GrpcLogEntry) error {
fs.mu.Lock() fs.mu.Lock()
defer fs.mu.Unlock() defer fs.mu.Unlock()
if !fs.flusherStarted { if !fs.flusherStarted {

View File

@ -21,19 +21,42 @@ package envconfig
import ( import (
"os" "os"
"strconv"
"strings" "strings"
) )
const (
prefix = "GRPC_GO_"
txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS"
advertiseCompressorsStr = prefix + "ADVERTISE_COMPRESSORS"
)
var ( var (
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false"). // TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false") TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
// AdvertiseCompressors is set if registered compressor should be advertised // AdvertiseCompressors is set if registered compressor should be advertised
// ("GRPC_GO_ADVERTISE_COMPRESSORS" is not "false"). // ("GRPC_GO_ADVERTISE_COMPRESSORS" is not "false").
AdvertiseCompressors = !strings.EqualFold(os.Getenv(advertiseCompressorsStr), "false") AdvertiseCompressors = boolFromEnv("GRPC_GO_ADVERTISE_COMPRESSORS", true)
// RingHashCap indicates the maximum ring size which defaults to 4096
// entries but may be overridden by setting the environment variable
// "GRPC_RING_HASH_CAP". This does not override the default bounds
// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
) )
func boolFromEnv(envVar string, def bool) bool {
if def {
// The default is true; return true unless the variable is "false".
return !strings.EqualFold(os.Getenv(envVar), "false")
}
// The default is false; return false unless the variable is "true".
return strings.EqualFold(os.Getenv(envVar), "true")
}
func uint64FromEnv(envVar string, def, min, max uint64) uint64 {
v, err := strconv.ParseUint(os.Getenv(envVar), 10, 64)
if err != nil {
return def
}
if v < min {
return min
}
if v > max {
return max
}
return v
}

View File

@ -20,7 +20,6 @@ package envconfig
import ( import (
"os" "os"
"strings"
) )
const ( const (
@ -36,16 +35,6 @@ const (
// //
// When both bootstrap FileName and FileContent are set, FileName is used. // When both bootstrap FileName and FileContent are set, FileName is used.
XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG" XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG"
ringHashSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH"
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC"
outlierDetectionSupportEnv = "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION"
federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION"
rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB"
c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"
) )
var ( var (
@ -64,38 +53,40 @@ var (
// XDSRingHash indicates whether ring hash support is enabled, which can be // XDSRingHash indicates whether ring hash support is enabled, which can be
// disabled by setting the environment variable // disabled by setting the environment variable
// "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false". // "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false".
XDSRingHash = !strings.EqualFold(os.Getenv(ringHashSupportEnv), "false") XDSRingHash = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH", true)
// XDSClientSideSecurity is used to control processing of security // XDSClientSideSecurity is used to control processing of security
// configuration on the client-side. // configuration on the client-side.
// //
// Note that there is no env var protection for the server-side because we // Note that there is no env var protection for the server-side because we
// have a brand new API on the server-side and users explicitly need to use // have a brand new API on the server-side and users explicitly need to use
// the new API to get security integration on the server. // the new API to get security integration on the server.
XDSClientSideSecurity = !strings.EqualFold(os.Getenv(clientSideSecuritySupportEnv), "false") XDSClientSideSecurity = boolFromEnv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", true)
// XDSAggregateAndDNS indicates whether processing of aggregated cluster // XDSAggregateAndDNS indicates whether processing of aggregated cluster
// and DNS cluster is enabled, which can be enabled by setting the // and DNS cluster is enabled, which can be enabled by setting the
// environment variable // environment variable
// "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to // "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to
// "true". // "true".
XDSAggregateAndDNS = !strings.EqualFold(os.Getenv(aggregateAndDNSSupportEnv), "false") XDSAggregateAndDNS = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", true)
// XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled, // XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled,
// which can be disabled by setting the environment variable // which can be disabled by setting the environment variable
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false". // "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false") XDSRBAC = boolFromEnv("GRPC_XDS_EXPERIMENTAL_RBAC", true)
// XDSOutlierDetection indicates whether outlier detection support is // XDSOutlierDetection indicates whether outlier detection support is
// enabled, which can be disabled by setting the environment variable // enabled, which can be disabled by setting the environment variable
// "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false". // "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false".
XDSOutlierDetection = !strings.EqualFold(os.Getenv(outlierDetectionSupportEnv), "false") XDSOutlierDetection = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION", true)
// XDSFederation indicates whether federation support is enabled. // XDSFederation indicates whether federation support is enabled, which can
XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true") // be enabled by setting the environment variable
// "GRPC_EXPERIMENTAL_XDS_FEDERATION" to "true".
XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", false)
// XDSRLS indicates whether processing of Cluster Specifier plugins and // XDSRLS indicates whether processing of Cluster Specifier plugins and
// support for the RLS CLuster Specifier is enabled, which can be enabled by // support for the RLS CLuster Specifier is enabled, which can be enabled by
// setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to // setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to
// "true". // "true".
XDSRLS = strings.EqualFold(os.Getenv(rlsInXDSEnv), "true") XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", false)
// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing. // C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv(c2pResolverTestOnlyTrafficDirectorURIEnv) C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI")
) )

View File

@ -77,6 +77,9 @@ var (
// ClearGlobalDialOptions clears the array of extra DialOption. This // ClearGlobalDialOptions clears the array of extra DialOption. This
// method is useful in testing and benchmarking. // method is useful in testing and benchmarking.
ClearGlobalDialOptions func() ClearGlobalDialOptions func()
// JoinDialOptions combines the dial options passed as arguments into a
// single dial option.
JoinDialOptions interface{} // func(...grpc.DialOption) grpc.DialOption
// JoinServerOptions combines the server options passed as arguments into a // JoinServerOptions combines the server options passed as arguments into a
// single server option. // single server option.
JoinServerOptions interface{} // func(...grpc.ServerOption) grpc.ServerOption JoinServerOptions interface{} // func(...grpc.ServerOption) grpc.ServerOption

View File

@ -116,7 +116,7 @@ type dnsBuilder struct{}
// Build creates and starts a DNS resolver that watches the name resolution of the target. // Build creates and starts a DNS resolver that watches the name resolution of the target.
func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
host, port, err := parseTarget(target.Endpoint, defaultPort) host, port, err := parseTarget(target.Endpoint(), defaultPort)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -31,7 +31,7 @@ const scheme = "passthrough"
type passthroughBuilder struct{} type passthroughBuilder struct{}
func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
if target.Endpoint == "" && opts.Dialer == nil { if target.Endpoint() == "" && opts.Dialer == nil {
return nil, errors.New("passthrough: received empty target in Build()") return nil, errors.New("passthrough: received empty target in Build()")
} }
r := &passthroughResolver{ r := &passthroughResolver{
@ -52,7 +52,7 @@ type passthroughResolver struct {
} }
func (r *passthroughResolver) start() { func (r *passthroughResolver) start() {
r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint}}}) r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint()}}})
} }
func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {} func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {}

View File

@ -527,6 +527,9 @@ const minBatchSize = 1000
// As an optimization, to increase the batch size for each flush, loopy yields the processor, once // As an optimization, to increase the batch size for each flush, loopy yields the processor, once
// if the batch size is too low to give stream goroutines a chance to fill it up. // if the batch size is too low to give stream goroutines a chance to fill it up.
func (l *loopyWriter) run() (err error) { func (l *loopyWriter) run() (err error) {
// Always flush the writer before exiting in case there are pending frames
// to be sent.
defer l.framer.writer.Flush()
for { for {
it, err := l.cbuf.get(true) it, err := l.cbuf.get(true)
if err != nil { if err != nil {
@ -650,16 +653,18 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
itl: &itemList{}, itl: &itemList{},
wq: h.wq, wq: h.wq,
} }
str.itl.enqueue(h) return l.originateStream(str, h)
return l.originateStream(str)
} }
func (l *loopyWriter) originateStream(str *outStream) error { func (l *loopyWriter) originateStream(str *outStream, hdr *headerFrame) error {
hdr := str.itl.dequeue().(*headerFrame) // l.draining is set when handling GoAway. In which case, we want to avoid
if err := hdr.initStream(str.id); err != nil { // creating new streams.
if err == errStreamDrain { // errStreamDrain need not close transport if l.draining {
// TODO: provide a better error with the reason we are in draining.
hdr.onOrphaned(errStreamDrain)
return nil return nil
} }
if err := hdr.initStream(str.id); err != nil {
return err return err
} }
if err := l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil { if err := l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
@ -757,7 +762,7 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
return err return err
} }
} }
if l.side == clientSide && l.draining && len(l.estdStreams) == 0 { if l.draining && len(l.estdStreams) == 0 {
return errors.New("finished processing active streams while in draining mode") return errors.New("finished processing active streams while in draining mode")
} }
return nil return nil
@ -812,7 +817,6 @@ func (l *loopyWriter) goAwayHandler(g *goAway) error {
} }
func (l *loopyWriter) closeConnectionHandler() error { func (l *loopyWriter) closeConnectionHandler() error {
l.framer.writer.Flush()
// Exit loopyWriter entirely by returning an error here. This will lead to // Exit loopyWriter entirely by returning an error here. This will lead to
// the transport closing the connection, and, ultimately, transport // the transport closing the connection, and, ultimately, transport
// closure. // closure.

View File

@ -47,3 +47,9 @@ const (
defaultClientMaxHeaderListSize = uint32(16 << 20) defaultClientMaxHeaderListSize = uint32(16 << 20)
defaultServerMaxHeaderListSize = uint32(16 << 20) defaultServerMaxHeaderListSize = uint32(16 << 20)
) )
// MaxStreamID is the upper bound for the stream ID before the current
// transport gracefully closes and new transport is created for subsequent RPCs.
// This is set to 75% of 2^31-1. Streams are identified with an unsigned 31-bit
// integer. It's exported so that tests can override it.
var MaxStreamID = uint32(math.MaxInt32 * 3 / 4)

View File

@ -65,7 +65,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s
contentSubtype, validContentType := grpcutil.ContentSubtype(contentType) contentSubtype, validContentType := grpcutil.ContentSubtype(contentType)
if !validContentType { if !validContentType {
msg := fmt.Sprintf("invalid gRPC request content-type %q", contentType) msg := fmt.Sprintf("invalid gRPC request content-type %q", contentType)
http.Error(w, msg, http.StatusBadRequest) http.Error(w, msg, http.StatusUnsupportedMediaType)
return nil, errors.New(msg) return nil, errors.New(msg)
} }
if _, ok := w.(http.Flusher); !ok { if _, ok := w.(http.Flusher); !ok {
@ -87,7 +87,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s
if v := r.Header.Get("grpc-timeout"); v != "" { if v := r.Header.Get("grpc-timeout"); v != "" {
to, err := decodeTimeout(v) to, err := decodeTimeout(v)
if err != nil { if err != nil {
msg := fmt.Sprintf("malformed time-out: %v", err) msg := fmt.Sprintf("malformed grpc-timeout: %v", err)
http.Error(w, msg, http.StatusBadRequest) http.Error(w, msg, http.StatusBadRequest)
return nil, status.Error(codes.Internal, msg) return nil, status.Error(codes.Internal, msg)
} }

View File

@ -140,8 +140,7 @@ type http2Client struct {
channelzID *channelz.Identifier channelzID *channelz.Identifier
czData *channelzData czData *channelzData
onGoAway func(GoAwayReason) onClose func(GoAwayReason)
onClose func()
bufferPool *bufferPool bufferPool *bufferPool
@ -197,7 +196,7 @@ func isTemporary(err error) bool {
// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2
// and starts to receive messages on it. Non-nil error returns if construction // and starts to receive messages on it. Non-nil error returns if construction
// fails. // fails.
func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) { func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (_ *http2Client, err error) {
scheme := "http" scheme := "http"
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
defer func() { defer func() {
@ -217,7 +216,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
if opts.FailOnNonTempDialError { if opts.FailOnNonTempDialError {
return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err) return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
} }
return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err) return nil, connectionErrorf(true, err, "transport: Error while dialing: %v", err)
} }
// Any further errors will close the underlying connection // Any further errors will close the underlying connection
@ -343,7 +342,6 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
streamQuota: defaultMaxStreamsClient, streamQuota: defaultMaxStreamsClient,
streamsQuotaAvailable: make(chan struct{}, 1), streamsQuotaAvailable: make(chan struct{}, 1),
czData: new(channelzData), czData: new(channelzData),
onGoAway: onGoAway,
keepaliveEnabled: keepaliveEnabled, keepaliveEnabled: keepaliveEnabled,
bufferPool: newBufferPool(), bufferPool: newBufferPool(),
onClose: onClose, onClose: onClose,
@ -744,15 +742,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
endStream: false, endStream: false,
initStream: func(id uint32) error { initStream: func(id uint32) error {
t.mu.Lock() t.mu.Lock()
if state := t.state; state != reachable { // TODO: handle transport closure in loopy instead and remove this
// initStream is never called when transport is draining.
if t.state == closing {
t.mu.Unlock() t.mu.Unlock()
// Do a quick cleanup. cleanup(ErrConnClosing)
err := error(errStreamDrain) return ErrConnClosing
if state == closing {
err = ErrConnClosing
}
cleanup(err)
return err
} }
if channelz.IsOn() { if channelz.IsOn() {
atomic.AddInt64(&t.czData.streamsStarted, 1) atomic.AddInt64(&t.czData.streamsStarted, 1)
@ -770,6 +765,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
} }
firstTry := true firstTry := true
var ch chan struct{} var ch chan struct{}
transportDrainRequired := false
checkForStreamQuota := func(it interface{}) bool { checkForStreamQuota := func(it interface{}) bool {
if t.streamQuota <= 0 { // Can go negative if server decreases it. if t.streamQuota <= 0 { // Can go negative if server decreases it.
if firstTry { if firstTry {
@ -785,6 +781,11 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
h := it.(*headerFrame) h := it.(*headerFrame)
h.streamID = t.nextID h.streamID = t.nextID
t.nextID += 2 t.nextID += 2
// Drain client transport if nextID > MaxStreamID which signals gRPC that
// the connection is closed and a new one must be created for subsequent RPCs.
transportDrainRequired = t.nextID > MaxStreamID
s.id = h.streamID s.id = h.streamID
s.fc = &inFlow{limit: uint32(t.initialWindowSize)} s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
t.mu.Lock() t.mu.Lock()
@ -864,6 +865,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
sh.HandleRPC(s.ctx, outHeader) sh.HandleRPC(s.ctx, outHeader)
} }
} }
if transportDrainRequired {
if logger.V(logLevel) {
logger.Infof("transport: t.nextID > MaxStreamID. Draining")
}
t.GracefulClose()
}
return s, nil return s, nil
} }
@ -957,7 +964,9 @@ func (t *http2Client) Close(err error) {
} }
// Call t.onClose ASAP to prevent the client from attempting to create new // Call t.onClose ASAP to prevent the client from attempting to create new
// streams. // streams.
t.onClose() if t.state != draining {
t.onClose(GoAwayInvalid)
}
t.state = closing t.state = closing
streams := t.activeStreams streams := t.activeStreams
t.activeStreams = nil t.activeStreams = nil
@ -1010,6 +1019,7 @@ func (t *http2Client) GracefulClose() {
if logger.V(logLevel) { if logger.V(logLevel) {
logger.Infof("transport: GracefulClose called") logger.Infof("transport: GracefulClose called")
} }
t.onClose(GoAwayInvalid)
t.state = draining t.state = draining
active := len(t.activeStreams) active := len(t.activeStreams)
t.mu.Unlock() t.mu.Unlock()
@ -1172,7 +1182,7 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
statusCode, ok := http2ErrConvTab[f.ErrCode] statusCode, ok := http2ErrConvTab[f.ErrCode]
if !ok { if !ok {
if logger.V(logLevel) { if logger.V(logLevel) {
logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode) logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error: %v", f.ErrCode)
} }
statusCode = codes.Unknown statusCode = codes.Unknown
} }
@ -1290,9 +1300,11 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
// Notify the clientconn about the GOAWAY before we set the state to // Notify the clientconn about the GOAWAY before we set the state to
// draining, to allow the client to stop attempting to create streams // draining, to allow the client to stop attempting to create streams
// before disallowing new streams on this connection. // before disallowing new streams on this connection.
t.onGoAway(t.goAwayReason) if t.state != draining {
t.onClose(t.goAwayReason)
t.state = draining t.state = draining
} }
}
// All streams with IDs greater than the GoAwayId // All streams with IDs greater than the GoAwayId
// and smaller than the previous GoAway ID should be killed. // and smaller than the previous GoAway ID should be killed.
upperLimit := t.prevGoAwayID upperLimit := t.prevGoAwayID
@ -1780,3 +1792,9 @@ func (t *http2Client) getOutFlowWindow() int64 {
return -2 return -2
} }
} }
func (t *http2Client) stateForTesting() transportState {
t.mu.Lock()
defer t.mu.Unlock()
return t.state
}

View File

@ -380,13 +380,14 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
fc: &inFlow{limit: uint32(t.initialWindowSize)}, fc: &inFlow{limit: uint32(t.initialWindowSize)},
} }
var ( var (
// If a gRPC Response-Headers has already been received, then it means // if false, content-type was missing or invalid
// that the peer is speaking gRPC and we are in gRPC mode.
isGRPC = false isGRPC = false
contentType = ""
mdata = make(map[string][]string) mdata = make(map[string][]string)
httpMethod string httpMethod string
// headerError is set if an error is encountered while parsing the headers // these are set if an error is encountered while parsing the headers
headerError bool protocolError bool
headerError *status.Status
timeoutSet bool timeoutSet bool
timeout time.Duration timeout time.Duration
@ -397,6 +398,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
case "content-type": case "content-type":
contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value) contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value)
if !validContentType { if !validContentType {
contentType = hf.Value
break break
} }
mdata[hf.Name] = append(mdata[hf.Name], hf.Value) mdata[hf.Name] = append(mdata[hf.Name], hf.Value)
@ -412,7 +414,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
timeoutSet = true timeoutSet = true
var err error var err error
if timeout, err = decodeTimeout(hf.Value); err != nil { if timeout, err = decodeTimeout(hf.Value); err != nil {
headerError = true headerError = status.Newf(codes.Internal, "malformed grpc-timeout: %v", err)
} }
// "Transports must consider requests containing the Connection header // "Transports must consider requests containing the Connection header
// as malformed." - A41 // as malformed." - A41
@ -420,14 +422,14 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
if logger.V(logLevel) { if logger.V(logLevel) {
logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec") logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec")
} }
headerError = true protocolError = true
default: default:
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) { if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
break break
} }
v, err := decodeMetadataHeader(hf.Name, hf.Value) v, err := decodeMetadataHeader(hf.Name, hf.Value)
if err != nil { if err != nil {
headerError = true headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err)
logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err) logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err)
break break
} }
@ -446,7 +448,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
logger.Errorf("transport: %v", errMsg) logger.Errorf("transport: %v", errMsg)
} }
t.controlBuf.put(&earlyAbortStream{ t.controlBuf.put(&earlyAbortStream{
httpStatus: 400, httpStatus: http.StatusBadRequest,
streamID: streamID, streamID: streamID,
contentSubtype: s.contentSubtype, contentSubtype: s.contentSubtype,
status: status.New(codes.Internal, errMsg), status: status.New(codes.Internal, errMsg),
@ -455,7 +457,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
return nil return nil
} }
if !isGRPC || headerError { if protocolError {
t.controlBuf.put(&cleanupStream{ t.controlBuf.put(&cleanupStream{
streamID: streamID, streamID: streamID,
rst: true, rst: true,
@ -464,6 +466,26 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
}) })
return nil return nil
} }
if !isGRPC {
t.controlBuf.put(&earlyAbortStream{
httpStatus: http.StatusUnsupportedMediaType,
streamID: streamID,
contentSubtype: s.contentSubtype,
status: status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType),
rst: !frame.StreamEnded(),
})
return nil
}
if headerError != nil {
t.controlBuf.put(&earlyAbortStream{
httpStatus: http.StatusBadRequest,
streamID: streamID,
contentSubtype: s.contentSubtype,
status: headerError,
rst: !frame.StreamEnded(),
})
return nil
}
// "If :authority is missing, Host must be renamed to :authority." - A41 // "If :authority is missing, Host must be renamed to :authority." - A41
if len(mdata[":authority"]) == 0 { if len(mdata[":authority"]) == 0 {

View File

@ -583,8 +583,8 @@ type ConnectOptions struct {
// NewClientTransport establishes the transport with the required ConnectOptions // NewClientTransport establishes the transport with the required ConnectOptions
// and returns it to the caller. // and returns it to the caller.
func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) { func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (ClientTransport, error) {
return newHTTP2Client(connectCtx, ctx, addr, opts, onGoAway, onClose) return newHTTP2Client(connectCtx, ctx, addr, opts, onClose)
} }
// Options provides additional hints and information for message // Options provides additional hints and information for message

View File

@ -58,12 +58,18 @@ func (pw *pickerWrapper) updatePicker(p balancer.Picker) {
pw.mu.Unlock() pw.mu.Unlock()
} }
func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) func(balancer.DoneInfo) { // doneChannelzWrapper performs the following:
// - increments the calls started channelz counter
// - wraps the done function in the passed in result to increment the calls
// failed or calls succeeded channelz counter before invoking the actual
// done function.
func doneChannelzWrapper(acw *acBalancerWrapper, result *balancer.PickResult) {
acw.mu.Lock() acw.mu.Lock()
ac := acw.ac ac := acw.ac
acw.mu.Unlock() acw.mu.Unlock()
ac.incrCallsStarted() ac.incrCallsStarted()
return func(b balancer.DoneInfo) { done := result.Done
result.Done = func(b balancer.DoneInfo) {
if b.Err != nil && b.Err != io.EOF { if b.Err != nil && b.Err != io.EOF {
ac.incrCallsFailed() ac.incrCallsFailed()
} else { } else {
@ -82,7 +88,7 @@ func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) f
// - the current picker returns other errors and failfast is false. // - the current picker returns other errors and failfast is false.
// - the subConn returned by the current picker is not READY // - the subConn returned by the current picker is not READY
// When one of these situations happens, pick blocks until the picker gets updated. // When one of these situations happens, pick blocks until the picker gets updated.
func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, func(balancer.DoneInfo), error) { func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
var ch chan struct{} var ch chan struct{}
var lastPickErr error var lastPickErr error
@ -90,7 +96,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
pw.mu.Lock() pw.mu.Lock()
if pw.done { if pw.done {
pw.mu.Unlock() pw.mu.Unlock()
return nil, nil, ErrClientConnClosing return nil, balancer.PickResult{}, ErrClientConnClosing
} }
if pw.picker == nil { if pw.picker == nil {
@ -111,9 +117,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
} }
switch ctx.Err() { switch ctx.Err() {
case context.DeadlineExceeded: case context.DeadlineExceeded:
return nil, nil, status.Error(codes.DeadlineExceeded, errStr) return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
case context.Canceled: case context.Canceled:
return nil, nil, status.Error(codes.Canceled, errStr) return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
} }
case <-ch: case <-ch:
} }
@ -125,7 +131,6 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
pw.mu.Unlock() pw.mu.Unlock()
pickResult, err := p.Pick(info) pickResult, err := p.Pick(info)
if err != nil { if err != nil {
if err == balancer.ErrNoSubConnAvailable { if err == balancer.ErrNoSubConnAvailable {
continue continue
@ -136,7 +141,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
if istatus.IsRestrictedControlPlaneCode(st) { if istatus.IsRestrictedControlPlaneCode(st) {
err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err) err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
} }
return nil, nil, dropError{error: err} return nil, balancer.PickResult{}, dropError{error: err}
} }
// For all other errors, wait for ready RPCs should block and other // For all other errors, wait for ready RPCs should block and other
// RPCs should fail with unavailable. // RPCs should fail with unavailable.
@ -144,7 +149,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
lastPickErr = err lastPickErr = err
continue continue
} }
return nil, nil, status.Error(codes.Unavailable, err.Error()) return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
} }
acw, ok := pickResult.SubConn.(*acBalancerWrapper) acw, ok := pickResult.SubConn.(*acBalancerWrapper)
@ -154,9 +159,10 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
} }
if t := acw.getAddrConn().getReadyTransport(); t != nil { if t := acw.getAddrConn().getReadyTransport(); t != nil {
if channelz.IsOn() { if channelz.IsOn() {
return t, doneChannelzWrapper(acw, pickResult.Done), nil doneChannelzWrapper(acw, &pickResult)
return t, pickResult, nil
} }
return t, pickResult.Done, nil return t, pickResult, nil
} }
if pickResult.Done != nil { if pickResult.Done != nil {
// Calling done with nil error, no bytes sent and no bytes received. // Calling done with nil error, no bytes sent and no bytes received.

View File

@ -51,7 +51,7 @@ type pickfirstBalancer struct {
func (b *pickfirstBalancer) ResolverError(err error) { func (b *pickfirstBalancer) ResolverError(err error) {
if logger.V(2) { if logger.V(2) {
logger.Infof("pickfirstBalancer: ResolverError called with error %v", err) logger.Infof("pickfirstBalancer: ResolverError called with error: %v", err)
} }
if b.subConn == nil { if b.subConn == nil {
b.state = connectivity.TransientFailure b.state = connectivity.TransientFailure

View File

@ -24,6 +24,7 @@ import (
"context" "context"
"net" "net"
"net/url" "net/url"
"strings"
"google.golang.org/grpc/attributes" "google.golang.org/grpc/attributes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
@ -247,9 +248,6 @@ type Target struct {
Scheme string Scheme string
// Deprecated: use URL.Host instead. // Deprecated: use URL.Host instead.
Authority string Authority string
// Deprecated: use URL.Path or URL.Opaque instead. The latter is set when
// the former is empty.
Endpoint string
// URL contains the parsed dial target with an optional default scheme added // URL contains the parsed dial target with an optional default scheme added
// to it if the original dial target contained no scheme or contained an // to it if the original dial target contained no scheme or contained an
// unregistered scheme. Any query params specified in the original dial // unregistered scheme. Any query params specified in the original dial
@ -257,6 +255,24 @@ type Target struct {
URL url.URL URL url.URL
} }
// Endpoint retrieves endpoint without leading "/" from either `URL.Path`
// or `URL.Opaque`. The latter is used when the former is empty.
func (t Target) Endpoint() string {
endpoint := t.URL.Path
if endpoint == "" {
endpoint = t.URL.Opaque
}
// For targets of the form "[scheme]://[authority]/endpoint, the endpoint
// value returned from url.Parse() contains a leading "/". Although this is
// in accordance with RFC 3986, we do not want to break existing resolver
// implementations which expect the endpoint without the leading "/". So, we
// end up stripping the leading "/" here. But this will result in an
// incorrect parsing for something like "unix:///path/to/socket". Since we
// own the "unix" resolver, we can workaround in the unix resolver by using
// the `URL` field.
return strings.TrimPrefix(endpoint, "/")
}
// Builder creates a resolver that will be used to watch name resolution updates. // Builder creates a resolver that will be used to watch name resolution updates.
type Builder interface { type Builder interface {
// Build creates a new resolver for the given target. // Build creates a new resolver for the given target.

View File

@ -25,7 +25,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"math" "math"
"strings" "strings"
"sync" "sync"
@ -77,7 +76,7 @@ func NewGZIPCompressorWithLevel(level int) (Compressor, error) {
return &gzipCompressor{ return &gzipCompressor{
pool: sync.Pool{ pool: sync.Pool{
New: func() interface{} { New: func() interface{} {
w, err := gzip.NewWriterLevel(ioutil.Discard, level) w, err := gzip.NewWriterLevel(io.Discard, level)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -143,7 +142,7 @@ func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) {
z.Close() z.Close()
d.pool.Put(z) d.pool.Put(z)
}() }()
return ioutil.ReadAll(z) return io.ReadAll(z)
} }
func (d *gzipDecompressor) Type() string { func (d *gzipDecompressor) Type() string {
@ -297,7 +296,8 @@ func (o FailFastCallOption) before(c *callInfo) error {
func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {} func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {}
// MaxCallRecvMsgSize returns a CallOption which sets the maximum message size // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size
// in bytes the client can receive. // in bytes the client can receive. If this is not set, gRPC uses the default
// 4MB.
func MaxCallRecvMsgSize(bytes int) CallOption { func MaxCallRecvMsgSize(bytes int) CallOption {
return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes} return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes}
} }
@ -320,7 +320,8 @@ func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error {
func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {}
// MaxCallSendMsgSize returns a CallOption which sets the maximum message size // MaxCallSendMsgSize returns a CallOption which sets the maximum message size
// in bytes the client can send. // in bytes the client can send. If this is not set, gRPC uses the default
// `math.MaxInt32`.
func MaxCallSendMsgSize(bytes int) CallOption { func MaxCallSendMsgSize(bytes int) CallOption {
return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes} return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes}
} }
@ -711,7 +712,7 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei
d, size, err = decompress(compressor, d, maxReceiveMessageSize) d, size, err = decompress(compressor, d, maxReceiveMessageSize)
} }
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err)
} }
if size > maxReceiveMessageSize { if size > maxReceiveMessageSize {
// TODO: Revisit the error code. Currently keep it consistent with java // TODO: Revisit the error code. Currently keep it consistent with java
@ -746,7 +747,7 @@ func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize
} }
// Read from LimitReader with limit max+1. So if the underlying // Read from LimitReader with limit max+1. So if the underlying
// reader is over limit, the result will be bigger than max. // reader is over limit, the result will be bigger than max.
d, err = ioutil.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) d, err = io.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1))
return d, len(d), err return d, len(d), err
} }
@ -759,7 +760,7 @@ func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interf
return err return err
} }
if err := c.Unmarshal(d, m); err != nil { if err := c.Unmarshal(d, m); err != nil {
return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err)
} }
if payInfo != nil { if payInfo != nil {
payInfo.uncompressedBytes = d payInfo.uncompressedBytes = d

View File

@ -1299,7 +1299,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp)
if err != nil { if err != nil {
if e := t.WriteStatus(stream, status.Convert(err)); e != nil { if e := t.WriteStatus(stream, status.Convert(err)); e != nil {
channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status %v", e) channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status: %v", e)
} }
return err return err
} }

View File

@ -226,7 +226,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
var rsc jsonSC var rsc jsonSC
err := json.Unmarshal([]byte(js), &rsc) err := json.Unmarshal([]byte(js), &rsc)
if err != nil { if err != nil {
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
return &serviceconfig.ParseResult{Err: err} return &serviceconfig.ParseResult{Err: err}
} }
sc := ServiceConfig{ sc := ServiceConfig{
@ -254,7 +254,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
} }
d, err := parseDuration(m.Timeout) d, err := parseDuration(m.Timeout)
if err != nil { if err != nil {
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
return &serviceconfig.ParseResult{Err: err} return &serviceconfig.ParseResult{Err: err}
} }
@ -263,7 +263,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
Timeout: d, Timeout: d,
} }
if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil { if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
return &serviceconfig.ParseResult{Err: err} return &serviceconfig.ParseResult{Err: err}
} }
if m.MaxRequestMessageBytes != nil { if m.MaxRequestMessageBytes != nil {
@ -283,13 +283,13 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
for i, n := range *m.Name { for i, n := range *m.Name {
path, err := n.generatePath() path, err := n.generatePath()
if err != nil { if err != nil {
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err) logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err)
return &serviceconfig.ParseResult{Err: err} return &serviceconfig.ParseResult{Err: err}
} }
if _, ok := paths[path]; ok { if _, ok := paths[path]; ok {
err = errDuplicatedName err = errDuplicatedName
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err) logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err)
return &serviceconfig.ParseResult{Err: err} return &serviceconfig.ParseResult{Err: err}
} }
paths[path] = struct{}{} paths[path] = struct{}{}

View File

@ -438,7 +438,7 @@ func (a *csAttempt) getTransport() error {
cs := a.cs cs := a.cs
var err error var err error
a.t, a.done, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method) a.t, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method)
if err != nil { if err != nil {
if de, ok := err.(dropError); ok { if de, ok := err.(dropError); ok {
err = de.error err = de.error
@ -455,6 +455,25 @@ func (a *csAttempt) getTransport() error {
func (a *csAttempt) newStream() error { func (a *csAttempt) newStream() error {
cs := a.cs cs := a.cs
cs.callHdr.PreviousAttempts = cs.numRetries cs.callHdr.PreviousAttempts = cs.numRetries
// Merge metadata stored in PickResult, if any, with existing call metadata.
// It is safe to overwrite the csAttempt's context here, since all state
// maintained in it are local to the attempt. When the attempt has to be
// retried, a new instance of csAttempt will be created.
if a.pickResult.Metatada != nil {
// We currently do not have a function it the metadata package which
// merges given metadata with existing metadata in a context. Existing
// function `AppendToOutgoingContext()` takes a variadic argument of key
// value pairs.
//
// TODO: Make it possible to retrieve key value pairs from metadata.MD
// in a form passable to AppendToOutgoingContext(), or create a version
// of AppendToOutgoingContext() that accepts a metadata.MD.
md, _ := metadata.FromOutgoingContext(a.ctx)
md = metadata.Join(md, a.pickResult.Metatada)
a.ctx = metadata.NewOutgoingContext(a.ctx, md)
}
s, err := a.t.NewStream(a.ctx, cs.callHdr) s, err := a.t.NewStream(a.ctx, cs.callHdr)
if err != nil { if err != nil {
nse, ok := err.(*transport.NewStreamError) nse, ok := err.(*transport.NewStreamError)
@ -534,7 +553,7 @@ type csAttempt struct {
t transport.ClientTransport t transport.ClientTransport
s *transport.Stream s *transport.Stream
p *parser p *parser
done func(balancer.DoneInfo) pickResult balancer.PickResult
finished bool finished bool
dc Decompressor dc Decompressor
@ -1103,12 +1122,12 @@ func (a *csAttempt) finish(err error) {
tr = a.s.Trailer() tr = a.s.Trailer()
} }
if a.done != nil { if a.pickResult.Done != nil {
br := false br := false
if a.s != nil { if a.s != nil {
br = a.s.BytesReceived() br = a.s.BytesReceived()
} }
a.done(balancer.DoneInfo{ a.pickResult.Done(balancer.DoneInfo{
Err: err, Err: err,
Trailer: tr, Trailer: tr,
BytesSent: a.s != nil, BytesSent: a.s != nil,
@ -1464,6 +1483,9 @@ type ServerStream interface {
// It is safe to have a goroutine calling SendMsg and another goroutine // It is safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time, but it is not safe // calling RecvMsg on the same stream at the same time, but it is not safe
// to call SendMsg on the same stream in different goroutines. // to call SendMsg on the same stream in different goroutines.
//
// It is not safe to modify the message after calling SendMsg. Tracing
// libraries and stats handlers may use the message lazily.
SendMsg(m interface{}) error SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message into m or the stream is // RecvMsg blocks until it receives a message into m or the stream is
// done. It returns io.EOF when the client has performed a CloseSend. On // done. It returns io.EOF when the client has performed a CloseSend. On

View File

@ -19,4 +19,4 @@
package grpc package grpc
// Version is the current grpc version. // Version is the current grpc version.
const Version = "1.52.3" const Version = "1.53.0"

20
vendor/google.golang.org/grpc/vet.sh generated vendored
View File

@ -66,6 +66,17 @@ elif [[ "$#" -ne 0 ]]; then
die "Unknown argument(s): $*" die "Unknown argument(s): $*"
fi fi
# - Check that generated proto files are up to date.
if [[ -z "${VET_SKIP_PROTO}" ]]; then
PATH="/home/travis/bin:${PATH}" make proto && \
git status --porcelain 2>&1 | fail_on_output || \
(git status; git --no-pager diff; exit 1)
fi
if [[ -n "${VET_ONLY_PROTO}" ]]; then
exit 0
fi
# - Ensure all source files contain a copyright message. # - Ensure all source files contain a copyright message.
# (Done in two parts because Darwin "git grep" has broken support for compound # (Done in two parts because Darwin "git grep" has broken support for compound
# exclusion matches.) # exclusion matches.)
@ -93,13 +104,6 @@ git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.
misspell -error . misspell -error .
# - Check that generated proto files are up to date.
if [[ -z "${VET_SKIP_PROTO}" ]]; then
PATH="/home/travis/bin:${PATH}" make proto && \
git status --porcelain 2>&1 | fail_on_output || \
(git status; git --no-pager diff; exit 1)
fi
# - gofmt, goimports, golint (with exceptions for generated code), go vet, # - gofmt, goimports, golint (with exceptions for generated code), go vet,
# go mod tidy. # go mod tidy.
# Perform these checks on each module inside gRPC. # Perform these checks on each module inside gRPC.
@ -111,7 +115,7 @@ for MOD_FILE in $(find . -name 'go.mod'); do
goimports -l . 2>&1 | not grep -vE "\.pb\.go" goimports -l . 2>&1 | not grep -vE "\.pb\.go"
golint ./... 2>&1 | not grep -vE "/grpc_testing_not_regenerate/.*\.pb\.go:" golint ./... 2>&1 | not grep -vE "/grpc_testing_not_regenerate/.*\.pb\.go:"
go mod tidy go mod tidy -compat=1.17
git status --porcelain 2>&1 | fail_on_output || \ git status --porcelain 2>&1 | fail_on_output || \
(git status; git --no-pager diff; exit 1) (git status; git --no-pager diff; exit 1)
popd popd

8
vendor/modules.txt vendored
View File

@ -141,7 +141,7 @@ github.com/ceph/go-ceph/internal/timespec
github.com/ceph/go-ceph/rados github.com/ceph/go-ceph/rados
github.com/ceph/go-ceph/rbd github.com/ceph/go-ceph/rbd
github.com/ceph/go-ceph/rbd/admin github.com/ceph/go-ceph/rbd/admin
# github.com/cespare/xxhash/v2 v2.1.2 # github.com/cespare/xxhash/v2 v2.2.0
## explicit; go 1.11 ## explicit; go 1.11
github.com/cespare/xxhash/v2 github.com/cespare/xxhash/v2
# github.com/container-storage-interface/spec v1.7.0 # github.com/container-storage-interface/spec v1.7.0
@ -633,7 +633,7 @@ golang.org/x/net/internal/socks
golang.org/x/net/internal/timeseries golang.org/x/net/internal/timeseries
golang.org/x/net/proxy golang.org/x/net/proxy
golang.org/x/net/trace golang.org/x/net/trace
# golang.org/x/oauth2 v0.2.0 # golang.org/x/oauth2 v0.4.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/internal golang.org/x/oauth2/internal
@ -687,13 +687,13 @@ google.golang.org/appengine/internal/log
google.golang.org/appengine/internal/remote_api google.golang.org/appengine/internal/remote_api
google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 # google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f
## explicit; go 1.19 ## explicit; go 1.19
google.golang.org/genproto/googleapis/api/httpbody google.golang.org/genproto/googleapis/api/httpbody
google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/errdetails
google.golang.org/genproto/googleapis/rpc/status google.golang.org/genproto/googleapis/rpc/status
google.golang.org/genproto/protobuf/field_mask google.golang.org/genproto/protobuf/field_mask
# google.golang.org/grpc v1.52.3 # google.golang.org/grpc v1.53.0
## explicit; go 1.17 ## explicit; go 1.17
google.golang.org/grpc google.golang.org/grpc
google.golang.org/grpc/attributes google.golang.org/grpc/attributes