Update containerd.

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu 2018-04-13 06:58:22 +00:00
parent 77a33b10a9
commit da285a10b9
105 changed files with 7240 additions and 3062 deletions

View File

@ -4,11 +4,11 @@ github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130 github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925 github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925
github.com/containerd/containerd v1.1.0-rc.1 github.com/containerd/containerd v1.1.0-rc.2
github.com/containerd/continuity 3e8f2ea4b190484acb976a5b378d373429639a1a github.com/containerd/continuity 3e8f2ea4b190484acb976a5b378d373429639a1a
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/containerd/go-runc bcb223a061a3dd7de1a89c0b402a60f4dd9bd307
github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7 github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7
github.com/containerd/go-runc bcb223a061a3dd7de1a89c0b402a60f4dd9bd307
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
github.com/containernetworking/cni v0.6.0 github.com/containernetworking/cni v0.6.0
github.com/containernetworking/plugins v0.7.0 github.com/containernetworking/plugins v0.7.0
@ -23,7 +23,8 @@ github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
github.com/emicklei/go-restful ff4f55a206334ef123e4f79bbf348980da81ca46 github.com/emicklei/go-restful ff4f55a206334ef123e4f79bbf348980da81ca46
github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee
github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f
github.com/gogo/protobuf v0.5 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
github.com/gogo/protobuf v1.0.0
github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed
github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
@ -54,14 +55,14 @@ github.com/stretchr/testify v1.1.4
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
google.golang.org/grpc v1.7.4 google.golang.org/grpc v1.10.1
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77 gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77
k8s.io/api 7e796de92438aede7cb5d6bcf6c10f4fa65db560 k8s.io/api 7e796de92438aede7cb5d6bcf6c10f4fa65db560

View File

@ -48,11 +48,11 @@ import google_protobuf "github.com/gogo/protobuf/types"
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" // skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
// skipping weak import containerd_plugin "github.com/containerd/containerd/protobuf/plugin" // skipping weak import containerd_plugin "github.com/containerd/containerd/protobuf/plugin"
import github_com_containerd_typeurl "github.com/containerd/typeurl" import typeurl "github.com/containerd/typeurl"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -153,7 +153,7 @@ func (m *ContainerCreate_Runtime) Field(fieldpath []string) (string, bool) {
case "name": case "name":
return string(m.Name), len(m.Name) > 0 return string(m.Name), len(m.Name) > 0
case "options": case "options":
decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Options) decoded, err := typeurl.UnmarshalAny(m.Options)
if err != nil { if err != nil {
return "", false return "", false
} }
@ -478,7 +478,7 @@ func (this *ContainerUpdate) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])

View File

@ -11,7 +11,7 @@ import math "math"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -291,7 +291,7 @@ func (this *ImageCreate) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -312,7 +312,7 @@ func (this *ImageUpdate) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])

View File

@ -12,7 +12,7 @@ import math "math"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -292,7 +292,7 @@ func (this *NamespaceCreate) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -313,7 +313,7 @@ func (this *NamespaceUpdate) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])

View File

@ -15,7 +15,7 @@ import containerd_types "github.com/containerd/containerd/api/types"
import time "time" import time "time"
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -468,8 +468,8 @@ func (m *TaskDelete) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x22 dAtA[i] = 0x22
i++ i++
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n2, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -562,8 +562,8 @@ func (m *TaskExit) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x2a dAtA[i] = 0x2a
i++ i++
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n3, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -804,7 +804,7 @@ func (m *TaskDelete) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovTask(uint64(m.ExitStatus)) n += 1 + sovTask(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTask(uint64(l)) n += 1 + l + sovTask(uint64(l))
return n return n
} }
@ -847,7 +847,7 @@ func (m *TaskExit) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovTask(uint64(m.ExitStatus)) n += 1 + sovTask(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTask(uint64(l)) n += 1 + l + sovTask(uint64(l))
return n return n
} }
@ -1518,7 +1518,7 @@ func (m *TaskDelete) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -1851,7 +1851,7 @@ func (m *TaskExit) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -33,16 +33,14 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -516,16 +514,16 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x42 dAtA[i] = 0x42
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) i = encodeVarintContainers(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) n3, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n3 i += n3
dAtA[i] = 0x4a dAtA[i] = 0x4a
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintContainers(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n4, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -888,9 +886,9 @@ func (m *Container) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovContainers(uint64(l)) n += 1 + l + sovContainers(uint64(l))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) l = types.SizeOfStdTime(m.CreatedAt)
n += 1 + l + sovContainers(uint64(l)) n += 1 + l + sovContainers(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovContainers(uint64(l)) n += 1 + l + sovContainers(uint64(l))
if len(m.Extensions) > 0 { if len(m.Extensions) > 0 {
for k, v := range m.Extensions { for k, v := range m.Extensions {
@ -1027,7 +1025,7 @@ func (this *Container) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -1037,7 +1035,7 @@ func (this *Container) String() string {
for k, _ := range this.Extensions { for k, _ := range this.Extensions {
keysForExtensions = append(keysForExtensions, k) keysForExtensions = append(keysForExtensions, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForExtensions) sortkeys.Strings(keysForExtensions)
mapStringForExtensions := "map[string]google_protobuf1.Any{" mapStringForExtensions := "map[string]google_protobuf1.Any{"
for _, k := range keysForExtensions { for _, k := range keysForExtensions {
mapStringForExtensions += fmt.Sprintf("%v: %v,", k, this.Extensions[k]) mapStringForExtensions += fmt.Sprintf("%v: %v,", k, this.Extensions[k])
@ -1523,7 +1521,7 @@ func (m *Container) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -1553,7 +1551,7 @@ func (m *Container) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -41,16 +41,14 @@ import google_protobuf3 "github.com/gogo/protobuf/types"
import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest" import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
import time "time" import time "time"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -936,16 +934,16 @@ func (m *Info) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x1a dAtA[i] = 0x1a
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n1 i += n1
dAtA[i] = 0x22 dAtA[i] = 0x22
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n2, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1249,16 +1247,16 @@ func (m *Status) MarshalTo(dAtA []byte) (int, error) {
_ = l _ = l
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.StartedAt)))
n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:]) n7, err := types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n7 i += n7
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n8, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1493,16 +1491,16 @@ func (m *WriteContentResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.StartedAt)))
n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:]) n10, err := types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n10 i += n10
dAtA[i] = 0x1a dAtA[i] = 0x1a
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n11, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n11, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1569,9 +1567,9 @@ func (m *Info) Size() (n int) {
if m.Size_ != 0 { if m.Size_ != 0 {
n += 1 + sovContent(uint64(m.Size_)) n += 1 + sovContent(uint64(m.Size_))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) l = types.SizeOfStdTime(m.CreatedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
if len(m.Labels) > 0 { if len(m.Labels) > 0 {
for k, v := range m.Labels { for k, v := range m.Labels {
@ -1688,9 +1686,9 @@ func (m *ReadContentResponse) Size() (n int) {
func (m *Status) Size() (n int) { func (m *Status) Size() (n int) {
var l int var l int
_ = l _ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt) l = types.SizeOfStdTime(m.StartedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
l = len(m.Ref) l = len(m.Ref)
if l > 0 { if l > 0 {
@ -1794,9 +1792,9 @@ func (m *WriteContentResponse) Size() (n int) {
if m.Action != 0 { if m.Action != 0 {
n += 1 + sovContent(uint64(m.Action)) n += 1 + sovContent(uint64(m.Action))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt) l = types.SizeOfStdTime(m.StartedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovContent(uint64(l)) n += 1 + l + sovContent(uint64(l))
if m.Offset != 0 { if m.Offset != 0 {
n += 1 + sovContent(uint64(m.Offset)) n += 1 + sovContent(uint64(m.Offset))
@ -1842,7 +1840,7 @@ func (this *Info) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -2015,7 +2013,7 @@ func (this *WriteContentRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -2169,7 +2167,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -2199,7 +2197,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -3205,7 +3203,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -3235,7 +3233,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -4066,7 +4064,7 @@ func (m *WriteContentResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -4096,7 +4094,7 @@ func (m *WriteContentResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -23,14 +23,12 @@ import math "math"
import containerd_types "github.com/containerd/containerd/api/types" import containerd_types "github.com/containerd/containerd/api/types"
import containerd_types1 "github.com/containerd/containerd/api/types" import containerd_types1 "github.com/containerd/containerd/api/types"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -507,7 +505,7 @@ func (this *DiffRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])

View File

@ -27,14 +27,12 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import github_com_containerd_typeurl "github.com/containerd/typeurl" import typeurl "github.com/containerd/typeurl"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -110,7 +108,7 @@ func (m *Envelope) Field(fieldpath []string) (string, bool) {
case "topic": case "topic":
return string(m.Topic), len(m.Topic) > 0 return string(m.Topic), len(m.Topic) > 0
case "event": case "event":
decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Event) decoded, err := typeurl.UnmarshalAny(m.Event)
if err != nil { if err != nil {
return "", false return "", false
} }
@ -434,8 +432,8 @@ func (m *Envelope) MarshalTo(dAtA []byte) (int, error) {
_ = l _ = l
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintEvents(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) i = encodeVarintEvents(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) n3, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -513,7 +511,7 @@ func (m *SubscribeRequest) Size() (n int) {
func (m *Envelope) Size() (n int) { func (m *Envelope) Size() (n int) {
var l int var l int
_ = l _ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) l = types.SizeOfStdTime(m.Timestamp)
n += 1 + l + sovEvents(uint64(l)) n += 1 + l + sovEvents(uint64(l))
l = len(m.Namespace) l = len(m.Namespace)
if l > 0 { if l > 0 {
@ -924,7 +922,7 @@ func (m *Envelope) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -33,16 +33,14 @@ import containerd_types "github.com/containerd/containerd/api/types"
import time "time" import time "time"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -455,16 +453,16 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) {
i += n1 i += n1
dAtA[i] = 0x3a dAtA[i] = 0x3a
i++ i++
i = encodeVarintImages(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) i = encodeVarintImages(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) n2, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n2 i += n2
dAtA[i] = 0x42 dAtA[i] = 0x42
i++ i++
i = encodeVarintImages(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintImages(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n3, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -761,9 +759,9 @@ func (m *Image) Size() (n int) {
} }
l = m.Target.Size() l = m.Target.Size()
n += 1 + l + sovImages(uint64(l)) n += 1 + l + sovImages(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) l = types.SizeOfStdTime(m.CreatedAt)
n += 1 + l + sovImages(uint64(l)) n += 1 + l + sovImages(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovImages(uint64(l)) n += 1 + l + sovImages(uint64(l))
return n return n
} }
@ -882,7 +880,7 @@ func (this *Image) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -1230,7 +1228,7 @@ func (m *Image) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -1260,7 +1258,7 @@ func (m *Image) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -18,18 +18,16 @@ import proto "github.com/gogo/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import containerd_types "github.com/containerd/containerd/api/types" import containerd_types "github.com/containerd/containerd/api/types"
import google_rpc "github.com/containerd/containerd/protobuf/google/rpc" import google_rpc "github.com/gogo/googleapis/google/rpc"
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" // skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -460,7 +458,7 @@ func (this *Plugin) String() string {
for k, _ := range this.Exports { for k, _ := range this.Exports {
keysForExports = append(keysForExports, k) keysForExports = append(keysForExports, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForExports) sortkeys.Strings(keysForExports)
mapStringForExports := "map[string]string{" mapStringForExports := "map[string]string{"
for _, k := range keysForExports { for _, k := range keysForExports {
mapStringForExports += fmt.Sprintf("%v: %v,", k, this.Exports[k]) mapStringForExports += fmt.Sprintf("%v: %v,", k, this.Exports[k])

View File

@ -27,16 +27,14 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -290,8 +288,8 @@ func (m *Lease) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintLeases(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) i = encodeVarintLeases(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -488,7 +486,7 @@ func (m *Lease) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovLeases(uint64(l)) n += 1 + l + sovLeases(uint64(l))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) l = types.SizeOfStdTime(m.CreatedAt)
n += 1 + l + sovLeases(uint64(l)) n += 1 + l + sovLeases(uint64(l))
if len(m.Labels) > 0 { if len(m.Labels) > 0 {
for k, v := range m.Labels { for k, v := range m.Labels {
@ -584,7 +582,7 @@ func (this *Lease) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -606,7 +604,7 @@ func (this *CreateRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -751,7 +749,7 @@ func (m *Lease) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -29,14 +29,12 @@ import math "math"
import google_protobuf1 "github.com/gogo/protobuf/types" import google_protobuf1 "github.com/gogo/protobuf/types"
import google_protobuf2 "github.com/gogo/protobuf/types" import google_protobuf2 "github.com/gogo/protobuf/types"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -787,7 +785,7 @@ func (this *Namespace) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])

View File

@ -40,16 +40,14 @@ import containerd_types "github.com/containerd/containerd/api/types"
import time "time" import time "time"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -1027,16 +1025,16 @@ func (m *Info) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x22 dAtA[i] = 0x22
i++ i++
i = encodeVarintSnapshots(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) i = encodeVarintSnapshots(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n1 i += n1
dAtA[i] = 0x2a dAtA[i] = 0x2a
i++ i++
i = encodeVarintSnapshots(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) i = encodeVarintSnapshots(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) n2, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1446,9 +1444,9 @@ func (m *Info) Size() (n int) {
if m.Kind != 0 { if m.Kind != 0 {
n += 1 + sovSnapshots(uint64(m.Kind)) n += 1 + sovSnapshots(uint64(m.Kind))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) l = types.SizeOfStdTime(m.CreatedAt)
n += 1 + l + sovSnapshots(uint64(l)) n += 1 + l + sovSnapshots(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovSnapshots(uint64(l)) n += 1 + l + sovSnapshots(uint64(l))
if len(m.Labels) > 0 { if len(m.Labels) > 0 {
for k, v := range m.Labels { for k, v := range m.Labels {
@ -1562,7 +1560,7 @@ func (this *PrepareSnapshotRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -1595,7 +1593,7 @@ func (this *ViewSnapshotRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -1660,7 +1658,7 @@ func (this *CommitSnapshotRequest) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -1694,7 +1692,7 @@ func (this *Info) String() string {
for k, _ := range this.Labels { for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k) keysForLabels = append(keysForLabels, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{" mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels { for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
@ -3257,7 +3255,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -3287,7 +3285,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -54,12 +54,10 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest" import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -1198,8 +1196,8 @@ func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x22 dAtA[i] = 0x22
i++ i++
i = encodeVarintTasks(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintTasks(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n3, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1881,8 +1879,8 @@ func (m *WaitResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintTasks(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintTasks(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n8, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1997,7 +1995,7 @@ func (m *DeleteResponse) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovTasks(uint64(m.ExitStatus)) n += 1 + sovTasks(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTasks(uint64(l)) n += 1 + l + sovTasks(uint64(l))
return n return n
} }
@ -2288,7 +2286,7 @@ func (m *WaitResponse) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovTasks(uint64(m.ExitStatus)) n += 1 + sovTasks(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTasks(uint64(l)) n += 1 + l + sovTasks(uint64(l))
return n return n
} }
@ -3375,7 +3373,7 @@ func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -5572,7 +5570,7 @@ func (m *WaitResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -19,10 +19,8 @@ import google_protobuf "github.com/gogo/protobuf/types"
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" // skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
import ( import context "golang.org/x/net/context"
context "golang.org/x/net/context" import grpc "google.golang.org/grpc"
grpc "google.golang.org/grpc"
)
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"

View File

@ -13,7 +13,7 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types1 "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -56,8 +56,8 @@ func (m *Metric) MarshalTo(dAtA []byte) (int, error) {
_ = l _ = l
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintMetrics(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) i = encodeVarintMetrics(dAtA, i, uint64(types1.SizeOfStdTime(m.Timestamp)))
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) n1, err := types1.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -93,7 +93,7 @@ func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int {
func (m *Metric) Size() (n int) { func (m *Metric) Size() (n int) {
var l int var l int
_ = l _ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) l = types1.SizeOfStdTime(m.Timestamp)
n += 1 + l + sovMetrics(uint64(l)) n += 1 + l + sovMetrics(uint64(l))
l = len(m.ID) l = len(m.ID)
if l > 0 { if l > 0 {
@ -194,7 +194,7 @@ func (m *Metric) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { if err := types1.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -23,7 +23,7 @@ import google_protobuf2 "github.com/gogo/protobuf/types"
import time "time" import time "time"
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -182,8 +182,8 @@ func (m *Process) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x52 dAtA[i] = 0x52
i++ i++
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n1, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -268,7 +268,7 @@ func (m *Process) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovTask(uint64(m.ExitStatus)) n += 1 + sovTask(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTask(uint64(l)) n += 1 + l + sovTask(uint64(l))
return n return n
} }
@ -614,7 +614,7 @@ func (m *Process) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -23,6 +23,7 @@ import (
"net/http" "net/http"
"runtime" "runtime"
"strconv" "strconv"
"sync"
"time" "time"
containersapi "github.com/containerd/containerd/api/services/containers/v1" containersapi "github.com/containerd/containerd/api/services/containers/v1"
@ -148,6 +149,7 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
// using a uniform interface // using a uniform interface
type Client struct { type Client struct {
services services
connMu sync.Mutex
conn *grpc.ClientConn conn *grpc.ClientConn
runtime string runtime string
connector func() (*grpc.ClientConn, error) connector func() (*grpc.ClientConn, error)
@ -158,6 +160,8 @@ func (c *Client) Reconnect() error {
if c.connector == nil { if c.connector == nil {
return errors.New("unable to reconnect to containerd, no connector available") return errors.New("unable to reconnect to containerd, no connector available")
} }
c.connMu.Lock()
defer c.connMu.Unlock()
c.conn.Close() c.conn.Close()
conn, err := c.connector() conn, err := c.connector()
if err != nil { if err != nil {
@ -174,9 +178,12 @@ func (c *Client) Reconnect() error {
// connection. A timeout can be set in the context to ensure it returns // connection. A timeout can be set in the context to ensure it returns
// early. // early.
func (c *Client) IsServing(ctx context.Context) (bool, error) { func (c *Client) IsServing(ctx context.Context) (bool, error) {
c.connMu.Lock()
if c.conn == nil { if c.conn == nil {
c.connMu.Unlock()
return false, errors.New("no grpc connection available") return false, errors.New("no grpc connection available")
} }
c.connMu.Unlock()
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.FailFast(false)) r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.FailFast(false))
if err != nil { if err != nil {
return false, err return false, err
@ -424,7 +431,12 @@ func (c *Client) Subscribe(ctx context.Context, filters ...string) (ch <-chan *e
// Close closes the clients connection to containerd // Close closes the clients connection to containerd
func (c *Client) Close() error { func (c *Client) Close() error {
return c.conn.Close() c.connMu.Lock()
defer c.connMu.Unlock()
if c.conn != nil {
return c.conn.Close()
}
return nil
} }
// NamespaceService returns the underlying Namespaces Store // NamespaceService returns the underlying Namespaces Store
@ -524,9 +536,12 @@ type Version struct {
// Version returns the version of containerd that the client is connected to // Version returns the version of containerd that the client is connected to
func (c *Client) Version(ctx context.Context) (Version, error) { func (c *Client) Version(ctx context.Context) (Version, error) {
c.connMu.Lock()
if c.conn == nil { if c.conn == nil {
c.connMu.Unlock()
return Version{}, errors.New("no grpc connection available") return Version{}, errors.New("no grpc connection available")
} }
c.connMu.Unlock()
response, err := c.VersionService().Version(ctx, &ptypes.Empty{}) response, err := c.VersionService().Version(ctx, &ptypes.Empty{})
if err != nil { if err != nil {
return Version{}, err return Version{}, err

View File

@ -53,6 +53,14 @@ type Image interface {
var _ = (Image)(&image{}) var _ = (Image)(&image{})
// NewImage returns a client image object from the metadata image
func NewImage(client *Client, i images.Image) Image {
return &image{
client: client,
i: i,
}
}
type image struct { type image struct {
client *Client client *Client

View File

@ -44,13 +44,13 @@ import containerd_v1_types "github.com/containerd/containerd/api/types/task"
import time "time" import time "time"
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" import types "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import context "context" import context "context"
import github_com_stevvooe_ttrpc "github.com/stevvooe/ttrpc" import ttrpc "github.com/stevvooe/ttrpc"
import io "io" import io "io"
@ -429,8 +429,8 @@ func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x1a dAtA[i] = 0x1a
i++ i++
i = encodeVarintShim(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintShim(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n2, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -672,8 +672,8 @@ func (m *StateResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x52 dAtA[i] = 0x52
i++ i++
i = encodeVarintShim(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintShim(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n4, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -992,8 +992,8 @@ func (m *WaitResponse) MarshalTo(dAtA []byte) (int, error) {
} }
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintShim(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt))) i = encodeVarintShim(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:]) n7, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1079,7 +1079,7 @@ func (m *DeleteResponse) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovShim(uint64(m.ExitStatus)) n += 1 + sovShim(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovShim(uint64(l)) n += 1 + l + sovShim(uint64(l))
return n return n
} }
@ -1190,7 +1190,7 @@ func (m *StateResponse) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovShim(uint64(m.ExitStatus)) n += 1 + sovShim(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovShim(uint64(l)) n += 1 + l + sovShim(uint64(l))
return n return n
} }
@ -1318,7 +1318,7 @@ func (m *WaitResponse) Size() (n int) {
if m.ExitStatus != 0 { if m.ExitStatus != 0 {
n += 1 + sovShim(uint64(m.ExitStatus)) n += 1 + sovShim(uint64(m.ExitStatus))
} }
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt) l = types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovShim(uint64(l)) n += 1 + l + sovShim(uint64(l))
return n return n
} }
@ -1597,8 +1597,8 @@ type ShimService interface {
Wait(ctx context.Context, req *WaitRequest) (*WaitResponse, error) Wait(ctx context.Context, req *WaitRequest) (*WaitResponse, error)
} }
func RegisterShimService(srv *github_com_stevvooe_ttrpc.Server, svc ShimService) { func RegisterShimService(srv *ttrpc.Server, svc ShimService) {
srv.Register("containerd.runtime.linux.shim.v1.Shim", map[string]github_com_stevvooe_ttrpc.Method{ srv.Register("containerd.runtime.linux.shim.v1.Shim", map[string]ttrpc.Method{
"State": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { "State": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req StateRequest var req StateRequest
if err := unmarshal(&req); err != nil { if err := unmarshal(&req); err != nil {
@ -1715,10 +1715,10 @@ func RegisterShimService(srv *github_com_stevvooe_ttrpc.Server, svc ShimService)
} }
type shimClient struct { type shimClient struct {
client *github_com_stevvooe_ttrpc.Client client *ttrpc.Client
} }
func NewShimClient(client *github_com_stevvooe_ttrpc.Client) ShimService { func NewShimClient(client *ttrpc.Client) ShimService {
return &shimClient{ return &shimClient{
client: client, client: client,
} }
@ -2379,7 +2379,7 @@ func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -3225,7 +3225,7 @@ func (m *StateResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -4221,7 +4221,7 @@ func (m *WaitResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil { if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -164,19 +164,11 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
if len(fieldpaths) == 0 { if len(fieldpaths) == 0 {
// only allow updates to these field on full replace. // only allow updates to these field on full replace.
fieldpaths = []string{"labels", "spec", "extensions"} fieldpaths = []string{"labels", "spec", "extensions", "image", "snapshotkey"}
// Fields that are immutable must cause an error when no field paths // Fields that are immutable must cause an error when no field paths
// are provided. This allows these fields to become mutable in the // are provided. This allows these fields to become mutable in the
// future. // future.
if updated.Image != container.Image {
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "container.Image field is immutable")
}
if updated.SnapshotKey != container.SnapshotKey {
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "container.SnapshotKey field is immutable")
}
if updated.Snapshotter != container.Snapshotter { if updated.Snapshotter != container.Snapshotter {
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "container.Snapshotter field is immutable") return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "container.Snapshotter field is immutable")
} }
@ -215,6 +207,10 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
updated.Spec = container.Spec updated.Spec = container.Spec
case "extensions": case "extensions":
updated.Extensions = container.Extensions updated.Extensions = container.Extensions
case "image":
updated.Image = container.Image
case "snapshotkey":
updated.SnapshotKey = container.SnapshotKey
default: default:
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on %q", path, container.ID) return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on %q", path, container.ID)
} }

View File

@ -17,6 +17,7 @@
package metadata package metadata
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"strings" "strings"
@ -345,7 +346,10 @@ func sendSnapshotRefs(ns string, bkt *bolt.Bucket, fn func(gc.Node)) error {
lc := lbkt.Cursor() lc := lbkt.Cursor()
for k, v := lc.Seek(labelGCSnapRef); k != nil && strings.HasPrefix(string(k), string(labelGCSnapRef)); k, v = lc.Next() { for k, v := lc.Seek(labelGCSnapRef); k != nil && strings.HasPrefix(string(k), string(labelGCSnapRef)); k, v = lc.Next() {
snapshotter := string(k[len(labelGCSnapRef):]) snapshotter := k[len(labelGCSnapRef):]
if i := bytes.IndexByte(snapshotter, '/'); i >= 0 {
snapshotter = snapshotter[:i]
}
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v))) fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v)))
} }
} }
@ -361,8 +365,8 @@ func sendContentRefs(ns string, bkt *bolt.Bucket, fn func(gc.Node)) error {
labelRef := string(labelGCContentRef) labelRef := string(labelGCContentRef)
for k, v := lc.Seek(labelGCContentRef); k != nil && strings.HasPrefix(string(k), labelRef); k, v = lc.Next() { for k, v := lc.Seek(labelGCContentRef); k != nil && strings.HasPrefix(string(k), labelRef); k, v = lc.Next() {
if ks := string(k); ks != labelRef { if ks := string(k); ks != labelRef {
// Allow reference naming, ignore names // Allow reference naming separated by . or /, ignore names
if ks[len(labelRef)] != '.' { if ks[len(labelRef)] != '.' && ks[len(labelRef)] != '/' {
continue continue
} }
} }

View File

@ -1,18 +0,0 @@
This package copies definitions used with GRPC to represent error conditions
within GRPC data types. These files are licensed under the provisions outlined
at the top of each file.
## `containerd`
This is moved from the [googleapis
project](https://github.com/googleapis/googleapis/tree/master/google/rpc) to
allow us to regenerate these types for use with gogoprotobuf. We can move this
away if google can generate these sensibly.
These files were imported from changes after
7f47d894837ac1701ee555fd5c3d70e5d4a796b1. Updates should not be required.
The other option is to get these into an upstream project, like gogoprotobuf.
Note that the `go_package` option has been changed so that they generate
correctly in a common package in the containerd project.

View File

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

View File

@ -27,6 +27,7 @@ import (
"path" "path"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
@ -253,12 +254,12 @@ func (r *dockerResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher
type dockerBase struct { type dockerBase struct {
refspec reference.Spec refspec reference.Spec
base url.URL base url.URL
token string
client *http.Client client *http.Client
useBasic bool useBasic bool
username string username, secret string
secret string token string
mu sync.Mutex
} }
func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) { func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
@ -300,6 +301,23 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
}, nil }, nil
} }
func (r *dockerBase) getToken() string {
r.mu.Lock()
defer r.mu.Unlock()
return r.token
}
func (r *dockerBase) setToken(token string) bool {
r.mu.Lock()
defer r.mu.Unlock()
changed := r.token != token
r.token = token
return changed
}
func (r *dockerBase) url(ps ...string) string { func (r *dockerBase) url(ps ...string) string {
url := r.base url := r.base
url.Path = path.Join(url.Path, path.Join(ps...)) url.Path = path.Join(url.Path, path.Join(ps...))
@ -307,10 +325,11 @@ func (r *dockerBase) url(ps ...string) string {
} }
func (r *dockerBase) authorize(req *http.Request) { func (r *dockerBase) authorize(req *http.Request) {
token := r.getToken()
if r.useBasic { if r.useBasic {
req.SetBasicAuth(r.username, r.secret) req.SetBasicAuth(r.username, r.secret)
} else if r.token != "" { } else if token != "" {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", r.token)) req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
} }
} }
@ -358,7 +377,7 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
for _, c := range parseAuthHeader(last.Header) { for _, c := range parseAuthHeader(last.Header) {
if c.scheme == bearerAuth { if c.scheme == bearerAuth {
if err := invalidAuthorization(c, responses); err != nil { if err := invalidAuthorization(c, responses); err != nil {
r.token = "" r.setToken("")
return nil, err return nil, err
} }
if err := r.setTokenAuth(ctx, c.parameters); err != nil { if err := r.setTokenAuth(ctx, c.parameters); err != nil {
@ -443,19 +462,22 @@ func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string)
if len(to.scopes) == 0 { if len(to.scopes) == 0 {
return errors.Errorf("no scope specified for token auth challenge") return errors.Errorf("no scope specified for token auth challenge")
} }
var token string
if r.secret != "" { if r.secret != "" {
// Credential information is provided, use oauth POST endpoint // Credential information is provided, use oauth POST endpoint
r.token, err = r.fetchTokenWithOAuth(ctx, to) token, err = r.fetchTokenWithOAuth(ctx, to)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to fetch oauth token") return errors.Wrap(err, "failed to fetch oauth token")
} }
} else { } else {
// Do request anonymously // Do request anonymously
r.token, err = r.getToken(ctx, to) token, err = r.fetchToken(ctx, to)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to fetch anonymous token") return errors.Wrap(err, "failed to fetch anonymous token")
} }
} }
r.setToken(token)
return nil return nil
} }
@ -500,7 +522,7 @@ func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (
// As of September 2017, GCR is known to return 404. // As of September 2017, GCR is known to return 404.
// As of February 2018, JFrog Artifactory is known to return 401. // As of February 2018, JFrog Artifactory is known to return 401.
if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 { if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
return r.getToken(ctx, to) return r.fetchToken(ctx, to)
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 { } else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
log.G(ctx).WithFields(logrus.Fields{ log.G(ctx).WithFields(logrus.Fields{
@ -530,7 +552,7 @@ type getTokenResponse struct {
} }
// getToken fetches a token using a GET request // getToken fetches a token using a GET request
func (r *dockerBase) getToken(ctx context.Context, to tokenOptions) (string, error) { func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
req, err := http.NewRequest("GET", to.realm, nil) req, err := http.NewRequest("GET", to.realm, nil)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -22,7 +22,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/protobuf/google/rpc" "github.com/gogo/googleapis/google/rpc"
ptypes "github.com/gogo/protobuf/types" ptypes "github.com/gogo/protobuf/types"
context "golang.org/x/net/context" context "golang.org/x/net/context"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -142,7 +142,7 @@ func pluginsToPB(plugins []*plugin.Plugin) []api.Plugin {
} }
} else { } else {
initErr = &rpc.Status{ initErr = &rpc.Status{
Code: int32(rpc.Code_UNKNOWN), Code: int32(rpc.UNKNOWN),
Message: err.Error(), Message: err.Error(),
} }
} }

View File

@ -16,7 +16,8 @@ github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/matttproud/golang_protobuf_extensions v1.0.0
github.com/gogo/protobuf v0.5 github.com/gogo/protobuf v1.0.0
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
github.com/opencontainers/runtime-spec v1.0.1 github.com/opencontainers/runtime-spec v1.0.1
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340 github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
@ -24,7 +25,7 @@ github.com/sirupsen/logrus v1.0.0
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
google.golang.org/grpc v1.7.4 google.golang.org/grpc v1.10.1
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.8.0
github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448 github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448
golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys
@ -43,7 +44,7 @@ github.com/gotestyourself/gotestyourself 44dbf532bbf5767611f6f2a61bded572e337010
github.com/google/go-cmp v0.1.0 github.com/google/go-cmp v0.1.0
# cri dependencies # cri dependencies
github.com/containerd/cri v1.0.0-rc.1 github.com/containerd/cri v1.0.0-rc.2
github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7 github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7
github.com/blang/semver v3.1.0 github.com/blang/semver v3.1.0
github.com/containernetworking/cni v0.6.0 github.com/containernetworking/cni v0.6.0

View File

@ -21,7 +21,7 @@ var (
Package = "github.com/containerd/containerd" Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time. // Version holds the complete version number. Filled in at linking time.
Version = "1.1.0-rc.1+unknown" Version = "1.1.0-rc.2+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build // Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time. // the program at linking time.

5
vendor/github.com/gogo/googleapis/Readme.md generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Google APIs generated by gogoprotobuf
[![Build Status](https://travis-ci.org/gogo/googleapis.svg?branch=master)](https://travis-ci.org/gogo/googleapis)
The [grpc-example](https://github.com/gogo/grpc-example) includes an example usage of this repository.

View File

@ -1,43 +1,19 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT. // Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: github.com/containerd/containerd/protobuf/google/rpc/code.proto // source: google/rpc/code.proto
/*
Package rpc is a generated protocol buffer package.
It is generated from these files:
github.com/containerd/containerd/protobuf/google/rpc/code.proto
github.com/containerd/containerd/protobuf/google/rpc/error_details.proto
github.com/containerd/containerd/protobuf/google/rpc/status.proto
It has these top-level messages:
RetryInfo
DebugInfo
QuotaFailure
PreconditionFailure
BadRequest
RequestInfo
ResourceInfo
Help
LocalizedMessage
Status
*/
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import proto "github.com/gogo/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import strconv "strconv"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The canonical error codes for Google APIs. // The canonical error codes for Google APIs.
// //
// //
@ -51,11 +27,11 @@ const (
// Not an error; returned on success // Not an error; returned on success
// //
// HTTP Mapping: 200 OK // HTTP Mapping: 200 OK
Code_OK Code = 0 OK Code = 0
// The operation was cancelled, typically by the caller. // The operation was cancelled, typically by the caller.
// //
// HTTP Mapping: 499 Client Closed Request // HTTP Mapping: 499 Client Closed Request
Code_CANCELLED Code = 1 CANCELLED Code = 1
// Unknown error. For example, this error may be returned when // Unknown error. For example, this error may be returned when
// a `Status` value received from another address space belongs to // a `Status` value received from another address space belongs to
// an error space that is not known in this address space. Also // an error space that is not known in this address space. Also
@ -63,14 +39,14 @@ const (
// may be converted to this error. // may be converted to this error.
// //
// HTTP Mapping: 500 Internal Server Error // HTTP Mapping: 500 Internal Server Error
Code_UNKNOWN Code = 2 UNKNOWN Code = 2
// The client specified an invalid argument. Note that this differs // The client specified an invalid argument. Note that this differs
// from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments // from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
// that are problematic regardless of the state of the system // that are problematic regardless of the state of the system
// (e.g., a malformed file name). // (e.g., a malformed file name).
// //
// HTTP Mapping: 400 Bad Request // HTTP Mapping: 400 Bad Request
Code_INVALID_ARGUMENT Code = 3 INVALID_ARGUMENT Code = 3
// The deadline expired before the operation could complete. For operations // The deadline expired before the operation could complete. For operations
// that change the state of the system, this error may be returned // that change the state of the system, this error may be returned
// even if the operation has completed successfully. For example, a // even if the operation has completed successfully. For example, a
@ -78,7 +54,7 @@ const (
// enough for the deadline to expire. // enough for the deadline to expire.
// //
// HTTP Mapping: 504 Gateway Timeout // HTTP Mapping: 504 Gateway Timeout
Code_DEADLINE_EXCEEDED Code = 4 DEADLINE_EXCEEDED Code = 4
// Some requested entity (e.g., file or directory) was not found. // Some requested entity (e.g., file or directory) was not found.
// //
// Note to server developers: if a request is denied for an entire class // Note to server developers: if a request is denied for an entire class
@ -88,12 +64,12 @@ const (
// must be used. // must be used.
// //
// HTTP Mapping: 404 Not Found // HTTP Mapping: 404 Not Found
Code_NOT_FOUND Code = 5 NOT_FOUND Code = 5
// The entity that a client attempted to create (e.g., file or directory) // The entity that a client attempted to create (e.g., file or directory)
// already exists. // already exists.
// //
// HTTP Mapping: 409 Conflict // HTTP Mapping: 409 Conflict
Code_ALREADY_EXISTS Code = 6 ALREADY_EXISTS Code = 6
// The caller does not have permission to execute the specified // The caller does not have permission to execute the specified
// operation. `PERMISSION_DENIED` must not be used for rejections // operation. `PERMISSION_DENIED` must not be used for rejections
// caused by exhausting some resource (use `RESOURCE_EXHAUSTED` // caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
@ -104,17 +80,17 @@ const (
// other pre-conditions. // other pre-conditions.
// //
// HTTP Mapping: 403 Forbidden // HTTP Mapping: 403 Forbidden
Code_PERMISSION_DENIED Code = 7 PERMISSION_DENIED Code = 7
// The request does not have valid authentication credentials for the // The request does not have valid authentication credentials for the
// operation. // operation.
// //
// HTTP Mapping: 401 Unauthorized // HTTP Mapping: 401 Unauthorized
Code_UNAUTHENTICATED Code = 16 UNAUTHENTICATED Code = 16
// Some resource has been exhausted, perhaps a per-user quota, or // Some resource has been exhausted, perhaps a per-user quota, or
// perhaps the entire file system is out of space. // perhaps the entire file system is out of space.
// //
// HTTP Mapping: 429 Too Many Requests // HTTP Mapping: 429 Too Many Requests
Code_RESOURCE_EXHAUSTED Code = 8 RESOURCE_EXHAUSTED Code = 8
// The operation was rejected because the system is not in a state // The operation was rejected because the system is not in a state
// required for the operation's execution. For example, the directory // required for the operation's execution. For example, the directory
// to be deleted is non-empty, an rmdir operation is applied to // to be deleted is non-empty, an rmdir operation is applied to
@ -133,7 +109,7 @@ const (
// the files are deleted from the directory. // the files are deleted from the directory.
// //
// HTTP Mapping: 400 Bad Request // HTTP Mapping: 400 Bad Request
Code_FAILED_PRECONDITION Code = 9 FAILED_PRECONDITION Code = 9
// The operation was aborted, typically due to a concurrency issue such as // The operation was aborted, typically due to a concurrency issue such as
// a sequencer check failure or transaction abort. // a sequencer check failure or transaction abort.
// //
@ -141,7 +117,7 @@ const (
// `ABORTED`, and `UNAVAILABLE`. // `ABORTED`, and `UNAVAILABLE`.
// //
// HTTP Mapping: 409 Conflict // HTTP Mapping: 409 Conflict
Code_ABORTED Code = 10 ABORTED Code = 10
// The operation was attempted past the valid range. E.g., seeking or // The operation was attempted past the valid range. E.g., seeking or
// reading past end-of-file. // reading past end-of-file.
// //
@ -159,18 +135,18 @@ const (
// they are done. // they are done.
// //
// HTTP Mapping: 400 Bad Request // HTTP Mapping: 400 Bad Request
Code_OUT_OF_RANGE Code = 11 OUT_OF_RANGE Code = 11
// The operation is not implemented or is not supported/enabled in this // The operation is not implemented or is not supported/enabled in this
// service. // service.
// //
// HTTP Mapping: 501 Not Implemented // HTTP Mapping: 501 Not Implemented
Code_UNIMPLEMENTED Code = 12 UNIMPLEMENTED Code = 12
// Internal errors. This means that some invariants expected by the // Internal errors. This means that some invariants expected by the
// underlying system have been broken. This error code is reserved // underlying system have been broken. This error code is reserved
// for serious errors. // for serious errors.
// //
// HTTP Mapping: 500 Internal Server Error // HTTP Mapping: 500 Internal Server Error
Code_INTERNAL Code = 13 INTERNAL Code = 13
// The service is currently unavailable. This is most likely a // The service is currently unavailable. This is most likely a
// transient condition, which can be corrected by retrying with // transient condition, which can be corrected by retrying with
// a backoff. // a backoff.
@ -179,11 +155,11 @@ const (
// `ABORTED`, and `UNAVAILABLE`. // `ABORTED`, and `UNAVAILABLE`.
// //
// HTTP Mapping: 503 Service Unavailable // HTTP Mapping: 503 Service Unavailable
Code_UNAVAILABLE Code = 14 UNAVAILABLE Code = 14
// Unrecoverable data loss or corruption. // Unrecoverable data loss or corruption.
// //
// HTTP Mapping: 500 Internal Server Error // HTTP Mapping: 500 Internal Server Error
Code_DATA_LOSS Code = 15 DATA_LOSS Code = 15
) )
var Code_name = map[int32]string{ var Code_name = map[int32]string{
@ -225,45 +201,46 @@ var Code_value = map[string]int32{
"DATA_LOSS": 15, "DATA_LOSS": 15,
} }
func (x Code) String() string {
return proto.EnumName(Code_name, int32(x))
}
func (Code) EnumDescriptor() ([]byte, []int) { return fileDescriptorCode, []int{0} } func (Code) EnumDescriptor() ([]byte, []int) { return fileDescriptorCode, []int{0} }
func init() { func init() {
proto.RegisterEnum("google.rpc.Code", Code_name, Code_value) proto.RegisterEnum("google.rpc.Code", Code_name, Code_value)
} }
func (x Code) String() string {
func init() { s, ok := Code_name[int32(x)]
proto.RegisterFile("github.com/containerd/containerd/protobuf/google/rpc/code.proto", fileDescriptorCode) if ok {
return s
}
return strconv.Itoa(int(x))
} }
func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptorCode) }
var fileDescriptorCode = []byte{ var fileDescriptorCode = []byte{
// 405 bytes of a gzipped FileDescriptorProto // 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0xbb, 0x72, 0x13, 0x31, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41,
0x14, 0x86, 0xbd, 0x4e, 0x70, 0x62, 0xf9, 0x76, 0xa2, 0x70, 0xe9, 0xf6, 0x01, 0x28, 0xec, 0x82, 0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a,
0x86, 0x19, 0x0a, 0xe6, 0x78, 0x75, 0x9c, 0x68, 0x22, 0x1f, 0xed, 0x68, 0xa5, 0x10, 0x68, 0x76, 0x4e, 0xf0, 0xbc, 0xf3, 0x9c, 0x8c, 0x32, 0x7e, 0xb3, 0x9a, 0x9d, 0x09, 0x01, 0x21, 0xad, 0xc4,
0xf0, 0xda, 0x98, 0xcc, 0x90, 0xac, 0x67, 0xc7, 0xee, 0x79, 0x16, 0x5e, 0x82, 0x57, 0x48, 0x49, 0xc6, 0x4a, 0x03, 0x5a, 0xcb, 0xe2, 0x00, 0x9c, 0x85, 0x8a, 0x1b, 0x70, 0x85, 0x94, 0x29, 0x29,
0x49, 0x49, 0xfc, 0x24, 0x8c, 0x4c, 0x01, 0x35, 0x9d, 0xe6, 0xff, 0x75, 0x2e, 0xff, 0x77, 0xc4, 0xf1, 0xa6, 0xa1, 0x74, 0x49, 0x89, 0x06, 0x0a, 0xda, 0x9f, 0xde, 0xc7, 0xff, 0x43, 0x9e, 0xdf,
0xdb, 0xf5, 0xed, 0xf6, 0xf3, 0x6e, 0x31, 0xae, 0xea, 0xbb, 0x49, 0x55, 0xdf, 0x6f, 0x3f, 0xde, 0xb7, 0xed, 0xfd, 0xc7, 0xcd, 0xc5, 0x6e, 0xdb, 0x5c, 0x34, 0xed, 0xdd, 0x66, 0xb1, 0xdd, 0xb5,
0xde, 0xaf, 0x9a, 0xe5, 0xbf, 0xcf, 0x4d, 0x53, 0x6f, 0xeb, 0xc5, 0xee, 0xd3, 0x64, 0x5d, 0xd7, 0x9f, 0x5b, 0x25, 0xff, 0xe1, 0xc5, 0x6e, 0xdb, 0xbc, 0xfa, 0xde, 0x97, 0x47, 0x45, 0x7b, 0xb7,
0xeb, 0x2f, 0xab, 0x49, 0xb3, 0xa9, 0x26, 0x55, 0xbd, 0x5c, 0x8d, 0x0f, 0x86, 0x14, 0x7f, 0xe4, 0x51, 0x43, 0xd9, 0xf7, 0xd7, 0xd0, 0x53, 0x53, 0x39, 0x2a, 0x90, 0x0b, 0x72, 0x8e, 0x0c, 0x08,
0x71, 0xb3, 0xa9, 0x5e, 0x7e, 0x6f, 0x8b, 0xe3, 0xac, 0x5e, 0xae, 0x64, 0x47, 0xb4, 0xed, 0x15, 0x35, 0x96, 0xc7, 0x89, 0xaf, 0xd9, 0xbf, 0x61, 0xe8, 0xab, 0xe7, 0x12, 0x2c, 0xdf, 0xa0, 0xb3,
0xb4, 0xe4, 0x40, 0x74, 0x33, 0xe4, 0x8c, 0x8c, 0x21, 0x05, 0x89, 0xec, 0x89, 0x93, 0xc0, 0x57, 0xa6, 0xc6, 0x70, 0x99, 0xd6, 0xc4, 0x11, 0x06, 0xea, 0x5c, 0x9e, 0x1a, 0x42, 0xe3, 0x2c, 0x53,
0x6c, 0xdf, 0x31, 0xb4, 0xe5, 0x53, 0x01, 0x9a, 0xaf, 0xd1, 0x68, 0x55, 0xa2, 0xbb, 0x08, 0x73, 0x4d, 0xb7, 0x05, 0x91, 0x21, 0x03, 0x47, 0xf9, 0x10, 0xfb, 0x58, 0xaf, 0x7c, 0x62, 0x03, 0xcf,
0x62, 0x0f, 0x47, 0xf2, 0x99, 0x38, 0x53, 0x84, 0xca, 0x68, 0xa6, 0x92, 0x6e, 0x32, 0x22, 0x45, 0x94, 0x92, 0x33, 0x74, 0x81, 0xd0, 0xbc, 0xad, 0xe9, 0xd6, 0x56, 0xb1, 0x82, 0x61, 0xde, 0x2c,
0x0a, 0x8e, 0x63, 0x23, 0xb6, 0xbe, 0x9c, 0xd9, 0xc0, 0x0a, 0x9e, 0x48, 0x29, 0x86, 0x68, 0x1c, 0x29, 0xac, 0x6d, 0x55, 0x59, 0xcf, 0xb5, 0x21, 0xb6, 0x64, 0xe0, 0x58, 0x9d, 0xc9, 0x79, 0x62,
0xa1, 0x7a, 0x5f, 0xd2, 0x8d, 0x2e, 0x7c, 0x01, 0x9d, 0x58, 0x99, 0x93, 0x9b, 0xeb, 0xa2, 0xd0, 0x4c, 0xf1, 0x8a, 0x38, 0xda, 0x02, 0x23, 0x19, 0x00, 0xf5, 0x42, 0xaa, 0x40, 0x95, 0x4f, 0xa1,
0x96, 0x4b, 0x45, 0xac, 0x49, 0xc1, 0x89, 0x3c, 0x17, 0xa3, 0xc0, 0x18, 0xfc, 0x25, 0xb1, 0xd7, 0xc8, 0x5f, 0xae, 0x30, 0x55, 0x99, 0x9f, 0xa8, 0x97, 0xf2, 0x6c, 0x85, 0xd6, 0x91, 0xa9, 0xcb,
0x19, 0x7a, 0x52, 0x00, 0xf2, 0xb9, 0x90, 0x8e, 0x0a, 0x1b, 0x5c, 0x16, 0xa7, 0x5c, 0x62, 0x28, 0x40, 0x85, 0x67, 0x63, 0xa3, 0xf5, 0x0c, 0xa3, 0xac, 0x1c, 0x97, 0x3e, 0xe4, 0x29, 0xa9, 0x40,
0xa2, 0x7e, 0x2a, 0x5f, 0x88, 0xf3, 0x19, 0x6a, 0x43, 0xaa, 0xcc, 0x1d, 0x65, 0x96, 0x95, 0xf6, 0x4e, 0x7c, 0x8a, 0xb5, 0x5f, 0xd5, 0x01, 0xf9, 0x92, 0x60, 0xac, 0x4e, 0xe5, 0x34, 0xb1, 0x5d,
0xda, 0x32, 0x74, 0xe3, 0xe6, 0x38, 0xb5, 0x2e, 0xfe, 0x12, 0x12, 0x44, 0xdf, 0x06, 0x5f, 0xda, 0x97, 0x8e, 0xb2, 0x0d, 0x32, 0x30, 0x51, 0x13, 0x79, 0x62, 0x39, 0x52, 0x60, 0x74, 0x30, 0x55,
0x59, 0xe9, 0x90, 0x2f, 0x08, 0x7a, 0xf2, 0x4c, 0x0c, 0x02, 0xeb, 0x79, 0x6e, 0x28, 0xc6, 0x20, 0x73, 0x39, 0x4e, 0x8c, 0x37, 0x68, 0x1d, 0x2e, 0x1d, 0xc1, 0x2c, 0x1b, 0x32, 0x18, 0xb1, 0x76,
0x05, 0x7d, 0xd9, 0x17, 0xa7, 0x9a, 0x3d, 0x39, 0x46, 0x03, 0x03, 0x39, 0x12, 0xbd, 0xc0, 0x78, 0xbe, 0xaa, 0x60, 0xbe, 0x7c, 0xff, 0xb8, 0xd7, 0xbd, 0x1f, 0x7b, 0xdd, 0x3b, 0xec, 0xb5, 0xf8,
0x8d, 0xda, 0xe0, 0xd4, 0x10, 0x0c, 0x63, 0x20, 0x85, 0x1e, 0x4b, 0x63, 0x8b, 0x02, 0x46, 0xd3, 0xbd, 0xd7, 0xe2, 0x4b, 0xa7, 0xc5, 0xb7, 0x4e, 0x8b, 0x87, 0x4e, 0x8b, 0xc7, 0x4e, 0x8b, 0x9f,
0xdd, 0xc3, 0x63, 0xda, 0xfa, 0xf9, 0x98, 0xb6, 0xbe, 0xee, 0xd3, 0xe4, 0x61, 0x9f, 0x26, 0x3f, 0x9d, 0x16, 0xbf, 0x3a, 0xdd, 0x3b, 0x64, 0xfe, 0xa4, 0xc5, 0xc3, 0x93, 0x16, 0x72, 0xd6, 0xb4,
0xf6, 0x69, 0xf2, 0x6b, 0x9f, 0x26, 0x62, 0x58, 0xd5, 0x77, 0xe3, 0xbf, 0x8c, 0xa7, 0xdd, 0x08, 0x9f, 0x16, 0xff, 0xf3, 0x5f, 0x8e, 0x72, 0xf8, 0x65, 0xae, 0xa5, 0x14, 0xef, 0x06, 0xbb, 0x6d,
0x38, 0x8f, 0xe8, 0xf3, 0xe4, 0xc3, 0xeb, 0xff, 0xb9, 0xde, 0x9b, 0x66, 0x53, 0x7d, 0x6b, 0x1f, 0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff,
0xb9, 0x3c, 0x5b, 0x74, 0x0e, 0xf6, 0xab, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf2, 0x0a, 0x2d, 0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00,
0x67, 0x06, 0x02, 0x00, 0x00,
} }

View File

@ -16,7 +16,7 @@ syntax = "proto3";
package google.rpc; package google.rpc;
option go_package = "github.com/containerd/containerd/protobuf/google/rpc;rpc"; option go_package = "rpc";
option java_multiple_files = true; option java_multiple_files = true;
option java_outer_classname = "CodeProto"; option java_outer_classname = "CodeProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";

View File

@ -18,7 +18,7 @@ package google.rpc;
import "google/protobuf/duration.proto"; import "google/protobuf/duration.proto";
option go_package = "github.com/containerd/containerd/protobuf/google/rpc;rpc"; option go_package = "rpc";
option java_multiple_files = true; option java_multiple_files = true;
option java_outer_classname = "ErrorDetailsProto"; option java_outer_classname = "ErrorDetailsProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";

View File

@ -1,12 +1,32 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT. // Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: github.com/containerd/containerd/protobuf/google/rpc/status.proto // source: google/rpc/status.proto
/*
Package rpc is a generated protocol buffer package.
It is generated from these files:
google/rpc/status.proto
google/rpc/error_details.proto
google/rpc/code.proto
It has these top-level messages:
Status
RetryInfo
DebugInfo
QuotaFailure
PreconditionFailure
BadRequest
RequestInfo
ResourceInfo
Help
LocalizedMessage
*/
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import proto "github.com/gogo/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import google_protobuf1 "github.com/gogo/protobuf/types" import google_protobuf "github.com/gogo/protobuf/types"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -18,6 +38,12 @@ var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for different // The `Status` type defines a logical error model that is suitable for different
// programming environments, including REST APIs and RPC APIs. It is used by // programming environments, including REST APIs and RPC APIs. It is used by
// [gRPC](https://github.com/grpc). The error model is designed to be: // [gRPC](https://github.com/grpc). The error model is designed to be:
@ -79,16 +105,147 @@ type Status struct {
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.
Details []*google_protobuf1.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"` Details []*google_protobuf.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"`
} }
func (m *Status) Reset() { *m = Status{} } func (m *Status) Reset() { *m = Status{} }
func (*Status) ProtoMessage() {} func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorStatus, []int{0} } func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorStatus, []int{0} }
func (m *Status) GetCode() int32 {
if m != nil {
return m.Code
}
return 0
}
func (m *Status) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Status) GetDetails() []*google_protobuf.Any {
if m != nil {
return m.Details
}
return nil
}
func (*Status) XXX_MessageName() string {
return "google.rpc.Status"
}
func init() { func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status") proto.RegisterType((*Status)(nil), "google.rpc.Status")
} }
func (this *Status) Compare(that interface{}) int {
if that == nil {
if this == nil {
return 0
}
return 1
}
that1, ok := that.(*Status)
if !ok {
that2, ok := that.(Status)
if ok {
that1 = &that2
} else {
return 1
}
}
if that1 == nil {
if this == nil {
return 0
}
return 1
} else if this == nil {
return -1
}
if this.Code != that1.Code {
if this.Code < that1.Code {
return -1
}
return 1
}
if this.Message != that1.Message {
if this.Message < that1.Message {
return -1
}
return 1
}
if len(this.Details) != len(that1.Details) {
if len(this.Details) < len(that1.Details) {
return -1
}
return 1
}
for i := range this.Details {
if c := this.Details[i].Compare(that1.Details[i]); c != 0 {
return c
}
}
return 0
}
func (this *Status) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*Status)
if !ok {
that2, ok := that.(Status)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if this.Code != that1.Code {
return false
}
if this.Message != that1.Message {
return false
}
if len(this.Details) != len(that1.Details) {
return false
}
for i := range this.Details {
if !this.Details[i].Equal(that1.Details[i]) {
return false
}
}
return true
}
func (this *Status) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&rpc.Status{")
s = append(s, "Code: "+fmt.Sprintf("%#v", this.Code)+",\n")
s = append(s, "Message: "+fmt.Sprintf("%#v", this.Message)+",\n")
if this.Details != nil {
s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func valueToGoStringStatus(v interface{}, typ string) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
}
func (m *Status) Marshal() (dAtA []byte, err error) { func (m *Status) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@ -139,6 +296,97 @@ func encodeVarintStatus(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v) dAtA[offset] = uint8(v)
return offset + 1 return offset + 1
} }
func NewPopulatedStatus(r randyStatus, easy bool) *Status {
this := &Status{}
this.Code = int32(r.Int31())
if r.Intn(2) == 0 {
this.Code *= -1
}
this.Message = string(randStringStatus(r))
if r.Intn(10) != 0 {
v1 := r.Intn(5)
this.Details = make([]*google_protobuf.Any, v1)
for i := 0; i < v1; i++ {
this.Details[i] = google_protobuf.NewPopulatedAny(r, easy)
}
}
if !easy && r.Intn(10) != 0 {
}
return this
}
type randyStatus interface {
Float32() float32
Float64() float64
Int63() int64
Int31() int32
Uint32() uint32
Intn(n int) int
}
func randUTF8RuneStatus(r randyStatus) rune {
ru := r.Intn(62)
if ru < 10 {
return rune(ru + 48)
} else if ru < 36 {
return rune(ru + 55)
}
return rune(ru + 61)
}
func randStringStatus(r randyStatus) string {
v2 := r.Intn(100)
tmps := make([]rune, v2)
for i := 0; i < v2; i++ {
tmps[i] = randUTF8RuneStatus(r)
}
return string(tmps)
}
func randUnrecognizedStatus(r randyStatus, maxFieldNumber int) (dAtA []byte) {
l := r.Intn(5)
for i := 0; i < l; i++ {
wire := r.Intn(4)
if wire == 3 {
wire = 5
}
fieldNumber := maxFieldNumber + r.Intn(100)
dAtA = randFieldStatus(dAtA, r, fieldNumber, wire)
}
return dAtA
}
func randFieldStatus(dAtA []byte, r randyStatus, fieldNumber int, wire int) []byte {
key := uint32(fieldNumber)<<3 | uint32(wire)
switch wire {
case 0:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
v3 := r.Int63()
if r.Intn(2) == 0 {
v3 *= -1
}
dAtA = encodeVarintPopulateStatus(dAtA, uint64(v3))
case 1:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
case 2:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
ll := r.Intn(100)
dAtA = encodeVarintPopulateStatus(dAtA, uint64(ll))
for j := 0; j < ll; j++ {
dAtA = append(dAtA, byte(r.Intn(256)))
}
default:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
}
return dAtA
}
func encodeVarintPopulateStatus(dAtA []byte, v uint64) []byte {
for v >= 1<<7 {
dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
v >>= 7
}
dAtA = append(dAtA, uint8(v))
return dAtA
}
func (m *Status) Size() (n int) { func (m *Status) Size() (n int) {
var l int var l int
_ = l _ = l
@ -178,7 +426,7 @@ func (this *Status) String() string {
s := strings.Join([]string{`&Status{`, s := strings.Join([]string{`&Status{`,
`Code:` + fmt.Sprintf("%v", this.Code) + `,`, `Code:` + fmt.Sprintf("%v", this.Code) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "google_protobuf1.Any", 1) + `,`, `Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "google_protobuf.Any", 1) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -294,7 +542,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Details = append(m.Details, &google_protobuf1.Any{}) m.Details = append(m.Details, &google_protobuf.Any{})
if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -425,25 +673,23 @@ var (
ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow") ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow")
) )
func init() { func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptorStatus) }
proto.RegisterFile("github.com/containerd/containerd/protobuf/google/rpc/status.proto", fileDescriptorStatus)
}
var fileDescriptorStatus = []byte{ var fileDescriptorStatus = []byte{
// 236 bytes of a gzipped FileDescriptorProto // 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4c, 0xcf, 0x2c, 0xc9, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0x4a, 0x41, 0x66, 0x16, 0x14, 0xe5, 0x97, 0xe4, 0x27, 0x95, 0xa6, 0xe9, 0xa7, 0xe7, 0xe7, 0xa7, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0xe7, 0xa4, 0xea, 0x17, 0x15, 0x24, 0xeb, 0x17, 0x97, 0x24, 0x96, 0x94, 0x16, 0xeb, 0x81, 0xa5, 0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0x84, 0xb8, 0x20, 0x12, 0x7a, 0x45, 0x05, 0xc9, 0x52, 0x92, 0x50, 0x45, 0x70, 0x4d, 0x89, 0x79, 0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0x95, 0x10, 0x65, 0x4a, 0x69, 0x5c, 0x6c, 0xc1, 0x60, 0x6d, 0x42, 0x42, 0x5c, 0x2c, 0xc9, 0xf9, 0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x29, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x60, 0xb6, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x6a, 0x71, 0x71, 0x62, 0x7a, 0xaa, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x8c, 0x2b, 0xa4, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xc7, 0xc5, 0x9e, 0x92, 0x5a, 0x92, 0x98, 0x99, 0x53, 0x2c, 0xc1, 0xac, 0xc0, 0xac, 0xc1, 0x6d, 0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xb8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0x24, 0xa2, 0x07, 0xb5, 0x10, 0x66, 0x89, 0x9e, 0x63, 0x5e, 0x65, 0x10, 0x4c, 0x91, 0x53, 0xf9, 0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x89, 0x87, 0x72, 0x0c, 0x37, 0x1e, 0xca, 0x31, 0x34, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0xb9, 0xf8, 0x92, 0xf3, 0x73, 0xf5, 0x10, 0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x8e, 0x75, 0xe2, 0x86, 0xb8, 0x27, 0x00, 0x64, 0x4c, 0x00, 0x63, 0x94, 0x05, 0x39, 0x41, 0x61, 0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x5d, 0x54, 0x90, 0xbc, 0x88, 0x89, 0x39, 0x28, 0xc0, 0x39, 0x89, 0x0d, 0x2c, 0x6d, 0x0c, 0x08, 0x15, 0x24, 0x2f, 0x62, 0x62, 0x0e, 0x0a, 0x70, 0x4e, 0x62, 0x03, 0x5b, 0x6b, 0x0c, 0x08, 0x00,
0x00, 0x00, 0xff, 0xff, 0x7d, 0xb3, 0x06, 0x51, 0x53, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x06, 0xa1, 0xaa, 0x10, 0x01, 0x00, 0x00,
} }

View File

@ -18,7 +18,7 @@ package google.rpc;
import "google/protobuf/any.proto"; import "google/protobuf/any.proto";
option go_package = "github.com/containerd/containerd/protobuf/google/rpc;rpc"; option go_package = "rpc";
option java_multiple_files = true; option java_multiple_files = true;
option java_outer_classname = "StatusProto"; option java_outer_classname = "StatusProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";

View File

@ -123,6 +123,7 @@ When the .proto file specifies `syntax="proto3"`, there are some differences:
Consider file test.proto, containing Consider file test.proto, containing
```proto ```proto
syntax = "proto2";
package example; package example;
enum FOO { X = 17; }; enum FOO { X = 17; };

View File

@ -43,8 +43,9 @@ These projects use gogoprotobuf:
- <a href="https://github.com/heroiclabs/nakama">nakama</a> - <a href="https://github.com/heroiclabs/nakama">nakama</a>
- <a href="https://github.com/src-d/proteus">proteus</a> - <a href="https://github.com/src-d/proteus">proteus</a>
- <a href="https://github.com/go-graphite">carbonzipper stack</a> - <a href="https://github.com/go-graphite">carbonzipper stack</a>
- <a href="https://sendgrid.com/">SendGrid</a> - <a href="https://sendgrid.com/">sendgrid</a>
- <a href="https://github.com/zero-os/0-stor">zero-os/0-stor</a>
Please let us know if you are using gogoprotobuf by posting on our <a href="https://groups.google.com/forum/#!topic/gogoprotobuf/Brw76BxmFpQ">GoogleGroup</a>. Please let us know if you are using gogoprotobuf by posting on our <a href="https://groups.google.com/forum/#!topic/gogoprotobuf/Brw76BxmFpQ">GoogleGroup</a>.
### Mentioned ### Mentioned
@ -64,10 +65,10 @@ After that you can choose:
### Installation ### Installation
To install it, you must first have Go (at least version 1.6.3) installed (see [http://golang.org/doc/install](http://golang.org/doc/install)). Go 1.8.3 and 1.9 are continuously tested. To install it, you must first have Go (at least version 1.6.3) installed (see [http://golang.org/doc/install](http://golang.org/doc/install)). Latest patch versions of Go 1.8, 1.9 and 1.10 are continuously tested.
Next, install the standard protocol buffer implementation from [https://github.com/google/protobuf](https://github.com/google/protobuf). Next, install the standard protocol buffer implementation from [https://github.com/google/protobuf](https://github.com/google/protobuf).
Most versions from 2.3.1 should not give any problems, but 2.6.1, 3.0.2 and 3.4.0 are continuously tested. Most versions from 2.3.1 should not give any problems, but 2.6.1, 3.0.2 and 3.5.1 are continuously tested.
### Speed ### Speed
@ -98,7 +99,23 @@ Installing any of these binaries is easy. Simply run:
go get github.com/gogo/protobuf/{binary} go get github.com/gogo/protobuf/{binary}
go get github.com/gogo/protobuf/gogoproto go get github.com/gogo/protobuf/gogoproto
These binaries allow you to using gogoprotobuf [extensions](https://github.com/gogo/protobuf/blob/master/extensions.md). These binaries allow you to use gogoprotobuf [extensions](https://github.com/gogo/protobuf/blob/master/extensions.md). You can also use your own binary.
To generate the code, you also need to set the include path properly.
protoc -I=. -I=$GOPATH/src -I=$GOPATH/src/github.com/gogo/protobuf/protobuf --{binary}_out=. myproto.proto
To use proto files from "google/protobuf" you need to add additional args to protoc.
protoc -I=. -I=$GOPATH/src -I=$GOPATH/src/github.com/gogo/protobuf/protobuf --{binary}_out=\
Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types:. \
myproto.proto
Note that in the protoc command, {binary} does not contain the initial prefix of "protoc-gen".
### Most Speed and most customization ### Most Speed and most customization

View File

@ -723,81 +723,82 @@ func init() {
func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) } func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
var fileDescriptorGogo = []byte{ var fileDescriptorGogo = []byte{
// 1201 bytes of a gzipped FileDescriptorProto // 1220 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xcb, 0x6f, 0x1c, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x4b, 0x6f, 0x1c, 0x45,
0x13, 0xc0, 0xf5, 0xe9, 0x73, 0x64, 0x6f, 0xf9, 0x85, 0xd7, 0xc6, 0x84, 0x08, 0x44, 0x72, 0xe3, 0x10, 0x80, 0x85, 0x48, 0x14, 0x6f, 0xd9, 0x8e, 0xf1, 0xda, 0x98, 0x10, 0x81, 0x08, 0x9c, 0x38,
0xe4, 0x9c, 0x22, 0x94, 0xb6, 0x22, 0xcb, 0xb1, 0x1c, 0x2b, 0x11, 0x06, 0x63, 0xe2, 0x00, 0xe2, 0xd9, 0xa7, 0x08, 0xa5, 0xad, 0xc8, 0x72, 0x2c, 0xc7, 0x4a, 0x84, 0xc1, 0x98, 0x38, 0xbc, 0x0e,
0xb0, 0x9a, 0xdd, 0x6d, 0x4f, 0x06, 0x66, 0xa6, 0x87, 0x99, 0x9e, 0x28, 0xce, 0x0d, 0x85, 0x87, 0xab, 0xd9, 0xdd, 0xf6, 0x78, 0x60, 0x66, 0x7a, 0x98, 0xe9, 0x89, 0xe2, 0xdc, 0x50, 0x78, 0x08,
0x10, 0xe2, 0x8d, 0x04, 0x09, 0x49, 0x80, 0x03, 0xef, 0x67, 0x78, 0x1f, 0xb9, 0xf0, 0xb8, 0xf2, 0x21, 0xde, 0x48, 0x90, 0x90, 0x04, 0x38, 0xf0, 0x7e, 0x86, 0xf7, 0x91, 0x0b, 0x8f, 0x2b, 0xff,
0x3f, 0x70, 0x01, 0xcc, 0xdb, 0x37, 0x5f, 0x50, 0xcd, 0x56, 0xcd, 0xf6, 0xac, 0x57, 0xea, 0xde, 0x81, 0x0b, 0x60, 0xde, 0xbe, 0xf9, 0x82, 0x6a, 0xb6, 0x6a, 0xb6, 0x67, 0xbd, 0x52, 0xf7, 0xde,
0xdb, 0xec, 0xba, 0x7f, 0xbf, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x31, 0x80, 0xaf, 0x7c, 0x35, 0x97, 0xc6, 0xeb, 0xfe, 0xbe, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x59, 0x00, 0x5f, 0xf9, 0x6a, 0x3a, 0x49,
0xa4, 0x4a, 0xab, 0x7a, 0x0d, 0xaf, 0x8b, 0xcb, 0x03, 0x07, 0x7d, 0xa5, 0xfc, 0x50, 0x1e, 0x2e, 0x95, 0x56, 0xf5, 0x1a, 0x5e, 0x17, 0x97, 0x07, 0x0f, 0xf9, 0x4a, 0xf9, 0xa1, 0x9c, 0x29, 0xfe,
0x3e, 0x35, 0xf3, 0xcd, 0xc3, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77, 0x6a, 0xe6, 0xeb, 0x33, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77, 0xc1,
0xc1, 0x34, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0x37, 0x83, 0xf3, 0xf5, 0x5b, 0xe6, 0x04, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0xd7, 0x83, 0xb3, 0xf5, 0x9b, 0xa6, 0x3b,
0x3a, 0xe4, 0x1c, 0x93, 0x73, 0xcb, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0xfe, 0xeb, 0xe4, 0x34, 0x93, 0xd3, 0x8b, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0x81, 0xab, 0xbf,
0x3f, 0xff, 0xff, 0xe0, 0xff, 0x6e, 0x1f, 0x59, 0x9f, 0x22, 0x14, 0xff, 0xb6, 0x56, 0x80, 0x62, 0x5c, 0x7b, 0xe8, 0x9a, 0xdb, 0x87, 0x56, 0xc7, 0x09, 0xc5, 0xff, 0xad, 0x14, 0xa0, 0x58, 0x85,
0x1d, 0x6e, 0xac, 0xf8, 0x32, 0x9d, 0x06, 0xb1, 0x2f, 0x53, 0x8b, 0xf1, 0x3b, 0x32, 0x4e, 0x1b, 0xeb, 0x2b, 0xbe, 0x4c, 0xa7, 0x41, 0xec, 0xcb, 0xd4, 0x62, 0xfc, 0x9e, 0x8c, 0x13, 0x86, 0xf1,
0xc6, 0x7b, 0x09, 0x15, 0x4b, 0x30, 0x3e, 0x88, 0xeb, 0x7b, 0x72, 0x8d, 0x49, 0x53, 0xb2, 0x02, 0x5e, 0x42, 0xc5, 0x02, 0x8c, 0x0e, 0xe2, 0xfa, 0x81, 0x5c, 0x23, 0xd2, 0x94, 0x2c, 0xc1, 0x58,
0x93, 0x85, 0xa4, 0x95, 0x67, 0x5a, 0x45, 0xb1, 0x17, 0x49, 0x8b, 0xe6, 0x87, 0x42, 0x53, 0x5b, 0x21, 0x69, 0xe5, 0x99, 0x56, 0x51, 0xec, 0x45, 0xd2, 0xa2, 0xf9, 0xb1, 0xd0, 0xd4, 0x56, 0xf7,
0x9f, 0x40, 0x6c, 0xa9, 0xa4, 0x84, 0x80, 0x11, 0xfc, 0xa6, 0x2d, 0x5b, 0xa1, 0xc5, 0xf0, 0x23, 0x23, 0xb6, 0x50, 0x52, 0x42, 0xc0, 0x10, 0x7e, 0xd2, 0x96, 0xad, 0xd0, 0x62, 0xf8, 0x89, 0x02,
0x05, 0x52, 0xae, 0x17, 0x67, 0x60, 0x06, 0xaf, 0xcf, 0x79, 0x61, 0x2e, 0xcd, 0x48, 0x0e, 0xf5, 0x29, 0xd7, 0x8b, 0xd3, 0x30, 0x89, 0xd7, 0x67, 0xbc, 0x30, 0x97, 0x66, 0x24, 0xb7, 0xf6, 0xf5,
0xf5, 0x9c, 0xc1, 0x65, 0x2c, 0xfb, 0xe9, 0xe2, 0x50, 0x11, 0xce, 0x74, 0x29, 0x30, 0x62, 0x32, 0x9c, 0xc6, 0x65, 0x2c, 0xfb, 0xf9, 0xfc, 0x9e, 0x22, 0x9c, 0x89, 0x52, 0x60, 0xc4, 0x64, 0x54,
0xaa, 0xe8, 0x4b, 0xad, 0x65, 0x9a, 0x35, 0xbc, 0xb0, 0x5f, 0x78, 0x27, 0x82, 0xb0, 0x34, 0x5e, 0xd1, 0x97, 0x5a, 0xcb, 0x34, 0x6b, 0x78, 0x61, 0xbf, 0xf0, 0x8e, 0x07, 0x61, 0x69, 0xbc, 0xb0,
0xda, 0xae, 0x56, 0x71, 0xa5, 0x43, 0x2e, 0x86, 0xa1, 0xd8, 0x80, 0x9b, 0xfa, 0x3c, 0x15, 0x0e, 0x55, 0xad, 0xe2, 0x52, 0x87, 0x9c, 0x0f, 0x43, 0xb1, 0x06, 0x37, 0xf4, 0x79, 0x2a, 0x1c, 0x9c,
0xce, 0xcb, 0xe4, 0x9c, 0xd9, 0xf3, 0x64, 0xa0, 0x76, 0x0d, 0xf8, 0xfb, 0xb2, 0x96, 0x0e, 0xce, 0x17, 0xc9, 0x39, 0xb9, 0xeb, 0xc9, 0x40, 0xed, 0x0a, 0xf0, 0xe7, 0x65, 0x2d, 0x1d, 0x9c, 0xaf,
0xd7, 0xc8, 0x59, 0x27, 0x96, 0x4b, 0x8a, 0xc6, 0x53, 0x30, 0x75, 0x4e, 0xa6, 0x4d, 0x95, 0xc9, 0x93, 0xb3, 0x4e, 0x2c, 0x97, 0x14, 0x8d, 0x27, 0x61, 0xfc, 0x8c, 0x4c, 0x9b, 0x2a, 0x93, 0x0d,
0x86, 0x7c, 0x24, 0xf7, 0x42, 0x07, 0xdd, 0x15, 0xd2, 0x4d, 0x12, 0xb8, 0x8c, 0x1c, 0xba, 0x8e, 0xf9, 0x68, 0xee, 0x85, 0x0e, 0xba, 0x4b, 0xa4, 0x1b, 0x23, 0x70, 0x11, 0x39, 0x74, 0x1d, 0x81,
0xc2, 0xc8, 0xa6, 0xd7, 0x92, 0x0e, 0x8a, 0xab, 0xa4, 0x18, 0xc6, 0xf5, 0x88, 0x2e, 0xc2, 0x98, 0xa1, 0x75, 0xaf, 0x25, 0x1d, 0x14, 0x97, 0x49, 0xb1, 0x0f, 0xd7, 0x23, 0x3a, 0x0f, 0x23, 0xbe,
0xaf, 0x3a, 0xb7, 0xe4, 0x80, 0x5f, 0x23, 0x7c, 0x94, 0x19, 0x52, 0x24, 0x2a, 0xc9, 0x43, 0x4f, 0xea, 0xdc, 0x92, 0x03, 0x7e, 0x85, 0xf0, 0x61, 0x66, 0x48, 0x91, 0xa8, 0x24, 0x0f, 0x3d, 0xed,
0xbb, 0x44, 0xf0, 0x3a, 0x2b, 0x98, 0x21, 0xc5, 0x00, 0x69, 0x7d, 0x83, 0x15, 0x99, 0x91, 0xcf, 0x12, 0xc1, 0x1b, 0xac, 0x60, 0x86, 0x14, 0x03, 0xa4, 0xf5, 0x4d, 0x56, 0x64, 0x46, 0x3e, 0xe7,
0x05, 0x18, 0x55, 0x71, 0xb8, 0xa5, 0x62, 0x97, 0x20, 0xde, 0x24, 0x03, 0x10, 0x82, 0x82, 0x79, 0x60, 0x58, 0xc5, 0xe1, 0xa6, 0x8a, 0x5d, 0x82, 0x78, 0x8b, 0x0c, 0x40, 0x08, 0x0a, 0x66, 0xa1,
0xa8, 0xb9, 0x16, 0xe2, 0xad, 0x6d, 0xde, 0x1e, 0x5c, 0x81, 0x15, 0x98, 0xe4, 0x06, 0x15, 0xa8, 0xe6, 0x5a, 0x88, 0xb7, 0xb7, 0x78, 0x7b, 0x70, 0x05, 0x96, 0x60, 0x8c, 0x1b, 0x54, 0xa0, 0x62,
0xd8, 0x41, 0xf1, 0x36, 0x29, 0x26, 0x0c, 0x8c, 0x6e, 0x43, 0xcb, 0x4c, 0xfb, 0xd2, 0x45, 0xf2, 0x07, 0xc5, 0x3b, 0xa4, 0xd8, 0x6f, 0x60, 0x74, 0x1b, 0x5a, 0x66, 0xda, 0x97, 0x2e, 0x92, 0x77,
0x0e, 0xdf, 0x06, 0x21, 0x94, 0xca, 0xa6, 0x8c, 0x5b, 0x67, 0xdd, 0x0c, 0xef, 0x72, 0x2a, 0x99, 0xf9, 0x36, 0x08, 0xa1, 0x54, 0x36, 0x65, 0xdc, 0xda, 0x70, 0x33, 0xbc, 0xc7, 0xa9, 0x64, 0x06,
0x41, 0xc5, 0x12, 0x8c, 0x47, 0x5e, 0x9a, 0x9d, 0xf5, 0x42, 0xa7, 0x72, 0xbc, 0x47, 0x8e, 0xb1, 0x15, 0x0b, 0x30, 0x1a, 0x79, 0x69, 0xb6, 0xe1, 0x85, 0x4e, 0xe5, 0x78, 0x9f, 0x1c, 0x23, 0x25,
0x12, 0xa2, 0x8c, 0xe4, 0xf1, 0x20, 0x9a, 0xf7, 0x39, 0x23, 0x06, 0x46, 0x5b, 0x2f, 0xd3, 0x5e, 0x44, 0x19, 0xc9, 0xe3, 0x41, 0x34, 0x1f, 0x70, 0x46, 0x0c, 0x8c, 0xb6, 0x5e, 0xa6, 0xbd, 0x66,
0x33, 0x94, 0x8d, 0x41, 0x6c, 0x1f, 0xf0, 0xd6, 0xeb, 0xb0, 0xab, 0xa6, 0x71, 0x1e, 0x6a, 0x59, 0x28, 0x1b, 0x83, 0xd8, 0x3e, 0xe4, 0xad, 0xd7, 0x61, 0x97, 0x4d, 0xe3, 0x2c, 0xd4, 0xb2, 0xe0,
0x70, 0xc1, 0x49, 0xf3, 0x21, 0x57, 0xba, 0x00, 0x10, 0x7e, 0x00, 0x6e, 0xee, 0x3b, 0x26, 0x1c, 0x9c, 0x93, 0xe6, 0x23, 0xae, 0x74, 0x01, 0x20, 0xfc, 0x00, 0xdc, 0xd8, 0x77, 0x4c, 0x38, 0xc8,
0x64, 0x1f, 0x91, 0x6c, 0xb6, 0xcf, 0xa8, 0xa0, 0x96, 0x30, 0xa8, 0xf2, 0x63, 0x6e, 0x09, 0xb2, 0x3e, 0x26, 0xd9, 0x54, 0x9f, 0x51, 0x41, 0x2d, 0x61, 0x50, 0xe5, 0x27, 0xdc, 0x12, 0x64, 0x8f,
0xc7, 0xb5, 0x06, 0x33, 0x79, 0x9c, 0x79, 0x9b, 0x83, 0x65, 0xed, 0x13, 0xce, 0x5a, 0x87, 0xad, 0x6b, 0x05, 0x26, 0xf3, 0x38, 0xf3, 0xd6, 0x07, 0xcb, 0xda, 0xa7, 0x9c, 0xb5, 0x0e, 0x5b, 0xc9,
0x64, 0xed, 0x34, 0xcc, 0x92, 0x71, 0xb0, 0xba, 0x7e, 0xca, 0x8d, 0xb5, 0x43, 0x6f, 0x54, 0xab, 0xda, 0x29, 0x98, 0x22, 0xe3, 0x60, 0x75, 0xfd, 0x8c, 0x1b, 0x6b, 0x87, 0x5e, 0xab, 0x56, 0xf7,
0xfb, 0x20, 0x1c, 0x28, 0xd3, 0x79, 0x5e, 0xcb, 0x38, 0x43, 0xa6, 0x11, 0x79, 0x89, 0x83, 0xf9, 0x21, 0x38, 0x58, 0xa6, 0xf3, 0xac, 0x96, 0x71, 0x86, 0x4c, 0x23, 0xf2, 0x12, 0x07, 0xf3, 0x55,
0x3a, 0x99, 0xb9, 0xe3, 0x2f, 0x97, 0x82, 0x55, 0x2f, 0x41, 0xf9, 0xfd, 0xb0, 0x9f, 0xe5, 0x79, 0x32, 0x73, 0xc7, 0x5f, 0x2c, 0x05, 0xcb, 0x5e, 0x82, 0xf2, 0xfb, 0xe1, 0x00, 0xcb, 0xf3, 0x38,
0x9c, 0xca, 0x96, 0xf2, 0xe3, 0xe0, 0x82, 0x6c, 0x3b, 0xa8, 0x3f, 0xeb, 0x29, 0xd5, 0x86, 0x81, 0x95, 0x2d, 0xe5, 0xc7, 0xc1, 0x39, 0xd9, 0x76, 0x50, 0x7f, 0xde, 0x53, 0xaa, 0x35, 0x03, 0x47,
0xa3, 0xf9, 0x24, 0xdc, 0x50, 0x9e, 0x55, 0x1a, 0x41, 0x94, 0xa8, 0x54, 0x5b, 0x8c, 0x9f, 0x73, 0xf3, 0x09, 0xb8, 0xae, 0x3c, 0xab, 0x34, 0x82, 0x28, 0x51, 0xa9, 0xb6, 0x18, 0xbf, 0xe0, 0x4a,
0xa5, 0x4a, 0xee, 0x64, 0x81, 0x89, 0x65, 0x98, 0x28, 0x3e, 0xba, 0x3e, 0x92, 0x5f, 0x90, 0x68, 0x95, 0xdc, 0x89, 0x02, 0x13, 0x8b, 0xb0, 0xbf, 0xf8, 0xd3, 0xf5, 0x91, 0xfc, 0x92, 0x44, 0xa3,
0xbc, 0x4b, 0x51, 0xe3, 0x68, 0xa9, 0x28, 0xf1, 0x52, 0x97, 0xfe, 0xf7, 0x25, 0x37, 0x0e, 0x42, 0x5d, 0x8a, 0x1a, 0x47, 0x4b, 0x45, 0x89, 0x97, 0xba, 0xf4, 0xbf, 0xaf, 0xb8, 0x71, 0x10, 0x42,
0xa8, 0x71, 0xe8, 0xad, 0x44, 0xe2, 0xb4, 0x77, 0x30, 0x7c, 0xc5, 0x8d, 0x83, 0x19, 0x52, 0xf0, 0x8d, 0x43, 0x6f, 0x26, 0x12, 0xa7, 0xbd, 0x83, 0xe1, 0x6b, 0x6e, 0x1c, 0xcc, 0x90, 0x82, 0x0f,
0x81, 0xc1, 0x41, 0xf1, 0x35, 0x2b, 0x98, 0x41, 0xc5, 0x3d, 0xdd, 0x41, 0x9b, 0x4a, 0x3f, 0xc8, 0x0c, 0x0e, 0x8a, 0x6f, 0x58, 0xc1, 0x0c, 0x2a, 0xee, 0xe9, 0x0e, 0xda, 0x54, 0xfa, 0x41, 0xa6,
0x74, 0xea, 0xe1, 0x6a, 0x8b, 0xea, 0x9b, 0xed, 0xea, 0x21, 0x6c, 0xdd, 0x40, 0xc5, 0x29, 0x98, 0x53, 0x0f, 0x57, 0x5b, 0x54, 0xdf, 0x6e, 0x55, 0x0f, 0x61, 0xab, 0x06, 0x2a, 0x4e, 0xc2, 0x58,
0xec, 0x39, 0x62, 0xd4, 0x6f, 0xdb, 0x63, 0x5b, 0x95, 0x59, 0xe6, 0xf9, 0xa5, 0xf0, 0xd1, 0x1d, 0xcf, 0x11, 0xa3, 0x7e, 0xcb, 0x2e, 0xdb, 0xb2, 0xcc, 0x32, 0xcf, 0x2f, 0x85, 0x8f, 0x6d, 0x53,
0x6a, 0x46, 0xd5, 0x13, 0x86, 0xb8, 0x13, 0xeb, 0x5e, 0x3d, 0x07, 0xd8, 0x65, 0x17, 0x77, 0xca, 0x33, 0xaa, 0x9e, 0x30, 0xc4, 0x9d, 0x58, 0xf7, 0xea, 0x39, 0xc0, 0x2e, 0x3b, 0xbf, 0x5d, 0x96,
0xd2, 0x57, 0x8e, 0x01, 0xe2, 0x04, 0x8c, 0x57, 0xce, 0x00, 0x76, 0xd5, 0x63, 0xa4, 0x1a, 0x33, 0xbe, 0x72, 0x0c, 0x10, 0xc7, 0x61, 0xb4, 0x72, 0x06, 0xb0, 0xab, 0x1e, 0x27, 0xd5, 0x88, 0x79,
0x8f, 0x00, 0xe2, 0x08, 0x0c, 0xe1, 0x3c, 0xb7, 0xe3, 0x8f, 0x13, 0x5e, 0x2c, 0x17, 0xc7, 0x60, 0x04, 0x10, 0x87, 0x61, 0x0f, 0xce, 0x73, 0x3b, 0xfe, 0x04, 0xe1, 0xc5, 0x72, 0x71, 0x14, 0x86,
0x84, 0xe7, 0xb8, 0x1d, 0x7d, 0x82, 0xd0, 0x12, 0x41, 0x9c, 0x67, 0xb8, 0x1d, 0x7f, 0x92, 0x71, 0x78, 0x8e, 0xdb, 0xd1, 0x27, 0x09, 0x2d, 0x11, 0xc4, 0x79, 0x86, 0xdb, 0xf1, 0xa7, 0x18, 0x67,
0x46, 0x10, 0x77, 0x4f, 0xe1, 0xb7, 0x4f, 0x0f, 0x51, 0x1f, 0xe6, 0xdc, 0xcd, 0xc3, 0x30, 0x0d, 0x04, 0x71, 0xf7, 0x14, 0x7e, 0xf7, 0xcc, 0x1e, 0xea, 0xc3, 0x9c, 0xbb, 0x59, 0xd8, 0x47, 0xc3,
0x6f, 0x3b, 0xfd, 0x14, 0xfd, 0x38, 0x13, 0xe2, 0x0e, 0xd8, 0xe7, 0x98, 0xf0, 0x67, 0x08, 0xed, 0xdb, 0x4e, 0x3f, 0x4d, 0x5f, 0xce, 0x84, 0xb8, 0x03, 0xf6, 0x3a, 0x26, 0xfc, 0x59, 0x42, 0x3b,
0xac, 0x17, 0x4b, 0x30, 0x6a, 0x0c, 0x6c, 0x3b, 0xfe, 0x2c, 0xe1, 0x26, 0x85, 0xa1, 0xd3, 0xc0, 0xeb, 0xc5, 0x02, 0x0c, 0x1b, 0x03, 0xdb, 0x8e, 0x3f, 0x47, 0xb8, 0x49, 0x61, 0xe8, 0x34, 0xb0,
0xb6, 0x0b, 0x9e, 0xe3, 0xd0, 0x89, 0xc0, 0xb4, 0xf1, 0xac, 0xb6, 0xd3, 0xcf, 0x73, 0xd6, 0x19, 0xed, 0x82, 0xe7, 0x39, 0x74, 0x22, 0x30, 0x6d, 0x3c, 0xab, 0xed, 0xf4, 0x0b, 0x9c, 0x75, 0x46,
0x11, 0x0b, 0x50, 0x2b, 0xfb, 0xaf, 0x9d, 0x7f, 0x81, 0xf8, 0x2e, 0x83, 0x19, 0x30, 0xfa, 0xbf, 0xc4, 0x1c, 0xd4, 0xca, 0xfe, 0x6b, 0xe7, 0x5f, 0x24, 0xbe, 0xcb, 0x60, 0x06, 0x8c, 0xfe, 0x6f,
0x5d, 0xf1, 0x22, 0x67, 0xc0, 0xa0, 0x70, 0x1b, 0xf5, 0xce, 0x74, 0xbb, 0xe9, 0x25, 0xde, 0x46, 0x57, 0xbc, 0xc4, 0x19, 0x30, 0x28, 0xdc, 0x46, 0xbd, 0x33, 0xdd, 0x6e, 0x7a, 0x99, 0xb7, 0x51,
0x3d, 0x23, 0x1d, 0xab, 0x59, 0xb4, 0x41, 0xbb, 0xe2, 0x65, 0xae, 0x66, 0xb1, 0x1e, 0xc3, 0xe8, 0xcf, 0x48, 0xc7, 0x6a, 0x16, 0x6d, 0xd0, 0xae, 0x78, 0x85, 0xab, 0x59, 0xac, 0xc7, 0x30, 0x7a,
0x1d, 0x92, 0x76, 0xc7, 0x2b, 0x1c, 0x46, 0xcf, 0x8c, 0x14, 0x6b, 0x50, 0xdf, 0x3b, 0x20, 0xed, 0x87, 0xa4, 0xdd, 0xf1, 0x2a, 0x87, 0xd1, 0x33, 0x23, 0xc5, 0x0a, 0xd4, 0x77, 0x0f, 0x48, 0xbb,
0xbe, 0x57, 0xc9, 0x37, 0xb5, 0x67, 0x3e, 0x8a, 0xfb, 0x60, 0xb6, 0xff, 0x70, 0xb4, 0x5b, 0x2f, 0xef, 0x35, 0xf2, 0x8d, 0xef, 0x9a, 0x8f, 0xe2, 0x3e, 0x98, 0xea, 0x3f, 0x1c, 0xed, 0xd6, 0x0b,
0xed, 0xf4, 0xbc, 0xce, 0x98, 0xb3, 0x51, 0x9c, 0xee, 0x76, 0x59, 0x73, 0x30, 0xda, 0xb5, 0x97, 0xdb, 0x3d, 0xaf, 0x33, 0xe6, 0x6c, 0x14, 0xa7, 0xba, 0x5d, 0xd6, 0x1c, 0x8c, 0x76, 0xed, 0xc5,
0x77, 0xaa, 0x8d, 0xd6, 0x9c, 0x8b, 0x62, 0x11, 0xa0, 0x3b, 0x93, 0xec, 0xae, 0x2b, 0xe4, 0x32, 0xed, 0x6a, 0xa3, 0x35, 0xe7, 0xa2, 0x98, 0x07, 0xe8, 0xce, 0x24, 0xbb, 0xeb, 0x12, 0xb9, 0x0c,
0x20, 0xdc, 0x1a, 0x34, 0x92, 0xec, 0xfc, 0x55, 0xde, 0x1a, 0x44, 0xe0, 0xd6, 0xe0, 0x69, 0x64, 0x08, 0xb7, 0x06, 0x8d, 0x24, 0x3b, 0x7f, 0x99, 0xb7, 0x06, 0x11, 0xb8, 0x35, 0x78, 0x1a, 0xd9,
0xa7, 0xaf, 0xf1, 0xd6, 0x60, 0x44, 0xcc, 0xc3, 0x48, 0x9c, 0x87, 0x21, 0x3e, 0x5b, 0xf5, 0x5b, 0xe9, 0x2b, 0xbc, 0x35, 0x18, 0x11, 0xb3, 0x30, 0x14, 0xe7, 0x61, 0x88, 0xcf, 0x56, 0xfd, 0xe6,
0xfb, 0x8c, 0x1b, 0x19, 0xb6, 0x19, 0xfe, 0x65, 0x97, 0x60, 0x06, 0xc4, 0x11, 0xd8, 0x27, 0xa3, 0x3e, 0xe3, 0x46, 0x86, 0x6d, 0x86, 0x7f, 0xdd, 0x21, 0x98, 0x01, 0x71, 0x18, 0xf6, 0xca, 0xa8,
0xa6, 0x6c, 0xdb, 0xc8, 0x5f, 0x77, 0xb9, 0x9f, 0xe0, 0x6a, 0xb1, 0x00, 0xd0, 0x79, 0x99, 0xc6, 0x29, 0xdb, 0x36, 0xf2, 0xb7, 0x1d, 0xee, 0x27, 0xb8, 0x5a, 0xcc, 0x01, 0x74, 0x5e, 0xa6, 0x31,
0x28, 0x6c, 0xec, 0x6f, 0xbb, 0x9d, 0xf7, 0x7a, 0x03, 0xe9, 0x0a, 0x8a, 0xb7, 0x71, 0x8b, 0x60, 0x0a, 0x1b, 0xfb, 0xfb, 0x4e, 0xe7, 0xbd, 0xde, 0x40, 0xba, 0x82, 0xe2, 0x6d, 0xdc, 0x22, 0xd8,
0xbb, 0x2a, 0x28, 0x5e, 0xc0, 0x8f, 0xc2, 0xf0, 0x43, 0x99, 0x8a, 0xb5, 0xe7, 0xdb, 0xe8, 0xdf, 0xaa, 0x0a, 0x8a, 0x17, 0xf0, 0x23, 0xb0, 0xef, 0xe1, 0x4c, 0xc5, 0xda, 0xf3, 0x6d, 0xf4, 0x1f,
0x89, 0xe6, 0xf5, 0x98, 0xb0, 0x48, 0xa5, 0x52, 0x7b, 0x7e, 0x66, 0x63, 0xff, 0x20, 0xb6, 0x04, 0x44, 0xf3, 0x7a, 0x4c, 0x58, 0xa4, 0x52, 0xa9, 0x3d, 0x3f, 0xb3, 0xb1, 0x7f, 0x12, 0x5b, 0x02,
0x10, 0x6e, 0x79, 0x99, 0x76, 0xb9, 0xef, 0x3f, 0x19, 0x66, 0x00, 0x83, 0xc6, 0xeb, 0x87, 0xe5, 0x08, 0xb7, 0xbc, 0x4c, 0xbb, 0xdc, 0xf7, 0x5f, 0x0c, 0x33, 0x80, 0x41, 0xe3, 0xf5, 0x23, 0x72,
0x96, 0x8d, 0xfd, 0x8b, 0x83, 0xa6, 0xf5, 0xe2, 0x18, 0xd4, 0xf0, 0xb2, 0xf8, 0x3f, 0x84, 0x0d, 0xd3, 0xc6, 0xfe, 0xcd, 0x41, 0xd3, 0x7a, 0x71, 0x14, 0x6a, 0x78, 0x59, 0xfc, 0x0e, 0x61, 0x83,
0xfe, 0x9b, 0xe0, 0x2e, 0x81, 0xbf, 0x9c, 0xe9, 0xb6, 0x0e, 0xec, 0xc9, 0xfe, 0x87, 0x2a, 0xcd, 0xff, 0x21, 0xb8, 0x4b, 0xe0, 0x37, 0x67, 0xba, 0xad, 0x03, 0x7b, 0xb2, 0xff, 0xa5, 0x4a, 0xf3,
0xeb, 0xc5, 0x22, 0x8c, 0x66, 0xba, 0xdd, 0xce, 0xe9, 0x44, 0x63, 0xc1, 0xff, 0xdd, 0x2d, 0x5f, 0x7a, 0x31, 0x0f, 0xc3, 0x99, 0x6e, 0xb7, 0x73, 0x3a, 0xd1, 0x58, 0xf0, 0xff, 0x76, 0xca, 0x97,
0x72, 0x4b, 0xe6, 0xf8, 0x21, 0x98, 0x6e, 0xa9, 0xa8, 0x17, 0x3c, 0x0e, 0x2b, 0x6a, 0x45, 0xad, 0xdc, 0x92, 0x39, 0xb6, 0x08, 0x13, 0x2d, 0x15, 0xf5, 0x82, 0xc7, 0x60, 0x49, 0x2d, 0xa9, 0x95,
0x15, 0xbb, 0xe8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x9c, 0xec, 0xd8, 0x50, 0x13, 0x00, 0x62, 0x17, 0x3d, 0x78, 0x9b, 0x1f, 0xe8, 0x8d, 0xbc, 0x39, 0xdd, 0x52, 0xd1, 0x0c, 0x1e, 0x35,
0x00, 0xbb, 0xbf, 0xa0, 0x95, 0x07, 0xcf, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xed, 0x5f, 0x6c, 0x20,
0x74, 0x13, 0x00, 0x00,
} }

View File

@ -33,6 +33,7 @@ import "google/protobuf/descriptor.proto";
option java_package = "com.google.protobuf"; option java_package = "com.google.protobuf";
option java_outer_classname = "GoGoProtos"; option java_outer_classname = "GoGoProtos";
option go_package = "github.com/gogo/protobuf/gogoproto";
extend google.protobuf.EnumOptions { extend google.protobuf.EnumOptions {
optional bool goproto_enum_prefix = 62001; optional bool goproto_enum_prefix = 62001;

151
vendor/github.com/gogo/protobuf/proto/discard.go generated vendored Normal file
View File

@ -0,0 +1,151 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2017 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
import (
"fmt"
"reflect"
"strings"
)
// DiscardUnknown recursively discards all unknown fields from this message
// and all embedded messages.
//
// When unmarshaling a message with unrecognized fields, the tags and values
// of such fields are preserved in the Message. This allows a later call to
// marshal to be able to produce a message that continues to have those
// unrecognized fields. To avoid this, DiscardUnknown is used to
// explicitly clear the unknown fields after unmarshaling.
//
// For proto2 messages, the unknown fields of message extensions are only
// discarded from messages that have been accessed via GetExtension.
func DiscardUnknown(m Message) {
discardLegacy(m)
}
func discardLegacy(m Message) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Ptr || v.IsNil() {
return
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
vf := v.Field(i)
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
case isSlice: // E.g., []*pb.T
for j := 0; j < vf.Len(); j++ {
discardLegacy(vf.Index(j).Interface().(Message))
}
default: // E.g., *pb.T
discardLegacy(vf.Interface().(Message))
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
default: // E.g., map[K]V
tv := vf.Type().Elem()
if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
for _, key := range vf.MapKeys() {
val := vf.MapIndex(key)
discardLegacy(val.Interface().(Message))
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
default: // E.g., test_proto.isCommunique_Union interface
if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
vf = vf.Elem() // E.g., *test_proto.Communique_Msg
if !vf.IsNil() {
vf = vf.Elem() // E.g., test_proto.Communique_Msg
vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
if vf.Kind() == reflect.Ptr {
discardLegacy(vf.Interface().(Message))
}
}
}
}
}
}
if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
if vf.Type() != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
vf.Set(reflect.ValueOf([]byte(nil)))
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, ok := extendable(m); ok {
// Ignore lock since discardLegacy is not concurrency safe.
emm, _ := em.extensionsRead()
for _, mx := range emm {
if m, ok := mx.value.(Message); ok {
discardLegacy(m)
}
}
}
}

View File

@ -45,6 +45,7 @@ option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos"; option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.Protobuf.Reflection"; option csharp_namespace = "Google.Protobuf.Reflection";
option objc_class_prefix = "GPB"; option objc_class_prefix = "GPB";
option cc_enable_arenas = true;
// descriptor.proto must be optimized for speed because reflection-based // descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping. // algorithms don't work during bootstrapping.
@ -225,6 +226,26 @@ message EnumDescriptorProto {
repeated EnumValueDescriptorProto value = 2; repeated EnumValueDescriptorProto value = 2;
optional EnumOptions options = 3; optional EnumOptions options = 3;
// Range of reserved numeric values. Reserved values may not be used by
// entries in the same enum. Reserved ranges may not overlap.
//
// Note that this is distinct from DescriptorProto.ReservedRange in that it
// is inclusive such that it can appropriately represent the entire int32
// domain.
message EnumReservedRange {
optional int32 start = 1; // Inclusive.
optional int32 end = 2; // Inclusive.
}
// Range of reserved numeric values. Reserved numeric values may not be used
// by enum values in the same enum declaration. Reserved ranges may not
// overlap.
repeated EnumReservedRange reserved_range = 4;
// Reserved enum value names, which may not be reused. A given name may only
// be reserved once.
repeated string reserved_name = 5;
} }
// Describes a value within an enum. // Describes a value within an enum.
@ -361,7 +382,7 @@ message FileOptions {
optional bool cc_generic_services = 16 [default=false]; optional bool cc_generic_services = 16 [default=false];
optional bool java_generic_services = 17 [default=false]; optional bool java_generic_services = 17 [default=false];
optional bool py_generic_services = 18 [default=false]; optional bool py_generic_services = 18 [default=false];
optional bool php_generic_services = 19 [default=false]; optional bool php_generic_services = 42 [default=false];
// Is this file deprecated? // Is this file deprecated?
// Depending on the target platform, this can emit Deprecated annotations // Depending on the target platform, this can emit Deprecated annotations

View File

@ -805,10 +805,17 @@ func (m *OneofDescriptorProto) GetOptions() *OneofOptions {
// Describes an enum type. // Describes an enum type.
type EnumDescriptorProto struct { type EnumDescriptorProto struct {
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"`
Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
XXX_unrecognized []byte `json:"-"` // Range of reserved numeric values. Reserved numeric values may not be used
// by enum values in the same enum declaration. Reserved ranges may not
// overlap.
ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
// Reserved enum value names, which may not be reused. A given name may only
// be reserved once.
ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
XXX_unrecognized []byte `json:"-"`
} }
func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
@ -837,6 +844,53 @@ func (m *EnumDescriptorProto) GetOptions() *EnumOptions {
return nil return nil
} }
func (m *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange {
if m != nil {
return m.ReservedRange
}
return nil
}
func (m *EnumDescriptorProto) GetReservedName() []string {
if m != nil {
return m.ReservedName
}
return nil
}
// Range of reserved numeric values. Reserved values may not be used by
// entries in the same enum. Reserved ranges may not overlap.
//
// Note that this is distinct from DescriptorProto.ReservedRange in that it
// is inclusive such that it can appropriately represent the entire int32
// domain.
type EnumDescriptorProto_EnumReservedRange struct {
Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *EnumDescriptorProto_EnumReservedRange) Reset() { *m = EnumDescriptorProto_EnumReservedRange{} }
func (m *EnumDescriptorProto_EnumReservedRange) String() string { return proto.CompactTextString(m) }
func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {}
func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) {
return fileDescriptorDescriptor, []int{6, 0}
}
func (m *EnumDescriptorProto_EnumReservedRange) GetStart() int32 {
if m != nil && m.Start != nil {
return *m.Start
}
return 0
}
func (m *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 {
if m != nil && m.End != nil {
return *m.End
}
return 0
}
// Describes a value within an enum. // Describes a value within an enum.
type EnumValueDescriptorProto struct { type EnumValueDescriptorProto struct {
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
@ -1020,7 +1074,7 @@ type FileOptions struct {
CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
PhpGenericServices *bool `protobuf:"varint,19,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"` PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
// Is this file deprecated? // Is this file deprecated?
// Depending on the target platform, this can emit Deprecated annotations // Depending on the target platform, this can emit Deprecated annotations
// for everything in the file, or it will be completely ignored; in the very // for everything in the file, or it will be completely ignored; in the very
@ -2037,6 +2091,7 @@ func init() {
proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto") proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto") proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto") proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
proto.RegisterType((*EnumDescriptorProto_EnumReservedRange)(nil), "google.protobuf.EnumDescriptorProto.EnumReservedRange")
proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto") proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto")
proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto") proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto")
proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto") proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto")
@ -2065,159 +2120,161 @@ func init() {
func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) } func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) }
var fileDescriptorDescriptor = []byte{ var fileDescriptorDescriptor = []byte{
// 2451 bytes of a gzipped FileDescriptorProto // 2487 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0xdb, 0xc8, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0xdb, 0xc8,
0x15, 0x5f, 0x7d, 0x5a, 0x7a, 0x92, 0xe5, 0xf1, 0xd8, 0x9b, 0x30, 0xce, 0x66, 0xe3, 0x28, 0xc9, 0x15, 0x5f, 0x7d, 0x5a, 0x7a, 0x92, 0xe5, 0xf1, 0xd8, 0x9b, 0x30, 0xde, 0x8f, 0x38, 0xda, 0x8f,
0xc6, 0x49, 0x5a, 0x65, 0xe1, 0x7c, 0xae, 0xb7, 0xd8, 0x56, 0x96, 0x18, 0xaf, 0x52, 0x59, 0x52, 0x38, 0x49, 0xab, 0x2c, 0x9c, 0xc4, 0xc9, 0x3a, 0xc5, 0xb6, 0xb2, 0xc4, 0x78, 0x95, 0xca, 0x92,
0x29, 0xb9, 0x9b, 0xec, 0x85, 0x18, 0x93, 0x23, 0x89, 0x09, 0x45, 0x72, 0x49, 0x2a, 0x89, 0x83, 0x4a, 0xc9, 0xdd, 0x64, 0x8b, 0x82, 0x18, 0x93, 0x23, 0x89, 0x09, 0x45, 0x72, 0x49, 0x2a, 0x89,
0x1e, 0x02, 0xf4, 0xd4, 0xff, 0xa0, 0x28, 0x8a, 0x1e, 0xf6, 0xb2, 0x40, 0xaf, 0x05, 0x0a, 0xb4, 0x83, 0x1e, 0x02, 0xf4, 0xd4, 0xff, 0xa0, 0x28, 0x8a, 0x1e, 0x7a, 0x59, 0xa0, 0xd7, 0x02, 0x05,
0xf7, 0x5e, 0x0b, 0xf4, 0xde, 0x43, 0x0f, 0x05, 0xda, 0x3f, 0xa3, 0x98, 0x19, 0x92, 0xa2, 0xbe, 0xda, 0x7b, 0xaf, 0x05, 0x7a, 0xef, 0xa1, 0x40, 0x0b, 0xb4, 0x7f, 0x42, 0x8f, 0xc5, 0xcc, 0x90,
0x12, 0x77, 0x81, 0x64, 0x4f, 0xf6, 0xfc, 0xde, 0xef, 0xbd, 0x79, 0xf3, 0xf8, 0x66, 0xde, 0x9b, 0x14, 0xf5, 0x95, 0x78, 0x17, 0x48, 0xf6, 0x64, 0xcf, 0xef, 0xfd, 0xde, 0xe3, 0x9b, 0x37, 0x6f,
0x11, 0x20, 0x9d, 0x7a, 0x9a, 0x6b, 0x38, 0xbe, 0xed, 0x56, 0x1c, 0xd7, 0xf6, 0x6d, 0xbc, 0x36, 0xde, 0xbc, 0x19, 0x01, 0xd2, 0xa9, 0xa7, 0xb9, 0x86, 0xe3, 0xdb, 0x6e, 0xc5, 0x71, 0x6d, 0xdf,
0xb0, 0xed, 0x81, 0x49, 0xc5, 0xe8, 0x78, 0xdc, 0x2f, 0x1f, 0xc2, 0xfa, 0x43, 0xc3, 0xa4, 0xf5, 0xc6, 0x6b, 0x03, 0xdb, 0x1e, 0x98, 0x54, 0x8c, 0x4e, 0xc6, 0xfd, 0xf2, 0x11, 0xac, 0xdf, 0x33,
0x88, 0xd8, 0xa5, 0x3e, 0x7e, 0x00, 0xe9, 0xbe, 0x61, 0x52, 0x29, 0xb1, 0x9d, 0xda, 0x29, 0xec, 0x4c, 0x5a, 0x8f, 0x88, 0x5d, 0xea, 0xe3, 0x3b, 0x90, 0xee, 0x1b, 0x26, 0x95, 0x12, 0xdb, 0xa9,
0x5e, 0xa9, 0xcc, 0x28, 0x55, 0xa6, 0x35, 0x3a, 0x0c, 0x56, 0xb8, 0x46, 0xf9, 0xdf, 0x69, 0xd8, 0x9d, 0xc2, 0xee, 0x87, 0x95, 0x19, 0xa5, 0xca, 0xb4, 0x46, 0x87, 0xc1, 0x0a, 0xd7, 0x28, 0xff,
0x58, 0x20, 0xc5, 0x18, 0xd2, 0x16, 0x19, 0x31, 0x8b, 0x89, 0x9d, 0xbc, 0xc2, 0xff, 0xc7, 0x12, 0x3b, 0x0d, 0x1b, 0x0b, 0xa4, 0x18, 0x43, 0xda, 0x22, 0x23, 0x66, 0x31, 0xb1, 0x93, 0x57, 0xf8,
0xac, 0x38, 0x44, 0x7b, 0x46, 0x06, 0x54, 0x4a, 0x72, 0x38, 0x1c, 0xe2, 0x8f, 0x01, 0x74, 0xea, 0xff, 0x58, 0x82, 0x15, 0x87, 0x68, 0x8f, 0xc9, 0x80, 0x4a, 0x49, 0x0e, 0x87, 0x43, 0xfc, 0x3e,
0x50, 0x4b, 0xa7, 0x96, 0x76, 0x22, 0xa5, 0xb6, 0x53, 0x3b, 0x79, 0x25, 0x86, 0xe0, 0x9b, 0xb0, 0x80, 0x4e, 0x1d, 0x6a, 0xe9, 0xd4, 0xd2, 0x4e, 0xa5, 0xd4, 0x76, 0x6a, 0x27, 0xaf, 0xc4, 0x10,
0xee, 0x8c, 0x8f, 0x4d, 0x43, 0x53, 0x63, 0x34, 0xd8, 0x4e, 0xed, 0x64, 0x14, 0x24, 0x04, 0xf5, 0x7c, 0x0d, 0xd6, 0x9d, 0xf1, 0x89, 0x69, 0x68, 0x6a, 0x8c, 0x06, 0xdb, 0xa9, 0x9d, 0x8c, 0x82,
0x09, 0xf9, 0x1a, 0xac, 0xbd, 0xa0, 0xe4, 0x59, 0x9c, 0x5a, 0xe0, 0xd4, 0x12, 0x83, 0x63, 0xc4, 0x84, 0xa0, 0x3e, 0x21, 0x5f, 0x86, 0xb5, 0xa7, 0x94, 0x3c, 0x8e, 0x53, 0x0b, 0x9c, 0x5a, 0x62,
0x1a, 0x14, 0x47, 0xd4, 0xf3, 0xc8, 0x80, 0xaa, 0xfe, 0x89, 0x43, 0xa5, 0x34, 0x5f, 0xfd, 0xf6, 0x70, 0x8c, 0x58, 0x83, 0xe2, 0x88, 0x7a, 0x1e, 0x19, 0x50, 0xd5, 0x3f, 0x75, 0xa8, 0x94, 0xe6,
0xdc, 0xea, 0x67, 0x57, 0x5e, 0x08, 0xb4, 0x7a, 0x27, 0x0e, 0xc5, 0x55, 0xc8, 0x53, 0x6b, 0x3c, 0xb3, 0xdf, 0x9e, 0x9b, 0xfd, 0xec, 0xcc, 0x0b, 0x81, 0x56, 0xef, 0xd4, 0xa1, 0xb8, 0x0a, 0x79,
0x12, 0x16, 0x32, 0x4b, 0xe2, 0x27, 0x5b, 0xe3, 0xd1, 0xac, 0x95, 0x1c, 0x53, 0x0b, 0x4c, 0xac, 0x6a, 0x8d, 0x47, 0xc2, 0x42, 0x66, 0x49, 0xfc, 0x64, 0x6b, 0x3c, 0x9a, 0xb5, 0x92, 0x63, 0x6a,
0x78, 0xd4, 0x7d, 0x6e, 0x68, 0x54, 0xca, 0x72, 0x03, 0xd7, 0xe6, 0x0c, 0x74, 0x85, 0x7c, 0xd6, 0x81, 0x89, 0x15, 0x8f, 0xba, 0x4f, 0x0c, 0x8d, 0x4a, 0x59, 0x6e, 0xe0, 0xf2, 0x9c, 0x81, 0xae,
0x46, 0xa8, 0x87, 0x6b, 0x90, 0xa7, 0x2f, 0x7d, 0x6a, 0x79, 0x86, 0x6d, 0x49, 0x2b, 0xdc, 0xc8, 0x90, 0xcf, 0xda, 0x08, 0xf5, 0x70, 0x0d, 0xf2, 0xf4, 0x99, 0x4f, 0x2d, 0xcf, 0xb0, 0x2d, 0x69,
0xd5, 0x05, 0x5f, 0x91, 0x9a, 0xfa, 0xac, 0x89, 0x89, 0x1e, 0xbe, 0x07, 0x2b, 0xb6, 0xe3, 0x1b, 0x85, 0x1b, 0xf9, 0x68, 0xc1, 0x2a, 0x52, 0x53, 0x9f, 0x35, 0x31, 0xd1, 0xc3, 0x7b, 0xb0, 0x62,
0xb6, 0xe5, 0x49, 0xb9, 0xed, 0xc4, 0x4e, 0x61, 0xf7, 0xa3, 0x85, 0x89, 0xd0, 0x16, 0x1c, 0x25, 0x3b, 0xbe, 0x61, 0x5b, 0x9e, 0x94, 0xdb, 0x4e, 0xec, 0x14, 0x76, 0xdf, 0x5d, 0x98, 0x08, 0x6d,
0x24, 0xe3, 0x06, 0x20, 0xcf, 0x1e, 0xbb, 0x1a, 0x55, 0x35, 0x5b, 0xa7, 0xaa, 0x61, 0xf5, 0x6d, 0xc1, 0x51, 0x42, 0x32, 0x6e, 0x00, 0xf2, 0xec, 0xb1, 0xab, 0x51, 0x55, 0xb3, 0x75, 0xaa, 0x1a,
0x29, 0xcf, 0x0d, 0x5c, 0x9c, 0x5f, 0x08, 0x27, 0xd6, 0x6c, 0x9d, 0x36, 0xac, 0xbe, 0xad, 0x94, 0x56, 0xdf, 0x96, 0xf2, 0xdc, 0xc0, 0xc5, 0xf9, 0x89, 0x70, 0x62, 0xcd, 0xd6, 0x69, 0xc3, 0xea,
0xbc, 0xa9, 0x31, 0x3e, 0x03, 0x59, 0xef, 0xc4, 0xf2, 0xc9, 0x4b, 0xa9, 0xc8, 0x33, 0x24, 0x18, 0xdb, 0x4a, 0xc9, 0x9b, 0x1a, 0xe3, 0x73, 0x90, 0xf5, 0x4e, 0x2d, 0x9f, 0x3c, 0x93, 0x8a, 0x3c,
0x95, 0xff, 0x92, 0x85, 0xb5, 0xd3, 0xa4, 0xd8, 0xe7, 0x90, 0xe9, 0xb3, 0x55, 0x4a, 0xc9, 0xff, 0x43, 0x82, 0x51, 0xf9, 0xcf, 0x59, 0x58, 0x3b, 0x4b, 0x8a, 0xdd, 0x85, 0x4c, 0x9f, 0xcd, 0x52,
0x27, 0x06, 0x42, 0x67, 0x3a, 0x88, 0xd9, 0xef, 0x19, 0xc4, 0x2a, 0x14, 0x2c, 0xea, 0xf9, 0x54, 0x4a, 0x7e, 0x93, 0x18, 0x08, 0x9d, 0xe9, 0x20, 0x66, 0xbf, 0x65, 0x10, 0xab, 0x50, 0xb0, 0xa8,
0x17, 0x19, 0x91, 0x3a, 0x65, 0x4e, 0x81, 0x50, 0x9a, 0x4f, 0xa9, 0xf4, 0xf7, 0x4a, 0xa9, 0xc7, 0xe7, 0x53, 0x5d, 0x64, 0x44, 0xea, 0x8c, 0x39, 0x05, 0x42, 0x69, 0x3e, 0xa5, 0xd2, 0xdf, 0x2a,
0xb0, 0x16, 0xb9, 0xa4, 0xba, 0xc4, 0x1a, 0x84, 0xb9, 0x79, 0xeb, 0x6d, 0x9e, 0x54, 0xe4, 0x50, 0xa5, 0x1e, 0xc0, 0x5a, 0xe4, 0x92, 0xea, 0x12, 0x6b, 0x10, 0xe6, 0xe6, 0xf5, 0x57, 0x79, 0x52,
0x4f, 0x61, 0x6a, 0x4a, 0x89, 0x4e, 0x8d, 0x71, 0x1d, 0xc0, 0xb6, 0xa8, 0xdd, 0x57, 0x75, 0xaa, 0x91, 0x43, 0x3d, 0x85, 0xa9, 0x29, 0x25, 0x3a, 0x35, 0xc6, 0x75, 0x00, 0xdb, 0xa2, 0x76, 0x5f,
0x99, 0x52, 0x6e, 0x49, 0x94, 0xda, 0x8c, 0x32, 0x17, 0x25, 0x5b, 0xa0, 0x9a, 0x89, 0x3f, 0x9b, 0xd5, 0xa9, 0x66, 0x4a, 0xb9, 0x25, 0x51, 0x6a, 0x33, 0xca, 0x5c, 0x94, 0x6c, 0x81, 0x6a, 0x26,
0xa4, 0xda, 0xca, 0x92, 0x4c, 0x39, 0x14, 0x9b, 0x6c, 0x2e, 0xdb, 0x8e, 0xa0, 0xe4, 0x52, 0x96, 0xfe, 0x74, 0x92, 0x6a, 0x2b, 0x4b, 0x32, 0xe5, 0x48, 0x6c, 0xb2, 0xb9, 0x6c, 0x3b, 0x86, 0x92,
0xf7, 0x54, 0x0f, 0x56, 0x96, 0xe7, 0x4e, 0x54, 0xde, 0xba, 0x32, 0x25, 0x50, 0x13, 0x0b, 0x5b, 0x4b, 0x59, 0xde, 0x53, 0x3d, 0x98, 0x59, 0x9e, 0x3b, 0x51, 0x79, 0xe5, 0xcc, 0x94, 0x40, 0x4d,
0x75, 0xe3, 0x43, 0x7c, 0x19, 0x22, 0x40, 0xe5, 0x69, 0x05, 0xfc, 0x14, 0x2a, 0x86, 0x60, 0x8b, 0x4c, 0x6c, 0xd5, 0x8d, 0x0f, 0xf1, 0x07, 0x10, 0x01, 0x2a, 0x4f, 0x2b, 0xe0, 0x55, 0xa8, 0x18,
0x8c, 0xe8, 0xd6, 0x2b, 0x28, 0x4d, 0x87, 0x07, 0x6f, 0x42, 0xc6, 0xf3, 0x89, 0xeb, 0xf3, 0x2c, 0x82, 0x2d, 0x32, 0xa2, 0x5b, 0xcf, 0xa1, 0x34, 0x1d, 0x1e, 0xbc, 0x09, 0x19, 0xcf, 0x27, 0xae,
0xcc, 0x28, 0x62, 0x80, 0x11, 0xa4, 0xa8, 0xa5, 0xf3, 0x53, 0x2e, 0xa3, 0xb0, 0x7f, 0xf1, 0xcf, 0xcf, 0xb3, 0x30, 0xa3, 0x88, 0x01, 0x46, 0x90, 0xa2, 0x96, 0xce, 0xab, 0x5c, 0x46, 0x61, 0xff,
0x26, 0x0b, 0x4e, 0xf1, 0x05, 0x7f, 0x32, 0xff, 0x45, 0xa7, 0x2c, 0xcf, 0xae, 0x7b, 0xeb, 0x3e, 0xe2, 0x1f, 0x4d, 0x26, 0x9c, 0xe2, 0x13, 0xfe, 0x78, 0x7e, 0x45, 0xa7, 0x2c, 0xcf, 0xce, 0x7b,
0xac, 0x4e, 0x2d, 0xe0, 0xb4, 0x53, 0x97, 0x7f, 0x05, 0x1f, 0x2e, 0x34, 0x8d, 0x1f, 0xc3, 0xe6, 0xeb, 0x36, 0xac, 0x4e, 0x4d, 0xe0, 0xac, 0x9f, 0x2e, 0xff, 0x02, 0xde, 0x5e, 0x68, 0x1a, 0x3f,
0xd8, 0x32, 0x2c, 0x9f, 0xba, 0x8e, 0x4b, 0x59, 0xc6, 0x8a, 0xa9, 0xa4, 0xff, 0xac, 0x2c, 0xc9, 0x80, 0xcd, 0xb1, 0x65, 0x58, 0x3e, 0x75, 0x1d, 0x97, 0xb2, 0x8c, 0x15, 0x9f, 0x92, 0xfe, 0xb3,
0xb9, 0xa3, 0x38, 0x5b, 0x58, 0x51, 0x36, 0xc6, 0xf3, 0xe0, 0x8d, 0x7c, 0xee, 0xbf, 0x2b, 0xe8, 0xb2, 0x24, 0xe7, 0x8e, 0xe3, 0x6c, 0x61, 0x45, 0xd9, 0x18, 0xcf, 0x83, 0x57, 0xf3, 0xb9, 0xff,
0xf5, 0xeb, 0xd7, 0xaf, 0x93, 0xe5, 0xdf, 0x66, 0x61, 0x73, 0xd1, 0x9e, 0x59, 0xb8, 0x7d, 0xcf, 0xae, 0xa0, 0x17, 0x2f, 0x5e, 0xbc, 0x48, 0x96, 0x7f, 0x9d, 0x85, 0xcd, 0x45, 0x7b, 0x66, 0xe1,
0x40, 0xd6, 0x1a, 0x8f, 0x8e, 0xa9, 0xcb, 0x83, 0x94, 0x51, 0x82, 0x11, 0xae, 0x42, 0xc6, 0x24, 0xf6, 0x3d, 0x07, 0x59, 0x6b, 0x3c, 0x3a, 0xa1, 0x2e, 0x0f, 0x52, 0x46, 0x09, 0x46, 0xb8, 0x0a,
0xc7, 0xd4, 0x94, 0xd2, 0xdb, 0x89, 0x9d, 0xd2, 0xee, 0xcd, 0x53, 0xed, 0xca, 0x4a, 0x93, 0xa9, 0x19, 0x93, 0x9c, 0x50, 0x53, 0x4a, 0x6f, 0x27, 0x76, 0x4a, 0xbb, 0xd7, 0xce, 0xb4, 0x2b, 0x2b,
0x28, 0x42, 0x13, 0x7f, 0x01, 0xe9, 0xe0, 0x88, 0x66, 0x16, 0x6e, 0x9c, 0xce, 0x02, 0xdb, 0x4b, 0x4d, 0xa6, 0xa2, 0x08, 0x4d, 0xfc, 0x19, 0xa4, 0x83, 0x12, 0xcd, 0x2c, 0x5c, 0x3d, 0x9b, 0x05,
0x0a, 0xd7, 0xc3, 0xe7, 0x21, 0xcf, 0xfe, 0x8a, 0xdc, 0xc8, 0x72, 0x9f, 0x73, 0x0c, 0x60, 0x79, 0xb6, 0x97, 0x14, 0xae, 0x87, 0xdf, 0x81, 0x3c, 0xfb, 0x2b, 0x72, 0x23, 0xcb, 0x7d, 0xce, 0x31,
0x81, 0xb7, 0x20, 0xc7, 0xb7, 0x89, 0x4e, 0xc3, 0xd2, 0x16, 0x8d, 0x59, 0x62, 0xe9, 0xb4, 0x4f, 0x80, 0xe5, 0x05, 0xde, 0x82, 0x1c, 0xdf, 0x26, 0x3a, 0x0d, 0x8f, 0xb6, 0x68, 0xcc, 0x12, 0x4b,
0xc6, 0xa6, 0xaf, 0x3e, 0x27, 0xe6, 0x98, 0xf2, 0x84, 0xcf, 0x2b, 0xc5, 0x00, 0xfc, 0x25, 0xc3, 0xa7, 0x7d, 0x32, 0x36, 0x7d, 0xf5, 0x09, 0x31, 0xc7, 0x94, 0x27, 0x7c, 0x5e, 0x29, 0x06, 0xe0,
0xf0, 0x45, 0x28, 0x88, 0x5d, 0x65, 0x58, 0x3a, 0x7d, 0xc9, 0x4f, 0xcf, 0x8c, 0x22, 0x36, 0x5a, 0x4f, 0x19, 0x86, 0x2f, 0x42, 0x41, 0xec, 0x2a, 0xc3, 0xd2, 0xe9, 0x33, 0x5e, 0x3d, 0x33, 0x8a,
0x83, 0x21, 0x6c, 0xfa, 0xa7, 0x9e, 0x6d, 0x85, 0xa9, 0xc9, 0xa7, 0x60, 0x00, 0x9f, 0xfe, 0xfe, 0xd8, 0x68, 0x0d, 0x86, 0xb0, 0xcf, 0x3f, 0xf2, 0x6c, 0x2b, 0x4c, 0x4d, 0xfe, 0x09, 0x06, 0xf0,
0xec, 0xc1, 0x7d, 0x61, 0xf1, 0xf2, 0x66, 0x73, 0xaa, 0xfc, 0xe7, 0x24, 0xa4, 0xf9, 0x79, 0xb1, 0xcf, 0xdf, 0x9e, 0x2d, 0xdc, 0xef, 0x2d, 0x9e, 0xde, 0x6c, 0x4e, 0x95, 0xff, 0x94, 0x84, 0x34,
0x06, 0x85, 0xde, 0x93, 0x8e, 0xac, 0xd6, 0xdb, 0x47, 0xfb, 0x4d, 0x19, 0x25, 0x70, 0x09, 0x80, 0xaf, 0x17, 0x6b, 0x50, 0xe8, 0x3d, 0xec, 0xc8, 0x6a, 0xbd, 0x7d, 0x7c, 0xd0, 0x94, 0x51, 0x02,
0x03, 0x0f, 0x9b, 0xed, 0x6a, 0x0f, 0x25, 0xa3, 0x71, 0xa3, 0xd5, 0xbb, 0x77, 0x07, 0xa5, 0x22, 0x97, 0x00, 0x38, 0x70, 0xaf, 0xd9, 0xae, 0xf6, 0x50, 0x32, 0x1a, 0x37, 0x5a, 0xbd, 0xbd, 0x9b,
0x85, 0x23, 0x01, 0xa4, 0xe3, 0x84, 0xdb, 0xbb, 0x28, 0x83, 0x11, 0x14, 0x85, 0x81, 0xc6, 0x63, 0x28, 0x15, 0x29, 0x1c, 0x0b, 0x20, 0x1d, 0x27, 0xdc, 0xd8, 0x45, 0x19, 0x8c, 0xa0, 0x28, 0x0c,
0xb9, 0x7e, 0xef, 0x0e, 0xca, 0x4e, 0x23, 0xb7, 0x77, 0xd1, 0x0a, 0x5e, 0x85, 0x3c, 0x47, 0xf6, 0x34, 0x1e, 0xc8, 0xf5, 0xbd, 0x9b, 0x28, 0x3b, 0x8d, 0xdc, 0xd8, 0x45, 0x2b, 0x78, 0x15, 0xf2,
0xdb, 0xed, 0x26, 0xca, 0x45, 0x36, 0xbb, 0x3d, 0xa5, 0xd1, 0x3a, 0x40, 0xf9, 0xc8, 0xe6, 0x81, 0x1c, 0x39, 0x68, 0xb7, 0x9b, 0x28, 0x17, 0xd9, 0xec, 0xf6, 0x94, 0x46, 0xeb, 0x10, 0xe5, 0x23,
0xd2, 0x3e, 0xea, 0x20, 0x88, 0x2c, 0x1c, 0xca, 0xdd, 0x6e, 0xf5, 0x40, 0x46, 0x85, 0x88, 0xb1, 0x9b, 0x87, 0x4a, 0xfb, 0xb8, 0x83, 0x20, 0xb2, 0x70, 0x24, 0x77, 0xbb, 0xd5, 0x43, 0x19, 0x15,
0xff, 0xa4, 0x27, 0x77, 0x51, 0x71, 0xca, 0xad, 0xdb, 0xbb, 0x68, 0x35, 0x9a, 0x42, 0x6e, 0x1d, 0x22, 0xc6, 0xc1, 0xc3, 0x9e, 0xdc, 0x45, 0xc5, 0x29, 0xb7, 0x6e, 0xec, 0xa2, 0xd5, 0xe8, 0x13,
0x1d, 0xa2, 0x12, 0x5e, 0x87, 0x55, 0x31, 0x45, 0xe8, 0xc4, 0xda, 0x0c, 0x74, 0xef, 0x0e, 0x42, 0x72, 0xeb, 0xf8, 0x08, 0x95, 0xf0, 0x3a, 0xac, 0x8a, 0x4f, 0x84, 0x4e, 0xac, 0xcd, 0x40, 0x7b,
0x13, 0x47, 0x84, 0x95, 0xf5, 0x29, 0xe0, 0xde, 0x1d, 0x84, 0xcb, 0x35, 0xc8, 0xf0, 0xec, 0xc2, 0x37, 0x11, 0x9a, 0x38, 0x22, 0xac, 0xac, 0x4f, 0x01, 0x7b, 0x37, 0x11, 0x2e, 0xd7, 0x20, 0xc3,
0x18, 0x4a, 0xcd, 0xea, 0xbe, 0xdc, 0x54, 0xdb, 0x9d, 0x5e, 0xa3, 0xdd, 0xaa, 0x36, 0x51, 0x62, 0xb3, 0x0b, 0x63, 0x28, 0x35, 0xab, 0x07, 0x72, 0x53, 0x6d, 0x77, 0x7a, 0x8d, 0x76, 0xab, 0xda,
0x82, 0x29, 0xf2, 0x2f, 0x8e, 0x1a, 0x8a, 0x5c, 0x47, 0xc9, 0x38, 0xd6, 0x91, 0xab, 0x3d, 0xb9, 0x44, 0x89, 0x09, 0xa6, 0xc8, 0x3f, 0x39, 0x6e, 0x28, 0x72, 0x1d, 0x25, 0xe3, 0x58, 0x47, 0xae,
0x8e, 0x52, 0x65, 0x0d, 0x36, 0x17, 0x9d, 0x93, 0x0b, 0x77, 0x46, 0xec, 0x13, 0x27, 0x97, 0x7c, 0xf6, 0xe4, 0x3a, 0x4a, 0x95, 0x35, 0xd8, 0x5c, 0x54, 0x27, 0x17, 0xee, 0x8c, 0xd8, 0x12, 0x27,
0x62, 0x6e, 0x6b, 0xee, 0x13, 0x7f, 0x9b, 0x80, 0x8d, 0x05, 0xb5, 0x62, 0xe1, 0x24, 0x3f, 0x85, 0x97, 0x2c, 0x31, 0xb7, 0x35, 0xb7, 0xc4, 0xff, 0x4a, 0xc2, 0xc6, 0x82, 0xb3, 0x62, 0xe1, 0x47,
0x8c, 0x48, 0x51, 0x51, 0x3d, 0xaf, 0x2f, 0x2c, 0x3a, 0x3c, 0x61, 0xe7, 0x2a, 0x28, 0xd7, 0x8b, 0x7e, 0x08, 0x19, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb2, 0xf0, 0xd0, 0xe1, 0x09, 0x3b, 0x77, 0x82,
0x77, 0x10, 0xa9, 0x25, 0x1d, 0x04, 0x33, 0x31, 0xe7, 0xe4, 0xaf, 0x13, 0x20, 0x2d, 0xb3, 0xfd, 0x72, 0xbd, 0x78, 0x07, 0x91, 0x5a, 0xd2, 0x41, 0x30, 0x13, 0x73, 0x35, 0xfd, 0xe7, 0x73, 0x35,
0x96, 0x83, 0x22, 0x39, 0x75, 0x50, 0x7c, 0x3e, 0xeb, 0xc0, 0xa5, 0xe5, 0x6b, 0x98, 0xf3, 0xe2, 0x5d, 0x1c, 0x7b, 0x7b, 0x67, 0x39, 0xf6, 0x38, 0xf6, 0xcd, 0x6a, 0x7b, 0x66, 0x41, 0x6d, 0xbf,
0xbb, 0x04, 0x9c, 0x59, 0xdc, 0x68, 0x2d, 0xf4, 0xe1, 0x0b, 0xc8, 0x8e, 0xa8, 0x3f, 0xb4, 0xc3, 0x0b, 0xeb, 0x73, 0x86, 0xce, 0x5c, 0x63, 0x7f, 0x99, 0x00, 0x69, 0x59, 0x70, 0x5e, 0x51, 0xe9,
0x66, 0xe3, 0x93, 0x05, 0x25, 0x8c, 0x89, 0x67, 0x63, 0x15, 0x68, 0xc5, 0x6b, 0x60, 0x6a, 0x59, 0x92, 0x53, 0x95, 0xee, 0xee, 0x6c, 0x04, 0x2f, 0x2d, 0x5f, 0x84, 0xb9, 0xb5, 0xfe, 0x3a, 0x01,
0xb7, 0x24, 0xbc, 0x99, 0xf3, 0xf4, 0x37, 0x49, 0xf8, 0x70, 0xa1, 0xf1, 0x85, 0x8e, 0x5e, 0x00, 0xe7, 0x16, 0x77, 0x8a, 0x0b, 0x7d, 0xf8, 0x0c, 0xb2, 0x23, 0xea, 0x0f, 0xed, 0xb0, 0x5b, 0xfa,
0x30, 0x2c, 0x67, 0xec, 0x8b, 0x86, 0x42, 0x9c, 0x4f, 0x79, 0x8e, 0xf0, 0xbd, 0xcf, 0xce, 0x9e, 0x78, 0xc1, 0x19, 0xcc, 0xc4, 0xb3, 0x8b, 0x1d, 0x68, 0xc5, 0x0f, 0xf1, 0xd4, 0xb2, 0x76, 0x4f,
0xb1, 0x1f, 0xc9, 0x53, 0x5c, 0x0e, 0x02, 0xe2, 0x84, 0x07, 0x13, 0x47, 0xd3, 0xdc, 0xd1, 0x8f, 0x78, 0x33, 0xe7, 0xe9, 0xaf, 0x92, 0xf0, 0xf6, 0x42, 0xe3, 0x0b, 0x1d, 0x7d, 0x0f, 0xc0, 0xb0,
0x97, 0xac, 0x74, 0xae, 0x56, 0x7f, 0x0a, 0x48, 0x33, 0x0d, 0x6a, 0xf9, 0xaa, 0xe7, 0xbb, 0x94, 0x9c, 0xb1, 0x2f, 0x3a, 0x22, 0x51, 0x60, 0xf3, 0x1c, 0xe1, 0xc5, 0x8b, 0x15, 0xcf, 0xb1, 0x1f,
0x8c, 0x0c, 0x6b, 0xc0, 0x0f, 0xe0, 0xdc, 0x5e, 0xa6, 0x4f, 0x4c, 0x8f, 0x2a, 0x6b, 0x42, 0xdc, 0xc9, 0x53, 0x5c, 0x0e, 0x02, 0xe2, 0x84, 0x3b, 0x13, 0x47, 0xd3, 0xdc, 0xd1, 0xf7, 0x97, 0xcc,
0x0d, 0xa5, 0x4c, 0x83, 0xd7, 0x38, 0x37, 0xa6, 0x91, 0x9d, 0xd2, 0x10, 0xe2, 0x48, 0xa3, 0xfc, 0x74, 0x2e, 0x31, 0x3f, 0x01, 0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x46, 0x86,
0xa7, 0x1c, 0x14, 0x62, 0x6d, 0x29, 0xbe, 0x04, 0xc5, 0xa7, 0xe4, 0x39, 0x51, 0xc3, 0xab, 0x86, 0x35, 0xe0, 0x27, 0x48, 0x6e, 0x3f, 0xd3, 0x27, 0xa6, 0x47, 0x95, 0x35, 0x21, 0xee, 0x86, 0x52,
0x88, 0x44, 0x81, 0x61, 0x9d, 0xe0, 0xba, 0xf1, 0x29, 0x6c, 0x72, 0x8a, 0x3d, 0xf6, 0xa9, 0xab, 0xa6, 0xc1, 0x13, 0xc8, 0x8d, 0x69, 0x64, 0xa7, 0x34, 0x84, 0x38, 0xd2, 0x28, 0xff, 0x31, 0x07,
0x6a, 0x26, 0xf1, 0x3c, 0x1e, 0xb4, 0x1c, 0xa7, 0x62, 0x26, 0x6b, 0x33, 0x51, 0x2d, 0x94, 0xe0, 0x85, 0x58, 0x5f, 0x8d, 0x2f, 0x41, 0xf1, 0x11, 0x79, 0x42, 0xd4, 0xf0, 0xae, 0x24, 0x22, 0x51,
0xbb, 0xb0, 0xc1, 0x35, 0x46, 0x63, 0xd3, 0x37, 0x1c, 0x93, 0xaa, 0xec, 0xf2, 0xe3, 0xf1, 0x83, 0x60, 0x58, 0x27, 0xb8, 0x2f, 0x7d, 0x02, 0x9b, 0x9c, 0x62, 0x8f, 0x7d, 0xea, 0xaa, 0x9a, 0x49,
0x38, 0xf2, 0x6c, 0x9d, 0x31, 0x0e, 0x03, 0x02, 0xf3, 0xc8, 0xc3, 0x75, 0xb8, 0xc0, 0xd5, 0x06, 0x3c, 0x8f, 0x07, 0x2d, 0xc7, 0xa9, 0x98, 0xc9, 0xda, 0x4c, 0x54, 0x0b, 0x25, 0xf8, 0x16, 0x6c,
0xd4, 0xa2, 0x2e, 0xf1, 0xa9, 0x4a, 0xbf, 0x19, 0x13, 0xd3, 0x53, 0x89, 0xa5, 0xab, 0x43, 0xe2, 0x70, 0x8d, 0xd1, 0xd8, 0xf4, 0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xbd, 0x79, 0xfc, 0x24, 0x89, 0x3c,
0x0d, 0xa5, 0x4d, 0x66, 0x60, 0x3f, 0x29, 0x25, 0x94, 0x73, 0x8c, 0x78, 0x10, 0xf0, 0x64, 0x4e, 0x5b, 0x67, 0x8c, 0xa3, 0x80, 0xc0, 0x3c, 0xf2, 0x70, 0x1d, 0xde, 0xe3, 0x6a, 0x03, 0x6a, 0x51,
0xab, 0x5a, 0xfa, 0x97, 0xc4, 0x1b, 0xe2, 0x3d, 0x38, 0xc3, 0xad, 0x78, 0xbe, 0x6b, 0x58, 0x03, 0x97, 0xf8, 0x54, 0xa5, 0x5f, 0x8d, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x21, 0xf1, 0x86, 0xd2,
0x55, 0x1b, 0x52, 0xed, 0x99, 0x3a, 0xf6, 0xfb, 0x0f, 0xa4, 0xf3, 0xf1, 0xf9, 0xb9, 0x87, 0x5d, 0x26, 0x33, 0x70, 0x90, 0x94, 0x12, 0xca, 0x05, 0x46, 0x3c, 0x0c, 0x78, 0x32, 0xa7, 0x55, 0x2d,
0xce, 0xa9, 0x31, 0xca, 0x91, 0xdf, 0x7f, 0x80, 0xbb, 0x50, 0x64, 0x1f, 0x63, 0x64, 0xbc, 0xa2, 0xfd, 0x73, 0xe2, 0x0d, 0xf1, 0x3e, 0x9c, 0xe3, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x81, 0xaa, 0x0d,
0x6a, 0xdf, 0x76, 0x79, 0x65, 0x29, 0x2d, 0xd8, 0xd9, 0xb1, 0x08, 0x56, 0xda, 0x81, 0xc2, 0xa1, 0xa9, 0xf6, 0x58, 0x1d, 0xfb, 0xfd, 0x3b, 0xd2, 0x3b, 0xf1, 0xef, 0x73, 0x0f, 0xbb, 0x9c, 0x53,
0xad, 0xd3, 0xbd, 0x4c, 0xb7, 0x23, 0xcb, 0x75, 0xa5, 0x10, 0x5a, 0x79, 0x68, 0xbb, 0x2c, 0xa1, 0x63, 0x94, 0x63, 0xbf, 0x7f, 0x07, 0x77, 0xa1, 0xc8, 0x16, 0x63, 0x64, 0x3c, 0xa7, 0x6a, 0xdf,
0x06, 0x76, 0x14, 0xe0, 0x82, 0x48, 0xa8, 0x81, 0x1d, 0x86, 0xf7, 0x2e, 0x6c, 0x68, 0x9a, 0x58, 0x76, 0xf9, 0xd1, 0x58, 0x5a, 0x50, 0x9a, 0x62, 0x11, 0xac, 0xb4, 0x03, 0x85, 0x23, 0x5b, 0xa7,
0xb3, 0xa1, 0xa9, 0xc1, 0x15, 0xc5, 0x93, 0xd0, 0x54, 0xb0, 0x34, 0xed, 0x40, 0x10, 0x82, 0x1c, 0xfb, 0x99, 0x6e, 0x47, 0x96, 0xeb, 0x4a, 0x21, 0xb4, 0x72, 0xcf, 0x76, 0x59, 0x42, 0x0d, 0xec,
0xf7, 0xf0, 0x67, 0xf0, 0xe1, 0x24, 0x58, 0x71, 0xc5, 0xf5, 0xb9, 0x55, 0xce, 0xaa, 0xde, 0x85, 0x28, 0xc0, 0x05, 0x91, 0x50, 0x03, 0x3b, 0x0c, 0xef, 0x2d, 0xd8, 0xd0, 0x34, 0x31, 0x67, 0x43,
0x0d, 0xe7, 0x64, 0x5e, 0x11, 0x4f, 0xcd, 0xe8, 0x9c, 0xcc, 0xaa, 0xdd, 0x87, 0x4d, 0x67, 0xe8, 0x53, 0x83, 0x3b, 0x96, 0x27, 0xa1, 0xa9, 0x60, 0x69, 0xda, 0xa1, 0x20, 0x04, 0x39, 0xee, 0xe1,
0xcc, 0xeb, 0x6d, 0xc4, 0xf5, 0xb0, 0x33, 0x74, 0x66, 0x15, 0xaf, 0xf2, 0xfb, 0xaa, 0x4b, 0x35, 0x4f, 0xe1, 0xed, 0x49, 0xb0, 0xe2, 0x8a, 0xeb, 0x73, 0xb3, 0x9c, 0x55, 0xbd, 0x05, 0x1b, 0xce,
0xe2, 0x53, 0x5d, 0x3a, 0x1b, 0xa7, 0xc7, 0x04, 0xf8, 0x16, 0x20, 0x4d, 0x53, 0xa9, 0x45, 0x8e, 0xe9, 0xbc, 0x22, 0x9e, 0xfa, 0xa2, 0x73, 0x3a, 0xab, 0x76, 0x1b, 0x36, 0x9d, 0xa1, 0x33, 0xaf,
0x4d, 0xaa, 0x12, 0x97, 0x5a, 0xc4, 0x93, 0x2e, 0xc6, 0xc9, 0x25, 0x4d, 0x93, 0xb9, 0xb4, 0xca, 0x77, 0x35, 0xae, 0x87, 0x9d, 0xa1, 0x33, 0xab, 0xf8, 0x11, 0xbf, 0x70, 0xbb, 0x54, 0x23, 0x3e,
0x85, 0xf8, 0x06, 0xac, 0xdb, 0xc7, 0x4f, 0x35, 0x91, 0x92, 0xaa, 0xe3, 0xd2, 0xbe, 0xf1, 0x52, 0xd5, 0xa5, 0xf3, 0x71, 0x7a, 0x4c, 0x80, 0xaf, 0x03, 0xd2, 0x34, 0x95, 0x5a, 0xe4, 0xc4, 0xa4,
0xba, 0xc2, 0xe3, 0xbb, 0xc6, 0x04, 0x3c, 0x21, 0x3b, 0x1c, 0xc6, 0xd7, 0x01, 0x69, 0xde, 0x90, 0x2a, 0x71, 0xa9, 0x45, 0x3c, 0xe9, 0x62, 0x9c, 0x5c, 0xd2, 0x34, 0x99, 0x4b, 0xab, 0x5c, 0x88,
0xb8, 0x0e, 0xef, 0x09, 0x3c, 0x87, 0x68, 0x54, 0xba, 0x2a, 0xa8, 0x02, 0x6f, 0x85, 0x30, 0xdb, 0xaf, 0xc2, 0xba, 0x7d, 0xf2, 0x48, 0x13, 0x29, 0xa9, 0x3a, 0x2e, 0xed, 0x1b, 0xcf, 0xa4, 0x0f,
0x12, 0xde, 0x0b, 0xa3, 0xef, 0x87, 0x16, 0xaf, 0x89, 0x2d, 0xc1, 0xb1, 0xc0, 0xda, 0x0e, 0x20, 0x79, 0x7c, 0xd7, 0x98, 0x80, 0x27, 0x64, 0x87, 0xc3, 0xf8, 0x0a, 0x20, 0xcd, 0x1b, 0x12, 0xd7,
0x16, 0x8a, 0xa9, 0x89, 0x77, 0x38, 0xad, 0xe4, 0x0c, 0x9d, 0xf8, 0xbc, 0x97, 0x61, 0x95, 0x31, 0xe1, 0x35, 0xd9, 0x73, 0x88, 0x46, 0xa5, 0x8f, 0x04, 0x55, 0xe0, 0xad, 0x10, 0x66, 0x5b, 0xc2,
0x27, 0x93, 0x5e, 0x17, 0xfd, 0x8c, 0x33, 0x8c, 0xcd, 0xf8, 0xce, 0x5a, 0xcb, 0xf2, 0x1e, 0x14, 0x7b, 0x6a, 0xf4, 0xfd, 0xd0, 0xe2, 0x65, 0xb1, 0x25, 0x38, 0x16, 0x58, 0xdb, 0x01, 0xc4, 0x42,
0xe3, 0xf9, 0x89, 0xf3, 0x20, 0x32, 0x14, 0x25, 0x58, 0xad, 0xaf, 0xb5, 0xeb, 0xac, 0x4a, 0x7f, 0x31, 0xf5, 0xe1, 0x1d, 0x4e, 0x2b, 0x39, 0x43, 0x27, 0xfe, 0xdd, 0x0f, 0x60, 0x95, 0x31, 0x27,
0x2d, 0xa3, 0x24, 0xeb, 0x16, 0x9a, 0x8d, 0x9e, 0xac, 0x2a, 0x47, 0xad, 0x5e, 0xe3, 0x50, 0x46, 0x1f, 0xbd, 0x22, 0x1a, 0x32, 0x67, 0x18, 0xfb, 0xe2, 0x6b, 0xeb, 0x8d, 0xcb, 0xfb, 0x50, 0x8c,
0xa9, 0x78, 0x5b, 0xfa, 0xb7, 0x24, 0x94, 0xa6, 0x6f, 0x18, 0xf8, 0x27, 0x70, 0x36, 0x7c, 0x0e, 0xe7, 0x27, 0xce, 0x83, 0xc8, 0x50, 0x94, 0x60, 0xcd, 0x4a, 0xad, 0x5d, 0x67, 0x6d, 0xc6, 0x97,
0xf0, 0xa8, 0xaf, 0xbe, 0x30, 0x5c, 0xbe, 0x65, 0x46, 0x44, 0x74, 0xd8, 0xd1, 0x47, 0xdb, 0x0c, 0x32, 0x4a, 0xb2, 0x76, 0xa7, 0xd9, 0xe8, 0xc9, 0xaa, 0x72, 0xdc, 0xea, 0x35, 0x8e, 0x64, 0x94,
0x58, 0x5d, 0xea, 0x7f, 0x65, 0xb8, 0x6c, 0x43, 0x8c, 0x88, 0x8f, 0x9b, 0x70, 0xd1, 0xb2, 0x55, 0x8a, 0xf7, 0xd5, 0x7f, 0x4d, 0x42, 0x69, 0xfa, 0x8a, 0x84, 0x7f, 0x00, 0xe7, 0xc3, 0xf7, 0x0c,
0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3c, 0xc4, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xa2, 0x8f, 0xfa, 0xea, 0x53, 0xc3, 0xe5, 0x5b, 0x66, 0x44, 0xc4, 0xf1, 0x15, 0x2d, 0xda, 0x66, 0xc0,
0x54, 0x45, 0x56, 0x3e, 0xb2, 0xec, 0x6e, 0x40, 0x9e, 0x9c, 0xe1, 0xd5, 0x80, 0x3a, 0x93, 0x60, 0xea, 0x52, 0xff, 0x0b, 0xc3, 0x65, 0x1b, 0x62, 0x44, 0x7c, 0xdc, 0x84, 0x8b, 0x96, 0xad, 0x7a,
0xa9, 0x65, 0x09, 0x76, 0x1e, 0xf2, 0x23, 0xe2, 0xa8, 0xd4, 0xf2, 0xdd, 0x13, 0xde, 0x57, 0xe6, 0x3e, 0xb1, 0x74, 0xe2, 0xea, 0xea, 0xe4, 0x25, 0x49, 0x25, 0x9a, 0x46, 0x3d, 0xcf, 0x16, 0x47,
0x94, 0xdc, 0x88, 0x38, 0x32, 0x1b, 0xbf, 0x9f, 0xf6, 0xfe, 0x9f, 0x29, 0x28, 0xc6, 0x7b, 0x4b, 0x55, 0x64, 0xe5, 0x5d, 0xcb, 0xee, 0x06, 0xe4, 0x49, 0x0d, 0xaf, 0x06, 0xd4, 0x99, 0x04, 0x4b,
0xd6, 0xaa, 0x6b, 0xbc, 0x8e, 0x24, 0xf8, 0x49, 0x73, 0xf9, 0x8d, 0x9d, 0x68, 0xa5, 0xc6, 0x0a, 0x2d, 0x4b, 0xb0, 0x77, 0x20, 0x3f, 0x22, 0x8e, 0x4a, 0x2d, 0xdf, 0x3d, 0xe5, 0x8d, 0x71, 0x4e,
0xcc, 0x5e, 0x56, 0x74, 0x7c, 0x8a, 0xd0, 0x64, 0xc5, 0x9d, 0x9d, 0x2d, 0x54, 0xdc, 0x62, 0x72, 0xc9, 0x8d, 0x88, 0x23, 0xb3, 0xf1, 0x9b, 0xb9, 0x9f, 0xfc, 0x23, 0x05, 0xc5, 0x78, 0x73, 0xcc,
0x4a, 0x30, 0xc2, 0x07, 0x90, 0x7d, 0xea, 0x71, 0xdb, 0x59, 0x6e, 0xfb, 0xca, 0x9b, 0x6d, 0x3f, 0xee, 0x1a, 0x1a, 0x3f, 0x47, 0x12, 0xbc, 0xd2, 0x7c, 0xf0, 0xd2, 0x56, 0xba, 0x52, 0x63, 0x07,
0xea, 0x72, 0xe3, 0xf9, 0x47, 0x5d, 0xb5, 0xd5, 0x56, 0x0e, 0xab, 0x4d, 0x25, 0x50, 0xc7, 0xe7, 0xcc, 0x7e, 0x56, 0xb4, 0xac, 0x8a, 0xd0, 0x64, 0x87, 0x3b, 0xab, 0x2d, 0x54, 0xb4, 0x08, 0x39,
0x20, 0x6d, 0x92, 0x57, 0x27, 0xd3, 0xa5, 0x88, 0x43, 0xa7, 0x0d, 0xfc, 0x39, 0x48, 0xbf, 0xa0, 0x25, 0x18, 0xe1, 0x43, 0xc8, 0x3e, 0xf2, 0xb8, 0xed, 0x2c, 0xb7, 0xfd, 0xe1, 0xcb, 0x6d, 0xdf,
0xe4, 0xd9, 0x74, 0x01, 0xe0, 0xd0, 0x3b, 0x4c, 0xfd, 0x5b, 0x90, 0xe1, 0xf1, 0xc2, 0x00, 0x41, 0xef, 0x72, 0xe3, 0xf9, 0xfb, 0x5d, 0xb5, 0xd5, 0x56, 0x8e, 0xaa, 0x4d, 0x25, 0x50, 0xc7, 0x17,
0xc4, 0xd0, 0x07, 0x38, 0x07, 0xe9, 0x5a, 0x5b, 0x61, 0xe9, 0x8f, 0xa0, 0x28, 0x50, 0xb5, 0xd3, 0x20, 0x6d, 0x92, 0xe7, 0xa7, 0xd3, 0x47, 0x11, 0x87, 0xce, 0x1a, 0xf8, 0x0b, 0x90, 0x7e, 0x4a,
0x90, 0x6b, 0x32, 0x4a, 0x96, 0xef, 0x42, 0x56, 0x04, 0x81, 0x6d, 0x8d, 0x28, 0x0c, 0xe8, 0x83, 0xc9, 0xe3, 0xe9, 0x03, 0x80, 0x43, 0xaf, 0x31, 0xf5, 0xaf, 0x43, 0x86, 0xc7, 0x0b, 0x03, 0x04,
0x60, 0x18, 0xd8, 0x48, 0x84, 0xd2, 0xa3, 0xc3, 0x7d, 0x59, 0x41, 0xc9, 0xf8, 0xe7, 0xf5, 0xa0, 0x11, 0x43, 0x6f, 0xe1, 0x1c, 0xa4, 0x6b, 0x6d, 0x85, 0xa5, 0x3f, 0x82, 0xa2, 0x40, 0xd5, 0x4e,
0x18, 0x6f, 0x2b, 0xdf, 0x4f, 0x4e, 0xfd, 0x35, 0x01, 0x85, 0x58, 0x9b, 0xc8, 0x1a, 0x14, 0x62, 0x43, 0xae, 0xc9, 0x28, 0x59, 0xbe, 0x05, 0x59, 0x11, 0x04, 0xb6, 0x35, 0xa2, 0x30, 0xa0, 0xb7,
0x9a, 0xf6, 0x0b, 0x95, 0x98, 0x06, 0xf1, 0x82, 0xa4, 0x00, 0x0e, 0x55, 0x19, 0x72, 0xda, 0x8f, 0x82, 0x61, 0x60, 0x23, 0x11, 0x4a, 0x8f, 0x8f, 0x0e, 0x64, 0x05, 0x25, 0xe3, 0xcb, 0xeb, 0x41,
0xf6, 0x5e, 0x9c, 0xff, 0x43, 0x02, 0xd0, 0x6c, 0x8b, 0x39, 0xe3, 0x60, 0xe2, 0x07, 0x75, 0xf0, 0x31, 0xde, 0x17, 0xbf, 0x99, 0x9c, 0xfa, 0x4b, 0x02, 0x0a, 0xb1, 0x3e, 0x97, 0x35, 0x28, 0xc4,
0xf7, 0x09, 0x28, 0x4d, 0xf7, 0x95, 0x33, 0xee, 0x5d, 0xfa, 0x41, 0xdd, 0xfb, 0x57, 0x12, 0x56, 0x34, 0xed, 0xa7, 0x2a, 0x31, 0x0d, 0xe2, 0x05, 0x49, 0x01, 0x1c, 0xaa, 0x32, 0xe4, 0xac, 0x8b,
0xa7, 0xba, 0xc9, 0xd3, 0x7a, 0xf7, 0x0d, 0xac, 0x1b, 0x3a, 0x1d, 0x39, 0xb6, 0x4f, 0x2d, 0xed, 0xf6, 0x46, 0x9c, 0xff, 0x5d, 0x02, 0xd0, 0x6c, 0x8b, 0x39, 0xe3, 0x60, 0xe2, 0x3b, 0x75, 0xf0,
0x44, 0x35, 0xe9, 0x73, 0x6a, 0x4a, 0x65, 0x7e, 0x50, 0xdc, 0x7a, 0x73, 0xbf, 0x5a, 0x69, 0x4c, 0xb7, 0x09, 0x28, 0x4d, 0xf7, 0x95, 0x33, 0xee, 0x5d, 0xfa, 0x4e, 0xdd, 0xfb, 0x67, 0x12, 0x56,
0xf4, 0x9a, 0x4c, 0x6d, 0x6f, 0xa3, 0x51, 0x97, 0x0f, 0x3b, 0xed, 0x9e, 0xdc, 0xaa, 0x3d, 0x51, 0xa7, 0xba, 0xc9, 0xb3, 0x7a, 0xf7, 0x15, 0xac, 0x1b, 0x3a, 0x1d, 0x39, 0xb6, 0x4f, 0x2d, 0xed,
0x8f, 0x5a, 0x3f, 0x6f, 0xb5, 0xbf, 0x6a, 0x29, 0xc8, 0x98, 0xa1, 0xbd, 0xc3, 0xad, 0xde, 0x01, 0x54, 0x35, 0xe9, 0x13, 0x6a, 0x4a, 0x65, 0x5e, 0x28, 0xae, 0xbf, 0xbc, 0x5f, 0xad, 0x34, 0x26,
0x34, 0xeb, 0x14, 0x3e, 0x0b, 0x8b, 0xdc, 0x42, 0x1f, 0xe0, 0x0d, 0x58, 0x6b, 0xb5, 0xd5, 0x6e, 0x7a, 0x4d, 0xa6, 0xb6, 0xbf, 0xd1, 0xa8, 0xcb, 0x47, 0x9d, 0x76, 0x4f, 0x6e, 0xd5, 0x1e, 0xaa,
0xa3, 0x2e, 0xab, 0xf2, 0xc3, 0x87, 0x72, 0xad, 0xd7, 0x15, 0x17, 0xf8, 0x88, 0xdd, 0x9b, 0xde, 0xc7, 0xad, 0x1f, 0xb7, 0xda, 0x5f, 0xb4, 0x14, 0x64, 0xcc, 0xd0, 0x5e, 0xe3, 0x56, 0xef, 0x00,
0xd4, 0xbf, 0x4b, 0xc1, 0xc6, 0x02, 0x4f, 0x70, 0x35, 0xb8, 0x3b, 0x88, 0xeb, 0xcc, 0x8f, 0x4f, 0x9a, 0x75, 0x0a, 0x9f, 0x87, 0x45, 0x6e, 0xa1, 0xb7, 0xf0, 0x06, 0xac, 0xb5, 0xda, 0x6a, 0xb7,
0xe3, 0x7d, 0x85, 0x95, 0xfc, 0x0e, 0x71, 0xfd, 0xe0, 0xaa, 0x71, 0x1d, 0x58, 0x94, 0x2c, 0xdf, 0x51, 0x97, 0x55, 0xf9, 0xde, 0x3d, 0xb9, 0xd6, 0xeb, 0x8a, 0x17, 0x88, 0x88, 0xdd, 0x9b, 0xde,
0xe8, 0x1b, 0xd4, 0x0d, 0xde, 0x3b, 0xc4, 0x85, 0x62, 0x6d, 0x82, 0x8b, 0x27, 0x8f, 0x1f, 0x01, 0xd4, 0xbf, 0x49, 0xc1, 0xc6, 0x02, 0x4f, 0x70, 0x35, 0xb8, 0x3b, 0x88, 0xeb, 0xcc, 0xf7, 0xcf,
0x76, 0x6c, 0xcf, 0xf0, 0x8d, 0xe7, 0x54, 0x35, 0xac, 0xf0, 0x71, 0x84, 0x5d, 0x30, 0xd2, 0x0a, 0xe2, 0x7d, 0x85, 0x1d, 0xf9, 0x1d, 0xe2, 0xfa, 0xc1, 0x55, 0xe3, 0x0a, 0xb0, 0x28, 0x59, 0xbe,
0x0a, 0x25, 0x0d, 0xcb, 0x8f, 0xd8, 0x16, 0x1d, 0x90, 0x19, 0x36, 0x3b, 0xc0, 0x53, 0x0a, 0x0a, 0xd1, 0x37, 0xa8, 0x1b, 0x3c, 0xd8, 0x88, 0x0b, 0xc5, 0xda, 0x04, 0x17, 0x6f, 0x36, 0xdf, 0x03,
0x25, 0x11, 0xfb, 0x12, 0x14, 0x75, 0x7b, 0xcc, 0xba, 0x2e, 0xc1, 0x63, 0xf5, 0x22, 0xa1, 0x14, 0xec, 0xd8, 0x9e, 0xe1, 0x1b, 0x4f, 0xa8, 0x6a, 0x58, 0xe1, 0xeb, 0x0e, 0xbb, 0x60, 0xa4, 0x15,
0x04, 0x16, 0x51, 0x82, 0x7e, 0x7a, 0xf2, 0x2a, 0x53, 0x54, 0x0a, 0x02, 0x13, 0x94, 0x6b, 0xb0, 0x14, 0x4a, 0x1a, 0x96, 0x1f, 0xb1, 0x2d, 0x3a, 0x20, 0x33, 0x6c, 0x56, 0xc0, 0x53, 0x0a, 0x0a,
0x46, 0x06, 0x03, 0x97, 0x19, 0x0f, 0x0d, 0x89, 0x1b, 0x42, 0x29, 0x82, 0x39, 0x71, 0xeb, 0x11, 0x25, 0x11, 0xfb, 0x12, 0x14, 0x75, 0x7b, 0xcc, 0xba, 0x2e, 0xc1, 0x63, 0xe7, 0x45, 0x42, 0x29,
0xe4, 0xc2, 0x38, 0xb0, 0x92, 0xcc, 0x22, 0xa1, 0x3a, 0xe2, 0x65, 0x2e, 0xb9, 0x93, 0x57, 0x72, 0x08, 0x2c, 0xa2, 0x04, 0xfd, 0xf4, 0xe4, 0x59, 0xa9, 0xa8, 0x14, 0x04, 0x26, 0x28, 0x97, 0x61,
0x56, 0x28, 0xbc, 0x04, 0x45, 0xc3, 0x53, 0x27, 0x8f, 0xcc, 0xc9, 0xed, 0xe4, 0x4e, 0x4e, 0x29, 0x8d, 0x0c, 0x06, 0x2e, 0x33, 0x1e, 0x1a, 0x12, 0x37, 0x84, 0x52, 0x04, 0x73, 0xe2, 0xd6, 0x7d,
0x18, 0x5e, 0xf4, 0x40, 0x57, 0xfe, 0x2e, 0x09, 0xa5, 0xe9, 0x47, 0x72, 0x5c, 0x87, 0x9c, 0x69, 0xc8, 0x85, 0x71, 0x60, 0x47, 0x32, 0x8b, 0x84, 0xea, 0x88, 0x6b, 0x6f, 0x72, 0x27, 0xaf, 0xe4,
0x6b, 0x84, 0xa7, 0x96, 0xf8, 0x85, 0x66, 0xe7, 0x2d, 0xef, 0xea, 0x95, 0x66, 0xc0, 0x57, 0x22, 0xac, 0x50, 0x78, 0x09, 0x8a, 0x86, 0xa7, 0x4e, 0x5e, 0xc9, 0x93, 0xdb, 0xc9, 0x9d, 0x9c, 0x52,
0xcd, 0xad, 0xbf, 0x27, 0x20, 0x17, 0xc2, 0xf8, 0x0c, 0xa4, 0x1d, 0xe2, 0x0f, 0xb9, 0xb9, 0xcc, 0x30, 0xbc, 0xe8, 0x85, 0xb1, 0xfc, 0x75, 0x12, 0x4a, 0xd3, 0xaf, 0xfc, 0xb8, 0x0e, 0x39, 0xd3,
0x7e, 0x12, 0x25, 0x14, 0x3e, 0x66, 0xb8, 0xe7, 0x10, 0x8b, 0xa7, 0x40, 0x80, 0xb3, 0x31, 0xfb, 0xd6, 0x08, 0x4f, 0x2d, 0xf1, 0x13, 0xd3, 0xce, 0x2b, 0x7e, 0x18, 0xa8, 0x34, 0x03, 0xbe, 0x12,
0xae, 0x26, 0x25, 0x3a, 0xbf, 0x7e, 0xd8, 0xa3, 0x11, 0xb5, 0x7c, 0x2f, 0xfc, 0xae, 0x01, 0x5e, 0x69, 0x6e, 0xfd, 0x2d, 0x01, 0xb9, 0x10, 0xc6, 0xe7, 0x20, 0xed, 0x10, 0x7f, 0xc8, 0xcd, 0x65,
0x0b, 0x60, 0x7c, 0x13, 0xd6, 0x7d, 0x97, 0x18, 0xe6, 0x14, 0x37, 0xcd, 0xb9, 0x28, 0x14, 0x44, 0x0e, 0x92, 0x28, 0xa1, 0xf0, 0x31, 0xc3, 0x3d, 0x87, 0x58, 0x3c, 0x05, 0x02, 0x9c, 0x8d, 0xd9,
0xe4, 0x3d, 0x38, 0x17, 0xda, 0xd5, 0xa9, 0x4f, 0xb4, 0x21, 0xd5, 0x27, 0x4a, 0x59, 0xfe, 0x02, 0xba, 0x9a, 0x94, 0xe8, 0xfc, 0xfa, 0x61, 0x8f, 0x46, 0xd4, 0xf2, 0xbd, 0x70, 0x5d, 0x03, 0xbc,
0x7b, 0x36, 0x20, 0xd4, 0x03, 0x79, 0xa8, 0x5b, 0xfe, 0x47, 0x02, 0xd6, 0xc3, 0x0b, 0x93, 0x1e, 0x16, 0xc0, 0xf8, 0x1a, 0xac, 0xfb, 0x2e, 0x31, 0xcc, 0x29, 0x6e, 0x9a, 0x73, 0x51, 0x28, 0x88,
0x05, 0xeb, 0x10, 0x80, 0x58, 0x96, 0xed, 0xc7, 0xc3, 0x35, 0x9f, 0xca, 0x73, 0x7a, 0x95, 0x6a, 0xc8, 0xfb, 0x70, 0x21, 0xb4, 0xab, 0x53, 0x9f, 0x68, 0x43, 0xaa, 0x4f, 0x94, 0xb2, 0xfc, 0x99,
0xa4, 0xa4, 0xc4, 0x0c, 0x6c, 0x8d, 0x00, 0x26, 0x92, 0xa5, 0x61, 0xbb, 0x08, 0x85, 0xe0, 0x17, 0xe1, 0x7c, 0x40, 0xa8, 0x07, 0xf2, 0x50, 0xb7, 0xfc, 0xf7, 0x04, 0xac, 0x87, 0x17, 0x26, 0x3d,
0x10, 0xfe, 0x33, 0x9a, 0xb8, 0x62, 0x83, 0x80, 0xd8, 0xcd, 0x0a, 0x6f, 0x42, 0xe6, 0x98, 0x0e, 0x0a, 0xd6, 0x11, 0x00, 0xb1, 0x2c, 0xdb, 0x8f, 0x87, 0x6b, 0x3e, 0x95, 0xe7, 0xf4, 0x2a, 0xd5,
0x0c, 0x2b, 0x78, 0xd7, 0x14, 0x83, 0xf0, 0xad, 0x36, 0x1d, 0xbd, 0xd5, 0xee, 0x3f, 0x86, 0x0d, 0x48, 0x49, 0x89, 0x19, 0xd8, 0x1a, 0x01, 0x4c, 0x24, 0x4b, 0xc3, 0x76, 0x11, 0x0a, 0xc1, 0x4f,
0xcd, 0x1e, 0xcd, 0xba, 0xbb, 0x8f, 0x66, 0xae, 0xf9, 0xde, 0x97, 0x89, 0xaf, 0x61, 0xd2, 0x62, 0x38, 0xfc, 0x77, 0x40, 0x71, 0xc5, 0x06, 0x01, 0xb1, 0x9b, 0x15, 0xde, 0x84, 0xcc, 0x09, 0x1d,
0x7e, 0x9b, 0x4c, 0x1d, 0x74, 0xf6, 0xff, 0x98, 0xdc, 0x3a, 0x10, 0x7a, 0x9d, 0x70, 0x99, 0x0a, 0x18, 0x56, 0xf0, 0x30, 0x2b, 0x06, 0xe1, 0x43, 0x48, 0x3a, 0x7a, 0x08, 0x39, 0xf8, 0x19, 0x6c,
0xed, 0x9b, 0x54, 0x63, 0xae, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x03, 0xf1, 0x99, 0x1b, 0x68, 0xf6, 0x68, 0xd6, 0xdd, 0x03, 0x34, 0x73, 0xcd, 0xf7, 0x3e, 0x4f, 0x7c, 0x09, 0x93, 0x16,
0x1c, 0x00, 0x00, 0xf3, 0x7f, 0x89, 0xc4, 0xef, 0x93, 0xa9, 0xc3, 0xce, 0xc1, 0x1f, 0x92, 0x5b, 0x87, 0x42, 0xb5,
0x13, 0xce, 0x54, 0xa1, 0x7d, 0x93, 0x6a, 0xcc, 0xfb, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xa3,
0x58, 0x22, 0x30, 0xdf, 0x1c, 0x00, 0x00,
} }

View File

@ -34,11 +34,10 @@ package descriptor
import fmt "fmt" import fmt "fmt"
import strings "strings" import strings "strings"
import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" import proto "github.com/gogo/protobuf/proto"
import sort "sort" import sort "sort"
import strconv "strconv" import strconv "strconv"
import reflect "reflect" import reflect "reflect"
import proto "github.com/gogo/protobuf/proto"
import math "math" import math "math"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -270,7 +269,7 @@ func (this *EnumDescriptorProto) GoString() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
s := make([]string, 0, 7) s := make([]string, 0, 9)
s = append(s, "&descriptor.EnumDescriptorProto{") s = append(s, "&descriptor.EnumDescriptorProto{")
if this.Name != nil { if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
@ -281,6 +280,30 @@ func (this *EnumDescriptorProto) GoString() string {
if this.Options != nil { if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n") s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
} }
if this.ReservedRange != nil {
s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
}
if this.ReservedName != nil {
s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EnumDescriptorProto_EnumReservedRange) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.EnumDescriptorProto_EnumReservedRange{")
if this.Start != nil {
s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
}
if this.End != nil {
s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
}
if this.XXX_unrecognized != nil { if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
} }
@ -729,8 +752,8 @@ func valueToGoStringDescriptor(v interface{}, typ string) string {
pv := reflect.Indirect(rv).Interface() pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
} }
func extensionToGoStringDescriptor(m github_com_gogo_protobuf_proto.Message) string { func extensionToGoStringDescriptor(m proto.Message) string {
e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) e := proto.GetUnsafeExtensionsMap(m)
if e == nil { if e == nil {
return "nil" return "nil"
} }

View File

@ -0,0 +1,12 @@
syntax = "proto2";
package issue270.a;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "github.com/gogo/protobuf/test/issue270/a/a2.proto";
option (gogoproto.populate_all) = true;
message A1 {
optional A2 a2 = 1;
}

View File

@ -0,0 +1,12 @@
syntax = "proto2";
package issue270.a;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "github.com/gogo/protobuf/test/issue270/b/b.proto";
option (gogoproto.populate_all) = true;
message A2 {
optional issue270.b.B b = 1;
}

View File

@ -0,0 +1,6 @@
syntax = "proto2";
package issue270.b;
message B {
}

View File

@ -202,10 +202,7 @@ func (this *Any) Compare(that interface{}) int {
} }
func (this *Any) Equal(that interface{}) bool { func (this *Any) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Any) that1, ok := that.(*Any)
@ -218,10 +215,7 @@ func (this *Any) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }

View File

@ -169,10 +169,7 @@ func (this *Duration) Compare(that interface{}) int {
} }
func (this *Duration) Equal(that interface{}) bool { func (this *Duration) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Duration) that1, ok := that.(*Duration)
@ -185,10 +182,7 @@ func (this *Duration) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }

View File

@ -81,10 +81,7 @@ func (this *Empty) Compare(that interface{}) int {
} }
func (this *Empty) Equal(that interface{}) bool { func (this *Empty) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Empty) that1, ok := that.(*Empty)
@ -97,10 +94,7 @@ func (this *Empty) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }

View File

@ -295,10 +295,7 @@ func (this *FieldMask) Compare(that interface{}) int {
} }
func (this *FieldMask) Equal(that interface{}) bool { func (this *FieldMask) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*FieldMask) that1, ok := that.(*FieldMask)
@ -311,10 +308,7 @@ func (this *FieldMask) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }

View File

@ -22,9 +22,9 @@ import strconv "strconv"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" import sortkeys "github.com/gogo/protobuf/sortkeys"
import encoding_binary "encoding/binary" import binary "encoding/binary"
import io "io" import io "io"
@ -361,10 +361,7 @@ func (x NullValue) String() string {
} }
func (this *Struct) Equal(that interface{}) bool { func (this *Struct) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Struct) that1, ok := that.(*Struct)
@ -377,10 +374,7 @@ func (this *Struct) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -396,10 +390,7 @@ func (this *Struct) Equal(that interface{}) bool {
} }
func (this *Value) Equal(that interface{}) bool { func (this *Value) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value) that1, ok := that.(*Value)
@ -412,10 +403,7 @@ func (this *Value) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -432,10 +420,7 @@ func (this *Value) Equal(that interface{}) bool {
} }
func (this *Value_NullValue) Equal(that interface{}) bool { func (this *Value_NullValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_NullValue) that1, ok := that.(*Value_NullValue)
@ -448,10 +433,7 @@ func (this *Value_NullValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -462,10 +444,7 @@ func (this *Value_NullValue) Equal(that interface{}) bool {
} }
func (this *Value_NumberValue) Equal(that interface{}) bool { func (this *Value_NumberValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_NumberValue) that1, ok := that.(*Value_NumberValue)
@ -478,10 +457,7 @@ func (this *Value_NumberValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -492,10 +468,7 @@ func (this *Value_NumberValue) Equal(that interface{}) bool {
} }
func (this *Value_StringValue) Equal(that interface{}) bool { func (this *Value_StringValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_StringValue) that1, ok := that.(*Value_StringValue)
@ -508,10 +481,7 @@ func (this *Value_StringValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -522,10 +492,7 @@ func (this *Value_StringValue) Equal(that interface{}) bool {
} }
func (this *Value_BoolValue) Equal(that interface{}) bool { func (this *Value_BoolValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_BoolValue) that1, ok := that.(*Value_BoolValue)
@ -538,10 +505,7 @@ func (this *Value_BoolValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -552,10 +516,7 @@ func (this *Value_BoolValue) Equal(that interface{}) bool {
} }
func (this *Value_StructValue) Equal(that interface{}) bool { func (this *Value_StructValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_StructValue) that1, ok := that.(*Value_StructValue)
@ -568,10 +529,7 @@ func (this *Value_StructValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -582,10 +540,7 @@ func (this *Value_StructValue) Equal(that interface{}) bool {
} }
func (this *Value_ListValue) Equal(that interface{}) bool { func (this *Value_ListValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Value_ListValue) that1, ok := that.(*Value_ListValue)
@ -598,10 +553,7 @@ func (this *Value_ListValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -612,10 +564,7 @@ func (this *Value_ListValue) Equal(that interface{}) bool {
} }
func (this *ListValue) Equal(that interface{}) bool { func (this *ListValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*ListValue) that1, ok := that.(*ListValue)
@ -628,10 +577,7 @@ func (this *ListValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -655,7 +601,7 @@ func (this *Struct) GoString() string {
for k := range this.Fields { for k := range this.Fields {
keysForFields = append(keysForFields, k) keysForFields = append(keysForFields, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForFields) sortkeys.Strings(keysForFields)
mapStringForFields := "map[string]*Value{" mapStringForFields := "map[string]*Value{"
for _, k := range keysForFields { for _, k := range keysForFields {
mapStringForFields += fmt.Sprintf("%#v: %#v,", k, this.Fields[k]) mapStringForFields += fmt.Sprintf("%#v: %#v,", k, this.Fields[k])
@ -829,7 +775,7 @@ func (m *Value_NumberValue) MarshalTo(dAtA []byte) (int, error) {
i := 0 i := 0
dAtA[i] = 0x11 dAtA[i] = 0x11
i++ i++
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.NumberValue)))) binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.NumberValue))))
i += 8 i += 8
return i, nil return i, nil
} }
@ -1179,7 +1125,7 @@ func (this *Struct) String() string {
for k := range this.Fields { for k := range this.Fields {
keysForFields = append(keysForFields, k) keysForFields = append(keysForFields, k)
} }
github_com_gogo_protobuf_sortkeys.Strings(keysForFields) sortkeys.Strings(keysForFields)
mapStringForFields := "map[string]*Value{" mapStringForFields := "map[string]*Value{"
for _, k := range keysForFields { for _, k := range keysForFields {
mapStringForFields += fmt.Sprintf("%v: %v,", k, this.Fields[k]) mapStringForFields += fmt.Sprintf("%v: %v,", k, this.Fields[k])
@ -1509,7 +1455,7 @@ func (m *Value) Unmarshal(dAtA []byte) error {
if (iNdEx + 8) > l { if (iNdEx + 8) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:]))
iNdEx += 8 iNdEx += 8
m.Kind = &Value_NumberValue{float64(math.Float64frombits(v))} m.Kind = &Value_NumberValue{float64(math.Float64frombits(v))}
case 3: case 3:

View File

@ -185,10 +185,7 @@ func (this *Timestamp) Compare(that interface{}) int {
} }
func (this *Timestamp) Equal(that interface{}) bool { func (this *Timestamp) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Timestamp) that1, ok := that.(*Timestamp)
@ -201,10 +198,7 @@ func (this *Timestamp) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }

View File

@ -29,7 +29,7 @@ import bytes "bytes"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import encoding_binary "encoding/binary" import binary "encoding/binary"
import io "io" import io "io"
@ -531,10 +531,7 @@ func (this *BytesValue) Compare(that interface{}) int {
} }
func (this *DoubleValue) Equal(that interface{}) bool { func (this *DoubleValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*DoubleValue) that1, ok := that.(*DoubleValue)
@ -547,10 +544,7 @@ func (this *DoubleValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -561,10 +555,7 @@ func (this *DoubleValue) Equal(that interface{}) bool {
} }
func (this *FloatValue) Equal(that interface{}) bool { func (this *FloatValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*FloatValue) that1, ok := that.(*FloatValue)
@ -577,10 +568,7 @@ func (this *FloatValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -591,10 +579,7 @@ func (this *FloatValue) Equal(that interface{}) bool {
} }
func (this *Int64Value) Equal(that interface{}) bool { func (this *Int64Value) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Int64Value) that1, ok := that.(*Int64Value)
@ -607,10 +592,7 @@ func (this *Int64Value) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -621,10 +603,7 @@ func (this *Int64Value) Equal(that interface{}) bool {
} }
func (this *UInt64Value) Equal(that interface{}) bool { func (this *UInt64Value) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*UInt64Value) that1, ok := that.(*UInt64Value)
@ -637,10 +616,7 @@ func (this *UInt64Value) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -651,10 +627,7 @@ func (this *UInt64Value) Equal(that interface{}) bool {
} }
func (this *Int32Value) Equal(that interface{}) bool { func (this *Int32Value) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*Int32Value) that1, ok := that.(*Int32Value)
@ -667,10 +640,7 @@ func (this *Int32Value) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -681,10 +651,7 @@ func (this *Int32Value) Equal(that interface{}) bool {
} }
func (this *UInt32Value) Equal(that interface{}) bool { func (this *UInt32Value) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*UInt32Value) that1, ok := that.(*UInt32Value)
@ -697,10 +664,7 @@ func (this *UInt32Value) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -711,10 +675,7 @@ func (this *UInt32Value) Equal(that interface{}) bool {
} }
func (this *BoolValue) Equal(that interface{}) bool { func (this *BoolValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*BoolValue) that1, ok := that.(*BoolValue)
@ -727,10 +688,7 @@ func (this *BoolValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -741,10 +699,7 @@ func (this *BoolValue) Equal(that interface{}) bool {
} }
func (this *StringValue) Equal(that interface{}) bool { func (this *StringValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*StringValue) that1, ok := that.(*StringValue)
@ -757,10 +712,7 @@ func (this *StringValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -771,10 +723,7 @@ func (this *StringValue) Equal(that interface{}) bool {
} }
func (this *BytesValue) Equal(that interface{}) bool { func (this *BytesValue) Equal(that interface{}) bool {
if that == nil { if that == nil {
if this == nil { return this == nil
return true
}
return false
} }
that1, ok := that.(*BytesValue) that1, ok := that.(*BytesValue)
@ -787,10 +736,7 @@ func (this *BytesValue) Equal(that interface{}) bool {
} }
} }
if that1 == nil { if that1 == nil {
if this == nil { return this == nil
return true
}
return false
} else if this == nil { } else if this == nil {
return false return false
} }
@ -915,7 +861,7 @@ func (m *DoubleValue) MarshalTo(dAtA []byte) (int, error) {
if m.Value != 0 { if m.Value != 0 {
dAtA[i] = 0x9 dAtA[i] = 0x9
i++ i++
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value))))
i += 8 i += 8
} }
return i, nil return i, nil
@ -939,7 +885,7 @@ func (m *FloatValue) MarshalTo(dAtA []byte) (int, error) {
if m.Value != 0 { if m.Value != 0 {
dAtA[i] = 0xd dAtA[i] = 0xd
i++ i++
encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(math.Float32bits(float32(m.Value)))) binary.LittleEndian.PutUint32(dAtA[i:], uint32(math.Float32bits(float32(m.Value))))
i += 4 i += 4
} }
return i, nil return i, nil
@ -1513,7 +1459,7 @@ func (m *DoubleValue) Unmarshal(dAtA []byte) error {
if (iNdEx + 8) > l { if (iNdEx + 8) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:]))
iNdEx += 8 iNdEx += 8
m.Value = float64(math.Float64frombits(v)) m.Value = float64(math.Float64frombits(v))
default: default:
@ -1574,7 +1520,7 @@ func (m *FloatValue) Unmarshal(dAtA []byte) error {
if (iNdEx + 4) > l { if (iNdEx + 4) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
v = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) v = uint32(binary.LittleEndian.Uint32(dAtA[iNdEx:]))
iNdEx += 4 iNdEx += 4
m.Value = float32(math.Float32frombits(v)) m.Value = float32(math.Float32frombits(v))
default: default:

View File

@ -1,6 +1,6 @@
# gRPC-Go # gRPC-Go
[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) [![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) [![GoReportCard](https://goreportcard.com/badge/grpc/grpc-go)](https://goreportcard.com/report/github.com/grpc/grpc-go)
The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide. The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide.
@ -16,7 +16,8 @@ $ go get -u google.golang.org/grpc
Prerequisites Prerequisites
------------- -------------
This requires Go 1.7 or later. This requires Go 1.6 or later. Go 1.7 will be required as of the next gRPC-Go
release (1.8).
Constraints Constraints
----------- -----------

View File

@ -25,14 +25,12 @@ import (
// DefaultBackoffConfig uses values specified for backoff in // DefaultBackoffConfig uses values specified for backoff in
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
var ( var DefaultBackoffConfig = BackoffConfig{
DefaultBackoffConfig = BackoffConfig{ MaxDelay: 120 * time.Second,
MaxDelay: 120 * time.Second, baseDelay: 1.0 * time.Second,
baseDelay: 1.0 * time.Second, factor: 1.6,
factor: 1.6, jitter: 0.2,
jitter: 0.2, }
}
)
// backoffStrategy defines the methodology for backing off after a grpc // backoffStrategy defines the methodology for backing off after a grpc
// connection failure. // connection failure.

View File

@ -28,6 +28,7 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/naming" "google.golang.org/grpc/naming"
"google.golang.org/grpc/status"
) )
// Address represents a server the client connects to. // Address represents a server the client connects to.
@ -310,7 +311,7 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
if !opts.BlockingWait { if !opts.BlockingWait {
if len(rr.addrs) == 0 { if len(rr.addrs) == 0 {
rr.mu.Unlock() rr.mu.Unlock()
err = Errorf(codes.Unavailable, "there is no address available") err = status.Errorf(codes.Unavailable, "there is no address available")
return return
} }
// Returns the next addr on rr.addrs for failfast RPCs. // Returns the next addr on rr.addrs for failfast RPCs.

View File

@ -23,6 +23,7 @@ package balancer
import ( import (
"errors" "errors"
"net" "net"
"strings"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
@ -33,24 +34,23 @@ import (
var ( var (
// m is a map from name to balancer builder. // m is a map from name to balancer builder.
m = make(map[string]Builder) m = make(map[string]Builder)
// defaultBuilder is the default balancer to use.
defaultBuilder Builder // TODO(bar) install pickfirst as default.
) )
// Register registers the balancer builder to the balancer map. // Register registers the balancer builder to the balancer map.
// b.Name will be used as the name registered with this builder. // b.Name (lowercased) will be used as the name registered with
// this builder.
func Register(b Builder) { func Register(b Builder) {
m[b.Name()] = b m[strings.ToLower(b.Name())] = b
} }
// Get returns the resolver builder registered with the given name. // Get returns the resolver builder registered with the given name.
// If no builder is register with the name, the default pickfirst will // Note that the compare is done in a case-insenstive fashion.
// be used. // If no builder is register with the name, nil will be returned.
func Get(name string) Builder { func Get(name string) Builder {
if b, ok := m[name]; ok { if b, ok := m[strings.ToLower(name)]; ok {
return b return b
} }
return defaultBuilder return nil
} }
// SubConn represents a gRPC sub connection. // SubConn represents a gRPC sub connection.
@ -66,6 +66,11 @@ func Get(name string) Builder {
// When the connection encounters an error, it will reconnect immediately. // When the connection encounters an error, it will reconnect immediately.
// When the connection becomes IDLE, it will not reconnect unless Connect is // When the connection becomes IDLE, it will not reconnect unless Connect is
// called. // called.
//
// This interface is to be implemented by gRPC. Users should not need a
// brand new implementation of this interface. For the situations like
// testing, the new implementation should embed this interface. This allows
// gRPC to add new methods to this interface.
type SubConn interface { type SubConn interface {
// UpdateAddresses updates the addresses used in this SubConn. // UpdateAddresses updates the addresses used in this SubConn.
// gRPC checks if currently-connected address is still in the new list. // gRPC checks if currently-connected address is still in the new list.
@ -83,6 +88,11 @@ type SubConn interface {
type NewSubConnOptions struct{} type NewSubConnOptions struct{}
// ClientConn represents a gRPC ClientConn. // ClientConn represents a gRPC ClientConn.
//
// This interface is to be implemented by gRPC. Users should not need a
// brand new implementation of this interface. For the situations like
// testing, the new implementation should embed this interface. This allows
// gRPC to add new methods to this interface.
type ClientConn interface { type ClientConn interface {
// NewSubConn is called by balancer to create a new SubConn. // NewSubConn is called by balancer to create a new SubConn.
// It doesn't block and wait for the connections to be established. // It doesn't block and wait for the connections to be established.
@ -99,6 +109,9 @@ type ClientConn interface {
// on the new picker to pick new SubConn. // on the new picker to pick new SubConn.
UpdateBalancerState(s connectivity.State, p Picker) UpdateBalancerState(s connectivity.State, p Picker)
// ResolveNow is called by balancer to notify gRPC to do a name resolving.
ResolveNow(resolver.ResolveNowOption)
// Target returns the dial target for this ClientConn. // Target returns the dial target for this ClientConn.
Target() string Target() string
} }
@ -131,6 +144,10 @@ type PickOptions struct{}
type DoneInfo struct { type DoneInfo struct {
// Err is the rpc error the RPC finished with. It could be nil. // Err is the rpc error the RPC finished with. It could be nil.
Err error Err error
// BytesSent indicates if any bytes have been sent to the server.
BytesSent bool
// BytesReceived indicates if any byte has been received from the server.
BytesReceived bool
} }
var ( var (
@ -161,7 +178,7 @@ type Picker interface {
// If a SubConn is returned: // If a SubConn is returned:
// - If it is READY, gRPC will send the RPC on it; // - If it is READY, gRPC will send the RPC on it;
// - If it is not ready, or becomes not ready after it's returned, gRPC will block // - If it is not ready, or becomes not ready after it's returned, gRPC will block
// this call until a new picker is updated and will call pick on the new picker. // until UpdateBalancerState() is called and will call pick on the new picker.
// //
// If the returned error is not nil: // If the returned error is not nil:
// - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState() // - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState()

209
vendor/google.golang.org/grpc/balancer/base/balancer.go generated vendored Normal file
View File

@ -0,0 +1,209 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package base
import (
"golang.org/x/net/context"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/resolver"
)
type baseBuilder struct {
name string
pickerBuilder PickerBuilder
}
func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
return &baseBalancer{
cc: cc,
pickerBuilder: bb.pickerBuilder,
subConns: make(map[resolver.Address]balancer.SubConn),
scStates: make(map[balancer.SubConn]connectivity.State),
csEvltr: &connectivityStateEvaluator{},
// Initialize picker to a picker that always return
// ErrNoSubConnAvailable, because when state of a SubConn changes, we
// may call UpdateBalancerState with this picker.
picker: NewErrPicker(balancer.ErrNoSubConnAvailable),
}
}
func (bb *baseBuilder) Name() string {
return bb.name
}
type baseBalancer struct {
cc balancer.ClientConn
pickerBuilder PickerBuilder
csEvltr *connectivityStateEvaluator
state connectivity.State
subConns map[resolver.Address]balancer.SubConn
scStates map[balancer.SubConn]connectivity.State
picker balancer.Picker
}
func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
if err != nil {
grpclog.Infof("base.baseBalancer: HandleResolvedAddrs called with error %v", err)
return
}
grpclog.Infoln("base.baseBalancer: got new resolved addresses: ", addrs)
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
addrsSet := make(map[resolver.Address]struct{})
for _, a := range addrs {
addrsSet[a] = struct{}{}
if _, ok := b.subConns[a]; !ok {
// a is a new address (not existing in b.subConns).
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
if err != nil {
grpclog.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
continue
}
b.subConns[a] = sc
b.scStates[sc] = connectivity.Idle
sc.Connect()
}
}
for a, sc := range b.subConns {
// a was removed by resolver.
if _, ok := addrsSet[a]; !ok {
b.cc.RemoveSubConn(sc)
delete(b.subConns, a)
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
// The entry will be deleted in HandleSubConnStateChange.
}
}
}
// regeneratePicker takes a snapshot of the balancer, and generates a picker
// from it. The picker is
// - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
// - built by the pickerBuilder with all READY SubConns otherwise.
func (b *baseBalancer) regeneratePicker() {
if b.state == connectivity.TransientFailure {
b.picker = NewErrPicker(balancer.ErrTransientFailure)
return
}
readySCs := make(map[resolver.Address]balancer.SubConn)
// Filter out all ready SCs from full subConn map.
for addr, sc := range b.subConns {
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
readySCs[addr] = sc
}
}
b.picker = b.pickerBuilder.Build(readySCs)
}
func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
oldS, ok := b.scStates[sc]
if !ok {
grpclog.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
return
}
b.scStates[sc] = s
switch s {
case connectivity.Idle:
sc.Connect()
case connectivity.Shutdown:
// When an address was removed by resolver, b called RemoveSubConn but
// kept the sc's state in scStates. Remove state for this sc here.
delete(b.scStates, sc)
}
oldAggrState := b.state
b.state = b.csEvltr.recordTransition(oldS, s)
// Regenerate picker when one of the following happens:
// - this sc became ready from not-ready
// - this sc became not-ready from ready
// - the aggregated state of balancer became TransientFailure from non-TransientFailure
// - the aggregated state of balancer became non-TransientFailure from TransientFailure
if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
(b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
b.regeneratePicker()
}
b.cc.UpdateBalancerState(b.state, b.picker)
return
}
// Close is a nop because base balancer doesn't have internal state to clean up,
// and it doesn't need to call RemoveSubConn for the SubConns.
func (b *baseBalancer) Close() {
}
// NewErrPicker returns a picker that always returns err on Pick().
func NewErrPicker(err error) balancer.Picker {
return &errPicker{err: err}
}
type errPicker struct {
err error // Pick() always returns this err.
}
func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
return nil, nil, p.err
}
// connectivityStateEvaluator gets updated by addrConns when their
// states transition, based on which it evaluates the state of
// ClientConn.
type connectivityStateEvaluator struct {
numReady uint64 // Number of addrConns in ready state.
numConnecting uint64 // Number of addrConns in connecting state.
numTransientFailure uint64 // Number of addrConns in transientFailure.
}
// recordTransition records state change happening in every subConn and based on
// that it evaluates what aggregated state should be.
// It can only transition between Ready, Connecting and TransientFailure. Other states,
// Idle and Shutdown are transitioned into by ClientConn; in the beginning of the connection
// before any subConn is created ClientConn is in idle state. In the end when ClientConn
// closes it is in Shutdown state.
//
// recordTransition should only be called synchronously from the same goroutine.
func (cse *connectivityStateEvaluator) recordTransition(oldState, newState connectivity.State) connectivity.State {
// Update counters.
for idx, state := range []connectivity.State{oldState, newState} {
updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
switch state {
case connectivity.Ready:
cse.numReady += updateVal
case connectivity.Connecting:
cse.numConnecting += updateVal
case connectivity.TransientFailure:
cse.numTransientFailure += updateVal
}
}
// Evaluate.
if cse.numReady > 0 {
return connectivity.Ready
}
if cse.numConnecting > 0 {
return connectivity.Connecting
}
return connectivity.TransientFailure
}

52
vendor/google.golang.org/grpc/balancer/base/base.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package base defines a balancer base that can be used to build balancers with
// different picking algorithms.
//
// The base balancer creates a new SubConn for each resolved address. The
// provided picker will only be notified about READY SubConns.
//
// This package is the base of round_robin balancer, its purpose is to be used
// to build round_robin like balancers with complex picking algorithms.
// Balancers with more complicated logic should try to implement a balancer
// builder from scratch.
//
// All APIs in this package are experimental.
package base
import (
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/resolver"
)
// PickerBuilder creates balancer.Picker.
type PickerBuilder interface {
// Build takes a slice of ready SubConns, and returns a picker that will be
// used by gRPC to pick a SubConn.
Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker
}
// NewBalancerBuilder returns a balancer builder. The balancers
// built by this builder will use the picker builder to build pickers.
func NewBalancerBuilder(name string, pb PickerBuilder) balancer.Builder {
return &baseBuilder{
name: name,
pickerBuilder: pb,
}
}

View File

@ -0,0 +1,79 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
// installed as one of the default balancers in gRPC, users don't need to
// explicitly install this balancer.
package roundrobin
import (
"sync"
"golang.org/x/net/context"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/base"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/resolver"
)
// Name is the name of round_robin balancer.
const Name = "round_robin"
// newBuilder creates a new roundrobin balancer builder.
func newBuilder() balancer.Builder {
return base.NewBalancerBuilder(Name, &rrPickerBuilder{})
}
func init() {
balancer.Register(newBuilder())
}
type rrPickerBuilder struct{}
func (*rrPickerBuilder) Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker {
grpclog.Infof("roundrobinPicker: newPicker called with readySCs: %v", readySCs)
var scs []balancer.SubConn
for _, sc := range readySCs {
scs = append(scs, sc)
}
return &rrPicker{
subConns: scs,
}
}
type rrPicker struct {
// subConns is the snapshot of the roundrobin balancer when this picker was
// created. The slice is immutable. Each Get() will do a round robin
// selection from it and return the selected SubConn.
subConns []balancer.SubConn
mu sync.Mutex
next int
}
func (p *rrPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
if len(p.subConns) <= 0 {
return nil, nil, balancer.ErrNoSubConnAvailable
}
p.mu.Lock()
sc := p.subConns[p.next]
p.next = (p.next + 1) % len(p.subConns)
p.mu.Unlock()
return sc, nil, nil
}

View File

@ -19,6 +19,7 @@
package grpc package grpc
import ( import (
"fmt"
"sync" "sync"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
@ -73,7 +74,7 @@ func (b *scStateUpdateBuffer) load() {
} }
} }
// get returns the channel that receives a recvMsg in the buffer. // get returns the channel that the scStateUpdate will be sent to.
// //
// Upon receiving, the caller should call load to send another // Upon receiving, the caller should call load to send another
// scStateChangeTuple onto the channel if there is any. // scStateChangeTuple onto the channel if there is any.
@ -96,6 +97,9 @@ type ccBalancerWrapper struct {
stateChangeQueue *scStateUpdateBuffer stateChangeQueue *scStateUpdateBuffer
resolverUpdateCh chan *resolverUpdate resolverUpdateCh chan *resolverUpdate
done chan struct{} done chan struct{}
mu sync.Mutex
subConns map[*acBalancerWrapper]struct{}
} }
func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper { func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
@ -104,6 +108,7 @@ func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.Bui
stateChangeQueue: newSCStateUpdateBuffer(), stateChangeQueue: newSCStateUpdateBuffer(),
resolverUpdateCh: make(chan *resolverUpdate, 1), resolverUpdateCh: make(chan *resolverUpdate, 1),
done: make(chan struct{}), done: make(chan struct{}),
subConns: make(map[*acBalancerWrapper]struct{}),
} }
go ccb.watcher() go ccb.watcher()
ccb.balancer = b.Build(ccb, bopts) ccb.balancer = b.Build(ccb, bopts)
@ -117,8 +122,20 @@ func (ccb *ccBalancerWrapper) watcher() {
select { select {
case t := <-ccb.stateChangeQueue.get(): case t := <-ccb.stateChangeQueue.get():
ccb.stateChangeQueue.load() ccb.stateChangeQueue.load()
select {
case <-ccb.done:
ccb.balancer.Close()
return
default:
}
ccb.balancer.HandleSubConnStateChange(t.sc, t.state) ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
case t := <-ccb.resolverUpdateCh: case t := <-ccb.resolverUpdateCh:
select {
case <-ccb.done:
ccb.balancer.Close()
return
default:
}
ccb.balancer.HandleResolvedAddrs(t.addrs, t.err) ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
case <-ccb.done: case <-ccb.done:
} }
@ -126,6 +143,13 @@ func (ccb *ccBalancerWrapper) watcher() {
select { select {
case <-ccb.done: case <-ccb.done:
ccb.balancer.Close() ccb.balancer.Close()
ccb.mu.Lock()
scs := ccb.subConns
ccb.subConns = nil
ccb.mu.Unlock()
for acbw := range scs {
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
}
return return
default: default:
} }
@ -165,33 +189,54 @@ func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err
} }
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) { func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
grpclog.Infof("ccBalancerWrapper: new subconn: %v", addrs) if len(addrs) <= 0 {
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
}
ccb.mu.Lock()
defer ccb.mu.Unlock()
if ccb.subConns == nil {
return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
}
ac, err := ccb.cc.newAddrConn(addrs) ac, err := ccb.cc.newAddrConn(addrs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
acbw := &acBalancerWrapper{ac: ac} acbw := &acBalancerWrapper{ac: ac}
ac.mu.Lock() acbw.ac.mu.Lock()
ac.acbw = acbw ac.acbw = acbw
ac.mu.Unlock() acbw.ac.mu.Unlock()
ccb.subConns[acbw] = struct{}{}
return acbw, nil return acbw, nil
} }
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) { func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
grpclog.Infof("ccBalancerWrapper: removing subconn")
acbw, ok := sc.(*acBalancerWrapper) acbw, ok := sc.(*acBalancerWrapper)
if !ok { if !ok {
return return
} }
ccb.mu.Lock()
defer ccb.mu.Unlock()
if ccb.subConns == nil {
return
}
delete(ccb.subConns, acbw)
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain) ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
} }
func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) { func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
grpclog.Infof("ccBalancerWrapper: updating state and picker called by balancer: %v, %p", s, p) ccb.mu.Lock()
defer ccb.mu.Unlock()
if ccb.subConns == nil {
return
}
ccb.cc.csMgr.updateState(s) ccb.cc.csMgr.updateState(s)
ccb.cc.blockingpicker.updatePicker(p) ccb.cc.blockingpicker.updatePicker(p)
} }
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {
ccb.cc.resolveNow(o)
}
func (ccb *ccBalancerWrapper) Target() string { func (ccb *ccBalancerWrapper) Target() string {
return ccb.cc.target return ccb.cc.target
} }
@ -204,9 +249,12 @@ type acBalancerWrapper struct {
} }
func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
grpclog.Infof("acBalancerWrapper: UpdateAddresses called with %v", addrs)
acbw.mu.Lock() acbw.mu.Lock()
defer acbw.mu.Unlock() defer acbw.mu.Unlock()
if len(addrs) <= 0 {
acbw.ac.tearDown(errConnDrain)
return
}
if !acbw.ac.tryUpdateAddrs(addrs) { if !acbw.ac.tryUpdateAddrs(addrs) {
cc := acbw.ac.cc cc := acbw.ac.cc
acbw.ac.mu.Lock() acbw.ac.mu.Lock()
@ -234,7 +282,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
ac.acbw = acbw ac.acbw = acbw
ac.mu.Unlock() ac.mu.Unlock()
if acState != connectivity.Idle { if acState != connectivity.Idle {
ac.connect(false) ac.connect()
} }
} }
} }
@ -242,7 +290,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
func (acbw *acBalancerWrapper) Connect() { func (acbw *acBalancerWrapper) Connect() {
acbw.mu.Lock() acbw.mu.Lock()
defer acbw.mu.Unlock() defer acbw.mu.Unlock()
acbw.ac.connect(false) acbw.ac.connect()
} }
func (acbw *acBalancerWrapper) getAddrConn() *addrConn { func (acbw *acBalancerWrapper) getAddrConn() *addrConn {

View File

@ -19,6 +19,7 @@
package grpc package grpc
import ( import (
"strings"
"sync" "sync"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -27,6 +28,7 @@ import (
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
"google.golang.org/grpc/status"
) )
type balancerWrapperBuilder struct { type balancerWrapperBuilder struct {
@ -34,20 +36,27 @@ type balancerWrapperBuilder struct {
} }
func (bwb *balancerWrapperBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer { func (bwb *balancerWrapperBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
bwb.b.Start(cc.Target(), BalancerConfig{ targetAddr := cc.Target()
targetSplitted := strings.Split(targetAddr, ":///")
if len(targetSplitted) >= 2 {
targetAddr = targetSplitted[1]
}
bwb.b.Start(targetAddr, BalancerConfig{
DialCreds: opts.DialCreds, DialCreds: opts.DialCreds,
Dialer: opts.Dialer, Dialer: opts.Dialer,
}) })
_, pickfirst := bwb.b.(*pickFirst) _, pickfirst := bwb.b.(*pickFirst)
bw := &balancerWrapper{ bw := &balancerWrapper{
balancer: bwb.b, balancer: bwb.b,
pickfirst: pickfirst, pickfirst: pickfirst,
cc: cc, cc: cc,
startCh: make(chan struct{}), targetAddr: targetAddr,
conns: make(map[resolver.Address]balancer.SubConn), startCh: make(chan struct{}),
connSt: make(map[balancer.SubConn]*scState), conns: make(map[resolver.Address]balancer.SubConn),
csEvltr: &connectivityStateEvaluator{}, connSt: make(map[balancer.SubConn]*scState),
state: connectivity.Idle, csEvltr: &connectivityStateEvaluator{},
state: connectivity.Idle,
} }
cc.UpdateBalancerState(connectivity.Idle, bw) cc.UpdateBalancerState(connectivity.Idle, bw)
go bw.lbWatcher() go bw.lbWatcher()
@ -68,7 +77,8 @@ type balancerWrapper struct {
balancer Balancer // The v1 balancer. balancer Balancer // The v1 balancer.
pickfirst bool pickfirst bool
cc balancer.ClientConn cc balancer.ClientConn
targetAddr string // Target without the scheme.
// To aggregate the connectivity state. // To aggregate the connectivity state.
csEvltr *connectivityStateEvaluator csEvltr *connectivityStateEvaluator
@ -88,12 +98,11 @@ type balancerWrapper struct {
// connections accordingly. // connections accordingly.
func (bw *balancerWrapper) lbWatcher() { func (bw *balancerWrapper) lbWatcher() {
<-bw.startCh <-bw.startCh
grpclog.Infof("balancerWrapper: is pickfirst: %v\n", bw.pickfirst)
notifyCh := bw.balancer.Notify() notifyCh := bw.balancer.Notify()
if notifyCh == nil { if notifyCh == nil {
// There's no resolver in the balancer. Connect directly. // There's no resolver in the balancer. Connect directly.
a := resolver.Address{ a := resolver.Address{
Addr: bw.cc.Target(), Addr: bw.targetAddr,
Type: resolver.Backend, Type: resolver.Backend,
} }
sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{}) sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
@ -103,7 +112,7 @@ func (bw *balancerWrapper) lbWatcher() {
bw.mu.Lock() bw.mu.Lock()
bw.conns[a] = sc bw.conns[a] = sc
bw.connSt[sc] = &scState{ bw.connSt[sc] = &scState{
addr: Address{Addr: bw.cc.Target()}, addr: Address{Addr: bw.targetAddr},
s: connectivity.Idle, s: connectivity.Idle,
} }
bw.mu.Unlock() bw.mu.Unlock()
@ -165,10 +174,10 @@ func (bw *balancerWrapper) lbWatcher() {
sc.Connect() sc.Connect()
} }
} else { } else {
oldSC.UpdateAddresses(newAddrs)
bw.mu.Lock() bw.mu.Lock()
bw.connSt[oldSC].addr = addrs[0] bw.connSt[oldSC].addr = addrs[0]
bw.mu.Unlock() bw.mu.Unlock()
oldSC.UpdateAddresses(newAddrs)
} }
} else { } else {
var ( var (
@ -221,7 +230,6 @@ func (bw *balancerWrapper) lbWatcher() {
} }
func (bw *balancerWrapper) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) { func (bw *balancerWrapper) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
grpclog.Infof("balancerWrapper: handle subconn state change: %p, %v", sc, s)
bw.mu.Lock() bw.mu.Lock()
defer bw.mu.Unlock() defer bw.mu.Unlock()
scSt, ok := bw.connSt[sc] scSt, ok := bw.connSt[sc]
@ -310,12 +318,12 @@ func (bw *balancerWrapper) Pick(ctx context.Context, opts balancer.PickOptions)
Metadata: a.Metadata, Metadata: a.Metadata,
}] }]
if !ok && failfast { if !ok && failfast {
return nil, nil, Errorf(codes.Unavailable, "there is no connection available") return nil, nil, status.Errorf(codes.Unavailable, "there is no connection available")
} }
if s, ok := bw.connSt[sc]; failfast && (!ok || s.s != connectivity.Ready) { if s, ok := bw.connSt[sc]; failfast && (!ok || s.s != connectivity.Ready) {
// If the returned sc is not ready and RPC is failfast, // If the returned sc is not ready and RPC is failfast,
// return error, and this RPC will fail. // return error, and this RPC will fail.
return nil, nil, Errorf(codes.Unavailable, "there is no connection available") return nil, nil, status.Errorf(codes.Unavailable, "there is no connection available")
} }
} }

295
vendor/google.golang.org/grpc/call.go generated vendored
View File

@ -19,289 +19,56 @@
package grpc package grpc
import ( import (
"bytes"
"io"
"time"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/net/trace"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/peer"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
"google.golang.org/grpc/transport"
) )
// recvResponse receives and parses an RPC response. // Invoke sends the RPC request on the wire and returns after response is
// On error, it returns the error and indicates whether the call should be retried. // received. This is typically called by generated code.
// //
// TODO(zhaoq): Check whether the received message sequence is valid. // All errors returned by Invoke are compatible with the status package.
// TODO ctx is used for stats collection and processing. It is the context passed from the application. func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) (err error) {
// Try to acquire header metadata from the server if there is any.
defer func() {
if err != nil {
if _, ok := err.(transport.ConnectionError); !ok {
t.CloseStream(stream, err)
}
}
}()
c.headerMD, err = stream.Header()
if err != nil {
return
}
p := &parser{r: stream}
var inPayload *stats.InPayload
if dopts.copts.StatsHandler != nil {
inPayload = &stats.InPayload{
Client: true,
}
}
for {
if c.maxReceiveMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)")
}
if err = recv(p, dopts.codec, stream, dopts.dc, reply, *c.maxReceiveMessageSize, inPayload); err != nil {
if err == io.EOF {
break
}
return
}
}
if inPayload != nil && err == io.EOF && stream.Status().Code() == codes.OK {
// TODO in the current implementation, inTrailer may be handled before inPayload in some cases.
// Fix the order if necessary.
dopts.copts.StatsHandler.HandleRPC(ctx, inPayload)
}
c.trailerMD = stream.Trailer()
return nil
}
// sendRequest writes out various information of an RPC such as Context and Message.
func sendRequest(ctx context.Context, dopts dialOptions, compressor Compressor, c *callInfo, callHdr *transport.CallHdr, stream *transport.Stream, t transport.ClientTransport, args interface{}, opts *transport.Options) (err error) {
defer func() {
if err != nil {
// If err is connection error, t will be closed, no need to close stream here.
if _, ok := err.(transport.ConnectionError); !ok {
t.CloseStream(stream, err)
}
}
}()
var (
cbuf *bytes.Buffer
outPayload *stats.OutPayload
)
if compressor != nil {
cbuf = new(bytes.Buffer)
}
if dopts.copts.StatsHandler != nil {
outPayload = &stats.OutPayload{
Client: true,
}
}
hdr, data, err := encode(dopts.codec, args, compressor, cbuf, outPayload)
if err != nil {
return err
}
if c.maxSendMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)")
}
if len(data) > *c.maxSendMessageSize {
return Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(data), *c.maxSendMessageSize)
}
err = t.Write(stream, hdr, data, opts)
if err == nil && outPayload != nil {
outPayload.SentTime = time.Now()
dopts.copts.StatsHandler.HandleRPC(ctx, outPayload)
}
// t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method
// does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following
// recvResponse to get the final status.
if err != nil && err != io.EOF {
return err
}
// Sent successfully.
return nil
}
// Invoke sends the RPC request on the wire and returns after response is received.
// Invoke is called by generated code. Also users can call Invoke directly when it
// is really needed in their use cases.
func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
if cc.dopts.unaryInt != nil { if cc.dopts.unaryInt != nil {
return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...) return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
} }
return invoke(ctx, method, args, reply, cc, opts...) return invoke(ctx, method, args, reply, cc, opts...)
} }
func invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (e error) { // Invoke sends the RPC request on the wire and returns after response is
c := defaultCallInfo() // received. This is typically called by generated code.
mc := cc.GetMethodConfig(method) //
if mc.WaitForReady != nil { // DEPRECATED: Use ClientConn.Invoke instead.
c.failFast = !*mc.WaitForReady func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
} return cc.Invoke(ctx, method, args, reply, opts...)
}
if mc.Timeout != nil && *mc.Timeout >= 0 { var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)
defer cancel()
}
opts = append(cc.dopts.callOptions, opts...) func invoke(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
for _, o := range opts { // TODO: implement retries in clientStream and make this simply
if err := o.before(c); err != nil { // newClientStream, SendMsg, RecvMsg.
return toRPCErr(err) firstAttempt := true
}
}
defer func() {
for _, o := range opts {
o.after(c)
}
}()
c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize)
c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
if EnableTracing {
c.traceInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
defer c.traceInfo.tr.Finish()
c.traceInfo.firstLine.client = true
if deadline, ok := ctx.Deadline(); ok {
c.traceInfo.firstLine.deadline = deadline.Sub(time.Now())
}
c.traceInfo.tr.LazyLog(&c.traceInfo.firstLine, false)
// TODO(dsymonds): Arrange for c.traceInfo.firstLine.remoteAddr to be set.
defer func() {
if e != nil {
c.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{e}}, true)
c.traceInfo.tr.SetError()
}
}()
}
ctx = newContextWithRPCInfo(ctx, c.failFast)
sh := cc.dopts.copts.StatsHandler
if sh != nil {
ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast})
begin := &stats.Begin{
Client: true,
BeginTime: time.Now(),
FailFast: c.failFast,
}
sh.HandleRPC(ctx, begin)
defer func() {
end := &stats.End{
Client: true,
EndTime: time.Now(),
Error: e,
}
sh.HandleRPC(ctx, end)
}()
}
topts := &transport.Options{
Last: true,
Delay: false,
}
for { for {
var ( csInt, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
err error
t transport.ClientTransport
stream *transport.Stream
// Record the done handler from Balancer.Get(...). It is called once the
// RPC has completed or failed.
done func(balancer.DoneInfo)
)
// TODO(zhaoq): Need a formal spec of fail-fast.
callHdr := &transport.CallHdr{
Host: cc.authority,
Method: method,
}
if cc.dopts.cp != nil {
callHdr.SendCompress = cc.dopts.cp.Type()
}
if c.creds != nil {
callHdr.Creds = c.creds
}
t, done, err = cc.getTransport(ctx, c.failFast)
if err != nil { if err != nil {
// TODO(zhaoq): Probably revisit the error handling. return err
if _, ok := status.FromError(err); ok { }
return err cs := csInt.(*clientStream)
} if err := cs.SendMsg(req); err != nil {
if err == errConnClosing || err == errConnUnavailable { if !cs.c.failFast && cs.s.Unprocessed() && firstAttempt {
if c.failFast { // TODO: Add a field to header for grpc-transparent-retry-attempts
return Errorf(codes.Unavailable, "%v", err) firstAttempt = false
}
continue continue
} }
// All the other errors are treated as Internal errors. return err
return Errorf(codes.Internal, "%v", err)
} }
if c.traceInfo.tr != nil { if err := cs.RecvMsg(reply); err != nil {
c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true) if !cs.c.failFast && cs.s.Unprocessed() && firstAttempt {
} // TODO: Add a field to header for grpc-transparent-retry-attempts
stream, err = t.NewStream(ctx, callHdr) firstAttempt = false
if err != nil {
if done != nil {
if _, ok := err.(transport.ConnectionError); ok {
// If error is connection error, transport was sending data on wire,
// and we are not sure if anything has been sent on wire.
// If error is not connection error, we are sure nothing has been sent.
updateRPCInfoInContext(ctx, rpcInfo{bytesSent: true, bytesReceived: false})
}
done(balancer.DoneInfo{Err: err})
}
if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
continue continue
} }
return toRPCErr(err) return err
} }
if peer, ok := peer.FromContext(stream.Context()); ok { return nil
c.peer = peer
}
err = sendRequest(ctx, cc.dopts, cc.dopts.cp, c, callHdr, stream, t, args, topts)
if err != nil {
if done != nil {
updateRPCInfoInContext(ctx, rpcInfo{
bytesSent: stream.BytesSent(),
bytesReceived: stream.BytesReceived(),
})
done(balancer.DoneInfo{Err: err})
}
// Retry a non-failfast RPC when
// i) there is a connection error; or
// ii) the server started to drain before this RPC was initiated.
if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
continue
}
return toRPCErr(err)
}
err = recvResponse(ctx, cc.dopts, t, c, stream, reply)
if err != nil {
if done != nil {
updateRPCInfoInContext(ctx, rpcInfo{
bytesSent: stream.BytesSent(),
bytesReceived: stream.BytesReceived(),
})
done(balancer.DoneInfo{Err: err})
}
if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
continue
}
return toRPCErr(err)
}
if c.traceInfo.tr != nil {
c.traceInfo.tr.LazyLog(&payload{sent: false, msg: reply}, true)
}
t.CloseStream(stream, nil)
if done != nil {
updateRPCInfoInContext(ctx, rpcInfo{
bytesSent: stream.BytesSent(),
bytesReceived: stream.BytesReceived(),
})
done(balancer.DoneInfo{Err: err})
}
return stream.Status().Err()
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -19,86 +19,32 @@
package grpc package grpc
import ( import (
"math" "google.golang.org/grpc/encoding"
"sync" _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
"github.com/golang/protobuf/proto"
) )
// baseCodec contains the functionality of both Codec and encoding.Codec, but
// omits the name/string, which vary between the two and are not needed for
// anything besides the registry in the encoding package.
type baseCodec interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
}
var _ baseCodec = Codec(nil)
var _ baseCodec = encoding.Codec(nil)
// Codec defines the interface gRPC uses to encode and decode messages. // Codec defines the interface gRPC uses to encode and decode messages.
// Note that implementations of this interface must be thread safe; // Note that implementations of this interface must be thread safe;
// a Codec's methods can be called from concurrent goroutines. // a Codec's methods can be called from concurrent goroutines.
//
// Deprecated: use encoding.Codec instead.
type Codec interface { type Codec interface {
// Marshal returns the wire format of v. // Marshal returns the wire format of v.
Marshal(v interface{}) ([]byte, error) Marshal(v interface{}) ([]byte, error)
// Unmarshal parses the wire format into v. // Unmarshal parses the wire format into v.
Unmarshal(data []byte, v interface{}) error Unmarshal(data []byte, v interface{}) error
// String returns the name of the Codec implementation. The returned // String returns the name of the Codec implementation. This is unused by
// string will be used as part of content type in transmission. // gRPC.
String() string String() string
} }
// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC.
type protoCodec struct {
}
type cachedProtoBuffer struct {
lastMarshaledSize uint32
proto.Buffer
}
func capToMaxInt32(val int) uint32 {
if val > math.MaxInt32 {
return uint32(math.MaxInt32)
}
return uint32(val)
}
func (p protoCodec) marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
protoMsg := v.(proto.Message)
newSlice := make([]byte, 0, cb.lastMarshaledSize)
cb.SetBuf(newSlice)
cb.Reset()
if err := cb.Marshal(protoMsg); err != nil {
return nil, err
}
out := cb.Bytes()
cb.lastMarshaledSize = capToMaxInt32(len(out))
return out, nil
}
func (p protoCodec) Marshal(v interface{}) ([]byte, error) {
cb := protoBufferPool.Get().(*cachedProtoBuffer)
out, err := p.marshal(v, cb)
// put back buffer and lose the ref to the slice
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return out, err
}
func (p protoCodec) Unmarshal(data []byte, v interface{}) error {
cb := protoBufferPool.Get().(*cachedProtoBuffer)
cb.SetBuf(data)
v.(proto.Message).Reset()
err := cb.Unmarshal(v.(proto.Message))
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return err
}
func (protoCodec) String() string {
return "proto"
}
var (
protoBufferPool = &sync.Pool{
New: func() interface{} {
return &cachedProtoBuffer{
Buffer: proto.Buffer{},
lastMarshaledSize: 16,
}
},
}
)

View File

@ -1,16 +1,62 @@
// Code generated by "stringer -type=Code"; DO NOT EDIT. /*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package codes package codes
import "fmt" import "strconv"
const _Code_name = "OKCanceledUnknownInvalidArgumentDeadlineExceededNotFoundAlreadyExistsPermissionDeniedResourceExhaustedFailedPreconditionAbortedOutOfRangeUnimplementedInternalUnavailableDataLossUnauthenticated" func (c Code) String() string {
switch c {
var _Code_index = [...]uint8{0, 2, 10, 17, 32, 48, 56, 69, 85, 102, 120, 127, 137, 150, 158, 169, 177, 192} case OK:
return "OK"
func (i Code) String() string { case Canceled:
if i >= Code(len(_Code_index)-1) { return "Canceled"
return fmt.Sprintf("Code(%d)", i) case Unknown:
return "Unknown"
case InvalidArgument:
return "InvalidArgument"
case DeadlineExceeded:
return "DeadlineExceeded"
case NotFound:
return "NotFound"
case AlreadyExists:
return "AlreadyExists"
case PermissionDenied:
return "PermissionDenied"
case ResourceExhausted:
return "ResourceExhausted"
case FailedPrecondition:
return "FailedPrecondition"
case Aborted:
return "Aborted"
case OutOfRange:
return "OutOfRange"
case Unimplemented:
return "Unimplemented"
case Internal:
return "Internal"
case Unavailable:
return "Unavailable"
case DataLoss:
return "DataLoss"
case Unauthenticated:
return "Unauthenticated"
default:
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
} }
return _Code_name[_Code_index[i]:_Code_index[i+1]]
} }

View File

@ -20,11 +20,13 @@
// consistent across various languages. // consistent across various languages.
package codes // import "google.golang.org/grpc/codes" package codes // import "google.golang.org/grpc/codes"
import (
"fmt"
)
// A Code is an unsigned 32-bit error code as defined in the gRPC spec. // A Code is an unsigned 32-bit error code as defined in the gRPC spec.
type Code uint32 type Code uint32
//go:generate stringer -type=Code
const ( const (
// OK is returned on success. // OK is returned on success.
OK Code = 0 OK Code = 0
@ -32,9 +34,9 @@ const (
// Canceled indicates the operation was canceled (typically by the caller). // Canceled indicates the operation was canceled (typically by the caller).
Canceled Code = 1 Canceled Code = 1
// Unknown error. An example of where this error may be returned is // Unknown error. An example of where this error may be returned is
// if a Status value received from another address space belongs to // if a Status value received from another address space belongs to
// an error-space that is not known in this address space. Also // an error-space that is not known in this address space. Also
// errors raised by APIs that do not return enough error information // errors raised by APIs that do not return enough error information
// may be converted to this error. // may be converted to this error.
Unknown Code = 2 Unknown Code = 2
@ -63,15 +65,11 @@ const (
// PermissionDenied indicates the caller does not have permission to // PermissionDenied indicates the caller does not have permission to
// execute the specified operation. It must not be used for rejections // execute the specified operation. It must not be used for rejections
// caused by exhausting some resource (use ResourceExhausted // caused by exhausting some resource (use ResourceExhausted
// instead for those errors). It must not be // instead for those errors). It must not be
// used if the caller cannot be identified (use Unauthenticated // used if the caller cannot be identified (use Unauthenticated
// instead for those errors). // instead for those errors).
PermissionDenied Code = 7 PermissionDenied Code = 7
// Unauthenticated indicates the request does not have valid
// authentication credentials for the operation.
Unauthenticated Code = 16
// ResourceExhausted indicates some resource has been exhausted, perhaps // ResourceExhausted indicates some resource has been exhausted, perhaps
// a per-user quota, or perhaps the entire file system is out of space. // a per-user quota, or perhaps the entire file system is out of space.
ResourceExhausted Code = 8 ResourceExhausted Code = 8
@ -87,7 +85,7 @@ const (
// (b) Use Aborted if the client should retry at a higher-level // (b) Use Aborted if the client should retry at a higher-level
// (e.g., restarting a read-modify-write sequence). // (e.g., restarting a read-modify-write sequence).
// (c) Use FailedPrecondition if the client should not retry until // (c) Use FailedPrecondition if the client should not retry until
// the system state has been explicitly fixed. E.g., if an "rmdir" // the system state has been explicitly fixed. E.g., if an "rmdir"
// fails because the directory is non-empty, FailedPrecondition // fails because the directory is non-empty, FailedPrecondition
// should be returned since the client should not retry unless // should be returned since the client should not retry unless
// they have first fixed up the directory by deleting files from it. // they have first fixed up the directory by deleting files from it.
@ -116,7 +114,7 @@ const (
// file size. // file size.
// //
// There is a fair bit of overlap between FailedPrecondition and // There is a fair bit of overlap between FailedPrecondition and
// OutOfRange. We recommend using OutOfRange (the more specific // OutOfRange. We recommend using OutOfRange (the more specific
// error) when it applies so that callers who are iterating through // error) when it applies so that callers who are iterating through
// a space can easily look for an OutOfRange error to detect when // a space can easily look for an OutOfRange error to detect when
// they are done. // they are done.
@ -126,8 +124,8 @@ const (
// supported/enabled in this service. // supported/enabled in this service.
Unimplemented Code = 12 Unimplemented Code = 12
// Internal errors. Means some invariants expected by underlying // Internal errors. Means some invariants expected by underlying
// system has been broken. If you see one of these errors, // system has been broken. If you see one of these errors,
// something is very broken. // something is very broken.
Internal Code = 13 Internal Code = 13
@ -141,4 +139,46 @@ const (
// DataLoss indicates unrecoverable data loss or corruption. // DataLoss indicates unrecoverable data loss or corruption.
DataLoss Code = 15 DataLoss Code = 15
// Unauthenticated indicates the request does not have valid
// authentication credentials for the operation.
Unauthenticated Code = 16
) )
var strToCode = map[string]Code{
`"OK"`: OK,
`"CANCELLED"`:/* [sic] */ Canceled,
`"UNKNOWN"`: Unknown,
`"INVALID_ARGUMENT"`: InvalidArgument,
`"DEADLINE_EXCEEDED"`: DeadlineExceeded,
`"NOT_FOUND"`: NotFound,
`"ALREADY_EXISTS"`: AlreadyExists,
`"PERMISSION_DENIED"`: PermissionDenied,
`"RESOURCE_EXHAUSTED"`: ResourceExhausted,
`"FAILED_PRECONDITION"`: FailedPrecondition,
`"ABORTED"`: Aborted,
`"OUT_OF_RANGE"`: OutOfRange,
`"UNIMPLEMENTED"`: Unimplemented,
`"INTERNAL"`: Internal,
`"UNAVAILABLE"`: Unavailable,
`"DATA_LOSS"`: DataLoss,
`"UNAUTHENTICATED"`: Unauthenticated,
}
// UnmarshalJSON unmarshals b into the Code.
func (c *Code) UnmarshalJSON(b []byte) error {
// From json.Unmarshaler: By convention, to approximate the behavior of
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
// a no-op.
if string(b) == "null" {
return nil
}
if c == nil {
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
}
if jc, ok := strToCode[string(b)]; ok {
*c = jc
return nil
}
return fmt.Errorf("invalid code: %q", string(b))
}

View File

@ -34,10 +34,8 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
) )
var ( // alpnProtoStr are the specified application level protocols for gRPC.
// alpnProtoStr are the specified application level protocols for gRPC. var alpnProtoStr = []string{"h2"}
alpnProtoStr = []string{"h2"}
)
// PerRPCCredentials defines the common interface for the credentials which need to // PerRPCCredentials defines the common interface for the credentials which need to
// attach security information to every RPC (e.g., oauth2). // attach security information to every RPC (e.g., oauth2).
@ -45,8 +43,9 @@ type PerRPCCredentials interface {
// GetRequestMetadata gets the current request metadata, refreshing // GetRequestMetadata gets the current request metadata, refreshing
// tokens if required. This should be called by the transport layer on // tokens if required. This should be called by the transport layer on
// each request, and the data should be populated in headers or other // each request, and the data should be populated in headers or other
// context. uri is the URI of the entry point for the request. When // context. If a status code is returned, it will be used as the status
// supported by the underlying implementation, ctx can be used for // for the RPC. uri is the URI of the entry point for the request.
// When supported by the underlying implementation, ctx can be used for
// timeout and cancellation. // timeout and cancellation.
// TODO(zhaoq): Define the set of the qualified keys instead of leaving // TODO(zhaoq): Define the set of the qualified keys instead of leaving
// it as an arbitrary string. // it as an arbitrary string.
@ -74,11 +73,9 @@ type AuthInfo interface {
AuthType() string AuthType() string
} }
var ( // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC // and the caller should not close rawConn.
// and the caller should not close rawConn. var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
)
// TransportCredentials defines the common interface for all the live gRPC wire // TransportCredentials defines the common interface for all the live gRPC wire
// protocols and supported transport security protocols (e.g., TLS, SSL). // protocols and supported transport security protocols (e.g., TLS, SSL).
@ -135,15 +132,15 @@ func (c tlsCreds) Info() ProtocolInfo {
} }
} }
func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) { func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
// use local cfg to avoid clobbering ServerName if using multiple endpoints // use local cfg to avoid clobbering ServerName if using multiple endpoints
cfg := cloneTLSConfig(c.config) cfg := cloneTLSConfig(c.config)
if cfg.ServerName == "" { if cfg.ServerName == "" {
colonPos := strings.LastIndex(addr, ":") colonPos := strings.LastIndex(authority, ":")
if colonPos == -1 { if colonPos == -1 {
colonPos = len(addr) colonPos = len(authority)
} }
cfg.ServerName = addr[:colonPos] cfg.ServerName = authority[:colonPos]
} }
conn := tls.Client(rawConn, cfg) conn := tls.Client(rawConn, cfg)
errChannel := make(chan error, 1) errChannel := make(chan error, 1)

118
vendor/google.golang.org/grpc/encoding/encoding.go generated vendored Normal file
View File

@ -0,0 +1,118 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package encoding defines the interface for the compressor and codec, and
// functions to register and retrieve compressors and codecs.
//
// This package is EXPERIMENTAL.
package encoding
import (
"io"
"strings"
)
// Identity specifies the optional encoding for uncompressed streams.
// It is intended for grpc internal use only.
const Identity = "identity"
// Compressor is used for compressing and decompressing when sending or
// receiving messages.
type Compressor interface {
// Compress writes the data written to wc to w after compressing it. If an
// error occurs while initializing the compressor, that error is returned
// instead.
Compress(w io.Writer) (io.WriteCloser, error)
// Decompress reads data from r, decompresses it, and provides the
// uncompressed data via the returned io.Reader. If an error occurs while
// initializing the decompressor, that error is returned instead.
Decompress(r io.Reader) (io.Reader, error)
// Name is the name of the compression codec and is used to set the content
// coding header. The result must be static; the result cannot change
// between calls.
Name() string
}
var registeredCompressor = make(map[string]Compressor)
// RegisterCompressor registers the compressor with gRPC by its name. It can
// be activated when sending an RPC via grpc.UseCompressor(). It will be
// automatically accessed when receiving a message based on the content coding
// header. Servers also use it to send a response with the same encoding as
// the request.
//
// NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Compressors are
// registered with the same name, the one registered last will take effect.
func RegisterCompressor(c Compressor) {
registeredCompressor[c.Name()] = c
}
// GetCompressor returns Compressor for the given compressor name.
func GetCompressor(name string) Compressor {
return registeredCompressor[name]
}
// Codec defines the interface gRPC uses to encode and decode messages. Note
// that implementations of this interface must be thread safe; a Codec's
// methods can be called from concurrent goroutines.
type Codec interface {
// Marshal returns the wire format of v.
Marshal(v interface{}) ([]byte, error)
// Unmarshal parses the wire format into v.
Unmarshal(data []byte, v interface{}) error
// Name returns the name of the Codec implementation. The returned string
// will be used as part of content type in transmission. The result must be
// static; the result cannot change between calls.
Name() string
}
var registeredCodecs = make(map[string]Codec, 0)
// RegisterCodec registers the provided Codec for use with all gRPC clients and
// servers.
//
// The Codec will be stored and looked up by result of its Name() method, which
// should match the content-subtype of the encoding handled by the Codec. This
// is case-insensitive, and is stored and looked up as lowercase. If the
// result of calling Name() is an empty string, RegisterCodec will panic. See
// Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details.
//
// NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Compressors are
// registered with the same name, the one registered last will take effect.
func RegisterCodec(codec Codec) {
if codec == nil {
panic("cannot register a nil Codec")
}
contentSubtype := strings.ToLower(codec.Name())
if contentSubtype == "" {
panic("cannot register Codec with empty string result for String()")
}
registeredCodecs[contentSubtype] = codec
}
// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
// registered for the content-subtype.
//
// The content-subtype is expected to be lowercase.
func GetCodec(contentSubtype string) Codec {
return registeredCodecs[contentSubtype]
}

110
vendor/google.golang.org/grpc/encoding/proto/proto.go generated vendored Normal file
View File

@ -0,0 +1,110 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package proto defines the protobuf codec. Importing this package will
// register the codec.
package proto
import (
"math"
"sync"
"github.com/golang/protobuf/proto"
"google.golang.org/grpc/encoding"
)
// Name is the name registered for the proto compressor.
const Name = "proto"
func init() {
encoding.RegisterCodec(codec{})
}
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
type codec struct{}
type cachedProtoBuffer struct {
lastMarshaledSize uint32
proto.Buffer
}
func capToMaxInt32(val int) uint32 {
if val > math.MaxInt32 {
return uint32(math.MaxInt32)
}
return uint32(val)
}
func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
protoMsg := v.(proto.Message)
newSlice := make([]byte, 0, cb.lastMarshaledSize)
cb.SetBuf(newSlice)
cb.Reset()
if err := cb.Marshal(protoMsg); err != nil {
return nil, err
}
out := cb.Bytes()
cb.lastMarshaledSize = capToMaxInt32(len(out))
return out, nil
}
func (codec) Marshal(v interface{}) ([]byte, error) {
if pm, ok := v.(proto.Marshaler); ok {
// object can marshal itself, no need for buffer
return pm.Marshal()
}
cb := protoBufferPool.Get().(*cachedProtoBuffer)
out, err := marshal(v, cb)
// put back buffer and lose the ref to the slice
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return out, err
}
func (codec) Unmarshal(data []byte, v interface{}) error {
protoMsg := v.(proto.Message)
protoMsg.Reset()
if pu, ok := protoMsg.(proto.Unmarshaler); ok {
// object can unmarshal itself, no need for buffer
return pu.Unmarshal(data)
}
cb := protoBufferPool.Get().(*cachedProtoBuffer)
cb.SetBuf(data)
err := cb.Unmarshal(protoMsg)
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return err
}
func (codec) Name() string {
return Name
}
var protoBufferPool = &sync.Pool{
New: func() interface{} {
return &cachedProtoBuffer{
Buffer: proto.Buffer{},
lastMarshaledSize: 16,
}
},
}

99
vendor/google.golang.org/grpc/go16.go generated vendored Normal file
View File

@ -0,0 +1,99 @@
// +build go1.6,!go1.7
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"fmt"
"io"
"net"
"net/http"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/grpc/transport"
)
// dialContext connects to the address on the named network.
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
}
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
req.Cancel = ctx.Done()
if err := req.Write(conn); err != nil {
return fmt.Errorf("failed to write the HTTP request: %v", err)
}
return nil
}
// toRPCErr converts an error into an error from the status package.
func toRPCErr(err error) error {
if err == nil || err == io.EOF {
return err
}
if _, ok := status.FromError(err); ok {
return err
}
switch e := err.(type) {
case transport.StreamError:
return status.Error(e.Code, e.Desc)
case transport.ConnectionError:
return status.Error(codes.Unavailable, e.Desc)
default:
switch err {
case context.DeadlineExceeded:
return status.Error(codes.DeadlineExceeded, err.Error())
case context.Canceled:
return status.Error(codes.Canceled, err.Error())
}
}
return status.Error(codes.Unknown, err.Error())
}
// convertCode converts a standard Go error into its canonical code. Note that
// this is only used to translate the error returned by the server applications.
func convertCode(err error) codes.Code {
switch err {
case nil:
return codes.OK
case io.EOF:
return codes.OutOfRange
case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
return codes.FailedPrecondition
case os.ErrInvalid:
return codes.InvalidArgument
case context.Canceled:
return codes.Canceled
case context.DeadlineExceeded:
return codes.DeadlineExceeded
}
switch {
case os.IsExist(err):
return codes.AlreadyExists
case os.IsNotExist(err):
return codes.NotFound
case os.IsPermission(err):
return codes.PermissionDenied
}
return codes.Unknown
}

100
vendor/google.golang.org/grpc/go17.go generated vendored Normal file
View File

@ -0,0 +1,100 @@
// +build go1.7
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
netctx "golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/grpc/transport"
)
// dialContext connects to the address on the named network.
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{}).DialContext(ctx, network, address)
}
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
req = req.WithContext(ctx)
if err := req.Write(conn); err != nil {
return fmt.Errorf("failed to write the HTTP request: %v", err)
}
return nil
}
// toRPCErr converts an error into an error from the status package.
func toRPCErr(err error) error {
if err == nil || err == io.EOF {
return err
}
if _, ok := status.FromError(err); ok {
return err
}
switch e := err.(type) {
case transport.StreamError:
return status.Error(e.Code, e.Desc)
case transport.ConnectionError:
return status.Error(codes.Unavailable, e.Desc)
default:
switch err {
case context.DeadlineExceeded, netctx.DeadlineExceeded:
return status.Error(codes.DeadlineExceeded, err.Error())
case context.Canceled, netctx.Canceled:
return status.Error(codes.Canceled, err.Error())
}
}
return status.Error(codes.Unknown, err.Error())
}
// convertCode converts a standard Go error into its canonical code. Note that
// this is only used to translate the error returned by the server applications.
func convertCode(err error) codes.Code {
switch err {
case nil:
return codes.OK
case io.EOF:
return codes.OutOfRange
case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
return codes.FailedPrecondition
case os.ErrInvalid:
return codes.InvalidArgument
case context.Canceled, netctx.Canceled:
return codes.Canceled
case context.DeadlineExceeded, netctx.DeadlineExceeded:
return codes.DeadlineExceeded
}
switch {
case os.IsExist(err):
return codes.AlreadyExists
case os.IsNotExist(err):
return codes.NotFound
case os.IsPermission(err):
return codes.PermissionDenied
}
return codes.Unknown
}

View File

@ -19,21 +19,32 @@
package grpc package grpc
import ( import (
"errors" "strconv"
"fmt" "strings"
"math/rand"
"net"
"sync" "sync"
"time" "time"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/codes" "google.golang.org/grpc/balancer"
lbmpb "google.golang.org/grpc/grpclb/grpc_lb_v1/messages" "google.golang.org/grpc/connectivity"
lbpb "google.golang.org/grpc/grpclb/grpc_lb_v1/messages"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/resolver"
"google.golang.org/grpc/naming"
) )
const (
lbTokeyKey = "lb-token"
defaultFallbackTimeout = 10 * time.Second
grpclbName = "grpclb"
)
func convertDuration(d *lbpb.Duration) time.Duration {
if d == nil {
return 0
}
return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond
}
// Client API for LoadBalancer service. // Client API for LoadBalancer service.
// Mostly copied from generated pb.go file. // Mostly copied from generated pb.go file.
// To avoid circular dependency. // To avoid circular dependency.
@ -59,646 +70,273 @@ type balanceLoadClientStream struct {
ClientStream ClientStream
} }
func (x *balanceLoadClientStream) Send(m *lbmpb.LoadBalanceRequest) error { func (x *balanceLoadClientStream) Send(m *lbpb.LoadBalanceRequest) error {
return x.ClientStream.SendMsg(m) return x.ClientStream.SendMsg(m)
} }
func (x *balanceLoadClientStream) Recv() (*lbmpb.LoadBalanceResponse, error) { func (x *balanceLoadClientStream) Recv() (*lbpb.LoadBalanceResponse, error) {
m := new(lbmpb.LoadBalanceResponse) m := new(lbpb.LoadBalanceResponse)
if err := x.ClientStream.RecvMsg(m); err != nil { if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err return nil, err
} }
return m, nil return m, nil
} }
// NewGRPCLBBalancer creates a grpclb load balancer. func init() {
func NewGRPCLBBalancer(r naming.Resolver) Balancer { balancer.Register(newLBBuilder())
return &grpclbBalancer{ }
r: r,
// newLBBuilder creates a builder for grpclb.
func newLBBuilder() balancer.Builder {
return NewLBBuilderWithFallbackTimeout(defaultFallbackTimeout)
}
// NewLBBuilderWithFallbackTimeout creates a grpclb builder with the given
// fallbackTimeout. If no response is received from the remote balancer within
// fallbackTimeout, the backend addresses from the resolved address list will be
// used.
//
// Only call this function when a non-default fallback timeout is needed.
func NewLBBuilderWithFallbackTimeout(fallbackTimeout time.Duration) balancer.Builder {
return &lbBuilder{
fallbackTimeout: fallbackTimeout,
} }
} }
type remoteBalancerInfo struct { type lbBuilder struct {
addr string fallbackTimeout time.Duration
// the server name used for authentication with the remote LB server.
name string
} }
// grpclbAddrInfo consists of the information of a backend server. func (b *lbBuilder) Name() string {
type grpclbAddrInfo struct { return grpclbName
addr Address
connected bool
// dropForRateLimiting indicates whether this particular request should be
// dropped by the client for rate limiting.
dropForRateLimiting bool
// dropForLoadBalancing indicates whether this particular request should be
// dropped by the client for load balancing.
dropForLoadBalancing bool
} }
type grpclbBalancer struct { func (b *lbBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
r naming.Resolver // This generates a manual resolver builder with a random scheme. This
target string // scheme will be used to dial to remote LB, so we can send filtered address
mu sync.Mutex // updates to remote LB ClientConn using this manual resolver.
seq int // a sequence number to make sure addrCh does not get stale addresses. scheme := "grpclb_internal_" + strconv.FormatInt(time.Now().UnixNano(), 36)
w naming.Watcher r := &lbManualResolver{scheme: scheme, ccb: cc}
addrCh chan []Address
rbs []remoteBalancerInfo
addrs []*grpclbAddrInfo
next int
waitCh chan struct{}
done bool
rand *rand.Rand
clientStats lbmpb.ClientStats var target string
targetSplitted := strings.Split(cc.Target(), ":///")
if len(targetSplitted) < 2 {
target = cc.Target()
} else {
target = targetSplitted[1]
}
lb := &lbBalancer{
cc: cc,
target: target,
opt: opt,
fallbackTimeout: b.fallbackTimeout,
doneCh: make(chan struct{}),
manualResolver: r,
csEvltr: &connectivityStateEvaluator{},
subConns: make(map[resolver.Address]balancer.SubConn),
scStates: make(map[balancer.SubConn]connectivity.State),
picker: &errPicker{err: balancer.ErrNoSubConnAvailable},
clientStats: &rpcStats{},
}
return lb
} }
func (b *grpclbBalancer) watchAddrUpdates(w naming.Watcher, ch chan []remoteBalancerInfo) error { type lbBalancer struct {
updates, err := w.Next() cc balancer.ClientConn
if err != nil { target string
grpclog.Warningf("grpclb: failed to get next addr update from watcher: %v", err) opt balancer.BuildOptions
return err fallbackTimeout time.Duration
} doneCh chan struct{}
b.mu.Lock()
defer b.mu.Unlock() // manualResolver is used in the remote LB ClientConn inside grpclb. When
if b.done { // resolved address updates are received by grpclb, filtered updates will be
return ErrClientConnClosing // send to remote LB ClientConn through this resolver.
} manualResolver *lbManualResolver
for _, update := range updates { // The ClientConn to talk to the remote balancer.
switch update.Op { ccRemoteLB *ClientConn
case naming.Add:
var exist bool // Support client side load reporting. Each picker gets a reference to this,
for _, v := range b.rbs { // and will update its content.
// TODO: Is the same addr with different server name a different balancer? clientStats *rpcStats
if update.Addr == v.addr {
exist = true mu sync.Mutex // guards everything following.
break // The full server list including drops, used to check if the newly received
} // serverList contains anything new. Each generate picker will also have
} // reference to this list to do the first layer pick.
if exist { fullServerList []*lbpb.Server
continue // All backends addresses, with metadata set to nil. This list contains all
} // backend addresses in the same order and with the same duplicates as in
md, ok := update.Metadata.(*naming.AddrMetadataGRPCLB) // serverlist. When generating picker, a SubConn slice with the same order
if !ok { // but with only READY SCs will be gerenated.
// TODO: Revisit the handling here and may introduce some fallback mechanism. backendAddrs []resolver.Address
grpclog.Errorf("The name resolution contains unexpected metadata %v", update.Metadata) // Roundrobin functionalities.
continue csEvltr *connectivityStateEvaluator
} state connectivity.State
switch md.AddrType { subConns map[resolver.Address]balancer.SubConn // Used to new/remove SubConn.
case naming.Backend: scStates map[balancer.SubConn]connectivity.State // Used to filter READY SubConns.
// TODO: Revisit the handling here and may introduce some fallback mechanism. picker balancer.Picker
grpclog.Errorf("The name resolution does not give grpclb addresses") // Support fallback to resolved backend addresses if there's no response
continue // from remote balancer within fallbackTimeout.
case naming.GRPCLB: fallbackTimerExpired bool
b.rbs = append(b.rbs, remoteBalancerInfo{ serverListReceived bool
addr: update.Addr, // resolvedBackendAddrs is resolvedAddrs minus remote balancers. It's set
name: md.ServerName, // when resolved address updates are received, and read in the goroutine
}) // handling fallback.
default: resolvedBackendAddrs []resolver.Address
grpclog.Errorf("Received unknow address type %d", md.AddrType)
continue
}
case naming.Delete:
for i, v := range b.rbs {
if update.Addr == v.addr {
copy(b.rbs[i:], b.rbs[i+1:])
b.rbs = b.rbs[:len(b.rbs)-1]
break
}
}
default:
grpclog.Errorf("Unknown update.Op %v", update.Op)
}
}
// TODO: Fall back to the basic round-robin load balancing if the resulting address is
// not a load balancer.
select {
case <-ch:
default:
}
ch <- b.rbs
return nil
} }
func convertDuration(d *lbmpb.Duration) time.Duration { // regeneratePicker takes a snapshot of the balancer, and generates a picker from
if d == nil { // it. The picker
return 0 // - always returns ErrTransientFailure if the balancer is in TransientFailure,
} // - does two layer roundrobin pick otherwise.
return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond // Caller must hold lb.mu.
} func (lb *lbBalancer) regeneratePicker() {
if lb.state == connectivity.TransientFailure {
func (b *grpclbBalancer) processServerList(l *lbmpb.ServerList, seq int) { lb.picker = &errPicker{err: balancer.ErrTransientFailure}
if l == nil {
return return
} }
servers := l.GetServers() var readySCs []balancer.SubConn
var ( for _, a := range lb.backendAddrs {
sl []*grpclbAddrInfo if sc, ok := lb.subConns[a]; ok {
addrs []Address if st, ok := lb.scStates[sc]; ok && st == connectivity.Ready {
) readySCs = append(readySCs, sc)
for _, s := range servers { }
md := metadata.Pairs("lb-token", s.LoadBalanceToken)
ip := net.IP(s.IpAddress)
ipStr := ip.String()
if ip.To4() == nil {
// Add square brackets to ipv6 addresses, otherwise net.Dial() and
// net.SplitHostPort() will return too many colons error.
ipStr = fmt.Sprintf("[%s]", ipStr)
} }
addr := Address{
Addr: fmt.Sprintf("%s:%d", ipStr, s.Port),
Metadata: &md,
}
sl = append(sl, &grpclbAddrInfo{
addr: addr,
dropForRateLimiting: s.DropForRateLimiting,
dropForLoadBalancing: s.DropForLoadBalancing,
})
addrs = append(addrs, addr)
} }
b.mu.Lock()
defer b.mu.Unlock() if len(lb.fullServerList) <= 0 {
if b.done || seq < b.seq { if len(readySCs) <= 0 {
lb.picker = &errPicker{err: balancer.ErrNoSubConnAvailable}
return
}
lb.picker = &rrPicker{subConns: readySCs}
return return
} }
if len(sl) > 0 { lb.picker = &lbPicker{
// reset b.next to 0 when replacing the server list. serverList: lb.fullServerList,
b.next = 0 subConns: readySCs,
b.addrs = sl stats: lb.clientStats,
b.addrCh <- addrs
} }
return return
} }
func (b *grpclbBalancer) sendLoadReport(s *balanceLoadClientStream, interval time.Duration, done <-chan struct{}) { func (lb *lbBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
ticker := time.NewTicker(interval) grpclog.Infof("lbBalancer: handle SubConn state change: %p, %v", sc, s)
defer ticker.Stop() lb.mu.Lock()
for { defer lb.mu.Unlock()
select {
case <-ticker.C: oldS, ok := lb.scStates[sc]
case <-done: if !ok {
return grpclog.Infof("lbBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
} return
b.mu.Lock() }
stats := b.clientStats lb.scStates[sc] = s
b.clientStats = lbmpb.ClientStats{} // Clear the stats. switch s {
b.mu.Unlock() case connectivity.Idle:
t := time.Now() sc.Connect()
stats.Timestamp = &lbmpb.Timestamp{ case connectivity.Shutdown:
Seconds: t.Unix(), // When an address was removed by resolver, b called RemoveSubConn but
Nanos: int32(t.Nanosecond()), // kept the sc's state in scStates. Remove state for this sc here.
} delete(lb.scStates, sc)
if err := s.Send(&lbmpb.LoadBalanceRequest{ }
LoadBalanceRequestType: &lbmpb.LoadBalanceRequest_ClientStats{
ClientStats: &stats, oldAggrState := lb.state
}, lb.state = lb.csEvltr.recordTransition(oldS, s)
}); err != nil {
grpclog.Errorf("grpclb: failed to send load report: %v", err) // Regenerate picker when one of the following happens:
// - this sc became ready from not-ready
// - this sc became not-ready from ready
// - the aggregated state of balancer became TransientFailure from non-TransientFailure
// - the aggregated state of balancer became non-TransientFailure from TransientFailure
if (oldS == connectivity.Ready) != (s == connectivity.Ready) ||
(lb.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
lb.regeneratePicker()
}
lb.cc.UpdateBalancerState(lb.state, lb.picker)
return
}
// fallbackToBackendsAfter blocks for fallbackTimeout and falls back to use
// resolved backends (backends received from resolver, not from remote balancer)
// if no connection to remote balancers was successful.
func (lb *lbBalancer) fallbackToBackendsAfter(fallbackTimeout time.Duration) {
timer := time.NewTimer(fallbackTimeout)
defer timer.Stop()
select {
case <-timer.C:
case <-lb.doneCh:
return
}
lb.mu.Lock()
if lb.serverListReceived {
lb.mu.Unlock()
return
}
lb.fallbackTimerExpired = true
lb.refreshSubConns(lb.resolvedBackendAddrs)
lb.mu.Unlock()
}
// HandleResolvedAddrs sends the updated remoteLB addresses to remoteLB
// clientConn. The remoteLB clientConn will handle creating/removing remoteLB
// connections.
func (lb *lbBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
grpclog.Infof("lbBalancer: handleResolvedResult: %+v", addrs)
if len(addrs) <= 0 {
return
}
var remoteBalancerAddrs, backendAddrs []resolver.Address
for _, a := range addrs {
if a.Type == resolver.GRPCLB {
remoteBalancerAddrs = append(remoteBalancerAddrs, a)
} else {
backendAddrs = append(backendAddrs, a)
}
}
if lb.ccRemoteLB == nil {
if len(remoteBalancerAddrs) <= 0 {
grpclog.Errorf("grpclb: no remote balancer address is available, should never happen")
return return
} }
// First time receiving resolved addresses, create a cc to remote
// balancers.
lb.dialRemoteLB(remoteBalancerAddrs[0].ServerName)
// Start the fallback goroutine.
go lb.fallbackToBackendsAfter(lb.fallbackTimeout)
} }
// cc to remote balancers uses lb.manualResolver. Send the updated remote
// balancer addresses to it through manualResolver.
lb.manualResolver.NewAddress(remoteBalancerAddrs)
lb.mu.Lock()
lb.resolvedBackendAddrs = backendAddrs
// If serverListReceived is true, connection to remote balancer was
// successful and there's no need to do fallback anymore.
// If fallbackTimerExpired is false, fallback hasn't happened yet.
if !lb.serverListReceived && lb.fallbackTimerExpired {
// This means we received a new list of resolved backends, and we are
// still in fallback mode. Need to update the list of backends we are
// using to the new list of backends.
lb.refreshSubConns(lb.resolvedBackendAddrs)
}
lb.mu.Unlock()
} }
func (b *grpclbBalancer) callRemoteBalancer(lbc *loadBalancerClient, seq int) (retry bool) { func (lb *lbBalancer) Close() {
ctx, cancel := context.WithCancel(context.Background()) select {
defer cancel() case <-lb.doneCh:
stream, err := lbc.BalanceLoad(ctx)
if err != nil {
grpclog.Errorf("grpclb: failed to perform RPC to the remote balancer %v", err)
return return
default:
} }
b.mu.Lock() close(lb.doneCh)
if b.done { if lb.ccRemoteLB != nil {
b.mu.Unlock() lb.ccRemoteLB.Close()
return
}
b.mu.Unlock()
initReq := &lbmpb.LoadBalanceRequest{
LoadBalanceRequestType: &lbmpb.LoadBalanceRequest_InitialRequest{
InitialRequest: &lbmpb.InitialLoadBalanceRequest{
Name: b.target,
},
},
}
if err := stream.Send(initReq); err != nil {
grpclog.Errorf("grpclb: failed to send init request: %v", err)
// TODO: backoff on retry?
return true
}
reply, err := stream.Recv()
if err != nil {
grpclog.Errorf("grpclb: failed to recv init response: %v", err)
// TODO: backoff on retry?
return true
}
initResp := reply.GetInitialResponse()
if initResp == nil {
grpclog.Errorf("grpclb: reply from remote balancer did not include initial response.")
return
}
// TODO: Support delegation.
if initResp.LoadBalancerDelegate != "" {
// delegation
grpclog.Errorf("TODO: Delegation is not supported yet.")
return
}
streamDone := make(chan struct{})
defer close(streamDone)
b.mu.Lock()
b.clientStats = lbmpb.ClientStats{} // Clear client stats.
b.mu.Unlock()
if d := convertDuration(initResp.ClientStatsReportInterval); d > 0 {
go b.sendLoadReport(stream, d, streamDone)
}
// Retrieve the server list.
for {
reply, err := stream.Recv()
if err != nil {
grpclog.Errorf("grpclb: failed to recv server list: %v", err)
break
}
b.mu.Lock()
if b.done || seq < b.seq {
b.mu.Unlock()
return
}
b.seq++ // tick when receiving a new list of servers.
seq = b.seq
b.mu.Unlock()
if serverList := reply.GetServerList(); serverList != nil {
b.processServerList(serverList, seq)
}
}
return true
}
func (b *grpclbBalancer) Start(target string, config BalancerConfig) error {
b.rand = rand.New(rand.NewSource(time.Now().Unix()))
// TODO: Fall back to the basic direct connection if there is no name resolver.
if b.r == nil {
return errors.New("there is no name resolver installed")
}
b.target = target
b.mu.Lock()
if b.done {
b.mu.Unlock()
return ErrClientConnClosing
}
b.addrCh = make(chan []Address)
w, err := b.r.Resolve(target)
if err != nil {
b.mu.Unlock()
grpclog.Errorf("grpclb: failed to resolve address: %v, err: %v", target, err)
return err
}
b.w = w
b.mu.Unlock()
balancerAddrsCh := make(chan []remoteBalancerInfo, 1)
// Spawn a goroutine to monitor the name resolution of remote load balancer.
go func() {
for {
if err := b.watchAddrUpdates(w, balancerAddrsCh); err != nil {
grpclog.Warningf("grpclb: the naming watcher stops working due to %v.\n", err)
close(balancerAddrsCh)
return
}
}
}()
// Spawn a goroutine to talk to the remote load balancer.
go func() {
var (
cc *ClientConn
// ccError is closed when there is an error in the current cc.
// A new rb should be picked from rbs and connected.
ccError chan struct{}
rb *remoteBalancerInfo
rbs []remoteBalancerInfo
rbIdx int
)
defer func() {
if ccError != nil {
select {
case <-ccError:
default:
close(ccError)
}
}
if cc != nil {
cc.Close()
}
}()
for {
var ok bool
select {
case rbs, ok = <-balancerAddrsCh:
if !ok {
return
}
foundIdx := -1
if rb != nil {
for i, trb := range rbs {
if trb == *rb {
foundIdx = i
break
}
}
}
if foundIdx >= 0 {
if foundIdx >= 1 {
// Move the address in use to the beginning of the list.
b.rbs[0], b.rbs[foundIdx] = b.rbs[foundIdx], b.rbs[0]
rbIdx = 0
}
continue // If found, don't dial new cc.
} else if len(rbs) > 0 {
// Pick a random one from the list, instead of always using the first one.
if l := len(rbs); l > 1 && rb != nil {
tmpIdx := b.rand.Intn(l - 1)
b.rbs[0], b.rbs[tmpIdx] = b.rbs[tmpIdx], b.rbs[0]
}
rbIdx = 0
rb = &rbs[0]
} else {
// foundIdx < 0 && len(rbs) <= 0.
rb = nil
}
case <-ccError:
ccError = nil
if rbIdx < len(rbs)-1 {
rbIdx++
rb = &rbs[rbIdx]
} else {
rb = nil
}
}
if rb == nil {
continue
}
if cc != nil {
cc.Close()
}
// Talk to the remote load balancer to get the server list.
var (
err error
dopts []DialOption
)
if creds := config.DialCreds; creds != nil {
if rb.name != "" {
if err := creds.OverrideServerName(rb.name); err != nil {
grpclog.Warningf("grpclb: failed to override the server name in the credentials: %v", err)
continue
}
}
dopts = append(dopts, WithTransportCredentials(creds))
} else {
dopts = append(dopts, WithInsecure())
}
if dialer := config.Dialer; dialer != nil {
// WithDialer takes a different type of function, so we instead use a special DialOption here.
dopts = append(dopts, func(o *dialOptions) { o.copts.Dialer = dialer })
}
dopts = append(dopts, WithBlock())
ccError = make(chan struct{})
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
cc, err = DialContext(ctx, rb.addr, dopts...)
cancel()
if err != nil {
grpclog.Warningf("grpclb: failed to setup a connection to the remote balancer %v: %v", rb.addr, err)
close(ccError)
continue
}
b.mu.Lock()
b.seq++ // tick when getting a new balancer address
seq := b.seq
b.next = 0
b.mu.Unlock()
go func(cc *ClientConn, ccError chan struct{}) {
lbc := &loadBalancerClient{cc}
b.callRemoteBalancer(lbc, seq)
cc.Close()
select {
case <-ccError:
default:
close(ccError)
}
}(cc, ccError)
}
}()
return nil
}
func (b *grpclbBalancer) down(addr Address, err error) {
b.mu.Lock()
defer b.mu.Unlock()
for _, a := range b.addrs {
if addr == a.addr {
a.connected = false
break
}
} }
} }
func (b *grpclbBalancer) Up(addr Address) func(error) {
b.mu.Lock()
defer b.mu.Unlock()
if b.done {
return nil
}
var cnt int
for _, a := range b.addrs {
if a.addr == addr {
if a.connected {
return nil
}
a.connected = true
}
if a.connected && !a.dropForRateLimiting && !a.dropForLoadBalancing {
cnt++
}
}
// addr is the only one which is connected. Notify the Get() callers who are blocking.
if cnt == 1 && b.waitCh != nil {
close(b.waitCh)
b.waitCh = nil
}
return func(err error) {
b.down(addr, err)
}
}
func (b *grpclbBalancer) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
var ch chan struct{}
b.mu.Lock()
if b.done {
b.mu.Unlock()
err = ErrClientConnClosing
return
}
seq := b.seq
defer func() {
if err != nil {
return
}
put = func() {
s, ok := rpcInfoFromContext(ctx)
if !ok {
return
}
b.mu.Lock()
defer b.mu.Unlock()
if b.done || seq < b.seq {
return
}
b.clientStats.NumCallsFinished++
if !s.bytesSent {
b.clientStats.NumCallsFinishedWithClientFailedToSend++
} else if s.bytesReceived {
b.clientStats.NumCallsFinishedKnownReceived++
}
}
}()
b.clientStats.NumCallsStarted++
if len(b.addrs) > 0 {
if b.next >= len(b.addrs) {
b.next = 0
}
next := b.next
for {
a := b.addrs[next]
next = (next + 1) % len(b.addrs)
if a.connected {
if !a.dropForRateLimiting && !a.dropForLoadBalancing {
addr = a.addr
b.next = next
b.mu.Unlock()
return
}
if !opts.BlockingWait {
b.next = next
if a.dropForLoadBalancing {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithDropForLoadBalancing++
} else if a.dropForRateLimiting {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithDropForRateLimiting++
}
b.mu.Unlock()
err = Errorf(codes.Unavailable, "%s drops requests", a.addr.Addr)
return
}
}
if next == b.next {
// Has iterated all the possible address but none is connected.
break
}
}
}
if !opts.BlockingWait {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithClientFailedToSend++
b.mu.Unlock()
err = Errorf(codes.Unavailable, "there is no address available")
return
}
// Wait on b.waitCh for non-failfast RPCs.
if b.waitCh == nil {
ch = make(chan struct{})
b.waitCh = ch
} else {
ch = b.waitCh
}
b.mu.Unlock()
for {
select {
case <-ctx.Done():
b.mu.Lock()
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithClientFailedToSend++
b.mu.Unlock()
err = ctx.Err()
return
case <-ch:
b.mu.Lock()
if b.done {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithClientFailedToSend++
b.mu.Unlock()
err = ErrClientConnClosing
return
}
if len(b.addrs) > 0 {
if b.next >= len(b.addrs) {
b.next = 0
}
next := b.next
for {
a := b.addrs[next]
next = (next + 1) % len(b.addrs)
if a.connected {
if !a.dropForRateLimiting && !a.dropForLoadBalancing {
addr = a.addr
b.next = next
b.mu.Unlock()
return
}
if !opts.BlockingWait {
b.next = next
if a.dropForLoadBalancing {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithDropForLoadBalancing++
} else if a.dropForRateLimiting {
b.clientStats.NumCallsFinished++
b.clientStats.NumCallsFinishedWithDropForRateLimiting++
}
b.mu.Unlock()
err = Errorf(codes.Unavailable, "drop requests for the addreess %s", a.addr.Addr)
return
}
}
if next == b.next {
// Has iterated all the possible address but none is connected.
break
}
}
}
// The newly added addr got removed by Down() again.
if b.waitCh == nil {
ch = make(chan struct{})
b.waitCh = ch
} else {
ch = b.waitCh
}
b.mu.Unlock()
}
}
}
func (b *grpclbBalancer) Notify() <-chan []Address {
return b.addrCh
}
func (b *grpclbBalancer) Close() error {
b.mu.Lock()
defer b.mu.Unlock()
if b.done {
return errBalancerClosed
}
b.done = true
if b.waitCh != nil {
close(b.waitCh)
}
if b.addrCh != nil {
close(b.addrCh)
}
if b.w != nil {
b.w.Close()
}
return nil
}

View File

@ -15,7 +15,7 @@
syntax = "proto3"; syntax = "proto3";
package grpc.lb.v1; package grpc.lb.v1;
option go_package = "messages"; option go_package = "google.golang.org/grpc/grpclb/grpc_lb_v1/messages";
message Duration { message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000 // Signed seconds of the span of time. Must be from -315,576,000,000

159
vendor/google.golang.org/grpc/grpclb_picker.go generated vendored Normal file
View File

@ -0,0 +1,159 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"sync"
"sync/atomic"
"golang.org/x/net/context"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/codes"
lbpb "google.golang.org/grpc/grpclb/grpc_lb_v1/messages"
"google.golang.org/grpc/status"
)
type rpcStats struct {
NumCallsStarted int64
NumCallsFinished int64
NumCallsFinishedWithDropForRateLimiting int64
NumCallsFinishedWithDropForLoadBalancing int64
NumCallsFinishedWithClientFailedToSend int64
NumCallsFinishedKnownReceived int64
}
// toClientStats converts rpcStats to lbpb.ClientStats, and clears rpcStats.
func (s *rpcStats) toClientStats() *lbpb.ClientStats {
stats := &lbpb.ClientStats{
NumCallsStarted: atomic.SwapInt64(&s.NumCallsStarted, 0),
NumCallsFinished: atomic.SwapInt64(&s.NumCallsFinished, 0),
NumCallsFinishedWithDropForRateLimiting: atomic.SwapInt64(&s.NumCallsFinishedWithDropForRateLimiting, 0),
NumCallsFinishedWithDropForLoadBalancing: atomic.SwapInt64(&s.NumCallsFinishedWithDropForLoadBalancing, 0),
NumCallsFinishedWithClientFailedToSend: atomic.SwapInt64(&s.NumCallsFinishedWithClientFailedToSend, 0),
NumCallsFinishedKnownReceived: atomic.SwapInt64(&s.NumCallsFinishedKnownReceived, 0),
}
return stats
}
func (s *rpcStats) dropForRateLimiting() {
atomic.AddInt64(&s.NumCallsStarted, 1)
atomic.AddInt64(&s.NumCallsFinishedWithDropForRateLimiting, 1)
atomic.AddInt64(&s.NumCallsFinished, 1)
}
func (s *rpcStats) dropForLoadBalancing() {
atomic.AddInt64(&s.NumCallsStarted, 1)
atomic.AddInt64(&s.NumCallsFinishedWithDropForLoadBalancing, 1)
atomic.AddInt64(&s.NumCallsFinished, 1)
}
func (s *rpcStats) failedToSend() {
atomic.AddInt64(&s.NumCallsStarted, 1)
atomic.AddInt64(&s.NumCallsFinishedWithClientFailedToSend, 1)
atomic.AddInt64(&s.NumCallsFinished, 1)
}
func (s *rpcStats) knownReceived() {
atomic.AddInt64(&s.NumCallsStarted, 1)
atomic.AddInt64(&s.NumCallsFinishedKnownReceived, 1)
atomic.AddInt64(&s.NumCallsFinished, 1)
}
type errPicker struct {
// Pick always returns this err.
err error
}
func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
return nil, nil, p.err
}
// rrPicker does roundrobin on subConns. It's typically used when there's no
// response from remote balancer, and grpclb falls back to the resolved
// backends.
//
// It guaranteed that len(subConns) > 0.
type rrPicker struct {
mu sync.Mutex
subConns []balancer.SubConn // The subConns that were READY when taking the snapshot.
subConnsNext int
}
func (p *rrPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
p.mu.Lock()
defer p.mu.Unlock()
sc := p.subConns[p.subConnsNext]
p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
return sc, nil, nil
}
// lbPicker does two layers of picks:
//
// First layer: roundrobin on all servers in serverList, including drops and backends.
// - If it picks a drop, the RPC will fail as being dropped.
// - If it picks a backend, do a second layer pick to pick the real backend.
//
// Second layer: roundrobin on all READY backends.
//
// It's guaranteed that len(serverList) > 0.
type lbPicker struct {
mu sync.Mutex
serverList []*lbpb.Server
serverListNext int
subConns []balancer.SubConn // The subConns that were READY when taking the snapshot.
subConnsNext int
stats *rpcStats
}
func (p *lbPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
p.mu.Lock()
defer p.mu.Unlock()
// Layer one roundrobin on serverList.
s := p.serverList[p.serverListNext]
p.serverListNext = (p.serverListNext + 1) % len(p.serverList)
// If it's a drop, return an error and fail the RPC.
if s.DropForRateLimiting {
p.stats.dropForRateLimiting()
return nil, nil, status.Errorf(codes.Unavailable, "request dropped by grpclb")
}
if s.DropForLoadBalancing {
p.stats.dropForLoadBalancing()
return nil, nil, status.Errorf(codes.Unavailable, "request dropped by grpclb")
}
// If not a drop but there's no ready subConns.
if len(p.subConns) <= 0 {
return nil, nil, balancer.ErrNoSubConnAvailable
}
// Return the next ready subConn in the list, also collect rpc stats.
sc := p.subConns[p.subConnsNext]
p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
done := func(info balancer.DoneInfo) {
if !info.BytesSent {
p.stats.failedToSend()
} else if info.BytesReceived {
p.stats.knownReceived()
}
}
return sc, done, nil
}

254
vendor/google.golang.org/grpc/grpclb_remote_balancer.go generated vendored Normal file
View File

@ -0,0 +1,254 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"fmt"
"net"
"reflect"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity"
lbpb "google.golang.org/grpc/grpclb/grpc_lb_v1/messages"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver"
)
// processServerList updates balaner's internal state, create/remove SubConns
// and regenerates picker using the received serverList.
func (lb *lbBalancer) processServerList(l *lbpb.ServerList) {
grpclog.Infof("lbBalancer: processing server list: %+v", l)
lb.mu.Lock()
defer lb.mu.Unlock()
// Set serverListReceived to true so fallback will not take effect if it has
// not hit timeout.
lb.serverListReceived = true
// If the new server list == old server list, do nothing.
if reflect.DeepEqual(lb.fullServerList, l.Servers) {
grpclog.Infof("lbBalancer: new serverlist same as the previous one, ignoring")
return
}
lb.fullServerList = l.Servers
var backendAddrs []resolver.Address
for _, s := range l.Servers {
if s.DropForLoadBalancing || s.DropForRateLimiting {
continue
}
md := metadata.Pairs(lbTokeyKey, s.LoadBalanceToken)
ip := net.IP(s.IpAddress)
ipStr := ip.String()
if ip.To4() == nil {
// Add square brackets to ipv6 addresses, otherwise net.Dial() and
// net.SplitHostPort() will return too many colons error.
ipStr = fmt.Sprintf("[%s]", ipStr)
}
addr := resolver.Address{
Addr: fmt.Sprintf("%s:%d", ipStr, s.Port),
Metadata: &md,
}
backendAddrs = append(backendAddrs, addr)
}
// Call refreshSubConns to create/remove SubConns.
backendsUpdated := lb.refreshSubConns(backendAddrs)
// If no backend was updated, no SubConn will be newed/removed. But since
// the full serverList was different, there might be updates in drops or
// pick weights(different number of duplicates). We need to update picker
// with the fulllist.
if !backendsUpdated {
lb.regeneratePicker()
lb.cc.UpdateBalancerState(lb.state, lb.picker)
}
}
// refreshSubConns creates/removes SubConns with backendAddrs. It returns a bool
// indicating whether the backendAddrs are different from the cached
// backendAddrs (whether any SubConn was newed/removed).
// Caller must hold lb.mu.
func (lb *lbBalancer) refreshSubConns(backendAddrs []resolver.Address) bool {
lb.backendAddrs = nil
var backendsUpdated bool
// addrsSet is the set converted from backendAddrs, it's used to quick
// lookup for an address.
addrsSet := make(map[resolver.Address]struct{})
// Create new SubConns.
for _, addr := range backendAddrs {
addrWithoutMD := addr
addrWithoutMD.Metadata = nil
addrsSet[addrWithoutMD] = struct{}{}
lb.backendAddrs = append(lb.backendAddrs, addrWithoutMD)
if _, ok := lb.subConns[addrWithoutMD]; !ok {
backendsUpdated = true
// Use addrWithMD to create the SubConn.
sc, err := lb.cc.NewSubConn([]resolver.Address{addr}, balancer.NewSubConnOptions{})
if err != nil {
grpclog.Warningf("roundrobinBalancer: failed to create new SubConn: %v", err)
continue
}
lb.subConns[addrWithoutMD] = sc // Use the addr without MD as key for the map.
lb.scStates[sc] = connectivity.Idle
sc.Connect()
}
}
for a, sc := range lb.subConns {
// a was removed by resolver.
if _, ok := addrsSet[a]; !ok {
backendsUpdated = true
lb.cc.RemoveSubConn(sc)
delete(lb.subConns, a)
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
// The entry will be deleted in HandleSubConnStateChange.
}
}
return backendsUpdated
}
func (lb *lbBalancer) readServerList(s *balanceLoadClientStream) error {
for {
reply, err := s.Recv()
if err != nil {
return fmt.Errorf("grpclb: failed to recv server list: %v", err)
}
if serverList := reply.GetServerList(); serverList != nil {
lb.processServerList(serverList)
}
}
}
func (lb *lbBalancer) sendLoadReport(s *balanceLoadClientStream, interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
case <-s.Context().Done():
return
}
stats := lb.clientStats.toClientStats()
t := time.Now()
stats.Timestamp = &lbpb.Timestamp{
Seconds: t.Unix(),
Nanos: int32(t.Nanosecond()),
}
if err := s.Send(&lbpb.LoadBalanceRequest{
LoadBalanceRequestType: &lbpb.LoadBalanceRequest_ClientStats{
ClientStats: stats,
},
}); err != nil {
return
}
}
}
func (lb *lbBalancer) callRemoteBalancer() error {
lbClient := &loadBalancerClient{cc: lb.ccRemoteLB}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
stream, err := lbClient.BalanceLoad(ctx, FailFast(false))
if err != nil {
return fmt.Errorf("grpclb: failed to perform RPC to the remote balancer %v", err)
}
// grpclb handshake on the stream.
initReq := &lbpb.LoadBalanceRequest{
LoadBalanceRequestType: &lbpb.LoadBalanceRequest_InitialRequest{
InitialRequest: &lbpb.InitialLoadBalanceRequest{
Name: lb.target,
},
},
}
if err := stream.Send(initReq); err != nil {
return fmt.Errorf("grpclb: failed to send init request: %v", err)
}
reply, err := stream.Recv()
if err != nil {
return fmt.Errorf("grpclb: failed to recv init response: %v", err)
}
initResp := reply.GetInitialResponse()
if initResp == nil {
return fmt.Errorf("grpclb: reply from remote balancer did not include initial response")
}
if initResp.LoadBalancerDelegate != "" {
return fmt.Errorf("grpclb: Delegation is not supported")
}
go func() {
if d := convertDuration(initResp.ClientStatsReportInterval); d > 0 {
lb.sendLoadReport(stream, d)
}
}()
return lb.readServerList(stream)
}
func (lb *lbBalancer) watchRemoteBalancer() {
for {
err := lb.callRemoteBalancer()
select {
case <-lb.doneCh:
return
default:
if err != nil {
grpclog.Error(err)
}
}
}
}
func (lb *lbBalancer) dialRemoteLB(remoteLBName string) {
var dopts []DialOption
if creds := lb.opt.DialCreds; creds != nil {
if err := creds.OverrideServerName(remoteLBName); err == nil {
dopts = append(dopts, WithTransportCredentials(creds))
} else {
grpclog.Warningf("grpclb: failed to override the server name in the credentials: %v, using Insecure", err)
dopts = append(dopts, WithInsecure())
}
} else {
dopts = append(dopts, WithInsecure())
}
if lb.opt.Dialer != nil {
// WithDialer takes a different type of function, so we instead use a
// special DialOption here.
dopts = append(dopts, withContextDialer(lb.opt.Dialer))
}
// Explicitly set pickfirst as the balancer.
dopts = append(dopts, WithBalancerName(PickFirstBalancerName))
dopts = append(dopts, withResolverBuilder(lb.manualResolver))
// Dial using manualResolver.Scheme, which is a random scheme generated
// when init grpclb. The target name is not important.
cc, err := Dial("grpclb:///grpclb.server", dopts...)
if err != nil {
grpclog.Fatalf("failed to dial: %v", err)
}
lb.ccRemoteLB = cc
go lb.watchRemoteBalancer()
}

90
vendor/google.golang.org/grpc/grpclb_util.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/resolver"
)
// The parent ClientConn should re-resolve when grpclb loses connection to the
// remote balancer. When the ClientConn inside grpclb gets a TransientFailure,
// it calls lbManualResolver.ResolveNow(), which calls parent ClientConn's
// ResolveNow, and eventually results in re-resolve happening in parent
// ClientConn's resolver (DNS for example).
//
// parent
// ClientConn
// +-----------------------------------------------------------------+
// | parent +---------------------------------+ |
// | DNS ClientConn | grpclb | |
// | resolver balancerWrapper | | |
// | + + | grpclb grpclb | |
// | | | | ManualResolver ClientConn | |
// | | | | + + | |
// | | | | | | Transient | |
// | | | | | | Failure | |
// | | | | | <--------- | | |
// | | | <--------------- | ResolveNow | | |
// | | <--------- | ResolveNow | | | | |
// | | ResolveNow | | | | | |
// | | | | | | | |
// | + + | + + | |
// | +---------------------------------+ |
// +-----------------------------------------------------------------+
// lbManualResolver is used by the ClientConn inside grpclb. It's a manual
// resolver with a special ResolveNow() function.
//
// When ResolveNow() is called, it calls ResolveNow() on the parent ClientConn,
// so when grpclb client lose contact with remote balancers, the parent
// ClientConn's resolver will re-resolve.
type lbManualResolver struct {
scheme string
ccr resolver.ClientConn
ccb balancer.ClientConn
}
func (r *lbManualResolver) Build(_ resolver.Target, cc resolver.ClientConn, _ resolver.BuildOption) (resolver.Resolver, error) {
r.ccr = cc
return r, nil
}
func (r *lbManualResolver) Scheme() string {
return r.scheme
}
// ResolveNow calls resolveNow on the parent ClientConn.
func (r *lbManualResolver) ResolveNow(o resolver.ResolveNowOption) {
r.ccb.ResolveNow(o)
}
// Close is a noop for Resolver.
func (*lbManualResolver) Close() {}
// NewAddress calls cc.NewAddress.
func (r *lbManualResolver) NewAddress(addrs []resolver.Address) {
r.ccr.NewAddress(addrs)
}
// NewServiceConfig calls cc.NewServiceConfig.
func (r *lbManualResolver) NewServiceConfig(sc string) {
r.ccr.NewServiceConfig(sc)
}

View File

@ -26,9 +26,9 @@ import (
"sync" "sync"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
healthpb "google.golang.org/grpc/health/grpc_health_v1" healthpb "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/status"
) )
// Server implements `service Health`. // Server implements `service Health`.
@ -60,7 +60,7 @@ func (s *Server) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*h
Status: status, Status: status,
}, nil }, nil
} }
return nil, grpc.Errorf(codes.NotFound, "unknown service") return nil, status.Error(codes.NotFound, "unknown service")
} }
// SetServingStatus is called when need to reset the serving status of a service // SetServingStatus is called when need to reset the serving status of a service

View File

@ -19,13 +19,6 @@
// the godoc of the top-level grpc package. // the godoc of the top-level grpc package.
package internal package internal
// TestingCloseConns closes all existing transports but keeps
// grpcServer.lis accepting new connections.
//
// The provided grpcServer must be of type *grpc.Server. It is untyped
// for circular dependency reasons.
var TestingCloseConns func(grpcServer interface{})
// TestingUseHandlerImpl enables the http.Handler-based server implementation. // TestingUseHandlerImpl enables the http.Handler-based server implementation.
// It must be called before Serve and requires TLS credentials. // It must be called before Serve and requires TLS credentials.
// //

View File

@ -17,7 +17,8 @@
*/ */
// Package metadata define the structure of the metadata supported by gRPC library. // Package metadata define the structure of the metadata supported by gRPC library.
// Please refer to https://grpc.io/docs/guides/wire.html for more information about custom-metadata. // Please refer to https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
// for more information about custom-metadata.
package metadata // import "google.golang.org/grpc/metadata" package metadata // import "google.golang.org/grpc/metadata"
import ( import (
@ -115,9 +116,22 @@ func NewIncomingContext(ctx context.Context, md MD) context.Context {
return context.WithValue(ctx, mdIncomingKey{}, md) return context.WithValue(ctx, mdIncomingKey{}, md)
} }
// NewOutgoingContext creates a new context with outgoing md attached. // NewOutgoingContext creates a new context with outgoing md attached. If used
// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
// overwrite any previously-appended metadata.
func NewOutgoingContext(ctx context.Context, md MD) context.Context { func NewOutgoingContext(ctx context.Context, md MD) context.Context {
return context.WithValue(ctx, mdOutgoingKey{}, md) return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
}
// AppendToOutgoingContext returns a new context with the provided kv merged
// with any existing metadata in the context. Please refer to the
// documentation of Pairs for a description of kv.
func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
if len(kv)%2 == 1 {
panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
}
md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: append(md.added, kv)})
} }
// FromIncomingContext returns the incoming metadata in ctx if it exists. The // FromIncomingContext returns the incoming metadata in ctx if it exists. The
@ -128,10 +142,39 @@ func FromIncomingContext(ctx context.Context) (md MD, ok bool) {
return return
} }
// FromOutgoingContextRaw returns the un-merged, intermediary contents
// of rawMD. Remember to perform strings.ToLower on the keys. The returned
// MD should not be modified. Writing to it may cause races. Modification
// should be made to copies of the returned MD.
//
// This is intended for gRPC-internal use ONLY.
func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
if !ok {
return nil, nil, false
}
return raw.md, raw.added, true
}
// FromOutgoingContext returns the outgoing metadata in ctx if it exists. The // FromOutgoingContext returns the outgoing metadata in ctx if it exists. The
// returned MD should not be modified. Writing to it may cause races. // returned MD should not be modified. Writing to it may cause races.
// Modification should be made to the copies of the returned MD. // Modification should be made to the copies of the returned MD.
func FromOutgoingContext(ctx context.Context) (md MD, ok bool) { func FromOutgoingContext(ctx context.Context) (MD, bool) {
md, ok = ctx.Value(mdOutgoingKey{}).(MD) raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
return if !ok {
return nil, false
}
mds := make([]MD, 0, len(raw.added)+1)
mds = append(mds, raw.md)
for _, vv := range raw.added {
mds = append(mds, Pairs(vv...))
}
return Join(mds...), ok
}
type rawMD struct {
md MD
added [][]string
} }

View File

@ -1,4 +1,4 @@
// +build go1.7, !go1.8 // +build go1.6,!go1.8
/* /*
* *

View File

@ -97,7 +97,7 @@ func (bp *pickerWrapper) pick(ctx context.Context, failfast bool, opts balancer.
p = bp.picker p = bp.picker
bp.mu.Unlock() bp.mu.Unlock()
subConn, put, err := p.Pick(ctx, opts) subConn, done, err := p.Pick(ctx, opts)
if err != nil { if err != nil {
switch err { switch err {
@ -120,7 +120,7 @@ func (bp *pickerWrapper) pick(ctx context.Context, failfast bool, opts balancer.
continue continue
} }
if t, ok := acw.getAddrConn().getReadyTransport(); ok { if t, ok := acw.getAddrConn().getReadyTransport(); ok {
return t, put, nil return t, done, nil
} }
grpclog.Infof("blockingPicker: the picked transport is not ready, loop back to repick") grpclog.Infof("blockingPicker: the picked transport is not ready, loop back to repick")
// If ok == false, ac.state is not READY. // If ok == false, ac.state is not READY.

View File

@ -26,6 +26,9 @@ import (
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
) )
// PickFirstBalancerName is the name of the pick_first balancer.
const PickFirstBalancerName = "pick_first"
func newPickfirstBuilder() balancer.Builder { func newPickfirstBuilder() balancer.Builder {
return &pickfirstBuilder{} return &pickfirstBuilder{}
} }
@ -37,7 +40,7 @@ func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions
} }
func (*pickfirstBuilder) Name() string { func (*pickfirstBuilder) Name() string {
return "pickfirst" return PickFirstBalancerName
} }
type pickfirstBalancer struct { type pickfirstBalancer struct {
@ -57,14 +60,20 @@ func (b *pickfirstBalancer) HandleResolvedAddrs(addrs []resolver.Address, err er
return return
} }
b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc}) b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc})
b.sc.Connect()
} else { } else {
b.sc.UpdateAddresses(addrs) b.sc.UpdateAddresses(addrs)
b.sc.Connect()
} }
} }
func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) { func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s) grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s)
if b.sc != sc || s == connectivity.Shutdown { if b.sc != sc {
grpclog.Infof("pickfirstBalancer: ignored state change because sc is not recognized")
return
}
if s == connectivity.Shutdown {
b.sc = nil b.sc = nil
return return
} }
@ -93,3 +102,7 @@ func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.
} }
return p.sc, nil, nil return p.sc, nil, nil
} }
func init() {
balancer.Register(newPickfirstBuilder())
}

View File

@ -82,8 +82,7 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, addr string) (_
Header: map[string][]string{"User-Agent": {grpcUA}}, Header: map[string][]string{"User-Agent": {grpcUA}},
}) })
req = req.WithContext(ctx) if err := sendHTTPRequest(ctx, req, conn); err != nil {
if err := req.Write(conn); err != nil {
return nil, fmt.Errorf("failed to write the HTTP request: %v", err) return nil, fmt.Errorf("failed to write the HTTP request: %v", err)
} }

View File

@ -0,0 +1,377 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package dns implements a dns resolver to be installed as the default resolver
// in grpc.
package dns
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"os"
"strconv"
"strings"
"sync"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/resolver"
)
func init() {
resolver.Register(NewBuilder())
}
const (
defaultPort = "443"
defaultFreq = time.Minute * 30
golang = "GO"
// In DNS, service config is encoded in a TXT record via the mechanism
// described in RFC-1464 using the attribute name grpc_config.
txtAttribute = "grpc_config="
)
var errMissingAddr = errors.New("missing address")
// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
func NewBuilder() resolver.Builder {
return &dnsBuilder{freq: defaultFreq}
}
type dnsBuilder struct {
// frequency of polling the DNS server.
freq time.Duration
}
// 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.BuildOption) (resolver.Resolver, error) {
host, port, err := parseTarget(target.Endpoint)
if err != nil {
return nil, err
}
// IP address.
if net.ParseIP(host) != nil {
host, _ = formatIP(host)
addr := []resolver.Address{{Addr: host + ":" + port}}
i := &ipResolver{
cc: cc,
ip: addr,
rn: make(chan struct{}, 1),
q: make(chan struct{}),
}
cc.NewAddress(addr)
go i.watcher()
return i, nil
}
// DNS address (non-IP).
ctx, cancel := context.WithCancel(context.Background())
d := &dnsResolver{
freq: b.freq,
host: host,
port: port,
ctx: ctx,
cancel: cancel,
cc: cc,
t: time.NewTimer(0),
rn: make(chan struct{}, 1),
}
d.wg.Add(1)
go d.watcher()
return d, nil
}
// Scheme returns the naming scheme of this resolver builder, which is "dns".
func (b *dnsBuilder) Scheme() string {
return "dns"
}
// ipResolver watches for the name resolution update for an IP address.
type ipResolver struct {
cc resolver.ClientConn
ip []resolver.Address
// rn channel is used by ResolveNow() to force an immediate resolution of the target.
rn chan struct{}
q chan struct{}
}
// ResolveNow resend the address it stores, no resolution is needed.
func (i *ipResolver) ResolveNow(opt resolver.ResolveNowOption) {
select {
case i.rn <- struct{}{}:
default:
}
}
// Close closes the ipResolver.
func (i *ipResolver) Close() {
close(i.q)
}
func (i *ipResolver) watcher() {
for {
select {
case <-i.rn:
i.cc.NewAddress(i.ip)
case <-i.q:
return
}
}
}
// dnsResolver watches for the name resolution update for a non-IP target.
type dnsResolver struct {
freq time.Duration
host string
port string
ctx context.Context
cancel context.CancelFunc
cc resolver.ClientConn
// rn channel is used by ResolveNow() to force an immediate resolution of the target.
rn chan struct{}
t *time.Timer
// wg is used to enforce Close() to return after the watcher() goroutine has finished.
// Otherwise, data race will be possible. [Race Example] in dns_resolver_test we
// replace the real lookup functions with mocked ones to facilitate testing.
// If Close() doesn't wait for watcher() goroutine finishes, race detector sometimes
// will warns lookup (READ the lookup function pointers) inside watcher() goroutine
// has data race with replaceNetFunc (WRITE the lookup function pointers).
wg sync.WaitGroup
}
// ResolveNow invoke an immediate resolution of the target that this dnsResolver watches.
func (d *dnsResolver) ResolveNow(opt resolver.ResolveNowOption) {
select {
case d.rn <- struct{}{}:
default:
}
}
// Close closes the dnsResolver.
func (d *dnsResolver) Close() {
d.cancel()
d.wg.Wait()
d.t.Stop()
}
func (d *dnsResolver) watcher() {
defer d.wg.Done()
for {
select {
case <-d.ctx.Done():
return
case <-d.t.C:
case <-d.rn:
}
result, sc := d.lookup()
// Next lookup should happen after an interval defined by d.freq.
d.t.Reset(d.freq)
d.cc.NewServiceConfig(string(sc))
d.cc.NewAddress(result)
}
}
func (d *dnsResolver) lookupSRV() []resolver.Address {
var newAddrs []resolver.Address
_, srvs, err := lookupSRV(d.ctx, "grpclb", "tcp", d.host)
if err != nil {
grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
return nil
}
for _, s := range srvs {
lbAddrs, err := lookupHost(d.ctx, s.Target)
if err != nil {
grpclog.Warningf("grpc: failed load banlacer address dns lookup due to %v.\n", err)
continue
}
for _, a := range lbAddrs {
a, ok := formatIP(a)
if !ok {
grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
continue
}
addr := a + ":" + strconv.Itoa(int(s.Port))
newAddrs = append(newAddrs, resolver.Address{Addr: addr, Type: resolver.GRPCLB, ServerName: s.Target})
}
}
return newAddrs
}
func (d *dnsResolver) lookupTXT() string {
ss, err := lookupTXT(d.ctx, d.host)
if err != nil {
grpclog.Warningf("grpc: failed dns TXT record lookup due to %v.\n", err)
return ""
}
var res string
for _, s := range ss {
res += s
}
// TXT record must have "grpc_config=" attribute in order to be used as service config.
if !strings.HasPrefix(res, txtAttribute) {
grpclog.Warningf("grpc: TXT record %v missing %v attribute", res, txtAttribute)
return ""
}
return strings.TrimPrefix(res, txtAttribute)
}
func (d *dnsResolver) lookupHost() []resolver.Address {
var newAddrs []resolver.Address
addrs, err := lookupHost(d.ctx, d.host)
if err != nil {
grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
return nil
}
for _, a := range addrs {
a, ok := formatIP(a)
if !ok {
grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
continue
}
addr := a + ":" + d.port
newAddrs = append(newAddrs, resolver.Address{Addr: addr})
}
return newAddrs
}
func (d *dnsResolver) lookup() ([]resolver.Address, string) {
var newAddrs []resolver.Address
newAddrs = d.lookupSRV()
// Support fallback to non-balancer address.
newAddrs = append(newAddrs, d.lookupHost()...)
sc := d.lookupTXT()
return newAddrs, canaryingSC(sc)
}
// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
// If addr is an IPv4 address, return the addr and ok = true.
// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
func formatIP(addr string) (addrIP string, ok bool) {
ip := net.ParseIP(addr)
if ip == nil {
return "", false
}
if ip.To4() != nil {
return addr, true
}
return "[" + addr + "]", true
}
// parseTarget takes the user input target string, returns formatted host and port info.
// If target doesn't specify a port, set the port to be the defaultPort.
// If target is in IPv6 format and host-name is enclosed in sqarue brackets, brackets
// are strippd when setting the host.
// examples:
// target: "www.google.com" returns host: "www.google.com", port: "443"
// target: "ipv4-host:80" returns host: "ipv4-host", port: "80"
// target: "[ipv6-host]" returns host: "ipv6-host", port: "443"
// target: ":80" returns host: "localhost", port: "80"
// target: ":" returns host: "localhost", port: "443"
func parseTarget(target string) (host, port string, err error) {
if target == "" {
return "", "", errMissingAddr
}
if ip := net.ParseIP(target); ip != nil {
// target is an IPv4 or IPv6(without brackets) address
return target, defaultPort, nil
}
if host, port, err = net.SplitHostPort(target); err == nil {
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
if host == "" {
// Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
host = "localhost"
}
if port == "" {
// If the port field is empty(target ends with colon), e.g. "[::1]:", defaultPort is used.
port = defaultPort
}
return host, port, nil
}
if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
// target doesn't have port
return host, port, nil
}
return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
}
type rawChoice struct {
ClientLanguage *[]string `json:"clientLanguage,omitempty"`
Percentage *int `json:"percentage,omitempty"`
ClientHostName *[]string `json:"clientHostName,omitempty"`
ServiceConfig *json.RawMessage `json:"serviceConfig,omitempty"`
}
func containsString(a *[]string, b string) bool {
if a == nil {
return true
}
for _, c := range *a {
if c == b {
return true
}
}
return false
}
func chosenByPercentage(a *int) bool {
if a == nil {
return true
}
s := rand.NewSource(time.Now().UnixNano())
r := rand.New(s)
if r.Intn(100)+1 > *a {
return false
}
return true
}
func canaryingSC(js string) string {
if js == "" {
return ""
}
var rcs []rawChoice
err := json.Unmarshal([]byte(js), &rcs)
if err != nil {
grpclog.Warningf("grpc: failed to parse service config json string due to %v.\n", err)
return ""
}
cliHostname, err := os.Hostname()
if err != nil {
grpclog.Warningf("grpc: failed to get client hostname due to %v.\n", err)
return ""
}
var sc string
for _, c := range rcs {
if !containsString(c.ClientLanguage, golang) ||
!chosenByPercentage(c.Percentage) ||
!containsString(c.ClientHostName, cliHostname) ||
c.ServiceConfig == nil {
continue
}
sc = string(*c.ServiceConfig)
break
}
return sc
}

35
vendor/google.golang.org/grpc/resolver/dns/go17.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
// +build go1.6, !go1.8
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dns
import (
"net"
"golang.org/x/net/context"
)
var (
lookupHost = func(ctx context.Context, host string) ([]string, error) { return net.LookupHost(host) }
lookupSRV = func(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) {
return net.LookupSRV(service, proto, name)
}
lookupTXT = func(ctx context.Context, name string) ([]string, error) { return net.LookupTXT(name) }
)

29
vendor/google.golang.org/grpc/resolver/dns/go18.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// +build go1.8
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dns
import "net"
var (
lookupHost = net.DefaultResolver.LookupHost
lookupSRV = net.DefaultResolver.LookupSRV
lookupTXT = net.DefaultResolver.LookupTXT
)

View File

@ -0,0 +1,57 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package passthrough implements a pass-through resolver. It sends the target
// name without scheme back to gRPC as resolved address.
package passthrough
import "google.golang.org/grpc/resolver"
const scheme = "passthrough"
type passthroughBuilder struct{}
func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
r := &passthroughResolver{
target: target,
cc: cc,
}
r.start()
return r, nil
}
func (*passthroughBuilder) Scheme() string {
return scheme
}
type passthroughResolver struct {
target resolver.Target
cc resolver.ClientConn
}
func (r *passthroughResolver) start() {
r.cc.NewAddress([]resolver.Address{{Addr: r.target.Endpoint}})
}
func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOption) {}
func (*passthroughResolver) Close() {}
func init() {
resolver.Register(&passthroughBuilder{})
}

View File

@ -24,7 +24,7 @@ var (
// m is a map from scheme to resolver builder. // m is a map from scheme to resolver builder.
m = make(map[string]Builder) m = make(map[string]Builder)
// defaultScheme is the default scheme to use. // defaultScheme is the default scheme to use.
defaultScheme string defaultScheme = "passthrough"
) )
// TODO(bar) install dns resolver in init(){}. // TODO(bar) install dns resolver in init(){}.
@ -36,30 +36,26 @@ func Register(b Builder) {
} }
// Get returns the resolver builder registered with the given scheme. // Get returns the resolver builder registered with the given scheme.
// If no builder is register with the scheme, the default scheme will //
// be used. // If no builder is register with the scheme, nil will be returned.
// If the default scheme is not modified, "dns" will be the default
// scheme, and the preinstalled dns resolver will be used.
// If the default scheme is modified, and a resolver is registered with
// the scheme, that resolver will be returned.
// If the default scheme is modified, and no resolver is registered with
// the scheme, nil will be returned.
func Get(scheme string) Builder { func Get(scheme string) Builder {
if b, ok := m[scheme]; ok { if b, ok := m[scheme]; ok {
return b return b
} }
if b, ok := m[defaultScheme]; ok {
return b
}
return nil return nil
} }
// SetDefaultScheme sets the default scheme that will be used. // SetDefaultScheme sets the default scheme that will be used.
// The default default scheme is "dns". // The default default scheme is "passthrough".
func SetDefaultScheme(scheme string) { func SetDefaultScheme(scheme string) {
defaultScheme = scheme defaultScheme = scheme
} }
// GetDefaultScheme gets the default scheme that will be used.
func GetDefaultScheme() string {
return defaultScheme
}
// AddressType indicates the address type returned by name resolution. // AddressType indicates the address type returned by name resolution.
type AddressType uint8 type AddressType uint8
@ -78,7 +74,9 @@ type Address struct {
// Type is the type of this address. // Type is the type of this address.
Type AddressType Type AddressType
// ServerName is the name of this address. // ServerName is the name of this address.
// It's the name of the grpc load balancer, which will be used for authentication. //
// e.g. if Type is GRPCLB, ServerName should be the name of the remote load
// balancer, not the name of the backend.
ServerName string ServerName string
// Metadata is the information associated with Addr, which may be used // Metadata is the information associated with Addr, which may be used
// to make load balancing decision. // to make load balancing decision.
@ -92,6 +90,11 @@ type BuildOption struct {
// ClientConn contains the callbacks for resolver to notify any updates // ClientConn contains the callbacks for resolver to notify any updates
// to the gRPC ClientConn. // to the gRPC ClientConn.
//
// This interface is to be implemented by gRPC. Users should not need a
// brand new implementation of this interface. For the situations like
// testing, the new implementation should embed this interface. This allows
// gRPC to add new methods to this interface.
type ClientConn interface { type ClientConn interface {
// NewAddress is called by resolver to notify ClientConn a new list // NewAddress is called by resolver to notify ClientConn a new list
// of resolved addresses. // of resolved addresses.
@ -128,8 +131,10 @@ type ResolveNowOption struct{}
// Resolver watches for the updates on the specified target. // Resolver watches for the updates on the specified target.
// Updates include address updates and service config updates. // Updates include address updates and service config updates.
type Resolver interface { type Resolver interface {
// ResolveNow will be called by gRPC to try to resolve the target name again. // ResolveNow will be called by gRPC to try to resolve the target name
// It's just a hint, resolver can ignore this if it's not necessary. // again. It's just a hint, resolver can ignore this if it's not necessary.
//
// It could be called multiple times concurrently.
ResolveNow(ResolveNowOption) ResolveNow(ResolveNowOption)
// Close closes the resolver. // Close closes the resolver.
Close() Close()

View File

@ -19,6 +19,7 @@
package grpc package grpc
import ( import (
"fmt"
"strings" "strings"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
@ -36,20 +37,27 @@ type ccResolverWrapper struct {
} }
// split2 returns the values from strings.SplitN(s, sep, 2). // split2 returns the values from strings.SplitN(s, sep, 2).
// If sep is not found, it returns "", s instead. // If sep is not found, it returns ("", s, false) instead.
func split2(s, sep string) (string, string) { func split2(s, sep string) (string, string, bool) {
spl := strings.SplitN(s, sep, 2) spl := strings.SplitN(s, sep, 2)
if len(spl) < 2 { if len(spl) < 2 {
return "", s return "", "", false
} }
return spl[0], spl[1] return spl[0], spl[1], true
} }
// parseTarget splits target into a struct containing scheme, authority and // parseTarget splits target into a struct containing scheme, authority and
// endpoint. // endpoint.
//
// If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
// target}.
func parseTarget(target string) (ret resolver.Target) { func parseTarget(target string) (ret resolver.Target) {
ret.Scheme, ret.Endpoint = split2(target, "://") var ok bool
ret.Authority, ret.Endpoint = split2(ret.Endpoint, "/") ret.Scheme, ret.Endpoint, ok = split2(target, "://")
if !ok {
return resolver.Target{Endpoint: target}
}
ret.Authority, ret.Endpoint, _ = split2(ret.Endpoint, "/")
return ret return ret
} }
@ -57,18 +65,12 @@ func parseTarget(target string) (ret resolver.Target) {
// builder for this scheme. It then builds the resolver and starts the // builder for this scheme. It then builds the resolver and starts the
// monitoring goroutine for it. // monitoring goroutine for it.
// //
// This function could return nil, nil, in tests for old behaviors. // If withResolverBuilder dial option is set, the specified resolver will be
// TODO(bar) never return nil, nil when DNS becomes the default resolver. // used instead.
func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) { func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) {
target := parseTarget(cc.target) rb := cc.dopts.resolverBuilder
grpclog.Infof("dialing to target with scheme: %q", target.Scheme)
rb := resolver.Get(target.Scheme)
if rb == nil { if rb == nil {
// TODO(bar) return error when DNS becomes the default (implemented and return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme)
// registered by DNS package).
grpclog.Infof("could not get resolver for scheme: %q", target.Scheme)
return nil, nil
} }
ccr := &ccResolverWrapper{ ccr := &ccResolverWrapper{
@ -79,14 +81,17 @@ func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) {
} }
var err error var err error
ccr.resolver, err = rb.Build(target, ccr, resolver.BuildOption{}) ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, resolver.BuildOption{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
go ccr.watcher()
return ccr, nil return ccr, nil
} }
func (ccr *ccResolverWrapper) start() {
go ccr.watcher()
}
// watcher processes address updates and service config updates sequencially. // watcher processes address updates and service config updates sequencially.
// Otherwise, we need to resolve possible races between address and service // Otherwise, we need to resolve possible races between address and service
// config (e.g. they specify different balancer types). // config (e.g. they specify different balancer types).
@ -100,20 +105,31 @@ func (ccr *ccResolverWrapper) watcher() {
select { select {
case addrs := <-ccr.addrCh: case addrs := <-ccr.addrCh:
grpclog.Infof("ccResolverWrapper: sending new addresses to balancer wrapper: %v", addrs) select {
// TODO(bar switching) this should never be nil. Pickfirst should be default. case <-ccr.done:
if ccr.cc.balancerWrapper != nil { return
// TODO(bar switching) create balancer if it's nil? default:
ccr.cc.balancerWrapper.handleResolvedAddrs(addrs, nil)
} }
grpclog.Infof("ccResolverWrapper: sending new addresses to cc: %v", addrs)
ccr.cc.handleResolvedAddrs(addrs, nil)
case sc := <-ccr.scCh: case sc := <-ccr.scCh:
select {
case <-ccr.done:
return
default:
}
grpclog.Infof("ccResolverWrapper: got new service config: %v", sc) grpclog.Infof("ccResolverWrapper: got new service config: %v", sc)
ccr.cc.handleServiceConfig(sc)
case <-ccr.done: case <-ccr.done:
return return
} }
} }
} }
func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOption) {
ccr.resolver.ResolveNow(o)
}
func (ccr *ccResolverWrapper) close() { func (ccr *ccResolverWrapper) close() {
ccr.resolver.Close() ccr.resolver.Close()
close(ccr.done) close(ccr.done)

View File

@ -21,18 +21,19 @@ package grpc
import ( import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
stdctx "context"
"encoding/binary" "encoding/binary"
"io" "io"
"io/ioutil" "io/ioutil"
"math" "math"
"os" "strings"
"sync" "sync"
"time" "time"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/encoding/proto"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer" "google.golang.org/grpc/peer"
"google.golang.org/grpc/stats" "google.golang.org/grpc/stats"
@ -124,14 +125,15 @@ func (d *gzipDecompressor) Type() string {
// callInfo contains all related configuration and information about an RPC. // callInfo contains all related configuration and information about an RPC.
type callInfo struct { type callInfo struct {
compressorType string
failFast bool failFast bool
headerMD metadata.MD stream *transport.Stream
trailerMD metadata.MD
peer *peer.Peer
traceInfo traceInfo // in trace.go traceInfo traceInfo // in trace.go
maxReceiveMessageSize *int maxReceiveMessageSize *int
maxSendMessageSize *int maxSendMessageSize *int
creds credentials.PerRPCCredentials creds credentials.PerRPCCredentials
contentSubtype string
codec baseCodec
} }
func defaultCallInfo() *callInfo { func defaultCallInfo() *callInfo {
@ -172,7 +174,9 @@ func (o afterCall) after(c *callInfo) { o(c) }
// for a unary RPC. // for a unary RPC.
func Header(md *metadata.MD) CallOption { func Header(md *metadata.MD) CallOption {
return afterCall(func(c *callInfo) { return afterCall(func(c *callInfo) {
*md = c.headerMD if c.stream != nil {
*md, _ = c.stream.Header()
}
}) })
} }
@ -180,27 +184,34 @@ func Header(md *metadata.MD) CallOption {
// for a unary RPC. // for a unary RPC.
func Trailer(md *metadata.MD) CallOption { func Trailer(md *metadata.MD) CallOption {
return afterCall(func(c *callInfo) { return afterCall(func(c *callInfo) {
*md = c.trailerMD if c.stream != nil {
*md = c.stream.Trailer()
}
}) })
} }
// Peer returns a CallOption that retrieves peer information for a // Peer returns a CallOption that retrieves peer information for a
// unary RPC. // unary RPC.
func Peer(peer *peer.Peer) CallOption { func Peer(p *peer.Peer) CallOption {
return afterCall(func(c *callInfo) { return afterCall(func(c *callInfo) {
if c.peer != nil { if c.stream != nil {
*peer = *c.peer if x, ok := peer.FromContext(c.stream.Context()); ok {
*p = *x
}
} }
}) })
} }
// FailFast configures the action to take when an RPC is attempted on broken // FailFast configures the action to take when an RPC is attempted on broken
// connections or unreachable servers. If failfast is true, the RPC will fail // connections or unreachable servers. If failFast is true, the RPC will fail
// immediately. Otherwise, the RPC client will block the call until a // immediately. Otherwise, the RPC client will block the call until a
// connection is available (or the call is canceled or times out) and will retry // connection is available (or the call is canceled or times out) and will
// the call if it fails due to a transient error. Please refer to // retry the call if it fails due to a transient error. gRPC will not retry if
// data was written to the wire unless the server indicates it did not process
// the data. Please refer to
// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. // https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
// Note: failFast is default to true. //
// By default, RPCs are "Fail Fast".
func FailFast(failFast bool) CallOption { func FailFast(failFast bool) CallOption {
return beforeCall(func(c *callInfo) error { return beforeCall(func(c *callInfo) error {
c.failFast = failFast c.failFast = failFast
@ -233,6 +244,61 @@ func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption {
}) })
} }
// UseCompressor returns a CallOption which sets the compressor used when
// sending the request. If WithCompressor is also set, UseCompressor has
// higher priority.
//
// This API is EXPERIMENTAL.
func UseCompressor(name string) CallOption {
return beforeCall(func(c *callInfo) error {
c.compressorType = name
return nil
})
}
// CallContentSubtype returns a CallOption that will set the content-subtype
// for a call. For example, if content-subtype is "json", the Content-Type over
// the wire will be "application/grpc+json". The content-subtype is converted
// to lowercase before being included in Content-Type. See Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details.
//
// If CallCustomCodec is not also used, the content-subtype will be used to
// look up the Codec to use in the registry controlled by RegisterCodec. See
// the documention on RegisterCodec for details on registration. The lookup
// of content-subtype is case-insensitive. If no such Codec is found, the call
// will result in an error with code codes.Internal.
//
// If CallCustomCodec is also used, that Codec will be used for all request and
// response messages, with the content-subtype set to the given contentSubtype
// here for requests.
func CallContentSubtype(contentSubtype string) CallOption {
contentSubtype = strings.ToLower(contentSubtype)
return beforeCall(func(c *callInfo) error {
c.contentSubtype = contentSubtype
return nil
})
}
// CallCustomCodec returns a CallOption that will set the given Codec to be
// used for all request and response messages for a call. The result of calling
// String() will be used as the content-subtype in a case-insensitive manner.
//
// See Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details. Also see the documentation on RegisterCodec and
// CallContentSubtype for more details on the interaction between Codec and
// content-subtype.
//
// This function is provided for advanced users; prefer to use only
// CallContentSubtype to select a registered codec instead.
func CallCustomCodec(codec Codec) CallOption {
return beforeCall(func(c *callInfo) error {
c.codec = codec
return nil
})
}
// The format of the payload: compressed or not? // The format of the payload: compressed or not?
type payloadFormat uint8 type payloadFormat uint8
@ -248,8 +314,8 @@ type parser struct {
// error types. // error types.
r io.Reader r io.Reader
// The header of a gRPC message. Find more detail // The header of a gRPC message. Find more detail at
// at https://grpc.io/docs/guides/wire.html. // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
header [5]byte header [5]byte
} }
@ -277,8 +343,11 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
if length == 0 { if length == 0 {
return pf, nil, nil return pf, nil, nil
} }
if length > uint32(maxReceiveMessageSize) { if int64(length) > int64(maxInt) {
return 0, nil, Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize) return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt)
}
if int(length) > maxReceiveMessageSize {
return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize)
} }
// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead
// of making it for each message: // of making it for each message:
@ -294,18 +363,21 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
// encode serializes msg and returns a buffer of message header and a buffer of msg. // encode serializes msg and returns a buffer of message header and a buffer of msg.
// If msg is nil, it generates the message header and an empty msg buffer. // If msg is nil, it generates the message header and an empty msg buffer.
func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayload *stats.OutPayload) ([]byte, []byte, error) { // TODO(ddyihai): eliminate extra Compressor parameter.
var b []byte func encode(c baseCodec, msg interface{}, cp Compressor, outPayload *stats.OutPayload, compressor encoding.Compressor) ([]byte, []byte, error) {
var (
b []byte
cbuf *bytes.Buffer
)
const ( const (
payloadLen = 1 payloadLen = 1
sizeLen = 4 sizeLen = 4
) )
if msg != nil { if msg != nil {
var err error var err error
b, err = c.Marshal(msg) b, err = c.Marshal(msg)
if err != nil { if err != nil {
return nil, nil, Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) return nil, nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
} }
if outPayload != nil { if outPayload != nil {
outPayload.Payload = msg outPayload.Payload = msg
@ -313,24 +385,35 @@ func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayl
outPayload.Data = b outPayload.Data = b
outPayload.Length = len(b) outPayload.Length = len(b)
} }
if cp != nil { if compressor != nil || cp != nil {
if err := cp.Do(cbuf, b); err != nil { cbuf = new(bytes.Buffer)
return nil, nil, Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error()) // Has compressor, check Compressor is set by UseCompressor first.
if compressor != nil {
z, _ := compressor.Compress(cbuf)
if _, err := z.Write(b); err != nil {
return nil, nil, status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error())
}
z.Close()
} else {
// If Compressor is not set by UseCompressor, use default Compressor
if err := cp.Do(cbuf, b); err != nil {
return nil, nil, status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error())
}
} }
b = cbuf.Bytes() b = cbuf.Bytes()
} }
} }
if uint(len(b)) > math.MaxUint32 { if uint(len(b)) > math.MaxUint32 {
return nil, nil, Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b)) return nil, nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b))
} }
bufHeader := make([]byte, payloadLen+sizeLen) bufHeader := make([]byte, payloadLen+sizeLen)
if cp == nil { if compressor != nil || cp != nil {
bufHeader[0] = byte(compressionNone)
} else {
bufHeader[0] = byte(compressionMade) bufHeader[0] = byte(compressionMade)
} else {
bufHeader[0] = byte(compressionNone)
} }
// Write length of b into buf // Write length of b into buf
binary.BigEndian.PutUint32(bufHeader[payloadLen:], uint32(len(b))) binary.BigEndian.PutUint32(bufHeader[payloadLen:], uint32(len(b)))
if outPayload != nil { if outPayload != nil {
@ -339,20 +422,26 @@ func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayl
return bufHeader, b, nil return bufHeader, b, nil
} }
func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) error { func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool) *status.Status {
switch pf { switch pf {
case compressionNone: case compressionNone:
case compressionMade: case compressionMade:
if dc == nil || recvCompress != dc.Type() { if recvCompress == "" || recvCompress == encoding.Identity {
return Errorf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding")
}
if !haveCompressor {
return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress)
} }
default: default:
return Errorf(codes.Internal, "grpc: received unexpected payload format %d", pf) return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf)
} }
return nil return nil
} }
func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, inPayload *stats.InPayload) error { // For the two compressor parameters, both should not be set, but if they are,
// dc takes precedence over compressor.
// TODO(dfawley): wrap the old compressor/decompressor using the new API?
func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, inPayload *stats.InPayload, compressor encoding.Compressor) error {
pf, d, err := p.recvMsg(maxReceiveMessageSize) pf, d, err := p.recvMsg(maxReceiveMessageSize)
if err != nil { if err != nil {
return err return err
@ -360,22 +449,37 @@ func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{
if inPayload != nil { if inPayload != nil {
inPayload.WireLength = len(d) inPayload.WireLength = len(d)
} }
if err := checkRecvPayload(pf, s.RecvCompress(), dc); err != nil {
return err if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil {
return st.Err()
} }
if pf == compressionMade { if pf == compressionMade {
d, err = dc.Do(bytes.NewReader(d)) // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor,
if err != nil { // use this decompressor as the default.
return Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) if dc != nil {
d, err = dc.Do(bytes.NewReader(d))
if err != nil {
return status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
}
} else {
dcReader, err := compressor.Decompress(bytes.NewReader(d))
if err != nil {
return status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
}
d, err = ioutil.ReadAll(dcReader)
if err != nil {
return status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
}
} }
} }
if len(d) > maxReceiveMessageSize { if len(d) > maxReceiveMessageSize {
// TODO: Revisit the error code. Currently keep it consistent with java // TODO: Revisit the error code. Currently keep it consistent with java
// implementation. // implementation.
return Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(d), maxReceiveMessageSize) return status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(d), maxReceiveMessageSize)
} }
if err := c.Unmarshal(d, m); err != nil { if err := c.Unmarshal(d, m); err != nil {
return 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 inPayload != nil { if inPayload != nil {
inPayload.RecvTime = time.Now() inPayload.RecvTime = time.Now()
@ -388,9 +492,7 @@ func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{
} }
type rpcInfo struct { type rpcInfo struct {
failfast bool failfast bool
bytesSent bool
bytesReceived bool
} }
type rpcInfoContextKey struct{} type rpcInfoContextKey struct{}
@ -404,69 +506,10 @@ func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) {
return return
} }
func updateRPCInfoInContext(ctx context.Context, s rpcInfo) {
if ss, ok := rpcInfoFromContext(ctx); ok {
ss.bytesReceived = s.bytesReceived
ss.bytesSent = s.bytesSent
}
return
}
// toRPCErr converts an error into an error from the status package.
func toRPCErr(err error) error {
if _, ok := status.FromError(err); ok {
return err
}
switch e := err.(type) {
case transport.StreamError:
return status.Error(e.Code, e.Desc)
case transport.ConnectionError:
return status.Error(codes.Unavailable, e.Desc)
default:
switch err {
case context.DeadlineExceeded, stdctx.DeadlineExceeded:
return status.Error(codes.DeadlineExceeded, err.Error())
case context.Canceled, stdctx.Canceled:
return status.Error(codes.Canceled, err.Error())
case ErrClientConnClosing:
return status.Error(codes.FailedPrecondition, err.Error())
}
}
return status.Error(codes.Unknown, err.Error())
}
// convertCode converts a standard Go error into its canonical code. Note that
// this is only used to translate the error returned by the server applications.
func convertCode(err error) codes.Code {
switch err {
case nil:
return codes.OK
case io.EOF:
return codes.OutOfRange
case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
return codes.FailedPrecondition
case os.ErrInvalid:
return codes.InvalidArgument
case context.Canceled, stdctx.Canceled:
return codes.Canceled
case context.DeadlineExceeded, stdctx.DeadlineExceeded:
return codes.DeadlineExceeded
}
switch {
case os.IsExist(err):
return codes.AlreadyExists
case os.IsNotExist(err):
return codes.NotFound
case os.IsPermission(err):
return codes.PermissionDenied
}
return codes.Unknown
}
// Code returns the error code for err if it was produced by the rpc system. // Code returns the error code for err if it was produced by the rpc system.
// Otherwise, it returns codes.Unknown. // Otherwise, it returns codes.Unknown.
// //
// Deprecated; use status.FromError and Code method instead. // Deprecated: use status.FromError and Code method instead.
func Code(err error) codes.Code { func Code(err error) codes.Code {
if s, ok := status.FromError(err); ok { if s, ok := status.FromError(err); ok {
return s.Code() return s.Code()
@ -477,7 +520,7 @@ func Code(err error) codes.Code {
// ErrorDesc returns the error description of err if it was produced by the rpc system. // ErrorDesc returns the error description of err if it was produced by the rpc system.
// Otherwise, it returns err.Error() or empty string when err is nil. // Otherwise, it returns err.Error() or empty string when err is nil.
// //
// Deprecated; use status.FromError and Message method instead. // Deprecated: use status.FromError and Message method instead.
func ErrorDesc(err error) string { func ErrorDesc(err error) string {
if s, ok := status.FromError(err); ok { if s, ok := status.FromError(err); ok {
return s.Message() return s.Message()
@ -488,85 +531,47 @@ func ErrorDesc(err error) string {
// Errorf returns an error containing an error code and a description; // Errorf returns an error containing an error code and a description;
// Errorf returns nil if c is OK. // Errorf returns nil if c is OK.
// //
// Deprecated; use status.Errorf instead. // Deprecated: use status.Errorf instead.
func Errorf(c codes.Code, format string, a ...interface{}) error { func Errorf(c codes.Code, format string, a ...interface{}) error {
return status.Errorf(c, format, a...) return status.Errorf(c, format, a...)
} }
// MethodConfig defines the configuration recommended by the service providers for a // setCallInfoCodec should only be called after CallOptions have been applied.
// particular method. func setCallInfoCodec(c *callInfo) error {
// This is EXPERIMENTAL and subject to change. if c.codec != nil {
type MethodConfig struct { // codec was already set by a CallOption; use it.
// WaitForReady indicates whether RPCs sent to this method should wait until return nil
// the connection is ready by default (!failfast). The value specified via the }
// gRPC client API will override the value set here.
WaitForReady *bool if c.contentSubtype == "" {
// Timeout is the default timeout for RPCs sent to this method. The actual // No codec specified in CallOptions; use proto by default.
// deadline used will be the minimum of the value specified here and the value c.codec = encoding.GetCodec(proto.Name)
// set by the application via the gRPC client API. If either one is not set, return nil
// then the other will be used. If neither is set, then the RPC has no deadline. }
Timeout *time.Duration
// MaxReqSize is the maximum allowed payload size for an individual request in a // c.contentSubtype is already lowercased in CallContentSubtype
// stream (client->server) in bytes. The size which is measured is the serialized c.codec = encoding.GetCodec(c.contentSubtype)
// payload after per-message compression (but before stream compression) in bytes. if c.codec == nil {
// The actual value used is the minimum of the value specified here and the value set return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype)
// by the application via the gRPC client API. If either one is not set, then the other }
// will be used. If neither is set, then the built-in default is used. return nil
MaxReqSize *int
// MaxRespSize is the maximum allowed payload size for an individual response in a
// stream (server->client) in bytes.
MaxRespSize *int
} }
// ServiceConfig is provided by the service provider and contains parameters for how // The SupportPackageIsVersion variables are referenced from generated protocol
// clients that connect to the service should behave. // buffer files to ensure compatibility with the gRPC version used. The latest
// This is EXPERIMENTAL and subject to change. // support package version is 5.
type ServiceConfig struct {
// LB is the load balancer the service providers recommends. The balancer specified
// via grpc.WithBalancer will override this.
LB Balancer
// Methods contains a map for the methods in this service.
// If there is an exact match for a method (i.e. /service/method) in the map, use the corresponding MethodConfig.
// If there's no exact match, look for the default config for the service (/service/) and use the corresponding MethodConfig if it exists.
// Otherwise, the method has no MethodConfig to use.
Methods map[string]MethodConfig
}
func min(a, b *int) *int {
if *a < *b {
return a
}
return b
}
func getMaxSize(mcMax, doptMax *int, defaultVal int) *int {
if mcMax == nil && doptMax == nil {
return &defaultVal
}
if mcMax != nil && doptMax != nil {
return min(mcMax, doptMax)
}
if mcMax != nil {
return mcMax
}
return doptMax
}
// SupportPackageIsVersion3 is referenced from generated protocol buffer files.
// The latest support package version is 4.
// SupportPackageIsVersion3 is kept for compatibility. It will be removed in the
// next support package version update.
const SupportPackageIsVersion3 = true
// SupportPackageIsVersion4 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the grpc package.
// //
// This constant may be renamed in the future if a change in the generated code // Older versions are kept for compatibility. They may be removed if
// requires a synchronised update of grpc-go and protoc-gen-go. This constant // compatibility cannot be maintained.
// should not be referenced from any other code. //
const SupportPackageIsVersion4 = true // These constants should not be referenced from any other code.
const (
SupportPackageIsVersion3 = true
SupportPackageIsVersion4 = true
SupportPackageIsVersion5 = true
)
// Version is the current grpc version. // Version is the current grpc version.
const Version = "1.7.4" const Version = "1.10.1"
const grpcUA = "grpc-go/" + Version const grpcUA = "grpc-go/" + Version

View File

@ -32,11 +32,15 @@ import (
"sync" "sync"
"time" "time"
"io/ioutil"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/trace" "golang.org/x/net/trace"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/encoding/proto"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal" "google.golang.org/grpc/internal"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
@ -89,18 +93,20 @@ type Server struct {
conns map[io.Closer]bool conns map[io.Closer]bool
serve bool serve bool
drain bool drain bool
ctx context.Context cv *sync.Cond // signaled when connections close for GracefulStop
cancel context.CancelFunc
// A CondVar to let GracefulStop() blocks until all the pending RPCs are finished
// and all the transport goes away.
cv *sync.Cond
m map[string]*service // service name -> service info m map[string]*service // service name -> service info
events trace.EventLog events trace.EventLog
quit chan struct{}
done chan struct{}
quitOnce sync.Once
doneOnce sync.Once
serveWG sync.WaitGroup // counts active Serve goroutines for GracefulStop
} }
type options struct { type options struct {
creds credentials.TransportCredentials creds credentials.TransportCredentials
codec Codec codec baseCodec
cp Compressor cp Compressor
dc Decompressor dc Decompressor
unaryInt UnaryServerInterceptor unaryInt UnaryServerInterceptor
@ -177,20 +183,32 @@ func KeepaliveEnforcementPolicy(kep keepalive.EnforcementPolicy) ServerOption {
} }
// CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling. // CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling.
//
// This will override any lookups by content-subtype for Codecs registered with RegisterCodec.
func CustomCodec(codec Codec) ServerOption { func CustomCodec(codec Codec) ServerOption {
return func(o *options) { return func(o *options) {
o.codec = codec o.codec = codec
} }
} }
// RPCCompressor returns a ServerOption that sets a compressor for outbound messages. // RPCCompressor returns a ServerOption that sets a compressor for outbound
// messages. For backward compatibility, all outbound messages will be sent
// using this compressor, regardless of incoming message compression. By
// default, server messages will be sent using the same compressor with which
// request messages were sent.
//
// Deprecated: use encoding.RegisterCompressor instead.
func RPCCompressor(cp Compressor) ServerOption { func RPCCompressor(cp Compressor) ServerOption {
return func(o *options) { return func(o *options) {
o.cp = cp o.cp = cp
} }
} }
// RPCDecompressor returns a ServerOption that sets a decompressor for inbound messages. // RPCDecompressor returns a ServerOption that sets a decompressor for inbound
// messages. It has higher priority than decompressors registered via
// encoding.RegisterCompressor.
//
// Deprecated: use encoding.RegisterCompressor instead.
func RPCDecompressor(dc Decompressor) ServerOption { func RPCDecompressor(dc Decompressor) ServerOption {
return func(o *options) { return func(o *options) {
o.dc = dc o.dc = dc
@ -297,6 +315,8 @@ func UnknownServiceHandler(streamHandler StreamHandler) ServerOption {
// connection establishment (up to and including HTTP/2 handshaking) for all // connection establishment (up to and including HTTP/2 handshaking) for all
// new connections. If this is not set, the default is 120 seconds. A zero or // new connections. If this is not set, the default is 120 seconds. A zero or
// negative value will result in an immediate timeout. // negative value will result in an immediate timeout.
//
// This API is EXPERIMENTAL.
func ConnectionTimeout(d time.Duration) ServerOption { func ConnectionTimeout(d time.Duration) ServerOption {
return func(o *options) { return func(o *options) {
o.connectionTimeout = d o.connectionTimeout = d
@ -310,18 +330,15 @@ func NewServer(opt ...ServerOption) *Server {
for _, o := range opt { for _, o := range opt {
o(&opts) o(&opts)
} }
if opts.codec == nil {
// Set the default codec.
opts.codec = protoCodec{}
}
s := &Server{ s := &Server{
lis: make(map[net.Listener]bool), lis: make(map[net.Listener]bool),
opts: opts, opts: opts,
conns: make(map[io.Closer]bool), conns: make(map[io.Closer]bool),
m: make(map[string]*service), m: make(map[string]*service),
quit: make(chan struct{}),
done: make(chan struct{}),
} }
s.cv = sync.NewCond(&s.mu) s.cv = sync.NewCond(&s.mu)
s.ctx, s.cancel = context.WithCancel(context.Background())
if EnableTracing { if EnableTracing {
_, file, line, _ := runtime.Caller(1) _, file, line, _ := runtime.Caller(1)
s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line))
@ -430,11 +447,9 @@ func (s *Server) GetServiceInfo() map[string]ServiceInfo {
return ret return ret
} }
var ( // ErrServerStopped indicates that the operation is now illegal because of
// ErrServerStopped indicates that the operation is now illegal because of // the server being stopped.
// the server being stopped. var ErrServerStopped = errors.New("grpc: the server has been stopped")
ErrServerStopped = errors.New("grpc: the server has been stopped")
)
func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
if s.opts.creds == nil { if s.opts.creds == nil {
@ -448,16 +463,29 @@ func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credenti
// read gRPC requests and then call the registered handlers to reply to them. // read gRPC requests and then call the registered handlers to reply to them.
// Serve returns when lis.Accept fails with fatal errors. lis will be closed when // Serve returns when lis.Accept fails with fatal errors. lis will be closed when
// this method returns. // this method returns.
// Serve always returns non-nil error. // Serve will return a non-nil error unless Stop or GracefulStop is called.
func (s *Server) Serve(lis net.Listener) error { func (s *Server) Serve(lis net.Listener) error {
s.mu.Lock() s.mu.Lock()
s.printf("serving") s.printf("serving")
s.serve = true s.serve = true
if s.lis == nil { if s.lis == nil {
// Serve called after Stop or GracefulStop.
s.mu.Unlock() s.mu.Unlock()
lis.Close() lis.Close()
return ErrServerStopped return ErrServerStopped
} }
s.serveWG.Add(1)
defer func() {
s.serveWG.Done()
select {
// Stop or GracefulStop called; block until done and return nil.
case <-s.quit:
<-s.done
default:
}
}()
s.lis[lis] = true s.lis[lis] = true
s.mu.Unlock() s.mu.Unlock()
defer func() { defer func() {
@ -491,25 +519,39 @@ func (s *Server) Serve(lis net.Listener) error {
timer := time.NewTimer(tempDelay) timer := time.NewTimer(tempDelay)
select { select {
case <-timer.C: case <-timer.C:
case <-s.ctx.Done(): case <-s.quit:
timer.Stop()
return nil
} }
timer.Stop()
continue continue
} }
s.mu.Lock() s.mu.Lock()
s.printf("done serving; Accept = %v", err) s.printf("done serving; Accept = %v", err)
s.mu.Unlock() s.mu.Unlock()
select {
case <-s.quit:
return nil
default:
}
return err return err
} }
tempDelay = 0 tempDelay = 0
// Start a new goroutine to deal with rawConn // Start a new goroutine to deal with rawConn so we don't stall this Accept
// so we don't stall this Accept loop goroutine. // loop goroutine.
go s.handleRawConn(rawConn) //
// Make sure we account for the goroutine so GracefulStop doesn't nil out
// s.conns before this conn can be added.
s.serveWG.Add(1)
go func() {
s.handleRawConn(rawConn)
s.serveWG.Done()
}()
} }
} }
// handleRawConn is run in its own goroutine and handles a just-accepted // handleRawConn forks a goroutine to handle a just-accepted connection that
// connection that has not had any I/O performed on it yet. // has not had any I/O performed on it yet.
func (s *Server) handleRawConn(rawConn net.Conn) { func (s *Server) handleRawConn(rawConn net.Conn) {
rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout)) rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout))
conn, authInfo, err := s.useTransportAuthenticator(rawConn) conn, authInfo, err := s.useTransportAuthenticator(rawConn)
@ -534,17 +576,28 @@ func (s *Server) handleRawConn(rawConn net.Conn) {
} }
s.mu.Unlock() s.mu.Unlock()
var serve func()
c := conn.(io.Closer)
if s.opts.useHandlerImpl { if s.opts.useHandlerImpl {
rawConn.SetDeadline(time.Time{}) serve = func() { s.serveUsingHandler(conn) }
s.serveUsingHandler(conn)
} else { } else {
// Finish handshaking (HTTP2)
st := s.newHTTP2Transport(conn, authInfo) st := s.newHTTP2Transport(conn, authInfo)
if st == nil { if st == nil {
return return
} }
rawConn.SetDeadline(time.Time{}) c = st
s.serveStreams(st) serve = func() { s.serveStreams(st) }
} }
rawConn.SetDeadline(time.Time{})
if !s.addConn(c) {
return
}
go func() {
serve()
s.removeConn(c)
}()
} }
// newHTTP2Transport sets up a http/2 transport (using the // newHTTP2Transport sets up a http/2 transport (using the
@ -571,15 +624,10 @@ func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) tr
grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err) grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err)
return nil return nil
} }
if !s.addConn(st) {
st.Close()
return nil
}
return st return st
} }
func (s *Server) serveStreams(st transport.ServerTransport) { func (s *Server) serveStreams(st transport.ServerTransport) {
defer s.removeConn(st)
defer st.Close() defer st.Close()
var wg sync.WaitGroup var wg sync.WaitGroup
st.HandleStreams(func(stream *transport.Stream) { st.HandleStreams(func(stream *transport.Stream) {
@ -613,11 +661,6 @@ var _ http.Handler = (*Server)(nil)
// //
// conn is the *tls.Conn that's already been authenticated. // conn is the *tls.Conn that's already been authenticated.
func (s *Server) serveUsingHandler(conn net.Conn) { func (s *Server) serveUsingHandler(conn net.Conn) {
if !s.addConn(conn) {
conn.Close()
return
}
defer s.removeConn(conn)
h2s := &http2.Server{ h2s := &http2.Server{
MaxConcurrentStreams: s.opts.maxConcurrentStreams, MaxConcurrentStreams: s.opts.maxConcurrentStreams,
} }
@ -651,13 +694,12 @@ func (s *Server) serveUsingHandler(conn net.Conn) {
// available through grpc-go's HTTP/2 server, and it is currently EXPERIMENTAL // available through grpc-go's HTTP/2 server, and it is currently EXPERIMENTAL
// and subject to change. // and subject to change.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
st, err := transport.NewServerHandlerTransport(w, r) st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandler)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
if !s.addConn(st) { if !s.addConn(st) {
st.Close()
return return
} }
defer s.removeConn(st) defer s.removeConn(st)
@ -687,9 +729,15 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea
func (s *Server) addConn(c io.Closer) bool { func (s *Server) addConn(c io.Closer) bool {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
if s.conns == nil || s.drain { if s.conns == nil {
c.Close()
return false return false
} }
if s.drain {
// Transport added after we drained our existing conns: drain it
// immediately.
c.(transport.ServerTransport).Drain()
}
s.conns[c] = true s.conns[c] = true
return true return true
} }
@ -703,18 +751,14 @@ func (s *Server) removeConn(c io.Closer) {
} }
} }
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options) error { func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
var ( var (
cbuf *bytes.Buffer
outPayload *stats.OutPayload outPayload *stats.OutPayload
) )
if cp != nil {
cbuf = new(bytes.Buffer)
}
if s.opts.statsHandler != nil { if s.opts.statsHandler != nil {
outPayload = &stats.OutPayload{} outPayload = &stats.OutPayload{}
} }
hdr, data, err := encode(s.opts.codec, msg, cp, cbuf, outPayload) hdr, data, err := encode(s.getCodec(stream.ContentSubtype()), msg, cp, outPayload, comp)
if err != nil { if err != nil {
grpclog.Errorln("grpc: server failed to encode response: ", err) grpclog.Errorln("grpc: server failed to encode response: ", err)
return err return err
@ -758,10 +802,43 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
} }
}() }()
} }
if s.opts.cp != nil {
// NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. // comp and cp are used for compression. decomp and dc are used for
stream.SetSendCompress(s.opts.cp.Type()) // decompression. If comp and decomp are both set, they are the same;
// however they are kept separate to ensure that at most one of the
// compressor/decompressor variable pairs are set for use later.
var comp, decomp encoding.Compressor
var cp Compressor
var dc Decompressor
// If dc is set and matches the stream's compression, use it. Otherwise, try
// to find a matching registered compressor for decomp.
if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
dc = s.opts.dc
} else if rc != "" && rc != encoding.Identity {
decomp = encoding.GetCompressor(rc)
if decomp == nil {
st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
t.WriteStatus(stream, st)
return st.Err()
}
} }
// If cp is set, use it. Otherwise, attempt to compress the response using
// the incoming message compression method.
//
// NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
if s.opts.cp != nil {
cp = s.opts.cp
stream.SetSendCompress(cp.Type())
} else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
// Legacy compressor not specified; attempt to respond with same encoding.
comp = encoding.GetCompressor(rc)
if comp != nil {
stream.SetSendCompress(rc)
}
}
p := &parser{r: stream} p := &parser{r: stream}
pf, req, err := p.recvMsg(s.opts.maxReceiveMessageSize) pf, req, err := p.recvMsg(s.opts.maxReceiveMessageSize)
if err == io.EOF { if err == io.EOF {
@ -769,7 +846,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
return err return err
} }
if err == io.ErrUnexpectedEOF { if err == io.ErrUnexpectedEOF {
err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) err = status.Errorf(codes.Internal, io.ErrUnexpectedEOF.Error())
} }
if err != nil { if err != nil {
if st, ok := status.FromError(err); ok { if st, ok := status.FromError(err); ok {
@ -790,19 +867,11 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
} }
return err return err
} }
if st := checkRecvPayload(pf, stream.RecvCompress(), dc != nil || decomp != nil); st != nil {
if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { if e := t.WriteStatus(stream, st); e != nil {
if st, ok := status.FromError(err); ok {
if e := t.WriteStatus(stream, st); e != nil {
grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
}
return err
}
if e := t.WriteStatus(stream, status.New(codes.Internal, err.Error())); e != nil {
grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e) grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
} }
return st.Err()
// TODO checkRecvPayload always return RPC error. Add a return here if necessary.
} }
var inPayload *stats.InPayload var inPayload *stats.InPayload
if sh != nil { if sh != nil {
@ -816,9 +885,17 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
} }
if pf == compressionMade { if pf == compressionMade {
var err error var err error
req, err = s.opts.dc.Do(bytes.NewReader(req)) if dc != nil {
if err != nil { req, err = dc.Do(bytes.NewReader(req))
return Errorf(codes.Internal, err.Error()) if err != nil {
return status.Errorf(codes.Internal, err.Error())
}
} else {
tmp, _ := decomp.Decompress(bytes.NewReader(req))
req, err = ioutil.ReadAll(tmp)
if err != nil {
return status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
}
} }
} }
if len(req) > s.opts.maxReceiveMessageSize { if len(req) > s.opts.maxReceiveMessageSize {
@ -826,7 +903,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
// java implementation. // java implementation.
return status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(req), s.opts.maxReceiveMessageSize) return status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(req), s.opts.maxReceiveMessageSize)
} }
if err := s.opts.codec.Unmarshal(req, v); err != nil { if err := s.getCodec(stream.ContentSubtype()).Unmarshal(req, v); err != nil {
return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err) return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err)
} }
if inPayload != nil { if inPayload != nil {
@ -864,7 +941,8 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
Last: true, Last: true,
Delay: false, Delay: false,
} }
if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil {
if err := s.sendResponse(t, stream, reply, cp, opts, comp); err != nil {
if err == io.EOF { if err == io.EOF {
// The entire stream is done (for unary RPC only). // The entire stream is done (for unary RPC only).
return err return err
@ -913,21 +991,45 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
sh.HandleRPC(stream.Context(), end) sh.HandleRPC(stream.Context(), end)
}() }()
} }
if s.opts.cp != nil {
stream.SetSendCompress(s.opts.cp.Type())
}
ss := &serverStream{ ss := &serverStream{
t: t, t: t,
s: stream, s: stream,
p: &parser{r: stream}, p: &parser{r: stream},
codec: s.opts.codec, codec: s.getCodec(stream.ContentSubtype()),
cp: s.opts.cp,
dc: s.opts.dc,
maxReceiveMessageSize: s.opts.maxReceiveMessageSize, maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
maxSendMessageSize: s.opts.maxSendMessageSize, maxSendMessageSize: s.opts.maxSendMessageSize,
trInfo: trInfo, trInfo: trInfo,
statsHandler: sh, statsHandler: sh,
} }
// If dc is set and matches the stream's compression, use it. Otherwise, try
// to find a matching registered compressor for decomp.
if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
ss.dc = s.opts.dc
} else if rc != "" && rc != encoding.Identity {
ss.decomp = encoding.GetCompressor(rc)
if ss.decomp == nil {
st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
t.WriteStatus(ss.s, st)
return st.Err()
}
}
// If cp is set, use it. Otherwise, attempt to compress the response using
// the incoming message compression method.
//
// NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
if s.opts.cp != nil {
ss.cp = s.opts.cp
stream.SetSendCompress(s.opts.cp.Type())
} else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
// Legacy compressor not specified; attempt to respond with same encoding.
ss.comp = encoding.GetCompressor(rc)
if ss.comp != nil {
stream.SetSendCompress(rc)
}
}
if trInfo != nil { if trInfo != nil {
trInfo.tr.LazyLog(&trInfo.firstLine, false) trInfo.tr.LazyLog(&trInfo.firstLine, false)
defer func() { defer func() {
@ -1071,6 +1173,17 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str
// pending RPCs on the client side will get notified by connection // pending RPCs on the client side will get notified by connection
// errors. // errors.
func (s *Server) Stop() { func (s *Server) Stop() {
s.quitOnce.Do(func() {
close(s.quit)
})
defer func() {
s.serveWG.Wait()
s.doneOnce.Do(func() {
close(s.done)
})
}()
s.mu.Lock() s.mu.Lock()
listeners := s.lis listeners := s.lis
s.lis = nil s.lis = nil
@ -1088,7 +1201,6 @@ func (s *Server) Stop() {
} }
s.mu.Lock() s.mu.Lock()
s.cancel()
if s.events != nil { if s.events != nil {
s.events.Finish() s.events.Finish()
s.events = nil s.events = nil
@ -1100,22 +1212,38 @@ func (s *Server) Stop() {
// accepting new connections and RPCs and blocks until all the pending RPCs are // accepting new connections and RPCs and blocks until all the pending RPCs are
// finished. // finished.
func (s *Server) GracefulStop() { func (s *Server) GracefulStop() {
s.quitOnce.Do(func() {
close(s.quit)
})
defer func() {
s.doneOnce.Do(func() {
close(s.done)
})
}()
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock()
if s.conns == nil { if s.conns == nil {
s.mu.Unlock()
return return
} }
for lis := range s.lis { for lis := range s.lis {
lis.Close() lis.Close()
} }
s.lis = nil s.lis = nil
s.cancel()
if !s.drain { if !s.drain {
for c := range s.conns { for c := range s.conns {
c.(transport.ServerTransport).Drain() c.(transport.ServerTransport).Drain()
} }
s.drain = true s.drain = true
} }
// Wait for serving threads to be ready to exit. Only then can we be sure no
// new conns will be created.
s.mu.Unlock()
s.serveWG.Wait()
s.mu.Lock()
for len(s.conns) != 0 { for len(s.conns) != 0 {
s.cv.Wait() s.cv.Wait()
} }
@ -1124,26 +1252,29 @@ func (s *Server) GracefulStop() {
s.events.Finish() s.events.Finish()
s.events = nil s.events = nil
} }
s.mu.Unlock()
} }
func init() { func init() {
internal.TestingCloseConns = func(arg interface{}) {
arg.(*Server).testingCloseConns()
}
internal.TestingUseHandlerImpl = func(arg interface{}) { internal.TestingUseHandlerImpl = func(arg interface{}) {
arg.(*Server).opts.useHandlerImpl = true arg.(*Server).opts.useHandlerImpl = true
} }
} }
// testingCloseConns closes all existing transports but keeps s.lis // contentSubtype must be lowercase
// accepting new connections. // cannot return nil
func (s *Server) testingCloseConns() { func (s *Server) getCodec(contentSubtype string) baseCodec {
s.mu.Lock() if s.opts.codec != nil {
for c := range s.conns { return s.opts.codec
c.Close()
delete(s.conns, c)
} }
s.mu.Unlock() if contentSubtype == "" {
return encoding.GetCodec(proto.Name)
}
codec := encoding.GetCodec(contentSubtype)
if codec == nil {
return encoding.GetCodec(proto.Name)
}
return codec
} }
// SetHeader sets the header metadata. // SetHeader sets the header metadata.
@ -1158,7 +1289,7 @@ func SetHeader(ctx context.Context, md metadata.MD) error {
} }
stream, ok := transport.StreamFromContext(ctx) stream, ok := transport.StreamFromContext(ctx)
if !ok { if !ok {
return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
} }
return stream.SetHeader(md) return stream.SetHeader(md)
} }
@ -1168,7 +1299,7 @@ func SetHeader(ctx context.Context, md metadata.MD) error {
func SendHeader(ctx context.Context, md metadata.MD) error { func SendHeader(ctx context.Context, md metadata.MD) error {
stream, ok := transport.StreamFromContext(ctx) stream, ok := transport.StreamFromContext(ctx)
if !ok { if !ok {
return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
} }
t := stream.ServerTransport() t := stream.ServerTransport()
if t == nil { if t == nil {
@ -1188,7 +1319,7 @@ func SetTrailer(ctx context.Context, md metadata.MD) error {
} }
stream, ok := transport.StreamFromContext(ctx) stream, ok := transport.StreamFromContext(ctx)
if !ok { if !ok {
return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
} }
return stream.SetTrailer(md) return stream.SetTrailer(md)
} }

226
vendor/google.golang.org/grpc/service_config.go generated vendored Normal file
View File

@ -0,0 +1,226 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package grpc
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"google.golang.org/grpc/grpclog"
)
const maxInt = int(^uint(0) >> 1)
// MethodConfig defines the configuration recommended by the service providers for a
// particular method.
// DEPRECATED: Users should not use this struct. Service config should be received
// through name resolver, as specified here
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
type MethodConfig struct {
// WaitForReady indicates whether RPCs sent to this method should wait until
// the connection is ready by default (!failfast). The value specified via the
// gRPC client API will override the value set here.
WaitForReady *bool
// Timeout is the default timeout for RPCs sent to this method. The actual
// deadline used will be the minimum of the value specified here and the value
// set by the application via the gRPC client API. If either one is not set,
// then the other will be used. If neither is set, then the RPC has no deadline.
Timeout *time.Duration
// MaxReqSize is the maximum allowed payload size for an individual request in a
// stream (client->server) in bytes. The size which is measured is the serialized
// payload after per-message compression (but before stream compression) in bytes.
// The actual value used is the minimum of the value specified here and the value set
// by the application via the gRPC client API. If either one is not set, then the other
// will be used. If neither is set, then the built-in default is used.
MaxReqSize *int
// MaxRespSize is the maximum allowed payload size for an individual response in a
// stream (server->client) in bytes.
MaxRespSize *int
}
// ServiceConfig is provided by the service provider and contains parameters for how
// clients that connect to the service should behave.
// DEPRECATED: Users should not use this struct. Service config should be received
// through name resolver, as specified here
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
type ServiceConfig struct {
// LB is the load balancer the service providers recommends. The balancer specified
// via grpc.WithBalancer will override this.
LB *string
// Methods contains a map for the methods in this service.
// If there is an exact match for a method (i.e. /service/method) in the map, use the corresponding MethodConfig.
// If there's no exact match, look for the default config for the service (/service/) and use the corresponding MethodConfig if it exists.
// Otherwise, the method has no MethodConfig to use.
Methods map[string]MethodConfig
}
func parseDuration(s *string) (*time.Duration, error) {
if s == nil {
return nil, nil
}
if !strings.HasSuffix(*s, "s") {
return nil, fmt.Errorf("malformed duration %q", *s)
}
ss := strings.SplitN((*s)[:len(*s)-1], ".", 3)
if len(ss) > 2 {
return nil, fmt.Errorf("malformed duration %q", *s)
}
// hasDigits is set if either the whole or fractional part of the number is
// present, since both are optional but one is required.
hasDigits := false
var d time.Duration
if len(ss[0]) > 0 {
i, err := strconv.ParseInt(ss[0], 10, 32)
if err != nil {
return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
}
d = time.Duration(i) * time.Second
hasDigits = true
}
if len(ss) == 2 && len(ss[1]) > 0 {
if len(ss[1]) > 9 {
return nil, fmt.Errorf("malformed duration %q", *s)
}
f, err := strconv.ParseInt(ss[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
}
for i := 9; i > len(ss[1]); i-- {
f *= 10
}
d += time.Duration(f)
hasDigits = true
}
if !hasDigits {
return nil, fmt.Errorf("malformed duration %q", *s)
}
return &d, nil
}
type jsonName struct {
Service *string
Method *string
}
func (j jsonName) generatePath() (string, bool) {
if j.Service == nil {
return "", false
}
res := "/" + *j.Service + "/"
if j.Method != nil {
res += *j.Method
}
return res, true
}
// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
type jsonMC struct {
Name *[]jsonName
WaitForReady *bool
Timeout *string
MaxRequestMessageBytes *int64
MaxResponseMessageBytes *int64
}
// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
type jsonSC struct {
LoadBalancingPolicy *string
MethodConfig *[]jsonMC
}
func parseServiceConfig(js string) (ServiceConfig, error) {
var rsc jsonSC
err := json.Unmarshal([]byte(js), &rsc)
if err != nil {
grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
return ServiceConfig{}, err
}
sc := ServiceConfig{
LB: rsc.LoadBalancingPolicy,
Methods: make(map[string]MethodConfig),
}
if rsc.MethodConfig == nil {
return sc, nil
}
for _, m := range *rsc.MethodConfig {
if m.Name == nil {
continue
}
d, err := parseDuration(m.Timeout)
if err != nil {
grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
return ServiceConfig{}, err
}
mc := MethodConfig{
WaitForReady: m.WaitForReady,
Timeout: d,
}
if m.MaxRequestMessageBytes != nil {
if *m.MaxRequestMessageBytes > int64(maxInt) {
mc.MaxReqSize = newInt(maxInt)
} else {
mc.MaxReqSize = newInt(int(*m.MaxRequestMessageBytes))
}
}
if m.MaxResponseMessageBytes != nil {
if *m.MaxResponseMessageBytes > int64(maxInt) {
mc.MaxRespSize = newInt(maxInt)
} else {
mc.MaxRespSize = newInt(int(*m.MaxResponseMessageBytes))
}
}
for _, n := range *m.Name {
if path, valid := n.generatePath(); valid {
sc.Methods[path] = mc
}
}
}
return sc, nil
}
func min(a, b *int) *int {
if *a < *b {
return a
}
return b
}
func getMaxSize(mcMax, doptMax *int, defaultVal int) *int {
if mcMax == nil && doptMax == nil {
return &defaultVal
}
if mcMax != nil && doptMax != nil {
return min(mcMax, doptMax)
}
if mcMax != nil {
return mcMax
}
return doptMax
}
func newInt(b int) *int {
return &b
}

View File

@ -120,15 +120,23 @@ func FromProto(s *spb.Status) *Status {
} }
// FromError returns a Status representing err if it was produced from this // FromError returns a Status representing err if it was produced from this
// package, otherwise it returns nil, false. // package. Otherwise, ok is false and a Status is returned with codes.Unknown
// and the original error message.
func FromError(err error) (s *Status, ok bool) { func FromError(err error) (s *Status, ok bool) {
if err == nil { if err == nil {
return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
} }
if s, ok := err.(*statusError); ok { if se, ok := err.(*statusError); ok {
return s.status(), true return se.status(), true
} }
return nil, false return New(codes.Unknown, err.Error()), false
}
// Convert is a convenience function which removes the need to handle the
// boolean return value from FromError.
func Convert(err error) *Status {
s, _ := FromError(err)
return s
} }
// WithDetails returns a new status with the provided details messages appended to the status. // WithDetails returns a new status with the provided details messages appended to the status.
@ -166,3 +174,16 @@ func (s *Status) Details() []interface{} {
} }
return details return details
} }
// Code returns the Code of the error if it is a Status error, codes.OK if err
// is nil, or codes.Unknown otherwise.
func Code(err error) codes.Code {
// Don't use FromError to avoid allocation of OK status.
if err == nil {
return codes.OK
}
if se, ok := err.(*statusError); ok {
return se.status().Code()
}
return codes.Unknown
}

View File

@ -19,7 +19,6 @@
package grpc package grpc
import ( import (
"bytes"
"errors" "errors"
"io" "io"
"sync" "sync"
@ -29,8 +28,8 @@ import (
"golang.org/x/net/trace" "golang.org/x/net/trace"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
"google.golang.org/grpc/stats" "google.golang.org/grpc/stats"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/grpc/transport" "google.golang.org/grpc/transport"
@ -51,6 +50,8 @@ type StreamDesc struct {
} }
// Stream defines the common interface a client or server stream has to satisfy. // Stream defines the common interface a client or server stream has to satisfy.
//
// All errors returned from Stream are compatible with the status package.
type Stream interface { type Stream interface {
// Context returns the context for this stream. // Context returns the context for this stream.
Context() context.Context Context() context.Context
@ -89,41 +90,52 @@ type ClientStream interface {
// Stream.SendMsg() may return a non-nil error when something wrong happens sending // Stream.SendMsg() may return a non-nil error when something wrong happens sending
// the request. The returned error indicates the status of this sending, not the final // the request. The returned error indicates the status of this sending, not the final
// status of the RPC. // status of the RPC.
// Always call Stream.RecvMsg() to get the final status if you care about the status of //
// the RPC. // Always call Stream.RecvMsg() to drain the stream and get the final
// status, otherwise there could be leaked resources.
Stream Stream
} }
// NewClientStream creates a new Stream for the client side. This is called // NewStream creates a new Stream for the client side. This is typically
// by generated code. // called by generated code.
func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
if cc.dopts.streamInt != nil { if cc.dopts.streamInt != nil {
return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...) return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...)
} }
return newClientStream(ctx, desc, cc, method, opts...) return newClientStream(ctx, desc, cc, method, opts...)
} }
// NewClientStream creates a new Stream for the client side. This is typically
// called by generated code.
//
// DEPRECATED: Use ClientConn.NewStream instead.
func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
return cc.NewStream(ctx, desc, method, opts...)
}
func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) {
var (
t transport.ClientTransport
s *transport.Stream
done func(balancer.DoneInfo)
cancel context.CancelFunc
)
c := defaultCallInfo() c := defaultCallInfo()
mc := cc.GetMethodConfig(method) mc := cc.GetMethodConfig(method)
if mc.WaitForReady != nil { if mc.WaitForReady != nil {
c.failFast = !*mc.WaitForReady c.failFast = !*mc.WaitForReady
} }
if mc.Timeout != nil { // Possible context leak:
// The cancel function for the child context we create will only be called
// when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
// an error is generated by SendMsg.
// https://github.com/grpc/grpc-go/issues/1818.
var cancel context.CancelFunc
if mc.Timeout != nil && *mc.Timeout >= 0 {
ctx, cancel = context.WithTimeout(ctx, *mc.Timeout) ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)
defer func() { } else {
if err != nil { ctx, cancel = context.WithCancel(ctx)
cancel()
}
}()
} }
defer func() {
if err != nil {
cancel()
}
}()
opts = append(cc.dopts.callOptions, opts...) opts = append(cc.dopts.callOptions, opts...)
for _, o := range opts { for _, o := range opts {
@ -133,6 +145,9 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
} }
c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize) c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize)
c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize) c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
if err := setCallInfoCodec(c); err != nil {
return nil, err
}
callHdr := &transport.CallHdr{ callHdr := &transport.CallHdr{
Host: cc.authority, Host: cc.authority,
@ -141,10 +156,27 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
// so we don't flush the header. // so we don't flush the header.
// If it's client streaming, the user may never send a request or send it any // If it's client streaming, the user may never send a request or send it any
// time soon, so we ask the transport to flush the header. // time soon, so we ask the transport to flush the header.
Flush: desc.ClientStreams, Flush: desc.ClientStreams,
ContentSubtype: c.contentSubtype,
} }
if cc.dopts.cp != nil {
// Set our outgoing compression according to the UseCompressor CallOption, if
// set. In that case, also find the compressor from the encoding package.
// Otherwise, use the compressor configured by the WithCompressor DialOption,
// if set.
var cp Compressor
var comp encoding.Compressor
if ct := c.compressorType; ct != "" {
callHdr.SendCompress = ct
if ct != encoding.Identity {
comp = encoding.GetCompressor(ct)
if comp == nil {
return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
}
}
} else if cc.dopts.cp != nil {
callHdr.SendCompress = cc.dopts.cp.Type() callHdr.SendCompress = cc.dopts.cp.Type()
cp = cc.dopts.cp
} }
if c.creds != nil { if c.creds != nil {
callHdr.Creds = c.creds callHdr.Creds = c.creds
@ -189,53 +221,53 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
} }
}() }()
} }
var (
t transport.ClientTransport
s *transport.Stream
done func(balancer.DoneInfo)
)
for { for {
// Check to make sure the context has expired. This will prevent us from
// looping forever if an error occurs for wait-for-ready RPCs where no data
// is sent on the wire.
select {
case <-ctx.Done():
return nil, toRPCErr(ctx.Err())
default:
}
t, done, err = cc.getTransport(ctx, c.failFast) t, done, err = cc.getTransport(ctx, c.failFast)
if err != nil { if err != nil {
// TODO(zhaoq): Probably revisit the error handling. return nil, err
if _, ok := status.FromError(err); ok {
return nil, err
}
if err == errConnClosing || err == errConnUnavailable {
if c.failFast {
return nil, Errorf(codes.Unavailable, "%v", err)
}
continue
}
// All the other errors are treated as Internal errors.
return nil, Errorf(codes.Internal, "%v", err)
} }
s, err = t.NewStream(ctx, callHdr) s, err = t.NewStream(ctx, callHdr)
if err != nil { if err != nil {
if _, ok := err.(transport.ConnectionError); ok && done != nil {
// If error is connection error, transport was sending data on wire,
// and we are not sure if anything has been sent on wire.
// If error is not connection error, we are sure nothing has been sent.
updateRPCInfoInContext(ctx, rpcInfo{bytesSent: true, bytesReceived: false})
}
if done != nil { if done != nil {
done(balancer.DoneInfo{Err: err}) done(balancer.DoneInfo{Err: err})
done = nil done = nil
} }
if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast { // In the event of any error from NewStream, we never attempted to write
// anything to the wire, so we can retry indefinitely for non-fail-fast
// RPCs.
if !c.failFast {
continue continue
} }
return nil, toRPCErr(err) return nil, toRPCErr(err)
} }
break break
} }
// Set callInfo.peer object from stream's context.
if peer, ok := peer.FromContext(s.Context()); ok { c.stream = s
c.peer = peer
}
cs := &clientStream{ cs := &clientStream{
opts: opts, opts: opts,
c: c, c: c,
desc: desc, desc: desc,
codec: cc.dopts.codec, codec: c.codec,
cp: cc.dopts.cp, cp: cp,
dc: cc.dopts.dc, dc: cc.dopts.dc,
comp: comp,
cancel: cancel, cancel: cancel,
done: done, done: done,
@ -249,50 +281,49 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
statsCtx: ctx, statsCtx: ctx,
statsHandler: cc.dopts.copts.StatsHandler, statsHandler: cc.dopts.copts.StatsHandler,
} }
// Listen on ctx.Done() to detect cancellation and s.Done() to detect normal termination if desc != unaryStreamDesc {
// when there is no pending I/O operations on this stream. // Listen on cc and stream contexts to cleanup when the user closes the
go func() { // ClientConn or cancels the stream context. In all other cases, an error
select { // should already be injected into the recv buffer by the transport, which
case <-t.Error(): // the client will eventually receive, and then we will cancel the stream's
// Incur transport error, simply exit. // context in clientStream.finish.
case <-cc.ctx.Done(): go func() {
cs.finish(ErrClientConnClosing) select {
cs.closeTransportStream(ErrClientConnClosing) case <-cc.ctx.Done():
case <-s.Done(): cs.finish(ErrClientConnClosing)
// TODO: The trace of the RPC is terminated here when there is no pending case <-ctx.Done():
// I/O, which is probably not the optimal solution. cs.finish(toRPCErr(s.Context().Err()))
cs.finish(s.Status().Err()) }
cs.closeTransportStream(nil) }()
case <-s.GoAway(): }
cs.finish(errConnDrain)
cs.closeTransportStream(errConnDrain)
case <-s.Context().Done():
err := s.Context().Err()
cs.finish(err)
cs.closeTransportStream(transport.ContextErr(err))
}
}()
return cs, nil return cs, nil
} }
// clientStream implements a client side Stream. // clientStream implements a client side Stream.
type clientStream struct { type clientStream struct {
opts []CallOption opts []CallOption
c *callInfo c *callInfo
t transport.ClientTransport t transport.ClientTransport
s *transport.Stream s *transport.Stream
p *parser p *parser
desc *StreamDesc desc *StreamDesc
codec Codec
cp Compressor codec baseCodec
dc Decompressor cp Compressor
dc Decompressor
comp encoding.Compressor
decomp encoding.Compressor
decompSet bool
// cancel is only called when RecvMsg() returns non-nil error, which means
// the stream finishes with error or with io.EOF.
cancel context.CancelFunc cancel context.CancelFunc
tracing bool // set to EnableTracing when the clientStream is created. tracing bool // set to EnableTracing when the clientStream is created.
mu sync.Mutex mu sync.Mutex
done func(balancer.DoneInfo) done func(balancer.DoneInfo)
closed bool sentLast bool // sent an end stream
finished bool finished bool
// trInfo.tr is set when the clientStream is created (if EnableTracing is true), // trInfo.tr is set when the clientStream is created (if EnableTracing is true),
// and is set to nil when the clientStream's finish method is called. // and is set to nil when the clientStream's finish method is called.
@ -312,9 +343,8 @@ func (cs *clientStream) Context() context.Context {
func (cs *clientStream) Header() (metadata.MD, error) { func (cs *clientStream) Header() (metadata.MD, error) {
m, err := cs.s.Header() m, err := cs.s.Header()
if err != nil { if err != nil {
if _, ok := err.(transport.ConnectionError); !ok { err = toRPCErr(err)
cs.closeTransportStream(err) cs.finish(err)
}
} }
return m, err return m, err
} }
@ -324,6 +354,7 @@ func (cs *clientStream) Trailer() metadata.MD {
} }
func (cs *clientStream) SendMsg(m interface{}) (err error) { func (cs *clientStream) SendMsg(m interface{}) (err error) {
// TODO: Check cs.sentLast and error if we already ended the stream.
if cs.tracing { if cs.tracing {
cs.mu.Lock() cs.mu.Lock()
if cs.trInfo.tr != nil { if cs.trInfo.tr != nil {
@ -334,26 +365,18 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
// TODO Investigate how to signal the stats handling party. // TODO Investigate how to signal the stats handling party.
// generate error stats if err != nil && err != io.EOF? // generate error stats if err != nil && err != io.EOF?
defer func() { defer func() {
if err != nil { // For non-client-streaming RPCs, we return nil instead of EOF on success
// because the generated code requires it. finish is not called; RecvMsg()
// will call it with the stream's status independently.
if err == io.EOF && !cs.desc.ClientStreams {
err = nil
}
if err != nil && err != io.EOF {
// Call finish for errors generated by this SendMsg call. (Transport
// errors are converted to an io.EOF error below; the real error will be
// returned from RecvMsg eventually in that case.)
cs.finish(err) cs.finish(err)
} }
if err == nil {
return
}
if err == io.EOF {
// Specialize the process for server streaming. SendMsg is only called
// once when creating the stream object. io.EOF needs to be skipped when
// the rpc is early finished (before the stream object is created.).
// TODO: It is probably better to move this into the generated code.
if !cs.desc.ClientStreams && cs.desc.ServerStreams {
err = nil
}
return
}
if _, ok := err.(transport.ConnectionError); !ok {
cs.closeTransportStream(err)
}
err = toRPCErr(err)
}() }()
var outPayload *stats.OutPayload var outPayload *stats.OutPayload
if cs.statsHandler != nil { if cs.statsHandler != nil {
@ -361,154 +384,143 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
Client: true, Client: true,
} }
} }
hdr, data, err := encode(cs.codec, m, cs.cp, bytes.NewBuffer([]byte{}), outPayload) hdr, data, err := encode(cs.codec, m, cs.cp, outPayload, cs.comp)
if err != nil { if err != nil {
return err return err
} }
if cs.c.maxSendMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)")
}
if len(data) > *cs.c.maxSendMessageSize { if len(data) > *cs.c.maxSendMessageSize {
return Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), *cs.c.maxSendMessageSize) return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), *cs.c.maxSendMessageSize)
} }
err = cs.t.Write(cs.s, hdr, data, &transport.Options{Last: false}) if !cs.desc.ClientStreams {
if err == nil && outPayload != nil { cs.sentLast = true
outPayload.SentTime = time.Now()
cs.statsHandler.HandleRPC(cs.statsCtx, outPayload)
} }
return err err = cs.t.Write(cs.s, hdr, data, &transport.Options{Last: !cs.desc.ClientStreams})
if err == nil {
if outPayload != nil {
outPayload.SentTime = time.Now()
cs.statsHandler.HandleRPC(cs.statsCtx, outPayload)
}
return nil
}
return io.EOF
} }
func (cs *clientStream) RecvMsg(m interface{}) (err error) { func (cs *clientStream) RecvMsg(m interface{}) (err error) {
defer func() {
if err != nil || !cs.desc.ServerStreams {
// err != nil or non-server-streaming indicates end of stream.
cs.finish(err)
}
}()
var inPayload *stats.InPayload var inPayload *stats.InPayload
if cs.statsHandler != nil { if cs.statsHandler != nil {
inPayload = &stats.InPayload{ inPayload = &stats.InPayload{
Client: true, Client: true,
} }
} }
if cs.c.maxReceiveMessageSize == nil { if !cs.decompSet {
return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)") // Block until we receive headers containing received message encoding.
if ct := cs.s.RecvCompress(); ct != "" && ct != encoding.Identity {
if cs.dc == nil || cs.dc.Type() != ct {
// No configured decompressor, or it does not match the incoming
// message encoding; attempt to find a registered compressor that does.
cs.dc = nil
cs.decomp = encoding.GetCompressor(ct)
}
} else {
// No compression is used; disable our decompressor.
cs.dc = nil
}
// Only initialize this state once per stream.
cs.decompSet = true
} }
err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, inPayload) err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, inPayload, cs.decomp)
defer func() { if err != nil {
// err != nil indicates the termination of the stream.
if err != nil {
cs.finish(err)
}
}()
if err == nil {
if cs.tracing {
cs.mu.Lock()
if cs.trInfo.tr != nil {
cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
}
cs.mu.Unlock()
}
if inPayload != nil {
cs.statsHandler.HandleRPC(cs.statsCtx, inPayload)
}
if !cs.desc.ClientStreams || cs.desc.ServerStreams {
return
}
// Special handling for client streaming rpc.
// This recv expects EOF or errors, so we don't collect inPayload.
if cs.c.maxReceiveMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)")
}
err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, nil)
cs.closeTransportStream(err)
if err == nil {
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
}
if err == io.EOF { if err == io.EOF {
if se := cs.s.Status().Err(); se != nil { if statusErr := cs.s.Status().Err(); statusErr != nil {
return se return statusErr
} }
cs.finish(err) return io.EOF // indicates successful end of stream.
return nil
} }
return toRPCErr(err) return toRPCErr(err)
} }
if _, ok := err.(transport.ConnectionError); !ok { if cs.tracing {
cs.closeTransportStream(err) cs.mu.Lock()
if cs.trInfo.tr != nil {
cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
}
cs.mu.Unlock()
}
if inPayload != nil {
cs.statsHandler.HandleRPC(cs.statsCtx, inPayload)
}
if cs.desc.ServerStreams {
// Subsequent messages should be received by subsequent RecvMsg calls.
return nil
}
// Special handling for non-server-stream rpcs.
// This recv expects EOF or errors, so we don't collect inPayload.
err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, nil, cs.decomp)
if err == nil {
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
} }
if err == io.EOF { if err == io.EOF {
if statusErr := cs.s.Status().Err(); statusErr != nil { return cs.s.Status().Err() // non-server streaming Recv returns nil on success
return statusErr
}
// Returns io.EOF to indicate the end of the stream.
return
} }
return toRPCErr(err) return toRPCErr(err)
} }
func (cs *clientStream) CloseSend() (err error) { func (cs *clientStream) CloseSend() error {
err = cs.t.Write(cs.s, nil, nil, &transport.Options{Last: true}) if cs.sentLast {
defer func() {
if err != nil {
cs.finish(err)
}
}()
if err == nil || err == io.EOF {
return nil return nil
} }
if _, ok := err.(transport.ConnectionError); !ok { cs.sentLast = true
cs.closeTransportStream(err) cs.t.Write(cs.s, nil, nil, &transport.Options{Last: true})
} // We ignore errors from Write and always return nil here. Any error it
err = toRPCErr(err) // would return would also be returned by a subsequent RecvMsg call, and the
return // user is supposed to always finish the stream by calling RecvMsg until it
} // returns err != nil.
return nil
func (cs *clientStream) closeTransportStream(err error) {
cs.mu.Lock()
if cs.closed {
cs.mu.Unlock()
return
}
cs.closed = true
cs.mu.Unlock()
cs.t.CloseStream(cs.s, err)
} }
func (cs *clientStream) finish(err error) { func (cs *clientStream) finish(err error) {
if err == io.EOF {
// Ending a stream with EOF indicates a success.
err = nil
}
cs.mu.Lock() cs.mu.Lock()
defer cs.mu.Unlock() defer cs.mu.Unlock()
if cs.finished { if cs.finished {
return return
} }
cs.finished = true cs.finished = true
defer func() { cs.t.CloseStream(cs.s, err)
if cs.cancel != nil {
cs.cancel()
}
}()
for _, o := range cs.opts { for _, o := range cs.opts {
o.after(cs.c) o.after(cs.c)
} }
if cs.done != nil { if cs.done != nil {
updateRPCInfoInContext(cs.s.Context(), rpcInfo{ cs.done(balancer.DoneInfo{
bytesSent: cs.s.BytesSent(), Err: err,
bytesReceived: cs.s.BytesReceived(), BytesSent: true,
BytesReceived: cs.s.BytesReceived(),
}) })
cs.done(balancer.DoneInfo{Err: err})
cs.done = nil cs.done = nil
} }
if cs.statsHandler != nil { if cs.statsHandler != nil {
end := &stats.End{ end := &stats.End{
Client: true, Client: true,
EndTime: time.Now(), EndTime: time.Now(),
} Error: err,
if err != io.EOF {
// end.Error is nil if the RPC finished successfully.
end.Error = toRPCErr(err)
} }
cs.statsHandler.HandleRPC(cs.statsCtx, end) cs.statsHandler.HandleRPC(cs.statsCtx, end)
} }
cs.cancel()
if !cs.tracing { if !cs.tracing {
return return
} }
if cs.trInfo.tr != nil { if cs.trInfo.tr != nil {
if err == nil || err == io.EOF { if err == nil {
cs.trInfo.tr.LazyPrintf("RPC: [OK]") cs.trInfo.tr.LazyPrintf("RPC: [OK]")
} else { } else {
cs.trInfo.tr.LazyPrintf("RPC: [%v]", err) cs.trInfo.tr.LazyPrintf("RPC: [%v]", err)
@ -540,12 +552,16 @@ type ServerStream interface {
// serverStream implements a server side Stream. // serverStream implements a server side Stream.
type serverStream struct { type serverStream struct {
t transport.ServerTransport t transport.ServerTransport
s *transport.Stream s *transport.Stream
p *parser p *parser
codec Codec codec baseCodec
cp Compressor
dc Decompressor cp Compressor
dc Decompressor
comp encoding.Compressor
decomp encoding.Compressor
maxReceiveMessageSize int maxReceiveMessageSize int
maxSendMessageSize int maxSendMessageSize int
trInfo *traceInfo trInfo *traceInfo
@ -601,12 +617,12 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
if ss.statsHandler != nil { if ss.statsHandler != nil {
outPayload = &stats.OutPayload{} outPayload = &stats.OutPayload{}
} }
hdr, data, err := encode(ss.codec, m, ss.cp, bytes.NewBuffer([]byte{}), outPayload) hdr, data, err := encode(ss.codec, m, ss.cp, outPayload, ss.comp)
if err != nil { if err != nil {
return err return err
} }
if len(data) > ss.maxSendMessageSize { if len(data) > ss.maxSendMessageSize {
return Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), ss.maxSendMessageSize) return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), ss.maxSendMessageSize)
} }
if err := ss.t.Write(ss.s, hdr, data, &transport.Options{Last: false}); err != nil { if err := ss.t.Write(ss.s, hdr, data, &transport.Options{Last: false}); err != nil {
return toRPCErr(err) return toRPCErr(err)
@ -641,12 +657,12 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
if ss.statsHandler != nil { if ss.statsHandler != nil {
inPayload = &stats.InPayload{} inPayload = &stats.InPayload{}
} }
if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, inPayload); err != nil { if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, inPayload, ss.decomp); err != nil {
if err == io.EOF { if err == io.EOF {
return err return err
} }
if err == io.ErrUnexpectedEOF { if err == io.ErrUnexpectedEOF {
err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) err = status.Errorf(codes.Internal, io.ErrUnexpectedEOF.Error())
} }
return toRPCErr(err) return toRPCErr(err)
} }
@ -655,3 +671,13 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
} }
return nil return nil
} }
// MethodFromServerStream returns the method string for the input stream.
// The returned string is in the format of "/service/method".
func MethodFromServerStream(stream ServerStream) (string, bool) {
s, ok := transport.StreamFromContext(stream.Context())
if !ok {
return "", ok
}
return s.Method(), ok
}

View File

@ -41,12 +41,9 @@ const (
gamma = 2 gamma = 2
) )
var ( // Adding arbitrary data to ping so that its ack can be identified.
// Adding arbitrary data to ping so that its ack can be // Easter-egg: what does the ping message say?
// identified. var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
// Easter-egg: what does the ping message say?
bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
)
type bdpEstimator struct { type bdpEstimator struct {
// sentAt is the time when the ping was sent. // sentAt is the time when the ping was sent.

View File

@ -20,9 +20,9 @@ package transport
import ( import (
"fmt" "fmt"
"io"
"math" "math"
"sync" "sync"
"sync/atomic"
"time" "time"
"golang.org/x/net/http2" "golang.org/x/net/http2"
@ -49,7 +49,7 @@ const (
// defaultLocalSendQuota sets is default value for number of data // defaultLocalSendQuota sets is default value for number of data
// bytes that each stream can schedule before some of it being // bytes that each stream can schedule before some of it being
// flushed out. // flushed out.
defaultLocalSendQuota = 64 * 1024 defaultLocalSendQuota = 128 * 1024
) )
// The following defines various control items which could flow through // The following defines various control items which could flow through
@ -89,12 +89,16 @@ type windowUpdate struct {
func (*windowUpdate) item() {} func (*windowUpdate) item() {}
type settings struct { type settings struct {
ack bool ss []http2.Setting
ss []http2.Setting
} }
func (*settings) item() {} func (*settings) item() {}
type settingsAck struct {
}
func (*settingsAck) item() {}
type resetStream struct { type resetStream struct {
streamID uint32 streamID uint32
code http2.ErrCode code http2.ErrCode
@ -112,6 +116,7 @@ type goAway struct {
func (*goAway) item() {} func (*goAway) item() {}
type flushIO struct { type flushIO struct {
closeTr bool
} }
func (*flushIO) item() {} func (*flushIO) item() {}
@ -126,9 +131,8 @@ func (*ping) item() {}
// quotaPool is a pool which accumulates the quota and sends it to acquire() // quotaPool is a pool which accumulates the quota and sends it to acquire()
// when it is available. // when it is available.
type quotaPool struct { type quotaPool struct {
c chan int
mu sync.Mutex mu sync.Mutex
c chan struct{}
version uint32 version uint32
quota int quota int
} }
@ -136,12 +140,8 @@ type quotaPool struct {
// newQuotaPool creates a quotaPool which has quota q available to consume. // newQuotaPool creates a quotaPool which has quota q available to consume.
func newQuotaPool(q int) *quotaPool { func newQuotaPool(q int) *quotaPool {
qb := &quotaPool{ qb := &quotaPool{
c: make(chan int, 1), quota: q,
} c: make(chan struct{}, 1),
if q > 0 {
qb.c <- q
} else {
qb.quota = q
} }
return qb return qb
} }
@ -155,60 +155,83 @@ func (qb *quotaPool) add(v int) {
} }
func (qb *quotaPool) lockedAdd(v int) { func (qb *quotaPool) lockedAdd(v int) {
select { var wakeUp bool
case n := <-qb.c: if qb.quota <= 0 {
qb.quota += n wakeUp = true // Wake up potential waiters.
default:
} }
qb.quota += v qb.quota += v
if qb.quota <= 0 { if wakeUp && qb.quota > 0 {
return select {
} case qb.c <- struct{}{}:
// After the pool has been created, this is the only place that sends on default:
// the channel. Since mu is held at this point and any quota that was sent }
// on the channel has been retrieved, we know that this code will always
// place any positive quota value on the channel.
select {
case qb.c <- qb.quota:
qb.quota = 0
default:
} }
} }
func (qb *quotaPool) addAndUpdate(v int) { func (qb *quotaPool) addAndUpdate(v int) {
qb.mu.Lock() qb.mu.Lock()
defer qb.mu.Unlock()
qb.lockedAdd(v) qb.lockedAdd(v)
// Update the version only after having added to the quota qb.version++
// so that if acquireWithVesrion sees the new vesrion it is qb.mu.Unlock()
// guaranteed to have seen the updated quota.
// Also, still keep this inside of the lock, so that when
// compareAndExecute is processing, this function doesn't
// get executed partially (quota gets updated but the version
// doesn't).
atomic.AddUint32(&(qb.version), 1)
} }
func (qb *quotaPool) acquireWithVersion() (<-chan int, uint32) { func (qb *quotaPool) get(v int, wc waiters) (int, uint32, error) {
return qb.c, atomic.LoadUint32(&(qb.version)) qb.mu.Lock()
if qb.quota > 0 {
if v > qb.quota {
v = qb.quota
}
qb.quota -= v
ver := qb.version
qb.mu.Unlock()
return v, ver, nil
}
qb.mu.Unlock()
for {
select {
case <-wc.ctx.Done():
return 0, 0, ContextErr(wc.ctx.Err())
case <-wc.tctx.Done():
return 0, 0, ErrConnClosing
case <-wc.done:
return 0, 0, io.EOF
case <-wc.goAway:
return 0, 0, errStreamDrain
case <-qb.c:
qb.mu.Lock()
if qb.quota > 0 {
if v > qb.quota {
v = qb.quota
}
qb.quota -= v
ver := qb.version
if qb.quota > 0 {
select {
case qb.c <- struct{}{}:
default:
}
}
qb.mu.Unlock()
return v, ver, nil
}
qb.mu.Unlock()
}
}
} }
func (qb *quotaPool) compareAndExecute(version uint32, success, failure func()) bool { func (qb *quotaPool) compareAndExecute(version uint32, success, failure func()) bool {
qb.mu.Lock() qb.mu.Lock()
defer qb.mu.Unlock() if version == qb.version {
if version == atomic.LoadUint32(&(qb.version)) {
success() success()
qb.mu.Unlock()
return true return true
} }
failure() failure()
qb.mu.Unlock()
return false return false
} }
// acquire returns the channel on which available quota amounts are sent.
func (qb *quotaPool) acquire() <-chan int {
return qb.c
}
// inFlow deals with inbound flow control // inFlow deals with inbound flow control
type inFlow struct { type inFlow struct {
mu sync.Mutex mu sync.Mutex

51
vendor/google.golang.org/grpc/transport/go16.go generated vendored Normal file
View File

@ -0,0 +1,51 @@
// +build go1.6,!go1.7
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package transport
import (
"net"
"net/http"
"google.golang.org/grpc/codes"
"golang.org/x/net/context"
)
// dialContext connects to the address on the named network.
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
}
// ContextErr converts the error from context package into a StreamError.
func ContextErr(err error) StreamError {
switch err {
case context.DeadlineExceeded:
return streamErrorf(codes.DeadlineExceeded, "%v", err)
case context.Canceled:
return streamErrorf(codes.Canceled, "%v", err)
}
return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
}
// contextFromRequest returns a background context.
func contextFromRequest(r *http.Request) context.Context {
return context.Background()
}

52
vendor/google.golang.org/grpc/transport/go17.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
// +build go1.7
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package transport
import (
"context"
"net"
"net/http"
"google.golang.org/grpc/codes"
netctx "golang.org/x/net/context"
)
// dialContext connects to the address on the named network.
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{}).DialContext(ctx, network, address)
}
// ContextErr converts the error from context package into a StreamError.
func ContextErr(err error) StreamError {
switch err {
case context.DeadlineExceeded, netctx.DeadlineExceeded:
return streamErrorf(codes.DeadlineExceeded, "%v", err)
case context.Canceled, netctx.Canceled:
return streamErrorf(codes.Canceled, "%v", err)
}
return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
}
// contextFromRequest returns a context from the HTTP Request.
func contextFromRequest(r *http.Request) context.Context {
return r.Context()
}

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