*: update vendor

This commit is contained in:
Gyu-Ho Lee 2016-06-26 10:38:51 -07:00
parent cf6907a1c9
commit c11e29e6da
16 changed files with 1667 additions and 434 deletions

29
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: 899cf0cc8fe75956e38ad46350724245f8d593c906f41981c573229c262a946e
updated: 2016-06-17T16:32:21.379557428-07:00
updated: 2016-06-26T10:38:34.458889325-07:00
imports:
- name: bitbucket.org/zombiezen/gopdf
version: 1c63dc69751bc45441c2ce1f56b631c55294b4d5
@ -12,7 +12,7 @@ imports:
- name: github.com/cloudfoundry-incubator/candiedyaml
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
- name: github.com/coreos/etcd
version: b03c832bed4cd0c7856ffb5b4ec52df5073be3f2
version: aab905f7ccd12733b16931953677bef7e8ce5400
subpackages:
- client
- clientv3
@ -24,15 +24,15 @@ imports:
- mvcc/mvccpb
- pkg/tlsutil
- name: github.com/coreos/go-systemd
version: a52323565816dee4d2f8dc5fdf1299f48757b848
version: b32b8467dbea18858bfebf65c1a6a761090f2c31
subpackages:
- journal
- name: github.com/coreos/pkg
version: 62adab7e2fbd7e45230489364764b5193f32f45a
version: a48e304ff9331be6d5df352b6b47bd1395ab5dd7
subpackages:
- capnslog
- name: github.com/dustin/go-humanize
version: 499693e27ee0d14ffab67c31ad065fdb3d34ea75
version: fef948f2d241bd1fd0631108ecc2c9553bae60bf
- name: github.com/fatih/color
version: 87d4004f2ab62d0d255e0a38f1680aa534549fe3
- name: github.com/gengo/grpc-gateway
@ -50,7 +50,7 @@ imports:
- proto
- protoc-gen-gogo/descriptor
- name: github.com/golang/freetype
version: a31d0146dac6f09aa27eda40995aeca7d7adc293
version: 38b4c392adc5eed94207994c4848fff99f4ac234
subpackages:
- truetype
- raster
@ -85,7 +85,7 @@ imports:
subpackages:
- ps
- name: github.com/hashicorp/consul
version: af332d6d771c55f4ac69d74dd702b7a3917bb9a0
version: 09cfda47ed103910a8e1af76fa378a7e6acd5310
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
@ -109,13 +109,13 @@ imports:
- name: github.com/mattn/go-runewidth
version: d6bea18f789704b5f83375793155289da36a3c7f
- name: github.com/olekukonko/tablewriter
version: 8d0265a48283795806b872b4728c67bf5c777f20
version: daf2955e742cf123959884fdff4685aa79b63135
- name: github.com/samuel/go-zookeeper
version: e64db453f3512cade908163702045e0f31137843
subpackages:
- zk
- name: github.com/spf13/cobra
version: bc81c21bd0d8be5ba2d6630a505d79d4467566e7
version: 6a8bd97bdb1fc0d08a83459940498ea49d3e8c93
- name: github.com/spf13/pflag
version: 367864438f1b1a3c7db4da06a2f55b144e6784e0
- name: github.com/ugorji/go
@ -132,7 +132,7 @@ imports:
- math/f64
- tiff/lzw
- name: golang.org/x/net
version: d7bf3545bb0dacf009c535b3d3fbf53ac0a339ab
version: e445b19913b9d40fdbdfe19ac5e3d314aafd6f63
subpackages:
- context
- http2
@ -160,7 +160,7 @@ imports:
- googleapi/internal/uritemplates
- gensupport
- name: google.golang.org/appengine
version: 7f59a8c76b8594d06044bfe0bcbe475cb2020482
version: 267c27e7492265b84fc6719503b14a1e17975d79
subpackages:
- urlfetch
- internal
@ -169,9 +169,10 @@ imports:
- internal/urlfetch
- internal/base
- internal/datastore
- internal/log
- internal/remote_api
- name: google.golang.org/cloud
version: 581cbbbaf53b821281c5df8f4bb9fa69c2d5f49c
version: a4c7c3139dc2772ad6c3bb73d0a9236a79063f8c
subpackages:
- storage
- compute/metadata
@ -179,7 +180,7 @@ imports:
- internal/opts
- internal/transport
- name: google.golang.org/grpc
version: e78224b060cf3215247b7be455f80ea22e469b66
version: 0eb7c5dcd059d77bde1eb5bc7d953940170d0d18
subpackages:
- codes
- credentials
@ -192,4 +193,4 @@ imports:
- credentials/oauth
- name: gopkg.in/yaml.v2
version: a83829b6f1293c91addabc89d0571c246397bbf4
devImports: []
testImports: []

16
script-update-vendor.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -e
echo "Installing glide..."
GLIDE_ROOT="$GOPATH/src/github.com/Masterminds/glide"
rm -rf $GLIDE_ROOT
go get -u github.com/Masterminds/glide
pushd "${GLIDE_ROOT}"
git reset --hard HEAD
go install
popd
rm -rf vendor
glide -v
glide update --strip-vendor --strip-vcs --update-vendored
glide vc --only-code --no-tests

View File

@ -134,7 +134,15 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
// TODO: handle other ops
case tRange:
var resp *pb.RangeResponse
r := &pb.RangeRequest{Key: op.key, RangeEnd: op.end, Limit: op.limit, Revision: op.rev, Serializable: op.serializable}
r := &pb.RangeRequest{
Key: op.key,
RangeEnd: op.end,
Limit: op.limit,
Revision: op.rev,
Serializable: op.serializable,
KeysOnly: op.keysOnly,
CountOnly: op.countOnly,
}
if op.sort != nil {
r.SortOrder = pb.RangeRequest_SortOrder(op.sort.Order)
r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)

View File

@ -354,8 +354,8 @@ func (l *lessor) recvKeepAlive(resp *pb.LeaseKeepAliveResponse) {
}
}
// deadlineLoop reaps any keep alive channels that have not recieved a resposne within
// the lease TTL
// deadlineLoop reaps any keep alive channels that have not received a response
// within the lease TTL
func (l *lessor) deadlineLoop() {
for {
select {

View File

@ -41,6 +41,8 @@ type Op struct {
limit int64
sort *SortOption
serializable bool
keysOnly bool
countOnly bool
// for range, watch
rev int64
@ -56,7 +58,15 @@ type Op struct {
func (op Op) toRequestOp() *pb.RequestOp {
switch op.t {
case tRange:
r := &pb.RangeRequest{Key: op.key, RangeEnd: op.end, Limit: op.limit, Revision: op.rev, Serializable: op.serializable}
r := &pb.RangeRequest{
Key: op.key,
RangeEnd: op.end,
Limit: op.limit,
Revision: op.rev,
Serializable: op.serializable,
KeysOnly: op.keysOnly,
CountOnly: op.countOnly,
}
if op.sort != nil {
r.SortOrder = pb.RangeRequest_SortOrder(op.sort.Order)
r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)
@ -97,6 +107,8 @@ func OpDelete(key string, opts ...OpOption) Op {
panic("unexpected sort in delete")
case ret.serializable:
panic("unexpected serializable in delete")
case ret.countOnly:
panic("unexpected countOnly in delete")
}
return ret
}
@ -115,6 +127,8 @@ func OpPut(key, val string, opts ...OpOption) Op {
panic("unexpected sort in put")
case ret.serializable:
panic("unexpected serializable in put")
case ret.countOnly:
panic("unexpected countOnly in delete")
}
return ret
}
@ -131,6 +145,8 @@ func opWatch(key string, opts ...OpOption) Op {
panic("unexpected sort in watch")
case ret.serializable:
panic("unexpected serializable in watch")
case ret.countOnly:
panic("unexpected countOnly in delete")
}
return ret
}
@ -208,6 +224,17 @@ func WithSerializable() OpOption {
return func(op *Op) { op.serializable = true }
}
// WithKeysOnly makes the 'Get' request return only the keys and the corresponding
// values will be omitted.
func WithKeysOnly() OpOption {
return func(op *Op) { op.keysOnly = true }
}
// WithCountOnly makes the 'Get' request return only the count of keys.
func WithCountOnly() OpOption {
return func(op *Op) { op.countOnly = true }
}
// WithFirstCreate gets the key with the oldest creation revision in the request range.
func WithFirstCreate() []OpOption { return withTop(SortByCreateRevision, SortAscend) }

View File

@ -17,6 +17,7 @@ package clientv3
import (
"fmt"
"sync"
"time"
v3rpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
@ -27,6 +28,8 @@ import (
const (
EventTypeDelete = mvccpb.DELETE
EventTypePut = mvccpb.PUT
closeSendErrTimeout = 250 * time.Millisecond
)
type Event mvccpb.Event
@ -56,6 +59,8 @@ type WatchResponse struct {
// If the watch failed and the stream was about to close, before the channel is closed,
// the channel sends a final response that has Canceled set to true with a non-nil Err().
Canceled bool
closeErr error
}
// IsCreate returns true if the event tells that the key is newly created.
@ -70,10 +75,12 @@ func (e *Event) IsModify() bool {
// Err is the error value if this WatchResponse holds an error.
func (wr *WatchResponse) Err() error {
if wr.CompactRevision != 0 {
switch {
case wr.closeErr != nil:
return v3rpc.Error(wr.closeErr)
case wr.CompactRevision != 0:
return v3rpc.ErrCompacted
}
if wr.Canceled {
case wr.Canceled:
return v3rpc.ErrFutureRev
}
return nil
@ -88,14 +95,26 @@ func (wr *WatchResponse) IsProgressNotify() bool {
type watcher struct {
remote pb.WatchClient
// mu protects the grpc streams map
mu sync.RWMutex
// streams holds all the active grpc streams keyed by ctx value.
streams map[string]*watchGrpcStream
}
type watchGrpcStream struct {
owner *watcher
remote pb.WatchClient
// ctx controls internal remote.Watch requests
ctx context.Context
ctx context.Context
// ctxKey is the key used when looking up this stream's context
ctxKey string
cancel context.CancelFunc
// streams holds all active watchers
streams map[int64]*watcherStream
// mu protects the streams map
mu sync.RWMutex
// streams holds all active watchers
streams map[int64]*watcherStream
// reqc sends a watch request from Watch() to the main goroutine
reqc chan *watchRequest
@ -105,8 +124,11 @@ type watcher struct {
stopc chan struct{}
// donec closes to broadcast shutdown
donec chan struct{}
// errc transmits errors from grpc Recv
// errc transmits errors from grpc Recv to the watch stream reconn logic
errc chan error
// the error that closed the watch stream
closeErr error
}
// watchRequest is issued by the subscriber to start a new watcher
@ -123,6 +145,7 @@ type watchRequest struct {
// watcherStream represents a registered watcher
type watcherStream struct {
// initReq is the request that initiated this request
initReq watchRequest
// outc publishes watch responses to subscriber
@ -138,10 +161,30 @@ type watcherStream struct {
}
func NewWatcher(c *Client) Watcher {
ctx, cancel := context.WithCancel(context.Background())
w := &watcher{
return &watcher{
remote: pb.NewWatchClient(c.conn),
streams: make(map[string]*watchGrpcStream),
}
}
// never closes
var valCtxCh = make(chan struct{})
var zeroTime = time.Unix(0, 0)
// ctx with only the values; never Done
type valCtx struct{ context.Context }
func (vc *valCtx) Deadline() (time.Time, bool) { return zeroTime, false }
func (vc *valCtx) Done() <-chan struct{} { return valCtxCh }
func (vc *valCtx) Err() error { return nil }
func (w *watcher) newWatcherGrpcStream(inctx context.Context) *watchGrpcStream {
ctx, cancel := context.WithCancel(&valCtx{inctx})
wgs := &watchGrpcStream{
owner: w,
remote: w.remote,
ctx: ctx,
ctxKey: fmt.Sprintf("%v", inctx),
cancel: cancel,
streams: make(map[int64]*watcherStream),
@ -151,8 +194,8 @@ func NewWatcher(c *Client) Watcher {
donec: make(chan struct{}),
errc: make(chan error, 1),
}
go w.run()
return w
go wgs.run()
return wgs
}
// Watch posts a watch request to run() and waits for a new watcher channel
@ -170,13 +213,41 @@ func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) Watch
}
ok := false
ctxKey := fmt.Sprintf("%v", ctx)
// find or allocate appropriate grpc watch stream
w.mu.Lock()
if w.streams == nil {
// closed
w.mu.Unlock()
ch := make(chan WatchResponse)
close(ch)
return ch
}
wgs := w.streams[ctxKey]
if wgs == nil {
wgs = w.newWatcherGrpcStream(ctx)
w.streams[ctxKey] = wgs
}
donec := wgs.donec
reqc := wgs.reqc
w.mu.Unlock()
// couldn't create channel; return closed channel
closeCh := make(chan WatchResponse, 1)
// submit request
select {
case w.reqc <- wr:
case reqc <- wr:
ok = true
case <-wr.ctx.Done():
case <-w.donec:
case <-donec:
if wgs.closeErr != nil {
closeCh <- WatchResponse{closeErr: wgs.closeErr}
break
}
// retry; may have dropped stream from no ctxs
return w.Watch(ctx, key, opts...)
}
// receive channel
@ -185,23 +256,44 @@ func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) Watch
case ret := <-retc:
return ret
case <-ctx.Done():
case <-w.donec:
case <-donec:
if wgs.closeErr != nil {
closeCh <- WatchResponse{closeErr: wgs.closeErr}
break
}
// retry; may have dropped stream from no ctxs
return w.Watch(ctx, key, opts...)
}
}
// couldn't create channel; return closed channel
ch := make(chan WatchResponse)
close(ch)
return ch
close(closeCh)
return closeCh
}
func (w *watcher) Close() error {
func (w *watcher) Close() (err error) {
w.mu.Lock()
streams := w.streams
w.streams = nil
w.mu.Unlock()
for _, wgs := range streams {
if werr := wgs.Close(); werr != nil {
err = werr
}
}
return err
}
func (w *watchGrpcStream) Close() (err error) {
close(w.stopc)
<-w.donec
return toErr(w.ctx, <-w.errc)
select {
case err = <-w.errc:
default:
}
return toErr(w.ctx, err)
}
func (w *watcher) addStream(resp *pb.WatchResponse, pendingReq *watchRequest) {
func (w *watchGrpcStream) addStream(resp *pb.WatchResponse, pendingReq *watchRequest) {
if pendingReq == nil {
// no pending request; ignore
return
@ -254,27 +346,27 @@ func (w *watcher) addStream(resp *pb.WatchResponse, pendingReq *watchRequest) {
}
// closeStream closes the watcher resources and removes it
func (w *watcher) closeStream(ws *watcherStream) {
func (w *watchGrpcStream) closeStream(ws *watcherStream) {
// cancels request stream; subscriber receives nil channel
close(ws.initReq.retc)
// close subscriber's channel
close(ws.outc)
// shutdown serveStream
close(ws.recvc)
delete(w.streams, ws.id)
}
// run is the root of the goroutines for managing a watcher client
func (w *watcher) run() {
func (w *watchGrpcStream) run() {
var wc pb.Watch_WatchClient
var closeErr error
defer func() {
select {
case w.errc <- closeErr:
default:
w.owner.mu.Lock()
w.closeErr = closeErr
if w.owner.streams != nil {
delete(w.owner.streams, w.ctxKey)
}
close(w.donec)
w.owner.mu.Unlock()
w.cancel()
}()
@ -308,6 +400,18 @@ func (w *watcher) run() {
curReqC = w.reqc
case pbresp.Canceled:
delete(cancelSet, pbresp.WatchId)
// shutdown serveStream, if any
w.mu.Lock()
if ws, ok := w.streams[pbresp.WatchId]; ok {
close(ws.recvc)
delete(w.streams, ws.id)
}
numStreams := len(w.streams)
w.mu.Unlock()
if numStreams == 0 {
// don't leak watcher streams
return
}
default:
// dispatch to appropriate watch stream
if ok := w.dispatchEvent(pbresp); ok {
@ -328,7 +432,11 @@ func (w *watcher) run() {
}
// watch client failed to recv; spawn another if possible
// TODO report watch client errors from errc?
case <-w.errc:
case err := <-w.errc:
if toErr(w.ctx, err) == v3rpc.ErrNoLeader {
closeErr = err
return
}
if wc, closeErr = w.newWatchClient(); closeErr != nil {
return
}
@ -357,7 +465,7 @@ func (w *watcher) run() {
}
// dispatchEvent sends a WatchResponse to the appropriate watcher stream
func (w *watcher) dispatchEvent(pbresp *pb.WatchResponse) bool {
func (w *watchGrpcStream) dispatchEvent(pbresp *pb.WatchResponse) bool {
w.mu.RLock()
defer w.mu.RUnlock()
ws, ok := w.streams[pbresp.WatchId]
@ -377,7 +485,7 @@ func (w *watcher) dispatchEvent(pbresp *pb.WatchResponse) bool {
}
// serveWatchClient forwards messages from the grpc stream to run()
func (w *watcher) serveWatchClient(wc pb.Watch_WatchClient) {
func (w *watchGrpcStream) serveWatchClient(wc pb.Watch_WatchClient) {
for {
resp, err := wc.Recv()
if err != nil {
@ -396,7 +504,7 @@ func (w *watcher) serveWatchClient(wc pb.Watch_WatchClient) {
}
// serveStream forwards watch responses from run() to the subscriber
func (w *watcher) serveStream(ws *watcherStream) {
func (w *watchGrpcStream) serveStream(ws *watcherStream) {
emptyWr := &WatchResponse{}
wrs := []*WatchResponse{}
resuming := false
@ -465,13 +573,23 @@ func (w *watcher) serveStream(ws *watcherStream) {
closing = true
}
}
// try to send off close error
if w.closeErr != nil {
select {
case ws.outc <- WatchResponse{closeErr: w.closeErr}:
case <-w.donec:
case <-time.After(closeSendErrTimeout):
}
}
w.mu.Lock()
w.closeStream(ws)
w.mu.Unlock()
// lazily send cancel message if events on missing id
}
func (w *watcher) newWatchClient() (pb.Watch_WatchClient, error) {
func (w *watchGrpcStream) newWatchClient() (pb.Watch_WatchClient, error) {
ws, rerr := w.resume()
if rerr != nil {
return nil, rerr
@ -481,7 +599,7 @@ func (w *watcher) newWatchClient() (pb.Watch_WatchClient, error) {
}
// resume creates a new WatchClient with all current watchers reestablished
func (w *watcher) resume() (ws pb.Watch_WatchClient, err error) {
func (w *watchGrpcStream) resume() (ws pb.Watch_WatchClient, err error) {
for {
if ws, err = w.openWatchClient(); err != nil {
break
@ -493,7 +611,7 @@ func (w *watcher) resume() (ws pb.Watch_WatchClient, err error) {
}
// openWatchClient retries opening a watchclient until retryConnection fails
func (w *watcher) openWatchClient() (ws pb.Watch_WatchClient, err error) {
func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error) {
for {
select {
case <-w.stopc:
@ -514,7 +632,7 @@ func (w *watcher) openWatchClient() (ws pb.Watch_WatchClient, err error) {
}
// resumeWatchers rebuilds every registered watcher on a new client
func (w *watcher) resumeWatchers(wc pb.Watch_WatchClient) error {
func (w *watchGrpcStream) resumeWatchers(wc pb.Watch_WatchClient) error {
w.mu.RLock()
streams := make([]*watcherStream, 0, len(w.streams))
for _, ws := range w.streams {

View File

@ -222,6 +222,10 @@ type RangeRequest struct {
// a serializable range request is served locally without needing to reach consensus
// with other nodes in the cluster.
Serializable bool `protobuf:"varint,7,opt,name=serializable,proto3" json:"serializable,omitempty"`
// keys_only when set returns only the keys and not the values.
KeysOnly bool `protobuf:"varint,8,opt,name=keys_only,json=keysOnly,proto3" json:"keys_only,omitempty"`
// count_only when set returns only the count of the keys in the range.
CountOnly bool `protobuf:"varint,9,opt,name=count_only,json=countOnly,proto3" json:"count_only,omitempty"`
}
func (m *RangeRequest) Reset() { *m = RangeRequest{} }
@ -232,9 +236,12 @@ func (*RangeRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []
type RangeResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// kvs is the list of key-value pairs matched by the range request.
// kvs is empty when count is requested.
Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"`
// more indicates if there are more keys to return in the requested range.
More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"`
// count is set to the number of keys within the range when requested.
Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"`
}
func (m *RangeResponse) Reset() { *m = RangeResponse{} }
@ -3648,6 +3655,26 @@ func (m *RangeRequest) MarshalTo(data []byte) (int, error) {
}
i++
}
if m.KeysOnly {
data[i] = 0x40
i++
if m.KeysOnly {
data[i] = 1
} else {
data[i] = 0
}
i++
}
if m.CountOnly {
data[i] = 0x48
i++
if m.CountOnly {
data[i] = 1
} else {
data[i] = 0
}
i++
}
return i, nil
}
@ -3698,6 +3725,11 @@ func (m *RangeResponse) MarshalTo(data []byte) (int, error) {
}
i++
}
if m.Count != 0 {
data[i] = 0x20
i++
i = encodeVarintRpc(data, i, uint64(m.Count))
}
return i, nil
}
@ -6199,6 +6231,12 @@ func (m *RangeRequest) Size() (n int) {
if m.Serializable {
n += 2
}
if m.KeysOnly {
n += 2
}
if m.CountOnly {
n += 2
}
return n
}
@ -6218,6 +6256,9 @@ func (m *RangeResponse) Size() (n int) {
if m.More {
n += 2
}
if m.Count != 0 {
n += 1 + sovRpc(uint64(m.Count))
}
return n
}
@ -7558,6 +7599,46 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
}
m.Serializable = bool(v != 0)
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field KeysOnly", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.KeysOnly = bool(v != 0)
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CountOnly", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.CountOnly = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
@ -7692,6 +7773,25 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
}
m.More = bool(v != 0)
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType)
}
m.Count = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.Count |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
@ -15025,198 +15125,200 @@ var (
)
var fileDescriptorRpc = []byte{
// 3078 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0x4b, 0x6f, 0x23, 0xc7,
0xf1, 0xdf, 0x21, 0xa9, 0x07, 0x8b, 0x14, 0x57, 0xdb, 0xd2, 0xae, 0xa5, 0x59, 0xad, 0x56, 0xdb,
0xfb, 0xf4, 0x4b, 0xfc, 0x5b, 0xf6, 0x3f, 0x87, 0x24, 0x30, 0x40, 0x89, 0xcc, 0x5a, 0x96, 0x2c,
0xad, 0x47, 0x5c, 0xd9, 0x01, 0x82, 0x08, 0x23, 0xb2, 0x57, 0x22, 0xc4, 0x97, 0x67, 0x86, 0xda,
0x5d, 0x27, 0x06, 0x02, 0x23, 0x3e, 0x24, 0x57, 0x07, 0x08, 0x92, 0x1c, 0xf3, 0x19, 0x72, 0xcb,
0x07, 0x08, 0x72, 0x49, 0x80, 0x1c, 0x73, 0x09, 0x82, 0x1c, 0x72, 0xc8, 0x3d, 0xc8, 0x29, 0xe9,
0xe7, 0x4c, 0xcf, 0xb0, 0x87, 0x92, 0x33, 0xf1, 0x61, 0x57, 0xd3, 0xd5, 0xd5, 0xf5, 0xab, 0xae,
0xee, 0xaa, 0xa9, 0xaa, 0x21, 0x14, 0xbd, 0x61, 0x6b, 0x7d, 0xe8, 0x0d, 0x82, 0x01, 0x2a, 0x93,
0xa0, 0xd5, 0xf6, 0x89, 0x77, 0x4e, 0xbc, 0xe1, 0xb1, 0xbd, 0x78, 0x32, 0x38, 0x19, 0xf0, 0x89,
0x2a, 0x7b, 0x12, 0x3c, 0xf6, 0x32, 0xe3, 0xa9, 0xf6, 0xce, 0x5b, 0x2d, 0xfe, 0xdf, 0xf0, 0xb8,
0x7a, 0x76, 0x2e, 0xa7, 0x6e, 0xf2, 0x29, 0x77, 0x14, 0x9c, 0xf2, 0xff, 0xe8, 0x14, 0xfb, 0x23,
0x27, 0x57, 0x4e, 0x06, 0x83, 0x93, 0x2e, 0xa9, 0xba, 0xc3, 0x4e, 0xd5, 0xed, 0xf7, 0x07, 0x81,
0x1b, 0x74, 0x06, 0x7d, 0x5f, 0xcc, 0xe2, 0x2f, 0x2c, 0xa8, 0x38, 0xc4, 0x1f, 0x52, 0x0a, 0x79,
0x8f, 0xb8, 0x6d, 0xe2, 0xa1, 0x5b, 0x00, 0xad, 0xee, 0xc8, 0x0f, 0x88, 0x77, 0xd4, 0x69, 0x2f,
0x59, 0x6b, 0xd6, 0xa3, 0x82, 0x53, 0x94, 0x94, 0xed, 0x36, 0xba, 0x09, 0xc5, 0x1e, 0xe9, 0x1d,
0x8b, 0xd9, 0x1c, 0x9f, 0x9d, 0x15, 0x04, 0x3a, 0x69, 0xc3, 0xac, 0x47, 0xce, 0x3b, 0x3e, 0x45,
0x58, 0xca, 0xd3, 0xb9, 0xbc, 0x13, 0x8e, 0xd9, 0x42, 0xcf, 0x7d, 0x16, 0x1c, 0x51, 0x31, 0xbd,
0xa5, 0x82, 0x58, 0xc8, 0x08, 0x4d, 0x3a, 0xc6, 0x3f, 0xcb, 0x43, 0xd9, 0x71, 0xfb, 0x27, 0xc4,
0x21, 0x9f, 0x8c, 0x88, 0x1f, 0xa0, 0x79, 0xc8, 0x9f, 0x91, 0x97, 0x1c, 0xbe, 0xec, 0xb0, 0x47,
0xb1, 0x9e, 0x72, 0x1c, 0x91, 0xbe, 0x00, 0x2e, 0xb3, 0xf5, 0x94, 0xd0, 0xe8, 0xb7, 0xd1, 0x22,
0x4c, 0x75, 0x3b, 0xbd, 0x4e, 0x20, 0x51, 0xc5, 0x20, 0xa6, 0x4e, 0x21, 0xa1, 0xce, 0x16, 0x80,
0x3f, 0xf0, 0x82, 0xa3, 0x81, 0x47, 0x37, 0xbd, 0x34, 0x45, 0x67, 0x2b, 0x1b, 0xf7, 0xd6, 0xf5,
0x83, 0x58, 0xd7, 0x15, 0x5a, 0x3f, 0xa0, 0xcc, 0xfb, 0x8c, 0xd7, 0x29, 0xfa, 0xea, 0x11, 0x7d,
0x07, 0x4a, 0x5c, 0x48, 0xe0, 0x7a, 0x27, 0x24, 0x58, 0x9a, 0xe6, 0x52, 0xee, 0x5f, 0x20, 0xa5,
0xc9, 0x99, 0x1d, 0x0e, 0x2f, 0x9e, 0x11, 0x86, 0x32, 0xe5, 0xef, 0xb8, 0xdd, 0xce, 0xa7, 0xee,
0x71, 0x97, 0x2c, 0xcd, 0x50, 0x41, 0xb3, 0x4e, 0x8c, 0x86, 0xd7, 0xa1, 0x18, 0xea, 0x80, 0x66,
0xa1, 0xb0, 0xb7, 0xbf, 0xd7, 0x98, 0xbf, 0x82, 0x00, 0xa6, 0x6b, 0x07, 0x5b, 0x8d, 0xbd, 0xfa,
0xbc, 0x85, 0x4a, 0x30, 0x53, 0x6f, 0x88, 0x41, 0x0e, 0x6f, 0x02, 0x44, 0x68, 0x68, 0x06, 0xf2,
0x3b, 0x8d, 0xef, 0x52, 0x7e, 0xca, 0x73, 0xd8, 0x70, 0x0e, 0xb6, 0xf7, 0xf7, 0xe8, 0x02, 0xba,
0x78, 0xcb, 0x69, 0xd4, 0x9a, 0x8d, 0xf9, 0x1c, 0xe3, 0xf8, 0x60, 0xbf, 0x3e, 0x9f, 0x47, 0x45,
0x98, 0x3a, 0xac, 0xed, 0x3e, 0x6d, 0xcc, 0x17, 0xf0, 0x67, 0x30, 0x27, 0xd5, 0x17, 0x57, 0x04,
0xbd, 0x03, 0xd3, 0xa7, 0xfc, 0x9a, 0xf0, 0x93, 0x29, 0x6d, 0xac, 0x24, 0xf6, 0x1a, 0xbb, 0x4a,
0x8e, 0xe4, 0xa5, 0xdb, 0xcb, 0x9f, 0x9d, 0xfb, 0xf4, 0xd0, 0xf2, 0x74, 0xc9, 0xfc, 0xba, 0xb8,
0xbf, 0xeb, 0x3b, 0xe4, 0xe5, 0xa1, 0xdb, 0x1d, 0x11, 0x87, 0x4d, 0x22, 0x04, 0x85, 0xde, 0xc0,
0x23, 0xfc, 0x00, 0x67, 0x1d, 0xfe, 0x8c, 0xdf, 0x07, 0x78, 0x32, 0x0a, 0xd2, 0xaf, 0x04, 0x3d,
0xf5, 0x73, 0x26, 0x41, 0x5e, 0x07, 0x31, 0xe0, 0x77, 0x81, 0xb8, 0x3e, 0x09, 0xef, 0x02, 0x1b,
0xe0, 0x2d, 0x28, 0x71, 0x59, 0x59, 0x36, 0x42, 0x85, 0xa0, 0x3a, 0xe9, 0x92, 0x80, 0x64, 0xb8,
0xab, 0x98, 0xc0, 0x42, 0x4c, 0x48, 0x26, 0xd3, 0x2e, 0xc1, 0x4c, 0x9b, 0x0b, 0x13, 0x38, 0x79,
0x47, 0x0d, 0xf1, 0x3f, 0x2c, 0x28, 0x4a, 0x0d, 0xf7, 0x87, 0xa8, 0x06, 0x73, 0x9e, 0x18, 0x1c,
0x71, 0x45, 0x24, 0x88, 0x9d, 0x7e, 0x57, 0xdf, 0xbb, 0xe2, 0x94, 0xe5, 0x12, 0x4e, 0x46, 0xdf,
0x82, 0x92, 0x12, 0x31, 0x1c, 0x05, 0x1c, 0xae, 0xb4, 0xb1, 0x14, 0x17, 0x10, 0x1d, 0x17, 0x5d,
0x0e, 0x92, 0x9d, 0x12, 0x51, 0x13, 0x16, 0xd5, 0x62, 0xa1, 0xa0, 0x54, 0x23, 0xcf, 0xa5, 0xac,
0xc5, 0xa5, 0x8c, 0xdb, 0x98, 0x4a, 0x43, 0x72, 0xbd, 0x36, 0xb9, 0x59, 0x84, 0x19, 0x49, 0xc5,
0xff, 0xb4, 0x00, 0x94, 0x8d, 0xe8, 0x7e, 0xeb, 0x50, 0xf1, 0xe4, 0x28, 0xb6, 0xe1, 0x9b, 0xc6,
0x0d, 0x4b, 0xd3, 0x5e, 0x71, 0xe6, 0xd4, 0x22, 0xb1, 0xe5, 0x77, 0xa1, 0x1c, 0x4a, 0x89, 0xf6,
0xbc, 0x6c, 0xd8, 0x73, 0x28, 0xa1, 0xa4, 0x16, 0xb0, 0x5d, 0x7f, 0x04, 0xd7, 0xc3, 0xf5, 0x86,
0x6d, 0xdf, 0x99, 0xb0, 0xed, 0x50, 0xe0, 0x82, 0x92, 0xa0, 0x6f, 0x1c, 0x58, 0x64, 0x13, 0x64,
0xfc, 0xcb, 0x3c, 0xcc, 0x6c, 0x0d, 0x7a, 0x43, 0xd7, 0x63, 0x67, 0x34, 0x4d, 0xe9, 0xa3, 0x6e,
0xc0, 0xb7, 0x5b, 0xd9, 0xb8, 0x1b, 0x47, 0x90, 0x6c, 0xea, 0xaf, 0xc3, 0x59, 0x1d, 0xb9, 0x84,
0x2d, 0x96, 0x81, 0x2c, 0x77, 0x89, 0xc5, 0x32, 0x8c, 0xc9, 0x25, 0xca, 0x09, 0xf2, 0x91, 0x13,
0xd8, 0x30, 0x43, 0x17, 0x46, 0xc1, 0x97, 0xee, 0x45, 0x11, 0xd0, 0xab, 0x70, 0xb5, 0xe5, 0x11,
0x97, 0xd9, 0x43, 0x05, 0xe8, 0x29, 0xc9, 0x53, 0x11, 0x13, 0x8e, 0x0a, 0xd4, 0x77, 0xa1, 0xdc,
0x1b, 0xb4, 0x23, 0xbe, 0x69, 0xc9, 0x57, 0xa2, 0xd4, 0x90, 0xe9, 0x86, 0x8a, 0x04, 0x2c, 0x72,
0x96, 0xe9, 0xac, 0x18, 0xe2, 0xb7, 0x60, 0x2e, 0xb6, 0x57, 0x16, 0xdc, 0x1a, 0x1f, 0x3e, 0xad,
0xed, 0x8a, 0x48, 0xf8, 0x98, 0x07, 0x3f, 0x87, 0x46, 0x42, 0x1a, 0x50, 0x77, 0x1b, 0x07, 0x07,
0x34, 0x6e, 0x7e, 0x3b, 0x5c, 0x22, 0x43, 0xa7, 0x16, 0x31, 0xaf, 0x68, 0x11, 0xd3, 0x52, 0x11,
0x33, 0x17, 0x45, 0xcc, 0xfc, 0x66, 0x05, 0xca, 0xc2, 0x20, 0x47, 0xa3, 0x3e, 0x55, 0x0c, 0xff,
0x9a, 0x5e, 0xcb, 0xe6, 0x8b, 0xbe, 0x0a, 0x15, 0x55, 0x98, 0x69, 0x09, 0xe1, 0xf4, 0x80, 0x58,
0x34, 0xbc, 0x6e, 0xb4, 0xb1, 0xa3, 0xb8, 0xd0, 0x5b, 0x30, 0xe3, 0x8f, 0x5a, 0x2d, 0xe2, 0xab,
0xf0, 0xf9, 0x4a, 0x32, 0x2c, 0x48, 0x0f, 0x77, 0x14, 0x1f, 0x5b, 0xf2, 0xcc, 0xed, 0x74, 0x47,
0x3c, 0x98, 0x4e, 0x5e, 0x22, 0xf9, 0xf0, 0x2f, 0x2c, 0x28, 0x71, 0x2d, 0x33, 0xc5, 0xa2, 0x15,
0x28, 0x72, 0x1d, 0x48, 0x5b, 0x46, 0xa3, 0x59, 0x27, 0x22, 0xa0, 0x6f, 0xd0, 0x98, 0x28, 0xd7,
0xf9, 0x52, 0xb1, 0x25, 0xb3, 0x58, 0xaa, 0x59, 0xc4, 0x8a, 0x77, 0xe0, 0x1a, 0xb7, 0x4a, 0x8b,
0xe5, 0x2d, 0xca, 0x8e, 0xfa, 0x9b, 0xdd, 0x4a, 0xbc, 0xd9, 0xe9, 0xdc, 0xf0, 0xf4, 0xa5, 0xdf,
0x69, 0xb9, 0x5d, 0xa9, 0x45, 0x38, 0xa6, 0x6f, 0x14, 0xa4, 0x0b, 0xcb, 0xf4, 0x32, 0x98, 0x83,
0xd2, 0x7b, 0xae, 0x7f, 0x2a, 0x55, 0xc2, 0x1f, 0x43, 0x59, 0x0c, 0x33, 0xd9, 0x90, 0xbe, 0x06,
0x4f, 0xa9, 0x14, 0xae, 0xf8, 0x9c, 0xc3, 0x9f, 0xf1, 0x35, 0xb8, 0x7a, 0xd0, 0x77, 0x87, 0xfe,
0xe9, 0x40, 0x05, 0x57, 0x96, 0xb7, 0xcd, 0x47, 0xb4, 0x4c, 0x88, 0x0f, 0xe1, 0xaa, 0x47, 0x7a,
0x6e, 0xa7, 0xdf, 0xe9, 0x9f, 0x1c, 0x1d, 0xbf, 0x0c, 0x88, 0x2f, 0xd3, 0xba, 0x4a, 0x48, 0xde,
0x64, 0x54, 0xa6, 0xda, 0x71, 0x77, 0x70, 0x2c, 0x5d, 0x9c, 0x3f, 0xe3, 0xdf, 0x58, 0x50, 0xfe,
0xc8, 0x0d, 0x5a, 0xca, 0x0a, 0x68, 0x1b, 0x2a, 0xa1, 0x63, 0x73, 0x8a, 0xd4, 0x25, 0x11, 0xe1,
0xf9, 0x9a, 0x2d, 0xe9, 0xe8, 0x2a, 0xc2, 0xcf, 0xb5, 0x74, 0x02, 0x17, 0xe5, 0xf6, 0x5b, 0xa4,
0x1b, 0x8a, 0xca, 0xa5, 0x8b, 0xe2, 0x8c, 0xba, 0x28, 0x9d, 0xb0, 0x79, 0x35, 0x7a, 0xfb, 0x09,
0xb7, 0xfc, 0xd2, 0x02, 0x34, 0xae, 0xc3, 0x57, 0xcd, 0x3a, 0xef, 0x43, 0xc5, 0xa7, 0xde, 0x1e,
0x1c, 0x25, 0x92, 0xde, 0x39, 0x4e, 0x0d, 0x83, 0x13, 0xb5, 0x30, 0xcd, 0xb6, 0x4f, 0xe8, 0x95,
0xf6, 0x8f, 0x68, 0x02, 0xde, 0x79, 0xf6, 0x92, 0x07, 0xc4, 0x59, 0xa7, 0xa2, 0xc8, 0x7b, 0x9c,
0x8a, 0xab, 0x4a, 0x29, 0x5d, 0x79, 0xb4, 0x0c, 0xb3, 0xcf, 0x19, 0x55, 0xa5, 0xe3, 0xf4, 0x1d,
0xcf, 0xc7, 0xdb, 0x6d, 0xfc, 0x77, 0x0b, 0xe6, 0xa4, 0xf9, 0x33, 0xdd, 0x01, 0x1d, 0x22, 0x17,
0x83, 0x60, 0x09, 0x86, 0x38, 0x96, 0xb6, 0x4c, 0xcd, 0xd4, 0x90, 0xf9, 0x99, 0xb0, 0x32, 0x9d,
0x12, 0xfb, 0x09, 0xc7, 0x34, 0xbe, 0xcf, 0xb7, 0x84, 0x9f, 0x25, 0x02, 0xbc, 0x73, 0x55, 0xd2,
0x43, 0xeb, 0xdc, 0x87, 0x69, 0x72, 0x4e, 0xfa, 0x81, 0xbf, 0x54, 0xe2, 0x41, 0x61, 0x4e, 0xe5,
0x87, 0x0d, 0x46, 0x75, 0xe4, 0x24, 0xfe, 0x7f, 0xb8, 0xb6, 0xcb, 0x12, 0xb9, 0xc7, 0xd4, 0xfa,
0x7a, 0x4a, 0xd8, 0x6c, 0xee, 0x4a, 0xab, 0xe4, 0x83, 0xe6, 0x2e, 0xaa, 0x40, 0x6e, 0xbb, 0x2e,
0xf7, 0x90, 0xeb, 0xd4, 0xf1, 0xe7, 0xf4, 0xa0, 0xf5, 0x75, 0x99, 0xcc, 0x94, 0x10, 0xae, 0xe0,
0xf3, 0x11, 0x3c, 0xcd, 0x3d, 0x89, 0xe7, 0x0d, 0x3c, 0x6e, 0x90, 0xa2, 0x23, 0x06, 0xf8, 0x9e,
0xd4, 0x81, 0xee, 0x79, 0x70, 0x16, 0x5e, 0x36, 0x21, 0xcd, 0x0a, 0x55, 0xdd, 0x81, 0x85, 0x18,
0x57, 0xa6, 0xe0, 0xf4, 0x10, 0xae, 0x73, 0x61, 0x3b, 0x84, 0x0c, 0x6b, 0xdd, 0xce, 0x79, 0x2a,
0xea, 0x10, 0x6e, 0x24, 0x19, 0xbf, 0x5e, 0x1b, 0xe1, 0x53, 0x98, 0xfe, 0x80, 0x17, 0x8c, 0x9a,
0x2e, 0x05, 0xce, 0x4b, 0x23, 0x4c, 0xdf, 0xed, 0x89, 0x74, 0xbe, 0xe8, 0xf0, 0x67, 0x1e, 0xcd,
0x09, 0xf1, 0x9e, 0x3a, 0xbb, 0xe2, 0xad, 0x51, 0x74, 0xc2, 0x31, 0x5a, 0x65, 0xa5, 0x6a, 0x87,
0x5e, 0x0f, 0x3e, 0x5b, 0xe0, 0xb3, 0x1a, 0x85, 0x96, 0x4c, 0xf3, 0x02, 0xa9, 0xd6, 0x6e, 0x6b,
0x6f, 0x8e, 0x50, 0x9e, 0x15, 0x97, 0x87, 0x9f, 0xc3, 0x35, 0x8d, 0x3f, 0x93, 0x19, 0xde, 0x80,
0x69, 0x51, 0x15, 0xcb, 0xa0, 0xb5, 0x18, 0x5f, 0x25, 0x60, 0x1c, 0xc9, 0x83, 0xef, 0xc3, 0x82,
0xa4, 0x90, 0xde, 0xc0, 0x74, 0x56, 0xdc, 0x3e, 0x78, 0x17, 0x16, 0xe3, 0x6c, 0x99, 0xae, 0x48,
0x4d, 0x81, 0x3e, 0x1d, 0xb6, 0xb5, 0x18, 0x98, 0x3c, 0x14, 0xdd, 0x60, 0xb9, 0x84, 0xc1, 0x42,
0x85, 0x94, 0x88, 0x4c, 0x0a, 0x2d, 0x28, 0xf3, 0xef, 0x76, 0xfc, 0xf0, 0x4d, 0xf7, 0x29, 0x20,
0x9d, 0x98, 0xe9, 0x50, 0xd6, 0x61, 0x46, 0x18, 0x5c, 0x25, 0x53, 0xe6, 0x53, 0x51, 0x4c, 0x4c,
0xa1, 0x3a, 0x79, 0xe6, 0xb9, 0x27, 0x3d, 0x12, 0xc6, 0x1c, 0x96, 0x42, 0xe8, 0xc4, 0x4c, 0x3b,
0xfe, 0x03, 0x7d, 0x7d, 0xd6, 0xba, 0xae, 0xd7, 0x53, 0xc6, 0x7f, 0x17, 0xa6, 0x45, 0x6e, 0x22,
0xf3, 0xf7, 0x07, 0x71, 0x31, 0x3a, 0xaf, 0x18, 0xd4, 0x44, 0x26, 0x23, 0x57, 0xb1, 0xc3, 0x92,
0xcd, 0x98, 0x7a, 0xa2, 0x39, 0x53, 0x47, 0x6f, 0xc2, 0x94, 0xcb, 0x96, 0x70, 0x5f, 0xac, 0x24,
0xb3, 0x42, 0x2e, 0xad, 0xf9, 0x72, 0x48, 0x1c, 0xc1, 0x85, 0xdf, 0x81, 0x92, 0x86, 0xc0, 0x92,
0xdd, 0xc7, 0x8d, 0x26, 0xcd, 0x80, 0xcb, 0x30, 0x5b, 0xdb, 0x6a, 0x6e, 0x1f, 0x8a, 0x1c, 0xb8,
0x02, 0x50, 0x6f, 0x84, 0xe3, 0x1c, 0xcd, 0x82, 0xc4, 0x2a, 0xe9, 0xe1, 0xba, 0x3e, 0x56, 0x9a,
0x3e, 0xb9, 0x4b, 0xe9, 0xf3, 0x02, 0xe6, 0xe4, 0xf6, 0x33, 0xdd, 0x81, 0xb7, 0xa8, 0x85, 0x99,
0x18, 0x75, 0x05, 0x96, 0x0d, 0xb0, 0xca, 0x3b, 0x05, 0x23, 0xa6, 0xd9, 0xc3, 0x41, 0xe0, 0x06,
0x23, 0x5f, 0x5d, 0x81, 0xdf, 0x5b, 0x50, 0x51, 0x94, 0xac, 0xd5, 0xbb, 0x2a, 0x91, 0x44, 0xcc,
0x0b, 0x0b, 0xa4, 0x1b, 0x30, 0xdd, 0x3e, 0x3e, 0xe8, 0x7c, 0xaa, 0xba, 0x18, 0x72, 0xc4, 0xe8,
0x5d, 0x81, 0x23, 0x5a, 0x68, 0x72, 0xc4, 0x72, 0x6f, 0xd6, 0x4c, 0xdb, 0xee, 0xb7, 0xc9, 0x0b,
0xfe, 0xa6, 0x2d, 0x38, 0x11, 0x81, 0xa7, 0xcb, 0xb2, 0xd5, 0xc6, 0xeb, 0x27, 0xbd, 0xf5, 0x46,
0x2f, 0x79, 0x6d, 0x14, 0x9c, 0x36, 0xfa, 0xac, 0xcb, 0xa4, 0x76, 0xb8, 0x08, 0x88, 0x11, 0xeb,
0x1d, 0x5f, 0xa7, 0x36, 0x60, 0x81, 0x51, 0xe9, 0xbd, 0xa7, 0xc9, 0x74, 0x14, 0x31, 0x54, 0xd8,
0xb6, 0x12, 0x61, 0xdb, 0xf5, 0xfd, 0xe7, 0x03, 0xaf, 0x2d, 0xb7, 0x16, 0x8e, 0x71, 0x5d, 0x08,
0x7f, 0xea, 0xc7, 0x02, 0xf3, 0x57, 0x95, 0xf2, 0x28, 0x92, 0xf2, 0x98, 0x04, 0x13, 0xa4, 0xe0,
0xd7, 0xe1, 0xba, 0xe2, 0x94, 0x35, 0xf4, 0x04, 0xe6, 0x7d, 0xb8, 0xa5, 0x98, 0xb7, 0x4e, 0x59,
0xa2, 0xf7, 0x44, 0x02, 0xfe, 0xb7, 0x7a, 0x6e, 0xc2, 0x52, 0xa8, 0x27, 0xcf, 0x41, 0x06, 0x5d,
0x5d, 0x81, 0x91, 0x2f, 0xef, 0x0c, 0x95, 0xc5, 0x9e, 0x19, 0xcd, 0xa3, 0x2c, 0xea, 0x25, 0xc8,
0x9e, 0xf1, 0x16, 0x2c, 0x2b, 0x19, 0x32, 0x3b, 0x88, 0x0b, 0x19, 0x53, 0xc8, 0x24, 0x44, 0x1a,
0x8c, 0x2d, 0x9d, 0x6c, 0x76, 0x9d, 0x33, 0x6e, 0x5a, 0x2e, 0xd3, 0xd2, 0x64, 0x5e, 0x17, 0x37,
0x82, 0x29, 0xa6, 0x07, 0x6d, 0x49, 0x66, 0x02, 0x74, 0xb2, 0x3c, 0x08, 0x46, 0x1e, 0x3b, 0x88,
0x31, 0xd1, 0xdf, 0x83, 0xd5, 0x50, 0x09, 0x66, 0xb7, 0x27, 0xf4, 0xb2, 0x76, 0x7c, 0x5f, 0x2b,
0x02, 0x4d, 0x1b, 0x7f, 0x00, 0x85, 0x21, 0x91, 0x31, 0xa5, 0xb4, 0x81, 0xd6, 0x45, 0x43, 0x7c,
0x5d, 0x5b, 0xcc, 0xe7, 0x71, 0x1b, 0x6e, 0x2b, 0xe9, 0xc2, 0xa2, 0x46, 0xf1, 0x49, 0xa5, 0x54,
0x81, 0x20, 0xcc, 0x3a, 0x5e, 0x20, 0xe4, 0xc5, 0xd9, 0x87, 0xad, 0xbe, 0xf7, 0x85, 0x21, 0x95,
0x6f, 0x65, 0x7a, 0x57, 0xec, 0x08, 0x9b, 0x86, 0x2e, 0x99, 0x49, 0xd8, 0x31, 0x2c, 0xc6, 0x3d,
0x39, 0x53, 0x18, 0xa3, 0x59, 0x6f, 0x40, 0x4d, 0xa8, 0x82, 0x98, 0x18, 0x28, 0x85, 0x43, 0x37,
0xcf, 0xa4, 0xb0, 0x1b, 0x09, 0xe3, 0x57, 0x32, 0xab, 0xbe, 0xec, 0x34, 0x55, 0x3e, 0x23, 0x06,
0x78, 0x0f, 0x6e, 0x24, 0xc3, 0x44, 0x26, 0x95, 0x0f, 0xc5, 0x05, 0x36, 0x45, 0x92, 0x4c, 0x72,
0x3f, 0x8c, 0x82, 0x81, 0x16, 0x50, 0x32, 0x89, 0x74, 0xc0, 0x36, 0xc5, 0x97, 0xff, 0xc5, 0x7d,
0x0d, 0xc3, 0x4d, 0x26, 0x61, 0x7e, 0x24, 0x2c, 0xfb, 0xf1, 0x47, 0x31, 0x22, 0x3f, 0x31, 0x46,
0x48, 0x27, 0x89, 0xa2, 0xd8, 0xd7, 0x70, 0xe9, 0x24, 0x46, 0x14, 0x40, 0xb3, 0x62, 0xb0, 0x77,
0x48, 0x88, 0xc1, 0x07, 0xea, 0x62, 0xeb, 0x61, 0x37, 0xd3, 0x61, 0x7c, 0x14, 0xc5, 0xce, 0xb1,
0xc8, 0x9c, 0x49, 0xf0, 0xc7, 0xb0, 0x96, 0x1e, 0x94, 0xb3, 0x48, 0x7e, 0x0d, 0x43, 0x31, 0x4c,
0x28, 0xb5, 0x8f, 0x67, 0x25, 0x98, 0xd9, 0xdb, 0x3f, 0x78, 0x52, 0xdb, 0xa2, 0xa9, 0xec, 0xc6,
0x9f, 0xf3, 0x90, 0xdb, 0x39, 0x44, 0xdf, 0x87, 0x29, 0xd1, 0xfc, 0x9f, 0xf0, 0x6d, 0xc4, 0x9e,
0xf4, 0x19, 0x01, 0xaf, 0x7c, 0xfe, 0xa7, 0xbf, 0x7d, 0x99, 0xbb, 0x81, 0xaf, 0x55, 0xcf, 0xdf,
0x76, 0xbb, 0xc3, 0x53, 0xb7, 0x7a, 0x76, 0x5e, 0xe5, 0xef, 0x84, 0x6f, 0x5a, 0xaf, 0xa1, 0x43,
0xc8, 0xb3, 0x4f, 0x03, 0xa9, 0x1f, 0x4e, 0xec, 0xf4, 0xcf, 0x0b, 0xd8, 0xe6, 0x92, 0x17, 0xf1,
0x55, 0x5d, 0xf2, 0x70, 0x14, 0x30, 0xb9, 0x4d, 0x28, 0x69, 0x5f, 0x08, 0xd0, 0x85, 0x9f, 0x54,
0xec, 0x8b, 0xbf, 0x3e, 0xe0, 0x2b, 0x4c, 0xdb, 0xe6, 0x8b, 0x7e, 0x52, 0xdb, 0xa8, 0xa3, 0x9d,
0xd4, 0x56, 0xeb, 0x22, 0x9b, 0xb5, 0x0d, 0x5e, 0xf4, 0x99, 0xb6, 0x03, 0xf9, 0xcd, 0xa2, 0x15,
0xa0, 0xdb, 0x86, 0x16, 0xb8, 0xde, 0xec, 0xb5, 0xd7, 0xd2, 0x19, 0x24, 0xd2, 0x1d, 0x8e, 0x74,
0x13, 0xdf, 0xd0, 0x91, 0x5a, 0x21, 0x1f, 0x05, 0xdc, 0x38, 0x85, 0x29, 0xde, 0x29, 0x43, 0x47,
0xea, 0xc1, 0x36, 0xf4, 0x11, 0x53, 0xce, 0x37, 0xd6, 0x63, 0xc3, 0xcb, 0x1c, 0x6d, 0x01, 0x57,
0x42, 0x34, 0xde, 0x2c, 0xa3, 0x28, 0x8f, 0xac, 0xff, 0xb3, 0x36, 0xfe, 0x95, 0x83, 0x29, 0xde,
0x52, 0x41, 0x43, 0x80, 0xa8, 0xf7, 0x94, 0xdc, 0xe7, 0x58, 0x37, 0x2b, 0xb9, 0xcf, 0xf1, 0xb6,
0x15, 0xbe, 0xcd, 0x91, 0x97, 0xf1, 0x62, 0x88, 0xcc, 0x3f, 0x6e, 0x56, 0x4f, 0x18, 0x17, 0x33,
0xeb, 0x73, 0x28, 0x69, 0x3d, 0x24, 0x64, 0x92, 0x18, 0x6b, 0x42, 0x25, 0x2f, 0x81, 0xa1, 0x01,
0x85, 0xef, 0x72, 0xd0, 0x5b, 0x78, 0x49, 0x37, 0xae, 0xc0, 0xf5, 0x38, 0x27, 0x03, 0xfe, 0x31,
0x2d, 0x89, 0xe2, 0x7d, 0x24, 0x74, 0xd7, 0x20, 0x3a, 0xd9, 0x8e, 0xb2, 0xef, 0x4d, 0x66, 0x4a,
0x55, 0x41, 0xe0, 0x9f, 0x51, 0x4e, 0x97, 0x71, 0x2a, 0xdb, 0xff, 0x9b, 0x7d, 0x0b, 0x13, 0xbf,
0x55, 0x40, 0x01, 0x14, 0xc3, 0x6e, 0x0e, 0x5a, 0x35, 0x55, 0xfa, 0x51, 0x1a, 0x6c, 0xdf, 0x4e,
0x9d, 0x97, 0x2a, 0x3c, 0xe0, 0x2a, 0xac, 0xe1, 0x9b, 0xa1, 0x0a, 0xf2, 0x37, 0x11, 0x55, 0x51,
0xd0, 0x56, 0xdd, 0x76, 0x9b, 0x19, 0xe2, 0x47, 0xb4, 0xa4, 0xd7, 0x9b, 0x34, 0xe8, 0x8e, 0xb1,
0xc7, 0xa0, 0xf7, 0x79, 0x6c, 0x3c, 0x89, 0x45, 0xe2, 0xbf, 0xca, 0xf1, 0xef, 0xe2, 0xd5, 0x34,
0x7c, 0x8f, 0xf3, 0xc7, 0x55, 0x10, 0x6d, 0x19, 0xb3, 0x0a, 0xb1, 0xae, 0x8f, 0x59, 0x85, 0x78,
0x57, 0xe7, 0x62, 0x15, 0x46, 0x9c, 0x9f, 0xa9, 0xf0, 0x02, 0x20, 0xea, 0xda, 0x20, 0xa3, 0x71,
0xb5, 0xc2, 0x20, 0x79, 0xf3, 0xc7, 0x1b, 0x3e, 0xf8, 0x21, 0xc7, 0xbe, 0x83, 0x57, 0xd2, 0xb0,
0xbb, 0x94, 0x9b, 0xf9, 0xf9, 0x6f, 0x0b, 0x50, 0xfa, 0xc0, 0xed, 0xf4, 0x03, 0xd2, 0x67, 0xcd,
0x68, 0x74, 0x02, 0x53, 0x3c, 0xf2, 0x27, 0xdd, 0x5d, 0x6f, 0xa5, 0x24, 0xdd, 0x3d, 0xd6, 0x67,
0xc0, 0xf7, 0x39, 0xf4, 0x6d, 0x6c, 0x87, 0xd0, 0xbd, 0x48, 0x7e, 0x95, 0xf7, 0x08, 0xd8, 0x96,
0xcf, 0x60, 0x5a, 0xf4, 0x04, 0x50, 0x42, 0x5a, 0xac, 0x77, 0x60, 0xaf, 0x98, 0x27, 0x53, 0x6f,
0x99, 0x8e, 0xe5, 0x73, 0x66, 0x06, 0xf6, 0x03, 0x80, 0xa8, 0x09, 0x95, 0xb4, 0xef, 0x58, 0xcf,
0xca, 0x5e, 0x4b, 0x67, 0x90, 0xc0, 0xaf, 0x71, 0xe0, 0x7b, 0xf8, 0xb6, 0x11, 0xb8, 0x1d, 0x2e,
0x60, 0xe0, 0x2d, 0x28, 0xb0, 0x2f, 0x5d, 0x28, 0x11, 0xfa, 0xb5, 0x8f, 0x61, 0xb6, 0x6d, 0x9a,
0x92, 0x50, 0xf7, 0x38, 0xd4, 0x2a, 0x5e, 0x36, 0x42, 0xb1, 0x2f, 0x5e, 0x0c, 0x64, 0x04, 0xb3,
0xea, 0x03, 0x17, 0xba, 0x95, 0xb0, 0x59, 0xfc, 0x63, 0x98, 0xbd, 0x9a, 0x36, 0x2d, 0x01, 0x1f,
0x71, 0x40, 0x8c, 0x6f, 0x99, 0x8d, 0x2a, 0xd9, 0x29, 0x28, 0x0d, 0x20, 0x3f, 0x9d, 0x87, 0x02,
0xcb, 0x41, 0x58, 0xec, 0x8e, 0x4a, 0xb7, 0xa4, 0x85, 0xc7, 0x1a, 0x26, 0x49, 0x0b, 0x8f, 0x57,
0x7d, 0x86, 0xd8, 0xcd, 0x7f, 0xb1, 0x45, 0x38, 0x17, 0xdb, 0x71, 0x00, 0x25, 0xad, 0xc0, 0x43,
0x06, 0x89, 0xf1, 0x76, 0x4c, 0x32, 0x76, 0x1b, 0xaa, 0x43, 0xbc, 0xc6, 0x41, 0x6d, 0x7c, 0x3d,
0x0e, 0xda, 0x16, 0x6c, 0x0c, 0xf5, 0x87, 0x50, 0xd6, 0x2b, 0x41, 0x64, 0x10, 0x9a, 0xe8, 0xf7,
0x24, 0x63, 0x85, 0xa9, 0x90, 0x34, 0x38, 0x4d, 0xf8, 0xfb, 0x34, 0xc5, 0xcb, 0xd0, 0x3f, 0x81,
0x19, 0x59, 0x1f, 0x9a, 0xf6, 0x1b, 0xef, 0x10, 0x99, 0xf6, 0x9b, 0x28, 0x2e, 0x0d, 0x89, 0x00,
0x87, 0x65, 0x79, 0xb0, 0x0a, 0xd0, 0x12, 0x92, 0x96, 0x11, 0x69, 0x90, 0x51, 0xcf, 0x23, 0x0d,
0x52, 0xab, 0x41, 0x26, 0x42, 0x9e, 0x90, 0x40, 0xde, 0x65, 0x95, 0xe0, 0xa3, 0x14, 0x89, 0x7a,
0x34, 0xc4, 0x93, 0x58, 0x24, 0x2a, 0xe6, 0xa8, 0x2b, 0xf8, 0x15, 0x03, 0xaa, 0x0c, 0x85, 0xe8,
0x33, 0x80, 0xa8, 0x98, 0x4d, 0xbe, 0x8e, 0x8d, 0x1d, 0xb1, 0xe4, 0xeb, 0xd8, 0x5c, 0x0f, 0x1b,
0x3c, 0x38, 0x02, 0x17, 0x3f, 0x73, 0x61, 0xf0, 0x3f, 0xb7, 0x00, 0x8d, 0x17, 0xbf, 0xe8, 0x75,
0x33, 0x84, 0xb1, 0xd9, 0x66, 0xbf, 0x71, 0x39, 0xe6, 0xd4, 0xe8, 0x19, 0xe9, 0xd5, 0xe2, 0x4b,
0x86, 0xcf, 0x99, 0x66, 0x5f, 0x58, 0x30, 0x17, 0x2b, 0x9f, 0xd1, 0x83, 0x94, 0x73, 0x4e, 0x34,
0xec, 0xec, 0x87, 0x17, 0xf2, 0xa5, 0x66, 0x2c, 0xda, 0xad, 0x50, 0xd9, 0xda, 0x4f, 0x68, 0xd2,
0x14, 0xaf, 0xb9, 0x51, 0x0a, 0xc0, 0x58, 0xd7, 0xcf, 0x7e, 0x74, 0x31, 0xe3, 0x25, 0x4e, 0x2b,
0x4a, 0xe0, 0xa8, 0x5b, 0xc8, 0x52, 0xdd, 0xe4, 0x16, 0xf1, 0xa6, 0xa1, 0xc9, 0x2d, 0x12, 0x75,
0x7e, 0x9a, 0x5b, 0xb0, 0xaa, 0x57, 0xf3, 0x44, 0x59, 0xd0, 0xa7, 0x41, 0x4e, 0xf6, 0xc4, 0x44,
0x37, 0x60, 0x22, 0x64, 0xe4, 0x89, 0xaa, 0x9c, 0x47, 0x29, 0x12, 0x2f, 0xf0, 0xc4, 0x64, 0x37,
0x20, 0xcd, 0x13, 0x39, 0xaa, 0xe6, 0x89, 0x51, 0xf5, 0x6d, 0xf2, 0xc4, 0xb1, 0x96, 0xa8, 0xc9,
0x13, 0xc7, 0x0b, 0xf8, 0xb4, 0xb3, 0xe5, 0xe0, 0x31, 0x4f, 0x5c, 0x30, 0x54, 0xeb, 0xe8, 0x8d,
0x14, 0x9b, 0x1a, 0xdb, 0xad, 0xf6, 0x9b, 0x97, 0xe4, 0x9e, 0xec, 0x01, 0xe2, 0x34, 0x94, 0x07,
0xfc, 0xca, 0x82, 0x45, 0x53, 0xb9, 0x8f, 0x52, 0xc0, 0x52, 0x7a, 0xb5, 0xf6, 0xfa, 0x65, 0xd9,
0x2f, 0x61, 0xb7, 0xd0, 0x27, 0x36, 0xcb, 0xbf, 0xfb, 0xeb, 0xaa, 0xf5, 0x47, 0xfa, 0xef, 0x2f,
0xf4, 0xdf, 0xf1, 0x34, 0xff, 0xc9, 0xf4, 0xdb, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xf7, 0xeb,
0x93, 0xc8, 0xb9, 0x2d, 0x00, 0x00,
// 3116 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0x4b, 0x73, 0x24, 0x47,
0x11, 0xde, 0x79, 0xe8, 0x31, 0x39, 0xa3, 0x59, 0x6d, 0x49, 0xbb, 0x1e, 0xf5, 0x6a, 0xb5, 0xda,
0xda, 0xa7, 0x5f, 0x1a, 0x2c, 0x1b, 0x0e, 0x40, 0x38, 0x62, 0xa4, 0x19, 0xd6, 0xb2, 0x64, 0x69,
0xdd, 0x9a, 0x95, 0x4d, 0x04, 0x81, 0xa2, 0x35, 0x53, 0x2b, 0x4d, 0x68, 0x5e, 0xee, 0xee, 0xd1,
0x4a, 0x06, 0x22, 0x08, 0x07, 0x3e, 0xc0, 0xd5, 0x07, 0x02, 0x38, 0xf2, 0x1b, 0xb8, 0xf1, 0x03,
0x08, 0x2e, 0x38, 0x82, 0x23, 0x17, 0x82, 0xe0, 0xc0, 0x81, 0x3b, 0xc1, 0x09, 0xea, 0xd9, 0x5d,
0xdd, 0x53, 0x3d, 0x92, 0x69, 0x7c, 0xd8, 0x55, 0x57, 0x56, 0x56, 0x7e, 0x59, 0x59, 0x95, 0xd9,
0x99, 0xd9, 0x03, 0x05, 0x77, 0xd8, 0x5a, 0x1b, 0xba, 0x03, 0x7f, 0x80, 0x4a, 0xc4, 0x6f, 0xb5,
0x3d, 0xe2, 0x9e, 0x11, 0x77, 0x78, 0x64, 0x2d, 0x1e, 0x0f, 0x8e, 0x07, 0x7c, 0xa2, 0xca, 0x9e,
0x04, 0x8f, 0xb5, 0xc4, 0x78, 0xaa, 0xbd, 0xb3, 0x56, 0x8b, 0xff, 0x37, 0x3c, 0xaa, 0x9e, 0x9e,
0xc9, 0xa9, 0xdb, 0x7c, 0xca, 0x19, 0xf9, 0x27, 0xfc, 0x3f, 0x3a, 0xc5, 0xfe, 0xc8, 0xc9, 0xe5,
0xe3, 0xc1, 0xe0, 0xb8, 0x4b, 0xaa, 0xce, 0xb0, 0x53, 0x75, 0xfa, 0xfd, 0x81, 0xef, 0xf8, 0x9d,
0x41, 0xdf, 0x13, 0xb3, 0xf8, 0xf3, 0x0c, 0x94, 0x6d, 0xe2, 0x0d, 0x29, 0x85, 0xbc, 0x47, 0x9c,
0x36, 0x71, 0xd1, 0x1d, 0x80, 0x56, 0x77, 0xe4, 0xf9, 0xc4, 0x3d, 0xec, 0xb4, 0x2b, 0x99, 0xd5,
0xcc, 0x93, 0xbc, 0x5d, 0x90, 0x94, 0xad, 0x36, 0xba, 0x0d, 0x85, 0x1e, 0xe9, 0x1d, 0x89, 0xd9,
0x2c, 0x9f, 0x9d, 0x15, 0x04, 0x3a, 0x69, 0xc1, 0xac, 0x4b, 0xce, 0x3a, 0x1e, 0x45, 0xa8, 0xe4,
0xe8, 0x5c, 0xce, 0x0e, 0xc6, 0x6c, 0xa1, 0xeb, 0xbc, 0xf0, 0x0f, 0xa9, 0x98, 0x5e, 0x25, 0x2f,
0x16, 0x32, 0x42, 0x93, 0x8e, 0xf1, 0x97, 0x39, 0x28, 0xd9, 0x4e, 0xff, 0x98, 0xd8, 0xe4, 0x93,
0x11, 0xf1, 0x7c, 0x34, 0x0f, 0xb9, 0x53, 0x72, 0xc1, 0xe1, 0x4b, 0x36, 0x7b, 0x14, 0xeb, 0x29,
0xc7, 0x21, 0xe9, 0x0b, 0xe0, 0x12, 0x5b, 0x4f, 0x09, 0x8d, 0x7e, 0x1b, 0x2d, 0xc2, 0x54, 0xb7,
0xd3, 0xeb, 0xf8, 0x12, 0x55, 0x0c, 0x22, 0xea, 0xe4, 0x63, 0xea, 0x6c, 0x02, 0x78, 0x03, 0xd7,
0x3f, 0x1c, 0xb8, 0x74, 0xd3, 0x95, 0x29, 0x3a, 0x5b, 0x5e, 0x7f, 0xb0, 0xa6, 0x1f, 0xc4, 0x9a,
0xae, 0xd0, 0xda, 0x3e, 0x65, 0xde, 0x63, 0xbc, 0x76, 0xc1, 0x53, 0x8f, 0xe8, 0x7b, 0x50, 0xe4,
0x42, 0x7c, 0xc7, 0x3d, 0x26, 0x7e, 0x65, 0x9a, 0x4b, 0x79, 0x78, 0x89, 0x94, 0x26, 0x67, 0xb6,
0x39, 0xbc, 0x78, 0x46, 0x18, 0x4a, 0x94, 0xbf, 0xe3, 0x74, 0x3b, 0x9f, 0x3a, 0x47, 0x5d, 0x52,
0x99, 0xa1, 0x82, 0x66, 0xed, 0x08, 0x8d, 0xed, 0x9f, 0x9a, 0xc1, 0x3b, 0x1c, 0xf4, 0xbb, 0x17,
0x95, 0x59, 0xce, 0x30, 0xcb, 0x08, 0x7b, 0x74, 0xcc, 0x0f, 0x6d, 0x30, 0xea, 0xfb, 0x62, 0xb6,
0xc0, 0x67, 0x0b, 0x9c, 0xc2, 0xa6, 0xf1, 0x1a, 0x14, 0x02, 0xfd, 0xd1, 0x2c, 0xe4, 0x77, 0xf7,
0x76, 0x1b, 0xf3, 0xd7, 0x10, 0xc0, 0x74, 0x6d, 0x7f, 0xb3, 0xb1, 0x5b, 0x9f, 0xcf, 0xa0, 0x22,
0xcc, 0xd4, 0x1b, 0x62, 0x90, 0xc5, 0x1b, 0x00, 0xa1, 0xa6, 0x68, 0x06, 0x72, 0xdb, 0x8d, 0xef,
0x53, 0x7e, 0xca, 0x73, 0xd0, 0xb0, 0xf7, 0xb7, 0xf6, 0x76, 0xe9, 0x02, 0xba, 0x78, 0xd3, 0x6e,
0xd4, 0x9a, 0x8d, 0xf9, 0x2c, 0xe3, 0xf8, 0x60, 0xaf, 0x3e, 0x9f, 0x43, 0x05, 0x98, 0x3a, 0xa8,
0xed, 0x3c, 0x6f, 0xcc, 0xe7, 0xf1, 0x17, 0x19, 0x98, 0x93, 0x7b, 0x17, 0xf7, 0x0b, 0xbd, 0x03,
0xd3, 0x27, 0xfc, 0x8e, 0xf1, 0x63, 0x2d, 0xae, 0x2f, 0xc7, 0x0c, 0x15, 0xb9, 0x87, 0xb6, 0xe4,
0xa5, 0xb6, 0xc9, 0x9d, 0x9e, 0x79, 0xf4, 0xc4, 0x73, 0x74, 0xc9, 0xfc, 0x9a, 0xb8, 0xfc, 0x6b,
0xdb, 0xe4, 0xe2, 0xc0, 0xe9, 0x8e, 0x88, 0xcd, 0x26, 0x11, 0x82, 0x7c, 0x6f, 0xe0, 0x12, 0x7e,
0xfa, 0xb3, 0x36, 0x7f, 0x66, 0x57, 0x82, 0x1b, 0x40, 0x9e, 0xbc, 0x18, 0xe0, 0xf7, 0x01, 0x9e,
0x8d, 0xfc, 0xe4, 0x5b, 0x46, 0x57, 0x9d, 0x31, 0xb9, 0xf2, 0x86, 0x89, 0x01, 0xbf, 0x5e, 0xc4,
0xf1, 0x48, 0x70, 0xbd, 0xd8, 0x00, 0x6f, 0x42, 0x91, 0xcb, 0x4a, 0xb3, 0x3d, 0x2a, 0x04, 0xd5,
0x49, 0x97, 0xf8, 0x24, 0xc5, 0xf5, 0xc7, 0x04, 0x16, 0x22, 0x42, 0x52, 0x19, 0xbc, 0x02, 0x33,
0x6d, 0x2e, 0x4c, 0xe0, 0xe4, 0x6c, 0x35, 0xc4, 0xff, 0xcc, 0x40, 0x41, 0x6a, 0xb8, 0x37, 0x44,
0x35, 0x98, 0x73, 0xc5, 0xe0, 0x90, 0x2b, 0x22, 0x41, 0xac, 0xe4, 0xeb, 0xff, 0xde, 0x35, 0xbb,
0x24, 0x97, 0x70, 0x32, 0xfa, 0x0e, 0x14, 0x95, 0x88, 0xe1, 0xc8, 0xe7, 0x70, 0xc5, 0xf5, 0x4a,
0x54, 0x40, 0x78, 0x5c, 0x74, 0x39, 0x48, 0x76, 0x4a, 0x44, 0x4d, 0x58, 0x54, 0x8b, 0x85, 0x82,
0x52, 0x8d, 0x1c, 0x97, 0xb2, 0x1a, 0x95, 0x32, 0x6e, 0x63, 0x2a, 0x0d, 0xc9, 0xf5, 0xda, 0xe4,
0x46, 0x01, 0x66, 0x24, 0x15, 0xff, 0x2b, 0x03, 0xa0, 0x6c, 0x44, 0xf7, 0x5b, 0x87, 0xb2, 0x2b,
0x47, 0x91, 0x0d, 0xdf, 0x36, 0x6e, 0x58, 0x9a, 0xf6, 0x9a, 0x3d, 0xa7, 0x16, 0x89, 0x2d, 0xbf,
0x0b, 0xa5, 0x40, 0x4a, 0xb8, 0xe7, 0x25, 0xc3, 0x9e, 0x03, 0x09, 0x45, 0xb5, 0x80, 0xed, 0xfa,
0x23, 0xb8, 0x19, 0xac, 0x37, 0x6c, 0xfb, 0xde, 0x84, 0x6d, 0x07, 0x02, 0x17, 0x94, 0x04, 0x7d,
0xe3, 0xc0, 0x82, 0xa5, 0x20, 0xe3, 0x5f, 0xe7, 0x60, 0x66, 0x73, 0xd0, 0x1b, 0x3a, 0x2e, 0x3b,
0xa3, 0x69, 0x4a, 0x1f, 0x75, 0x7d, 0xbe, 0xdd, 0xf2, 0xfa, 0xfd, 0x28, 0x82, 0x64, 0x53, 0x7f,
0x6d, 0xce, 0x6a, 0xcb, 0x25, 0x6c, 0xb1, 0x8c, 0x8d, 0xd9, 0x2b, 0x2c, 0x96, 0x91, 0x51, 0x2e,
0x51, 0x4e, 0x90, 0x0b, 0x9d, 0xc0, 0x82, 0x19, 0xba, 0x30, 0x8c, 0xe7, 0x74, 0x2f, 0x8a, 0x80,
0x5e, 0x85, 0xeb, 0x2d, 0x97, 0x38, 0xcc, 0x1e, 0x2a, 0xe6, 0x4f, 0x49, 0x9e, 0xb2, 0x98, 0xb0,
0x55, 0xec, 0xbf, 0x0f, 0xa5, 0xde, 0xa0, 0x1d, 0xf2, 0x4d, 0x4b, 0xbe, 0x22, 0xa5, 0x06, 0x4c,
0xb7, 0x54, 0x24, 0x60, 0xc1, 0xb8, 0x44, 0x67, 0xc5, 0x10, 0xbf, 0x05, 0x73, 0x91, 0xbd, 0xb2,
0x98, 0xd7, 0xf8, 0xf0, 0x79, 0x6d, 0x47, 0x04, 0xc8, 0xa7, 0x3c, 0x26, 0xda, 0x34, 0x40, 0xd2,
0x38, 0xbb, 0xd3, 0xd8, 0xdf, 0xa7, 0xe1, 0xf4, 0xbb, 0xc1, 0x12, 0x19, 0x51, 0xb5, 0x40, 0x7a,
0x4d, 0x0b, 0xa4, 0x19, 0x15, 0x48, 0xb3, 0x61, 0x20, 0xcd, 0x6d, 0x94, 0xa1, 0x24, 0x0c, 0x72,
0x38, 0xea, 0x53, 0xc5, 0xf0, 0x6f, 0xe9, 0xb5, 0x6c, 0x9e, 0xf7, 0x55, 0xa8, 0xa8, 0xc2, 0x4c,
0x4b, 0x08, 0xa7, 0x07, 0xc4, 0x62, 0xe4, 0x4d, 0xa3, 0x8d, 0x6d, 0xc5, 0x85, 0xde, 0x82, 0x19,
0x6f, 0xd4, 0x6a, 0x11, 0x4f, 0x05, 0xd5, 0x57, 0xe2, 0x61, 0x41, 0x7a, 0xb8, 0xad, 0xf8, 0xd8,
0x92, 0x17, 0x4e, 0xa7, 0x3b, 0xe2, 0x21, 0x76, 0xf2, 0x12, 0xc9, 0x87, 0x7f, 0x95, 0x81, 0x22,
0xd7, 0x32, 0x55, 0x2c, 0x5a, 0x86, 0x02, 0xd7, 0x81, 0xb4, 0x65, 0x34, 0xa2, 0xaf, 0xb5, 0x80,
0x80, 0xbe, 0x45, 0x63, 0xa2, 0x5c, 0xe7, 0x49, 0xc5, 0x2a, 0x66, 0xb1, 0x54, 0xb3, 0x90, 0x15,
0x6f, 0xc3, 0x0d, 0x6e, 0x95, 0x16, 0x4b, 0x85, 0x94, 0x1d, 0xf5, 0x64, 0x21, 0x13, 0x4b, 0x16,
0xe8, 0xdc, 0xf0, 0xe4, 0xc2, 0xeb, 0xb4, 0x9c, 0xae, 0xd4, 0x22, 0x18, 0xd3, 0x37, 0x0a, 0xd2,
0x85, 0xa5, 0x7a, 0x19, 0xcc, 0x41, 0xf1, 0x3d, 0xc7, 0x3b, 0x91, 0x2a, 0xe1, 0x8f, 0xa1, 0x24,
0x86, 0xa9, 0x6c, 0x48, 0x5f, 0x8e, 0x27, 0x54, 0x0a, 0x57, 0x7c, 0xce, 0xe6, 0xcf, 0xf8, 0x06,
0x5c, 0xdf, 0xef, 0x3b, 0x43, 0xef, 0x64, 0xa0, 0x82, 0x2b, 0x4b, 0x05, 0xe7, 0x43, 0x5a, 0x2a,
0xc4, 0xc7, 0x70, 0xdd, 0x25, 0x3d, 0xa7, 0xd3, 0xef, 0xf4, 0x8f, 0x0f, 0x8f, 0x2e, 0x7c, 0xe2,
0xc9, 0x4c, 0xb1, 0x1c, 0x90, 0x37, 0x18, 0x95, 0xa9, 0x76, 0xd4, 0x1d, 0x1c, 0x49, 0x17, 0xe7,
0xcf, 0xf8, 0x77, 0x19, 0x28, 0x7d, 0xe4, 0xf8, 0x2d, 0x65, 0x05, 0xb4, 0x05, 0xe5, 0xc0, 0xb1,
0x39, 0x45, 0xea, 0x12, 0x8b, 0xf0, 0x7c, 0xcd, 0xa6, 0x74, 0x74, 0x15, 0xe1, 0xe7, 0x5a, 0x3a,
0x81, 0x8b, 0x72, 0xfa, 0x2d, 0xd2, 0x0d, 0x44, 0x65, 0x93, 0x45, 0x71, 0x46, 0x5d, 0x94, 0x4e,
0xd8, 0xb8, 0x1e, 0xbe, 0xfd, 0x84, 0x5b, 0xd2, 0x7c, 0x07, 0x8d, 0xeb, 0xf0, 0x55, 0x13, 0xd9,
0x87, 0x50, 0xf6, 0xa8, 0xb7, 0xfb, 0x87, 0xb1, 0x3c, 0x7a, 0x8e, 0x53, 0x83, 0xe0, 0x44, 0x2d,
0x4c, 0x13, 0xf8, 0x63, 0x7a, 0xa5, 0xbd, 0x43, 0x9a, 0xd3, 0x77, 0x5e, 0x5c, 0xf0, 0x80, 0x38,
0x6b, 0x97, 0x15, 0x79, 0x97, 0x53, 0x71, 0x55, 0x29, 0xa5, 0x2b, 0x8f, 0x96, 0x60, 0xf6, 0x25,
0xa3, 0xaa, 0x0c, 0x9f, 0xbe, 0xe3, 0xf9, 0x78, 0xab, 0x8d, 0xff, 0x41, 0xd3, 0x36, 0x69, 0xfe,
0x54, 0x77, 0x40, 0x87, 0xc8, 0x46, 0x20, 0x58, 0x82, 0x21, 0x8e, 0xa5, 0x2d, 0x13, 0x36, 0x35,
0x64, 0x7e, 0x26, 0xac, 0x4c, 0xa7, 0xc4, 0x7e, 0x82, 0x31, 0x8d, 0xef, 0xf3, 0x2d, 0xe1, 0x67,
0xb1, 0x00, 0x6f, 0x5f, 0x97, 0xf4, 0xc0, 0x3a, 0x0f, 0x61, 0x9a, 0x9c, 0x91, 0xbe, 0xef, 0x55,
0x8a, 0x3c, 0x28, 0xcc, 0xa9, 0xac, 0xb1, 0xc1, 0xa8, 0xb6, 0x9c, 0xc4, 0xdf, 0x84, 0x1b, 0x3b,
0x2c, 0x91, 0x7b, 0x4a, 0xad, 0xaf, 0xa7, 0x84, 0xcd, 0xe6, 0x8e, 0xb4, 0x4a, 0xce, 0x6f, 0xee,
0xa0, 0x32, 0x64, 0xb7, 0xea, 0x72, 0x0f, 0xd9, 0x4e, 0x1d, 0x7f, 0x46, 0x0f, 0x5a, 0x5f, 0x97,
0xca, 0x4c, 0x31, 0xe1, 0x0a, 0x3e, 0x17, 0xc2, 0xd3, 0xdc, 0x93, 0xb8, 0xee, 0xc0, 0xe5, 0x06,
0x29, 0xd8, 0x62, 0x80, 0x1f, 0x48, 0x1d, 0xe8, 0x9e, 0x07, 0xa7, 0xc1, 0x65, 0x13, 0xd2, 0x32,
0x81, 0xaa, 0xdb, 0xb0, 0x10, 0xe1, 0x4a, 0x15, 0x9c, 0x1e, 0xc3, 0x4d, 0x2e, 0x6c, 0x9b, 0x90,
0x61, 0xad, 0xdb, 0x39, 0x4b, 0x44, 0x1d, 0xc2, 0xad, 0x38, 0xe3, 0xd7, 0x6b, 0x23, 0x7c, 0x02,
0xd3, 0x1f, 0xf0, 0x1a, 0x54, 0xd3, 0x25, 0xcf, 0x79, 0x69, 0x84, 0xe9, 0x3b, 0x3d, 0x91, 0xce,
0x17, 0x6c, 0xfe, 0xcc, 0xa3, 0x39, 0x21, 0xee, 0x73, 0x7b, 0x47, 0xbc, 0x35, 0x0a, 0x76, 0x30,
0x46, 0x2b, 0xac, 0xfa, 0xed, 0xd0, 0xeb, 0xc1, 0x67, 0xf3, 0x7c, 0x56, 0xa3, 0xd0, 0x4a, 0x6a,
0x5e, 0x20, 0xd5, 0xda, 0x6d, 0xed, 0xcd, 0x11, 0xc8, 0xcb, 0x44, 0xe5, 0xe1, 0x97, 0x70, 0x43,
0xe3, 0x4f, 0x65, 0x86, 0x37, 0x60, 0x5a, 0x14, 0xda, 0x32, 0x68, 0x2d, 0x46, 0x57, 0x09, 0x18,
0x5b, 0xf2, 0xe0, 0x87, 0xb0, 0x20, 0x29, 0xa4, 0x37, 0x30, 0x9d, 0x15, 0xb7, 0x0f, 0xde, 0x81,
0xc5, 0x28, 0x5b, 0xaa, 0x2b, 0x52, 0x53, 0xa0, 0xcf, 0x87, 0x6d, 0x2d, 0x06, 0xc6, 0x0f, 0x45,
0x37, 0x58, 0x36, 0x66, 0xb0, 0x40, 0x21, 0x25, 0x22, 0x95, 0x42, 0x0b, 0xca, 0xfc, 0x3b, 0x1d,
0x2f, 0x78, 0xd3, 0x7d, 0x0a, 0x48, 0x27, 0xa6, 0x3a, 0x94, 0x35, 0x98, 0x11, 0x06, 0x57, 0xc9,
0x94, 0xf9, 0x54, 0x14, 0x13, 0x53, 0xa8, 0x4e, 0x5e, 0xb8, 0xce, 0x71, 0x8f, 0x04, 0x31, 0x87,
0xa5, 0x10, 0x3a, 0x31, 0xd5, 0x8e, 0xff, 0x44, 0x5f, 0x9f, 0xb5, 0xae, 0xe3, 0xf6, 0x94, 0xf1,
0xdf, 0x85, 0x69, 0x91, 0x9b, 0xc8, 0xfc, 0xfd, 0x51, 0x54, 0x8c, 0xce, 0x2b, 0x06, 0x35, 0x91,
0xc9, 0xc8, 0x55, 0xec, 0xb0, 0x64, 0x7f, 0xa7, 0x1e, 0xeb, 0xf7, 0xd4, 0xd1, 0x9b, 0x30, 0xe5,
0xb0, 0x25, 0xdc, 0x17, 0xcb, 0xf1, 0xac, 0x90, 0x4b, 0x6b, 0x5e, 0x0c, 0x89, 0x2d, 0xb8, 0xf0,
0x3b, 0x50, 0xd4, 0x10, 0x58, 0xb2, 0xfb, 0xb4, 0xd1, 0xa4, 0x19, 0x70, 0x09, 0x66, 0x6b, 0x9b,
0xcd, 0xad, 0x03, 0x91, 0x03, 0x97, 0x01, 0xea, 0x8d, 0x60, 0x9c, 0xa5, 0x59, 0x90, 0x58, 0x25,
0x3d, 0x5c, 0xd7, 0x27, 0x93, 0xa4, 0x4f, 0xf6, 0x4a, 0xfa, 0x9c, 0xc3, 0x9c, 0xdc, 0x7e, 0xaa,
0x3b, 0xf0, 0x16, 0xb5, 0x30, 0x13, 0xa3, 0xae, 0xc0, 0x92, 0x01, 0x56, 0x79, 0xa7, 0x60, 0xc4,
0x34, 0x7b, 0xd8, 0xf7, 0x1d, 0x7f, 0xe4, 0xa9, 0x2b, 0xf0, 0xc7, 0x0c, 0x94, 0x15, 0x25, 0x6d,
0xf5, 0xae, 0x4a, 0x24, 0x11, 0xf3, 0x82, 0x02, 0xe9, 0x16, 0x4c, 0xb7, 0x8f, 0xf6, 0x3b, 0x9f,
0xaa, 0x2e, 0x86, 0x1c, 0x31, 0x7a, 0x57, 0xe0, 0x88, 0xae, 0x9c, 0x1c, 0xb1, 0xdc, 0x9b, 0xf5,
0xe7, 0xb6, 0xfa, 0x6d, 0x72, 0xce, 0xdf, 0xb4, 0x79, 0x3b, 0x24, 0xf0, 0x74, 0x59, 0x76, 0xef,
0x78, 0xfd, 0xa4, 0x77, 0xf3, 0xe8, 0x25, 0xaf, 0x8d, 0xfc, 0x93, 0x46, 0x9f, 0x35, 0xae, 0xd4,
0x0e, 0x17, 0x01, 0x31, 0x62, 0xbd, 0xe3, 0xe9, 0xd4, 0x06, 0x2c, 0x30, 0x2a, 0xbd, 0xf7, 0x34,
0x99, 0x0e, 0x23, 0x86, 0x0a, 0xdb, 0x99, 0x58, 0xd8, 0x76, 0x3c, 0xef, 0xe5, 0xc0, 0x6d, 0xcb,
0xad, 0x05, 0x63, 0x5c, 0x17, 0xc2, 0x9f, 0x7b, 0x91, 0xc0, 0xfc, 0x55, 0xa5, 0x3c, 0x09, 0xa5,
0x3c, 0x25, 0xfe, 0x04, 0x29, 0xf8, 0x75, 0xb8, 0xa9, 0x38, 0x65, 0x0d, 0x3d, 0x81, 0x79, 0x0f,
0xee, 0x28, 0xe6, 0xcd, 0x13, 0x96, 0xe8, 0x3d, 0x93, 0x80, 0xff, 0xab, 0x9e, 0x1b, 0x50, 0x09,
0xf4, 0xe4, 0x39, 0xc8, 0xa0, 0xab, 0x2b, 0x30, 0xf2, 0xe4, 0x9d, 0xa1, 0xb2, 0xd8, 0x33, 0xa3,
0xb9, 0x94, 0x45, 0xbd, 0x04, 0xd9, 0x33, 0xde, 0x84, 0x25, 0x25, 0x43, 0x66, 0x07, 0x51, 0x21,
0x63, 0x0a, 0x99, 0x84, 0x48, 0x83, 0xb1, 0xa5, 0x93, 0xcd, 0xae, 0x73, 0x46, 0x4d, 0xcb, 0x65,
0x66, 0x34, 0x99, 0x37, 0xc5, 0x8d, 0x60, 0x8a, 0xe9, 0x41, 0x5b, 0x92, 0x99, 0x00, 0x9d, 0x2c,
0x0f, 0x82, 0x91, 0xc7, 0x0e, 0x62, 0x4c, 0xf4, 0x0f, 0x60, 0x25, 0x50, 0x82, 0xd9, 0xed, 0x19,
0xbd, 0xac, 0x1d, 0xcf, 0xd3, 0x8a, 0x40, 0xd3, 0xc6, 0x1f, 0x41, 0x7e, 0x48, 0x64, 0x4c, 0x29,
0xae, 0xa3, 0x35, 0xd1, 0x63, 0x5f, 0xd3, 0x16, 0xf3, 0x79, 0xdc, 0x86, 0xbb, 0x4a, 0xba, 0xb0,
0xa8, 0x51, 0x7c, 0x5c, 0x29, 0x55, 0x20, 0x08, 0xb3, 0x8e, 0x17, 0x08, 0x39, 0x71, 0xf6, 0x41,
0xab, 0xef, 0x7d, 0x61, 0x48, 0xe5, 0x5b, 0xa9, 0xde, 0x15, 0xdb, 0xc2, 0xa6, 0x81, 0x4b, 0xa6,
0x12, 0x76, 0x04, 0x8b, 0x51, 0x4f, 0x4e, 0x15, 0xc6, 0x68, 0xd6, 0xeb, 0x53, 0x13, 0xaa, 0x20,
0x26, 0x06, 0x4a, 0xe1, 0xc0, 0xcd, 0x53, 0x29, 0xec, 0x84, 0xc2, 0xf8, 0x95, 0x4c, 0xab, 0x2f,
0x3b, 0x4d, 0x95, 0xcf, 0x88, 0x01, 0xde, 0x85, 0x5b, 0xf1, 0x30, 0x91, 0x4a, 0xe5, 0x03, 0x71,
0x81, 0x4d, 0x91, 0x24, 0x95, 0xdc, 0x0f, 0xc3, 0x60, 0xa0, 0x05, 0x94, 0x54, 0x22, 0x6d, 0xb0,
0x4c, 0xf1, 0xe5, 0xff, 0x71, 0x5f, 0x83, 0x70, 0x93, 0x4a, 0x98, 0x17, 0x0a, 0x4b, 0x7f, 0xfc,
0x61, 0x8c, 0xc8, 0x4d, 0x8c, 0x11, 0xd2, 0x49, 0xc2, 0x28, 0xf6, 0x35, 0x5c, 0x3a, 0x89, 0x11,
0x06, 0xd0, 0xb4, 0x18, 0xec, 0x1d, 0x12, 0x60, 0xf0, 0x81, 0xba, 0xd8, 0x7a, 0xd8, 0x4d, 0x75,
0x18, 0x1f, 0x85, 0xb1, 0x73, 0x2c, 0x32, 0xa7, 0x12, 0xfc, 0x31, 0xac, 0x26, 0x07, 0xe5, 0x34,
0x92, 0x5f, 0xc3, 0x50, 0x08, 0x12, 0x4a, 0xed, 0x9b, 0x5a, 0x11, 0x66, 0x76, 0xf7, 0xf6, 0x9f,
0xd5, 0x36, 0x69, 0x2a, 0xbb, 0xfe, 0x97, 0x1c, 0x64, 0xb7, 0x0f, 0xd0, 0x0f, 0x61, 0x4a, 0x34,
0xff, 0x27, 0x7c, 0x1b, 0xb1, 0x26, 0x7d, 0x46, 0xc0, 0xcb, 0x9f, 0xfd, 0xf9, 0xef, 0x5f, 0x64,
0x6f, 0xe1, 0x1b, 0xd5, 0xb3, 0xb7, 0x9d, 0xee, 0xf0, 0xc4, 0xa9, 0x9e, 0x9e, 0x55, 0xf9, 0x3b,
0xe1, 0xdb, 0x99, 0xd7, 0xd0, 0x01, 0xe4, 0xd8, 0xa7, 0x81, 0xc4, 0x0f, 0x27, 0x56, 0xf2, 0xe7,
0x05, 0x6c, 0x71, 0xc9, 0x8b, 0xf8, 0xba, 0x2e, 0x79, 0x38, 0xf2, 0x99, 0xdc, 0x26, 0x14, 0xb5,
0x2f, 0x04, 0xe8, 0xd2, 0x4f, 0x2a, 0xd6, 0xe5, 0x5f, 0x1f, 0xf0, 0x35, 0xa6, 0x6d, 0xf3, 0xbc,
0x1f, 0xd7, 0x36, 0xec, 0x68, 0xc7, 0xb5, 0xd5, 0xba, 0xc8, 0x66, 0x6d, 0xfd, 0xf3, 0x3e, 0xd3,
0x76, 0x20, 0xbf, 0x59, 0xb4, 0x7c, 0x74, 0xd7, 0xd0, 0x02, 0xd7, 0x9b, 0xbd, 0xd6, 0x6a, 0x32,
0x83, 0x44, 0xba, 0xc7, 0x91, 0x6e, 0xe3, 0x5b, 0x3a, 0x52, 0x2b, 0xe0, 0xa3, 0x80, 0xeb, 0x27,
0x30, 0xc5, 0x3b, 0x65, 0xe8, 0x50, 0x3d, 0x58, 0x86, 0x3e, 0x62, 0xc2, 0xf9, 0x46, 0x7a, 0x6c,
0x78, 0x89, 0xa3, 0x2d, 0xe0, 0x72, 0x80, 0xc6, 0x9b, 0x65, 0x14, 0xe5, 0x49, 0xe6, 0x1b, 0x99,
0xf5, 0x7f, 0x67, 0x61, 0x8a, 0xb7, 0x54, 0xd0, 0x10, 0x20, 0xec, 0x3d, 0xc5, 0xf7, 0x39, 0xd6,
0xcd, 0x8a, 0xef, 0x73, 0xbc, 0x6d, 0x85, 0xef, 0x72, 0xe4, 0x25, 0xbc, 0x18, 0x20, 0xf3, 0x8f,
0x9b, 0xd5, 0x63, 0xc6, 0xc5, 0xcc, 0xfa, 0x12, 0x8a, 0x5a, 0x0f, 0x09, 0x99, 0x24, 0x46, 0x9a,
0x50, 0xf1, 0x4b, 0x60, 0x68, 0x40, 0xe1, 0xfb, 0x1c, 0xf4, 0x0e, 0xae, 0xe8, 0xc6, 0x15, 0xb8,
0x2e, 0xe7, 0x64, 0xc0, 0x3f, 0xa3, 0x25, 0x51, 0xb4, 0x8f, 0x84, 0xee, 0x1b, 0x44, 0xc7, 0xdb,
0x51, 0xd6, 0x83, 0xc9, 0x4c, 0x89, 0x2a, 0x08, 0xfc, 0x53, 0xca, 0xe9, 0x30, 0x4e, 0x65, 0xfb,
0xff, 0xb0, 0x6f, 0x61, 0xe2, 0xe7, 0x0f, 0xc8, 0x87, 0x42, 0xd0, 0xcd, 0x41, 0x2b, 0xa6, 0x4a,
0x3f, 0x4c, 0x83, 0xad, 0xbb, 0x89, 0xf3, 0x52, 0x85, 0x47, 0x5c, 0x85, 0x55, 0x7c, 0x3b, 0x50,
0x41, 0xfe, 0xcc, 0xa2, 0x2a, 0x0a, 0xda, 0xaa, 0xd3, 0x6e, 0x33, 0x43, 0xfc, 0x94, 0x96, 0xf4,
0x7a, 0x93, 0x06, 0xdd, 0x33, 0xf6, 0x18, 0xf4, 0x3e, 0x8f, 0x85, 0x27, 0xb1, 0x48, 0xfc, 0x57,
0x39, 0xfe, 0x7d, 0xbc, 0x92, 0x84, 0xef, 0x72, 0xfe, 0xa8, 0x0a, 0xa2, 0x2d, 0x63, 0x56, 0x21,
0xd2, 0xf5, 0x31, 0xab, 0x10, 0xed, 0xea, 0x5c, 0xae, 0xc2, 0x88, 0xf3, 0x33, 0x15, 0xce, 0x01,
0xc2, 0xae, 0x0d, 0x32, 0x1a, 0x57, 0x2b, 0x0c, 0xe2, 0x37, 0x7f, 0xbc, 0xe1, 0x83, 0x1f, 0x73,
0xec, 0x7b, 0x78, 0x39, 0x09, 0xbb, 0x4b, 0xb9, 0x99, 0x9f, 0xff, 0x3e, 0x0f, 0xc5, 0x0f, 0x9c,
0x4e, 0xdf, 0x27, 0x7d, 0xd6, 0x8c, 0x46, 0xc7, 0x30, 0xc5, 0x23, 0x7f, 0xdc, 0xdd, 0xf5, 0x56,
0x4a, 0xdc, 0xdd, 0x23, 0x7d, 0x06, 0xfc, 0x90, 0x43, 0xdf, 0xc5, 0x56, 0x00, 0xdd, 0x0b, 0xe5,
0x57, 0x79, 0x8f, 0x80, 0x6d, 0xf9, 0x14, 0xa6, 0x45, 0x4f, 0x00, 0xc5, 0xa4, 0x45, 0x7a, 0x07,
0xd6, 0xb2, 0x79, 0x32, 0xf1, 0x96, 0xe9, 0x58, 0x1e, 0x67, 0x66, 0x60, 0x3f, 0x02, 0x08, 0x9b,
0x50, 0x71, 0xfb, 0x8e, 0xf5, 0xac, 0xac, 0xd5, 0x64, 0x06, 0x09, 0xfc, 0x1a, 0x07, 0x7e, 0x80,
0xef, 0x1a, 0x81, 0xdb, 0xc1, 0x02, 0x06, 0xde, 0x82, 0x3c, 0xfb, 0xd2, 0x85, 0x62, 0xa1, 0x5f,
0xfb, 0x18, 0x66, 0x59, 0xa6, 0x29, 0x09, 0xf5, 0x80, 0x43, 0xad, 0xe0, 0x25, 0x23, 0x14, 0xfb,
0xe2, 0xc5, 0x40, 0x46, 0x30, 0xab, 0x3e, 0x70, 0xa1, 0x3b, 0x31, 0x9b, 0x45, 0x3f, 0x86, 0x59,
0x2b, 0x49, 0xd3, 0x12, 0xf0, 0x09, 0x07, 0xc4, 0xf8, 0x8e, 0xd9, 0xa8, 0x92, 0x9d, 0x82, 0xd2,
0x00, 0xf2, 0x8b, 0x79, 0xc8, 0xb3, 0x1c, 0x84, 0xc5, 0xee, 0xb0, 0x74, 0x8b, 0x5b, 0x78, 0xac,
0x61, 0x12, 0xb7, 0xf0, 0x78, 0xd5, 0x67, 0x88, 0xdd, 0xfc, 0x47, 0x60, 0x84, 0x73, 0xb1, 0x1d,
0xfb, 0x50, 0xd4, 0x0a, 0x3c, 0x64, 0x90, 0x18, 0x6d, 0xc7, 0xc4, 0x63, 0xb7, 0xa1, 0x3a, 0xc4,
0xab, 0x1c, 0xd4, 0xc2, 0x37, 0xa3, 0xa0, 0x6d, 0xc1, 0xc6, 0x50, 0x7f, 0x0c, 0x25, 0xbd, 0x12,
0x44, 0x06, 0xa1, 0xb1, 0x7e, 0x4f, 0x3c, 0x56, 0x98, 0x0a, 0x49, 0x83, 0xd3, 0x04, 0x3f, 0x79,
0x53, 0xbc, 0x0c, 0xfd, 0x13, 0x98, 0x91, 0xf5, 0xa1, 0x69, 0xbf, 0xd1, 0x0e, 0x91, 0x69, 0xbf,
0xb1, 0xe2, 0xd2, 0x90, 0x08, 0x70, 0x58, 0x96, 0x07, 0xab, 0x00, 0x2d, 0x21, 0x69, 0x19, 0x91,
0x04, 0x19, 0xf6, 0x3c, 0x92, 0x20, 0xb5, 0x1a, 0x64, 0x22, 0xe4, 0x31, 0xf1, 0xe5, 0x5d, 0x56,
0x09, 0x3e, 0x4a, 0x90, 0xa8, 0x47, 0x43, 0x3c, 0x89, 0x45, 0xa2, 0x62, 0x8e, 0xba, 0x8c, 0x5f,
0x31, 0xa0, 0xca, 0x50, 0x88, 0x7e, 0x02, 0x10, 0x16, 0xb3, 0xf1, 0xd7, 0xb1, 0xb1, 0x23, 0x16,
0x7f, 0x1d, 0x9b, 0xeb, 0x61, 0x83, 0x07, 0x87, 0xe0, 0xe2, 0x67, 0x2e, 0x0c, 0xfe, 0x97, 0x19,
0x40, 0xe3, 0xc5, 0x2f, 0x7a, 0xdd, 0x0c, 0x61, 0x6c, 0xb6, 0x59, 0x6f, 0x5c, 0x8d, 0x39, 0x31,
0x7a, 0x86, 0x7a, 0xb5, 0xf8, 0x92, 0xe1, 0x4b, 0xa6, 0xd9, 0xe7, 0x19, 0x98, 0x8b, 0x94, 0xcf,
0xe8, 0x51, 0xc2, 0x39, 0xc7, 0x1a, 0x76, 0xd6, 0xe3, 0x4b, 0xf9, 0x12, 0x33, 0x16, 0xed, 0x56,
0xa8, 0x6c, 0xed, 0xe7, 0x34, 0x69, 0x8a, 0xd6, 0xdc, 0x28, 0x01, 0x60, 0xac, 0xeb, 0x67, 0x3d,
0xb9, 0x9c, 0xf1, 0x0a, 0xa7, 0x15, 0x26, 0x70, 0xd4, 0x2d, 0x64, 0xa9, 0x6e, 0x72, 0x8b, 0x68,
0xd3, 0xd0, 0xe4, 0x16, 0xb1, 0x3a, 0x3f, 0xc9, 0x2d, 0x58, 0xd5, 0xab, 0x79, 0xa2, 0x2c, 0xe8,
0x93, 0x20, 0x27, 0x7b, 0x62, 0xac, 0x1b, 0x30, 0x11, 0x32, 0xf4, 0x44, 0x55, 0xce, 0xa3, 0x04,
0x89, 0x97, 0x78, 0x62, 0xbc, 0x1b, 0x90, 0xe4, 0x89, 0x1c, 0x55, 0xf3, 0xc4, 0xb0, 0xfa, 0x36,
0x79, 0xe2, 0x58, 0x4b, 0xd4, 0xe4, 0x89, 0xe3, 0x05, 0x7c, 0xd2, 0xd9, 0x72, 0xf0, 0x88, 0x27,
0x2e, 0x18, 0xaa, 0x75, 0xf4, 0x46, 0x82, 0x4d, 0x8d, 0xed, 0x56, 0xeb, 0xcd, 0x2b, 0x72, 0x4f,
0xf6, 0x00, 0x71, 0x1a, 0xca, 0x03, 0x7e, 0x93, 0x81, 0x45, 0x53, 0xb9, 0x8f, 0x12, 0xc0, 0x12,
0x7a, 0xb5, 0xd6, 0xda, 0x55, 0xd9, 0xaf, 0x60, 0xb7, 0xc0, 0x27, 0x36, 0x4a, 0x7f, 0xf8, 0xdb,
0x4a, 0xe6, 0x4b, 0xfa, 0xef, 0xaf, 0xf4, 0xdf, 0xd1, 0x34, 0xff, 0x15, 0xf6, 0xdb, 0xff, 0x0d,
0x00, 0x00, 0xff, 0xff, 0x7b, 0x02, 0x74, 0xf8, 0x0c, 0x2e, 0x00, 0x00,
}

View File

@ -36,8 +36,8 @@ func NewURLs(strs []string) (URLs, error) {
if err != nil {
return nil, err
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("URL scheme must be http or https: %s", in)
if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" && u.Scheme != "unixs" {
return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in)
}
if _, _, err := net.SplitHostPort(u.Host); err != nil {
return nil, fmt.Errorf(`URL address does not have the form "host:port": %s`, in)

View File

@ -39,7 +39,7 @@ func Comma(v int64) string {
// Commaf produces a string form of the given number in base 10 with
// commas after every three orders of magnitude.
//
// e.g. Comma(834142.32) -> 834,142.32
// e.g. Commaf(834142.32) -> 834,142.32
func Commaf(v float64) string {
buf := &bytes.Buffer{}
if v < 0 {

View File

@ -34,8 +34,8 @@ const (
)
var (
decimal = regexp.MustCompile(`^\d*\.?\d*$`)
percent = regexp.MustCompile(`^\d*\.?\d*$%$`)
decimal = regexp.MustCompile(`^-*\d*\.?\d*$`)
percent = regexp.MustCompile(`^-*\d*\.?\d*$%$`)
)
type Border struct {

View File

@ -454,7 +454,7 @@ func terminalReadFrameError(err error) bool {
//
// If the frame is larger than previously set with SetMaxReadFrameSize, the
// returned error is ErrFrameTooLarge. Other errors may be of type
// ConnectionError, StreamError, or anything else from from the underlying
// ConnectionError, StreamError, or anything else from the underlying
// reader.
func (fr *Framer) ReadFrame() (Frame, error) {
fr.errDetail = nil

View File

@ -26,6 +26,8 @@ import (
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
basepb "google.golang.org/appengine/internal/base"
logpb "google.golang.org/appengine/internal/log"
remotepb "google.golang.org/appengine/internal/remote_api"
)
@ -50,6 +52,7 @@ var (
apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline")
apiContentType = http.CanonicalHeaderKey("Content-Type")
apiContentTypeValue = []string{"application/octet-stream"}
logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count")
apiHTTPClient = &http.Client{
Transport: &http.Transport{
@ -79,8 +82,8 @@ func handleHTTP(w http.ResponseWriter, r *http.Request) {
req: r,
outHeader: w.Header(),
apiURL: apiURL(),
logger: globalLogger(),
}
stopFlushing := make(chan int)
ctxs.Lock()
ctxs.m[r] = c
@ -109,9 +112,26 @@ func handleHTTP(w http.ResponseWriter, r *http.Request) {
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
}
// Start goroutine responsible for flushing app logs.
// This is done after adding c to ctx.m (and stopped before removing it)
// because flushing logs requires making an API call.
go c.logFlusher(stopFlushing)
executeRequestSafely(c, r)
c.outHeader = nil // make sure header changes aren't respected any more
stopFlushing <- 1 // any logging beyond this point will be dropped
// Flush any pending logs asynchronously.
c.pendingLogs.Lock()
flushes := c.pendingLogs.flushes
if len(c.pendingLogs.lines) > 0 {
flushes++
}
c.pendingLogs.Unlock()
go c.flushLog(false)
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
// Avoid nil Write call if c.Write is never called.
if c.outCode != 0 {
w.WriteHeader(c.outCode)
@ -186,13 +206,18 @@ var ctxs = struct {
// context represents the context of an in-flight HTTP request.
// It implements the appengine.Context and http.ResponseWriter interfaces.
type context struct {
req *http.Request
logger *jsonLogger
req *http.Request
outCode int
outHeader http.Header
outBody []byte
pendingLogs struct {
sync.Mutex
lines []*logpb.UserAppLogLine
flushes int
}
apiURL *url.URL
}
@ -265,9 +290,11 @@ func BackgroundContext() netcontext.Context {
},
},
apiURL: apiURL(),
logger: globalLogger(),
}
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
go ctxs.bg.logFlusher(make(chan int))
return toContext(ctxs.bg)
}
@ -279,7 +306,6 @@ func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netco
c := &context{
req: req,
apiURL: apiURL,
logger: globalLogger(),
}
ctxs.Lock()
defer ctxs.Unlock()
@ -501,9 +527,120 @@ func (c *context) Request() *http.Request {
return c.req
}
func ContextForTesting(req *http.Request) netcontext.Context {
return toContext(&context{
req: req,
logger: testLogger,
})
func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
// Truncate long log lines.
// TODO(dsymonds): Check if this is still necessary.
const lim = 8 << 10
if len(*ll.Message) > lim {
suffix := fmt.Sprintf("...(length %d)", len(*ll.Message))
ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix)
}
c.pendingLogs.Lock()
c.pendingLogs.lines = append(c.pendingLogs.lines, ll)
c.pendingLogs.Unlock()
}
var logLevelName = map[int64]string{
0: "DEBUG",
1: "INFO",
2: "WARNING",
3: "ERROR",
4: "CRITICAL",
}
func logf(c *context, level int64, format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
c.addLogLine(&logpb.UserAppLogLine{
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
Level: &level,
Message: &s,
})
log.Print(logLevelName[level] + ": " + s)
}
// flushLog attempts to flush any pending logs to the appserver.
// It should not be called concurrently.
func (c *context) flushLog(force bool) (flushed bool) {
c.pendingLogs.Lock()
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
n, rem := 0, 30<<20
for ; n < len(c.pendingLogs.lines); n++ {
ll := c.pendingLogs.lines[n]
// Each log line will require about 3 bytes of overhead.
nb := proto.Size(ll) + 3
if nb > rem {
break
}
rem -= nb
}
lines := c.pendingLogs.lines[:n]
c.pendingLogs.lines = c.pendingLogs.lines[n:]
c.pendingLogs.Unlock()
if len(lines) == 0 && !force {
// Nothing to flush.
return false
}
rescueLogs := false
defer func() {
if rescueLogs {
c.pendingLogs.Lock()
c.pendingLogs.lines = append(lines, c.pendingLogs.lines...)
c.pendingLogs.Unlock()
}
}()
buf, err := proto.Marshal(&logpb.UserAppLogGroup{
LogLine: lines,
})
if err != nil {
log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err)
rescueLogs = true
return false
}
req := &logpb.FlushRequest{
Logs: buf,
}
res := &basepb.VoidProto{}
c.pendingLogs.Lock()
c.pendingLogs.flushes++
c.pendingLogs.Unlock()
if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil {
log.Printf("internal.flushLog: Flush RPC: %v", err)
rescueLogs = true
return false
}
return true
}
const (
// Log flushing parameters.
flushInterval = 1 * time.Second
forceFlushInterval = 60 * time.Second
)
func (c *context) logFlusher(stop <-chan int) {
lastFlush := time.Now()
tick := time.NewTicker(flushInterval)
for {
select {
case <-stop:
// Request finished.
tick.Stop()
return
case <-tick.C:
force := time.Now().Sub(lastFlush) > forceFlushInterval
if c.flushLog(force) {
lastFlush = time.Now()
}
}
}
}
func ContextForTesting(req *http.Request) netcontext.Context {
return toContext(&context{req: req})
}

View File

@ -0,0 +1,899 @@
// Code generated by protoc-gen-go.
// source: google.golang.org/appengine/internal/log/log_service.proto
// DO NOT EDIT!
/*
Package log is a generated protocol buffer package.
It is generated from these files:
google.golang.org/appengine/internal/log/log_service.proto
It has these top-level messages:
LogServiceError
UserAppLogLine
UserAppLogGroup
FlushRequest
SetStatusRequest
LogOffset
LogLine
RequestLog
LogModuleVersion
LogReadRequest
LogReadResponse
LogUsageRecord
LogUsageRequest
LogUsageResponse
*/
package log
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type LogServiceError_ErrorCode int32
const (
LogServiceError_OK LogServiceError_ErrorCode = 0
LogServiceError_INVALID_REQUEST LogServiceError_ErrorCode = 1
LogServiceError_STORAGE_ERROR LogServiceError_ErrorCode = 2
)
var LogServiceError_ErrorCode_name = map[int32]string{
0: "OK",
1: "INVALID_REQUEST",
2: "STORAGE_ERROR",
}
var LogServiceError_ErrorCode_value = map[string]int32{
"OK": 0,
"INVALID_REQUEST": 1,
"STORAGE_ERROR": 2,
}
func (x LogServiceError_ErrorCode) Enum() *LogServiceError_ErrorCode {
p := new(LogServiceError_ErrorCode)
*p = x
return p
}
func (x LogServiceError_ErrorCode) String() string {
return proto.EnumName(LogServiceError_ErrorCode_name, int32(x))
}
func (x *LogServiceError_ErrorCode) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(LogServiceError_ErrorCode_value, data, "LogServiceError_ErrorCode")
if err != nil {
return err
}
*x = LogServiceError_ErrorCode(value)
return nil
}
type LogServiceError struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *LogServiceError) Reset() { *m = LogServiceError{} }
func (m *LogServiceError) String() string { return proto.CompactTextString(m) }
func (*LogServiceError) ProtoMessage() {}
type UserAppLogLine struct {
TimestampUsec *int64 `protobuf:"varint,1,req,name=timestamp_usec" json:"timestamp_usec,omitempty"`
Level *int64 `protobuf:"varint,2,req,name=level" json:"level,omitempty"`
Message *string `protobuf:"bytes,3,req,name=message" json:"message,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *UserAppLogLine) Reset() { *m = UserAppLogLine{} }
func (m *UserAppLogLine) String() string { return proto.CompactTextString(m) }
func (*UserAppLogLine) ProtoMessage() {}
func (m *UserAppLogLine) GetTimestampUsec() int64 {
if m != nil && m.TimestampUsec != nil {
return *m.TimestampUsec
}
return 0
}
func (m *UserAppLogLine) GetLevel() int64 {
if m != nil && m.Level != nil {
return *m.Level
}
return 0
}
func (m *UserAppLogLine) GetMessage() string {
if m != nil && m.Message != nil {
return *m.Message
}
return ""
}
type UserAppLogGroup struct {
LogLine []*UserAppLogLine `protobuf:"bytes,2,rep,name=log_line" json:"log_line,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *UserAppLogGroup) Reset() { *m = UserAppLogGroup{} }
func (m *UserAppLogGroup) String() string { return proto.CompactTextString(m) }
func (*UserAppLogGroup) ProtoMessage() {}
func (m *UserAppLogGroup) GetLogLine() []*UserAppLogLine {
if m != nil {
return m.LogLine
}
return nil
}
type FlushRequest struct {
Logs []byte `protobuf:"bytes,1,opt,name=logs" json:"logs,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *FlushRequest) Reset() { *m = FlushRequest{} }
func (m *FlushRequest) String() string { return proto.CompactTextString(m) }
func (*FlushRequest) ProtoMessage() {}
func (m *FlushRequest) GetLogs() []byte {
if m != nil {
return m.Logs
}
return nil
}
type SetStatusRequest struct {
Status *string `protobuf:"bytes,1,req,name=status" json:"status,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *SetStatusRequest) Reset() { *m = SetStatusRequest{} }
func (m *SetStatusRequest) String() string { return proto.CompactTextString(m) }
func (*SetStatusRequest) ProtoMessage() {}
func (m *SetStatusRequest) GetStatus() string {
if m != nil && m.Status != nil {
return *m.Status
}
return ""
}
type LogOffset struct {
RequestId []byte `protobuf:"bytes,1,opt,name=request_id" json:"request_id,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogOffset) Reset() { *m = LogOffset{} }
func (m *LogOffset) String() string { return proto.CompactTextString(m) }
func (*LogOffset) ProtoMessage() {}
func (m *LogOffset) GetRequestId() []byte {
if m != nil {
return m.RequestId
}
return nil
}
type LogLine struct {
Time *int64 `protobuf:"varint,1,req,name=time" json:"time,omitempty"`
Level *int32 `protobuf:"varint,2,req,name=level" json:"level,omitempty"`
LogMessage *string `protobuf:"bytes,3,req,name=log_message" json:"log_message,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogLine) Reset() { *m = LogLine{} }
func (m *LogLine) String() string { return proto.CompactTextString(m) }
func (*LogLine) ProtoMessage() {}
func (m *LogLine) GetTime() int64 {
if m != nil && m.Time != nil {
return *m.Time
}
return 0
}
func (m *LogLine) GetLevel() int32 {
if m != nil && m.Level != nil {
return *m.Level
}
return 0
}
func (m *LogLine) GetLogMessage() string {
if m != nil && m.LogMessage != nil {
return *m.LogMessage
}
return ""
}
type RequestLog struct {
AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"`
ModuleId *string `protobuf:"bytes,37,opt,name=module_id,def=default" json:"module_id,omitempty"`
VersionId *string `protobuf:"bytes,2,req,name=version_id" json:"version_id,omitempty"`
RequestId []byte `protobuf:"bytes,3,req,name=request_id" json:"request_id,omitempty"`
Offset *LogOffset `protobuf:"bytes,35,opt,name=offset" json:"offset,omitempty"`
Ip *string `protobuf:"bytes,4,req,name=ip" json:"ip,omitempty"`
Nickname *string `protobuf:"bytes,5,opt,name=nickname" json:"nickname,omitempty"`
StartTime *int64 `protobuf:"varint,6,req,name=start_time" json:"start_time,omitempty"`
EndTime *int64 `protobuf:"varint,7,req,name=end_time" json:"end_time,omitempty"`
Latency *int64 `protobuf:"varint,8,req,name=latency" json:"latency,omitempty"`
Mcycles *int64 `protobuf:"varint,9,req,name=mcycles" json:"mcycles,omitempty"`
Method *string `protobuf:"bytes,10,req,name=method" json:"method,omitempty"`
Resource *string `protobuf:"bytes,11,req,name=resource" json:"resource,omitempty"`
HttpVersion *string `protobuf:"bytes,12,req,name=http_version" json:"http_version,omitempty"`
Status *int32 `protobuf:"varint,13,req,name=status" json:"status,omitempty"`
ResponseSize *int64 `protobuf:"varint,14,req,name=response_size" json:"response_size,omitempty"`
Referrer *string `protobuf:"bytes,15,opt,name=referrer" json:"referrer,omitempty"`
UserAgent *string `protobuf:"bytes,16,opt,name=user_agent" json:"user_agent,omitempty"`
UrlMapEntry *string `protobuf:"bytes,17,req,name=url_map_entry" json:"url_map_entry,omitempty"`
Combined *string `protobuf:"bytes,18,req,name=combined" json:"combined,omitempty"`
ApiMcycles *int64 `protobuf:"varint,19,opt,name=api_mcycles" json:"api_mcycles,omitempty"`
Host *string `protobuf:"bytes,20,opt,name=host" json:"host,omitempty"`
Cost *float64 `protobuf:"fixed64,21,opt,name=cost" json:"cost,omitempty"`
TaskQueueName *string `protobuf:"bytes,22,opt,name=task_queue_name" json:"task_queue_name,omitempty"`
TaskName *string `protobuf:"bytes,23,opt,name=task_name" json:"task_name,omitempty"`
WasLoadingRequest *bool `protobuf:"varint,24,opt,name=was_loading_request" json:"was_loading_request,omitempty"`
PendingTime *int64 `protobuf:"varint,25,opt,name=pending_time" json:"pending_time,omitempty"`
ReplicaIndex *int32 `protobuf:"varint,26,opt,name=replica_index,def=-1" json:"replica_index,omitempty"`
Finished *bool `protobuf:"varint,27,opt,name=finished,def=1" json:"finished,omitempty"`
CloneKey []byte `protobuf:"bytes,28,opt,name=clone_key" json:"clone_key,omitempty"`
Line []*LogLine `protobuf:"bytes,29,rep,name=line" json:"line,omitempty"`
LinesIncomplete *bool `protobuf:"varint,36,opt,name=lines_incomplete" json:"lines_incomplete,omitempty"`
AppEngineRelease []byte `protobuf:"bytes,38,opt,name=app_engine_release" json:"app_engine_release,omitempty"`
ExitReason *int32 `protobuf:"varint,30,opt,name=exit_reason" json:"exit_reason,omitempty"`
WasThrottledForTime *bool `protobuf:"varint,31,opt,name=was_throttled_for_time" json:"was_throttled_for_time,omitempty"`
WasThrottledForRequests *bool `protobuf:"varint,32,opt,name=was_throttled_for_requests" json:"was_throttled_for_requests,omitempty"`
ThrottledTime *int64 `protobuf:"varint,33,opt,name=throttled_time" json:"throttled_time,omitempty"`
ServerName []byte `protobuf:"bytes,34,opt,name=server_name" json:"server_name,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *RequestLog) Reset() { *m = RequestLog{} }
func (m *RequestLog) String() string { return proto.CompactTextString(m) }
func (*RequestLog) ProtoMessage() {}
const Default_RequestLog_ModuleId string = "default"
const Default_RequestLog_ReplicaIndex int32 = -1
const Default_RequestLog_Finished bool = true
func (m *RequestLog) GetAppId() string {
if m != nil && m.AppId != nil {
return *m.AppId
}
return ""
}
func (m *RequestLog) GetModuleId() string {
if m != nil && m.ModuleId != nil {
return *m.ModuleId
}
return Default_RequestLog_ModuleId
}
func (m *RequestLog) GetVersionId() string {
if m != nil && m.VersionId != nil {
return *m.VersionId
}
return ""
}
func (m *RequestLog) GetRequestId() []byte {
if m != nil {
return m.RequestId
}
return nil
}
func (m *RequestLog) GetOffset() *LogOffset {
if m != nil {
return m.Offset
}
return nil
}
func (m *RequestLog) GetIp() string {
if m != nil && m.Ip != nil {
return *m.Ip
}
return ""
}
func (m *RequestLog) GetNickname() string {
if m != nil && m.Nickname != nil {
return *m.Nickname
}
return ""
}
func (m *RequestLog) GetStartTime() int64 {
if m != nil && m.StartTime != nil {
return *m.StartTime
}
return 0
}
func (m *RequestLog) GetEndTime() int64 {
if m != nil && m.EndTime != nil {
return *m.EndTime
}
return 0
}
func (m *RequestLog) GetLatency() int64 {
if m != nil && m.Latency != nil {
return *m.Latency
}
return 0
}
func (m *RequestLog) GetMcycles() int64 {
if m != nil && m.Mcycles != nil {
return *m.Mcycles
}
return 0
}
func (m *RequestLog) GetMethod() string {
if m != nil && m.Method != nil {
return *m.Method
}
return ""
}
func (m *RequestLog) GetResource() string {
if m != nil && m.Resource != nil {
return *m.Resource
}
return ""
}
func (m *RequestLog) GetHttpVersion() string {
if m != nil && m.HttpVersion != nil {
return *m.HttpVersion
}
return ""
}
func (m *RequestLog) GetStatus() int32 {
if m != nil && m.Status != nil {
return *m.Status
}
return 0
}
func (m *RequestLog) GetResponseSize() int64 {
if m != nil && m.ResponseSize != nil {
return *m.ResponseSize
}
return 0
}
func (m *RequestLog) GetReferrer() string {
if m != nil && m.Referrer != nil {
return *m.Referrer
}
return ""
}
func (m *RequestLog) GetUserAgent() string {
if m != nil && m.UserAgent != nil {
return *m.UserAgent
}
return ""
}
func (m *RequestLog) GetUrlMapEntry() string {
if m != nil && m.UrlMapEntry != nil {
return *m.UrlMapEntry
}
return ""
}
func (m *RequestLog) GetCombined() string {
if m != nil && m.Combined != nil {
return *m.Combined
}
return ""
}
func (m *RequestLog) GetApiMcycles() int64 {
if m != nil && m.ApiMcycles != nil {
return *m.ApiMcycles
}
return 0
}
func (m *RequestLog) GetHost() string {
if m != nil && m.Host != nil {
return *m.Host
}
return ""
}
func (m *RequestLog) GetCost() float64 {
if m != nil && m.Cost != nil {
return *m.Cost
}
return 0
}
func (m *RequestLog) GetTaskQueueName() string {
if m != nil && m.TaskQueueName != nil {
return *m.TaskQueueName
}
return ""
}
func (m *RequestLog) GetTaskName() string {
if m != nil && m.TaskName != nil {
return *m.TaskName
}
return ""
}
func (m *RequestLog) GetWasLoadingRequest() bool {
if m != nil && m.WasLoadingRequest != nil {
return *m.WasLoadingRequest
}
return false
}
func (m *RequestLog) GetPendingTime() int64 {
if m != nil && m.PendingTime != nil {
return *m.PendingTime
}
return 0
}
func (m *RequestLog) GetReplicaIndex() int32 {
if m != nil && m.ReplicaIndex != nil {
return *m.ReplicaIndex
}
return Default_RequestLog_ReplicaIndex
}
func (m *RequestLog) GetFinished() bool {
if m != nil && m.Finished != nil {
return *m.Finished
}
return Default_RequestLog_Finished
}
func (m *RequestLog) GetCloneKey() []byte {
if m != nil {
return m.CloneKey
}
return nil
}
func (m *RequestLog) GetLine() []*LogLine {
if m != nil {
return m.Line
}
return nil
}
func (m *RequestLog) GetLinesIncomplete() bool {
if m != nil && m.LinesIncomplete != nil {
return *m.LinesIncomplete
}
return false
}
func (m *RequestLog) GetAppEngineRelease() []byte {
if m != nil {
return m.AppEngineRelease
}
return nil
}
func (m *RequestLog) GetExitReason() int32 {
if m != nil && m.ExitReason != nil {
return *m.ExitReason
}
return 0
}
func (m *RequestLog) GetWasThrottledForTime() bool {
if m != nil && m.WasThrottledForTime != nil {
return *m.WasThrottledForTime
}
return false
}
func (m *RequestLog) GetWasThrottledForRequests() bool {
if m != nil && m.WasThrottledForRequests != nil {
return *m.WasThrottledForRequests
}
return false
}
func (m *RequestLog) GetThrottledTime() int64 {
if m != nil && m.ThrottledTime != nil {
return *m.ThrottledTime
}
return 0
}
func (m *RequestLog) GetServerName() []byte {
if m != nil {
return m.ServerName
}
return nil
}
type LogModuleVersion struct {
ModuleId *string `protobuf:"bytes,1,opt,name=module_id,def=default" json:"module_id,omitempty"`
VersionId *string `protobuf:"bytes,2,opt,name=version_id" json:"version_id,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogModuleVersion) Reset() { *m = LogModuleVersion{} }
func (m *LogModuleVersion) String() string { return proto.CompactTextString(m) }
func (*LogModuleVersion) ProtoMessage() {}
const Default_LogModuleVersion_ModuleId string = "default"
func (m *LogModuleVersion) GetModuleId() string {
if m != nil && m.ModuleId != nil {
return *m.ModuleId
}
return Default_LogModuleVersion_ModuleId
}
func (m *LogModuleVersion) GetVersionId() string {
if m != nil && m.VersionId != nil {
return *m.VersionId
}
return ""
}
type LogReadRequest struct {
AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"`
VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"`
ModuleVersion []*LogModuleVersion `protobuf:"bytes,19,rep,name=module_version" json:"module_version,omitempty"`
StartTime *int64 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"`
EndTime *int64 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"`
Offset *LogOffset `protobuf:"bytes,5,opt,name=offset" json:"offset,omitempty"`
RequestId [][]byte `protobuf:"bytes,6,rep,name=request_id" json:"request_id,omitempty"`
MinimumLogLevel *int32 `protobuf:"varint,7,opt,name=minimum_log_level" json:"minimum_log_level,omitempty"`
IncludeIncomplete *bool `protobuf:"varint,8,opt,name=include_incomplete" json:"include_incomplete,omitempty"`
Count *int64 `protobuf:"varint,9,opt,name=count" json:"count,omitempty"`
CombinedLogRegex *string `protobuf:"bytes,14,opt,name=combined_log_regex" json:"combined_log_regex,omitempty"`
HostRegex *string `protobuf:"bytes,15,opt,name=host_regex" json:"host_regex,omitempty"`
ReplicaIndex *int32 `protobuf:"varint,16,opt,name=replica_index" json:"replica_index,omitempty"`
IncludeAppLogs *bool `protobuf:"varint,10,opt,name=include_app_logs" json:"include_app_logs,omitempty"`
AppLogsPerRequest *int32 `protobuf:"varint,17,opt,name=app_logs_per_request" json:"app_logs_per_request,omitempty"`
IncludeHost *bool `protobuf:"varint,11,opt,name=include_host" json:"include_host,omitempty"`
IncludeAll *bool `protobuf:"varint,12,opt,name=include_all" json:"include_all,omitempty"`
CacheIterator *bool `protobuf:"varint,13,opt,name=cache_iterator" json:"cache_iterator,omitempty"`
NumShards *int32 `protobuf:"varint,18,opt,name=num_shards" json:"num_shards,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogReadRequest) Reset() { *m = LogReadRequest{} }
func (m *LogReadRequest) String() string { return proto.CompactTextString(m) }
func (*LogReadRequest) ProtoMessage() {}
func (m *LogReadRequest) GetAppId() string {
if m != nil && m.AppId != nil {
return *m.AppId
}
return ""
}
func (m *LogReadRequest) GetVersionId() []string {
if m != nil {
return m.VersionId
}
return nil
}
func (m *LogReadRequest) GetModuleVersion() []*LogModuleVersion {
if m != nil {
return m.ModuleVersion
}
return nil
}
func (m *LogReadRequest) GetStartTime() int64 {
if m != nil && m.StartTime != nil {
return *m.StartTime
}
return 0
}
func (m *LogReadRequest) GetEndTime() int64 {
if m != nil && m.EndTime != nil {
return *m.EndTime
}
return 0
}
func (m *LogReadRequest) GetOffset() *LogOffset {
if m != nil {
return m.Offset
}
return nil
}
func (m *LogReadRequest) GetRequestId() [][]byte {
if m != nil {
return m.RequestId
}
return nil
}
func (m *LogReadRequest) GetMinimumLogLevel() int32 {
if m != nil && m.MinimumLogLevel != nil {
return *m.MinimumLogLevel
}
return 0
}
func (m *LogReadRequest) GetIncludeIncomplete() bool {
if m != nil && m.IncludeIncomplete != nil {
return *m.IncludeIncomplete
}
return false
}
func (m *LogReadRequest) GetCount() int64 {
if m != nil && m.Count != nil {
return *m.Count
}
return 0
}
func (m *LogReadRequest) GetCombinedLogRegex() string {
if m != nil && m.CombinedLogRegex != nil {
return *m.CombinedLogRegex
}
return ""
}
func (m *LogReadRequest) GetHostRegex() string {
if m != nil && m.HostRegex != nil {
return *m.HostRegex
}
return ""
}
func (m *LogReadRequest) GetReplicaIndex() int32 {
if m != nil && m.ReplicaIndex != nil {
return *m.ReplicaIndex
}
return 0
}
func (m *LogReadRequest) GetIncludeAppLogs() bool {
if m != nil && m.IncludeAppLogs != nil {
return *m.IncludeAppLogs
}
return false
}
func (m *LogReadRequest) GetAppLogsPerRequest() int32 {
if m != nil && m.AppLogsPerRequest != nil {
return *m.AppLogsPerRequest
}
return 0
}
func (m *LogReadRequest) GetIncludeHost() bool {
if m != nil && m.IncludeHost != nil {
return *m.IncludeHost
}
return false
}
func (m *LogReadRequest) GetIncludeAll() bool {
if m != nil && m.IncludeAll != nil {
return *m.IncludeAll
}
return false
}
func (m *LogReadRequest) GetCacheIterator() bool {
if m != nil && m.CacheIterator != nil {
return *m.CacheIterator
}
return false
}
func (m *LogReadRequest) GetNumShards() int32 {
if m != nil && m.NumShards != nil {
return *m.NumShards
}
return 0
}
type LogReadResponse struct {
Log []*RequestLog `protobuf:"bytes,1,rep,name=log" json:"log,omitempty"`
Offset *LogOffset `protobuf:"bytes,2,opt,name=offset" json:"offset,omitempty"`
LastEndTime *int64 `protobuf:"varint,3,opt,name=last_end_time" json:"last_end_time,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogReadResponse) Reset() { *m = LogReadResponse{} }
func (m *LogReadResponse) String() string { return proto.CompactTextString(m) }
func (*LogReadResponse) ProtoMessage() {}
func (m *LogReadResponse) GetLog() []*RequestLog {
if m != nil {
return m.Log
}
return nil
}
func (m *LogReadResponse) GetOffset() *LogOffset {
if m != nil {
return m.Offset
}
return nil
}
func (m *LogReadResponse) GetLastEndTime() int64 {
if m != nil && m.LastEndTime != nil {
return *m.LastEndTime
}
return 0
}
type LogUsageRecord struct {
VersionId *string `protobuf:"bytes,1,opt,name=version_id" json:"version_id,omitempty"`
StartTime *int32 `protobuf:"varint,2,opt,name=start_time" json:"start_time,omitempty"`
EndTime *int32 `protobuf:"varint,3,opt,name=end_time" json:"end_time,omitempty"`
Count *int64 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"`
TotalSize *int64 `protobuf:"varint,5,opt,name=total_size" json:"total_size,omitempty"`
Records *int32 `protobuf:"varint,6,opt,name=records" json:"records,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogUsageRecord) Reset() { *m = LogUsageRecord{} }
func (m *LogUsageRecord) String() string { return proto.CompactTextString(m) }
func (*LogUsageRecord) ProtoMessage() {}
func (m *LogUsageRecord) GetVersionId() string {
if m != nil && m.VersionId != nil {
return *m.VersionId
}
return ""
}
func (m *LogUsageRecord) GetStartTime() int32 {
if m != nil && m.StartTime != nil {
return *m.StartTime
}
return 0
}
func (m *LogUsageRecord) GetEndTime() int32 {
if m != nil && m.EndTime != nil {
return *m.EndTime
}
return 0
}
func (m *LogUsageRecord) GetCount() int64 {
if m != nil && m.Count != nil {
return *m.Count
}
return 0
}
func (m *LogUsageRecord) GetTotalSize() int64 {
if m != nil && m.TotalSize != nil {
return *m.TotalSize
}
return 0
}
func (m *LogUsageRecord) GetRecords() int32 {
if m != nil && m.Records != nil {
return *m.Records
}
return 0
}
type LogUsageRequest struct {
AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"`
VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"`
StartTime *int32 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"`
EndTime *int32 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"`
ResolutionHours *uint32 `protobuf:"varint,5,opt,name=resolution_hours,def=1" json:"resolution_hours,omitempty"`
CombineVersions *bool `protobuf:"varint,6,opt,name=combine_versions" json:"combine_versions,omitempty"`
UsageVersion *int32 `protobuf:"varint,7,opt,name=usage_version" json:"usage_version,omitempty"`
VersionsOnly *bool `protobuf:"varint,8,opt,name=versions_only" json:"versions_only,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogUsageRequest) Reset() { *m = LogUsageRequest{} }
func (m *LogUsageRequest) String() string { return proto.CompactTextString(m) }
func (*LogUsageRequest) ProtoMessage() {}
const Default_LogUsageRequest_ResolutionHours uint32 = 1
func (m *LogUsageRequest) GetAppId() string {
if m != nil && m.AppId != nil {
return *m.AppId
}
return ""
}
func (m *LogUsageRequest) GetVersionId() []string {
if m != nil {
return m.VersionId
}
return nil
}
func (m *LogUsageRequest) GetStartTime() int32 {
if m != nil && m.StartTime != nil {
return *m.StartTime
}
return 0
}
func (m *LogUsageRequest) GetEndTime() int32 {
if m != nil && m.EndTime != nil {
return *m.EndTime
}
return 0
}
func (m *LogUsageRequest) GetResolutionHours() uint32 {
if m != nil && m.ResolutionHours != nil {
return *m.ResolutionHours
}
return Default_LogUsageRequest_ResolutionHours
}
func (m *LogUsageRequest) GetCombineVersions() bool {
if m != nil && m.CombineVersions != nil {
return *m.CombineVersions
}
return false
}
func (m *LogUsageRequest) GetUsageVersion() int32 {
if m != nil && m.UsageVersion != nil {
return *m.UsageVersion
}
return 0
}
func (m *LogUsageRequest) GetVersionsOnly() bool {
if m != nil && m.VersionsOnly != nil {
return *m.VersionsOnly
}
return false
}
type LogUsageResponse struct {
Usage []*LogUsageRecord `protobuf:"bytes,1,rep,name=usage" json:"usage,omitempty"`
Summary *LogUsageRecord `protobuf:"bytes,2,opt,name=summary" json:"summary,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LogUsageResponse) Reset() { *m = LogUsageResponse{} }
func (m *LogUsageResponse) String() string { return proto.CompactTextString(m) }
func (*LogUsageResponse) ProtoMessage() {}
func (m *LogUsageResponse) GetUsage() []*LogUsageRecord {
if m != nil {
return m.Usage
}
return nil
}
func (m *LogUsageResponse) GetSummary() *LogUsageRecord {
if m != nil {
return m.Summary
}
return nil
}
func init() {
}

View File

@ -1,109 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
package internal
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"strings"
"sync"
"time"
)
// jsonLogger writes logs in the JSON format required for Flex Logging. It can
// be used concurrently.
type jsonLogger struct {
mu sync.Mutex
enc *json.Encoder
}
type logLine struct {
Message string `json:"message"`
Timestamp logTimestamp `json:"timestamp"`
Severity string `json:"severity"`
TraceID string `json:"traceId,omitempty"`
}
type logTimestamp struct {
Seconds int64 `json:"seconds"`
Nanos int `json:"nanos"`
}
var (
logger *jsonLogger
loggerOnce sync.Once
logPath = "/var/log/app_engine/app.json"
stderrLogger = newJSONLogger(os.Stderr)
testLogger = newJSONLogger(ioutil.Discard)
levels = map[int64]string{
0: "DEBUG",
1: "INFO",
2: "WARNING",
3: "ERROR",
4: "CRITICAL",
}
)
func globalLogger() *jsonLogger {
loggerOnce.Do(func() {
f, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Printf("failed to open/create log file, logging to stderr: %v", err)
logger = stderrLogger
return
}
logger = newJSONLogger(f)
})
return logger
}
func logf(ctx *context, level int64, format string, args ...interface{}) {
s := strings.TrimSpace(fmt.Sprintf(format, args...))
now := time.Now()
trace := ctx.req.Header.Get(traceHeader)
if i := strings.Index(trace, "/"); i > -1 {
trace = trace[:i]
}
line := &logLine{
Message: s,
Timestamp: logTimestamp{
Seconds: now.Unix(),
Nanos: now.Nanosecond(),
},
Severity: levels[level],
TraceID: trace,
}
if err := ctx.logger.emit(line); err != nil {
log.Printf("failed to write log line to file: %v", err)
}
log.Print(levels[level] + ": " + s)
}
func newJSONLogger(w io.Writer) *jsonLogger {
return &jsonLogger{
enc: json.NewEncoder(w),
}
}
func (l *jsonLogger) emit(line *logLine) error {
l.mu.Lock()
defer l.mu.Unlock()
return l.enc.Encode(line)
}

View File

@ -139,16 +139,20 @@ func RoundRobin(r naming.Resolver) Balancer {
return &roundRobin{r: r}
}
type addrInfo struct {
addr Address
connected bool
}
type roundRobin struct {
r naming.Resolver
w naming.Watcher
open []Address // all the addresses the client should potentially connect
mu sync.Mutex
addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
connected []Address // all the connected addresses
next int // index of the next address to return for Get()
waitCh chan struct{} // the channel to block when there is no connected address available
done bool // The Balancer is closed.
r naming.Resolver
w naming.Watcher
addrs []*addrInfo // all the addresses the client should potentially connect
mu sync.Mutex
addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
next int // index of the next address to return for Get()
waitCh chan struct{} // the channel to block when there is no connected address available
done bool // The Balancer is closed.
}
func (rr *roundRobin) watchAddrUpdates() error {
@ -166,8 +170,8 @@ func (rr *roundRobin) watchAddrUpdates() error {
switch update.Op {
case naming.Add:
var exist bool
for _, v := range rr.open {
if addr == v {
for _, v := range rr.addrs {
if addr == v.addr {
exist = true
grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr)
break
@ -176,12 +180,12 @@ func (rr *roundRobin) watchAddrUpdates() error {
if exist {
continue
}
rr.open = append(rr.open, addr)
rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
case naming.Delete:
for i, v := range rr.open {
if v == addr {
copy(rr.open[i:], rr.open[i+1:])
rr.open = rr.open[:len(rr.open)-1]
for i, v := range rr.addrs {
if addr == v.addr {
copy(rr.addrs[i:], rr.addrs[i+1:])
rr.addrs = rr.addrs[:len(rr.addrs)-1]
break
}
}
@ -189,9 +193,11 @@ func (rr *roundRobin) watchAddrUpdates() error {
grpclog.Println("Unknown update.Op ", update.Op)
}
}
// Make a copy of rr.open and write it onto rr.addrCh so that gRPC internals gets notified.
open := make([]Address, len(rr.open), len(rr.open))
copy(open, rr.open)
// Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified.
open := make([]Address, len(rr.addrs))
for i, v := range rr.addrs {
open[i] = v.addr
}
if rr.done {
return ErrClientConnClosing
}
@ -202,7 +208,9 @@ func (rr *roundRobin) watchAddrUpdates() error {
func (rr *roundRobin) Start(target string) error {
if rr.r == nil {
// If there is no name resolver installed, it is not needed to
// do name resolution. In this case, rr.addrCh stays nil.
// do name resolution. In this case, target is added into rr.addrs
// as the only address available and rr.addrCh stays nil.
rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}})
return nil
}
w, err := rr.r.Resolve(target)
@ -221,38 +229,41 @@ func (rr *roundRobin) Start(target string) error {
return nil
}
// Up appends addr to the end of rr.connected and sends notification if there
// are pending Get() calls.
// Up sets the connected state of addr and sends notification if there are pending
// Get() calls.
func (rr *roundRobin) Up(addr Address) func(error) {
rr.mu.Lock()
defer rr.mu.Unlock()
for _, a := range rr.connected {
if a == addr {
return nil
var cnt int
for _, a := range rr.addrs {
if a.addr == addr {
if a.connected {
return nil
}
a.connected = true
}
if a.connected {
cnt++
}
}
rr.connected = append(rr.connected, addr)
if len(rr.connected) == 1 {
// addr is only one available. Notify the Get() callers who are blocking.
if rr.waitCh != nil {
close(rr.waitCh)
rr.waitCh = nil
}
// addr is only one which is connected. Notify the Get() callers who are blocking.
if cnt == 1 && rr.waitCh != nil {
close(rr.waitCh)
rr.waitCh = nil
}
return func(err error) {
rr.down(addr, err)
}
}
// down removes addr from rr.connected and moves the remaining addrs forward.
// down unsets the connected state of addr.
func (rr *roundRobin) down(addr Address, err error) {
rr.mu.Lock()
defer rr.mu.Unlock()
for i, a := range rr.connected {
if a == addr {
copy(rr.connected[i:], rr.connected[i+1:])
rr.connected = rr.connected[:len(rr.connected)-1]
return
for _, a := range rr.addrs {
if addr == a.addr {
a.connected = false
break
}
}
}
@ -266,14 +277,26 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
err = ErrClientConnClosing
return
}
if rr.next >= len(rr.connected) {
rr.next = 0
}
if len(rr.connected) > 0 {
addr = rr.connected[rr.next]
rr.next++
rr.mu.Unlock()
return
if len(rr.addrs) > 0 {
if rr.next >= len(rr.addrs) {
rr.next = 0
}
next := rr.next
for {
a := rr.addrs[next]
next = (next + 1) % len(rr.addrs)
if a.connected {
addr = a.addr
rr.next = next
rr.mu.Unlock()
return
}
if next == rr.next {
// Has iterated all the possible address but none is connected.
break
}
}
}
// There is no address available. Wait on rr.waitCh.
// TODO(zhaoq): Handle the case when opts.BlockingWait is false.
@ -296,24 +319,35 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
err = ErrClientConnClosing
return
}
if len(rr.connected) == 0 {
// The newly added addr got removed by Down() again.
if rr.waitCh == nil {
ch = make(chan struct{})
rr.waitCh = ch
} else {
ch = rr.waitCh
if len(rr.addrs) > 0 {
if rr.next >= len(rr.addrs) {
rr.next = 0
}
next := rr.next
for {
a := rr.addrs[next]
next = (next + 1) % len(rr.addrs)
if a.connected {
addr = a.addr
rr.next = next
rr.mu.Unlock()
return
}
if next == rr.next {
// Has iterated all the possible address but none is connected.
break
}
}
rr.mu.Unlock()
continue
}
if rr.next >= len(rr.connected) {
rr.next = 0
// The newly added addr got removed by Down() again.
if rr.waitCh == nil {
ch = make(chan struct{})
rr.waitCh = ch
} else {
ch = rr.waitCh
}
addr = rr.connected[rr.next]
rr.next++
rr.mu.Unlock()
return
}
}
}

View File

@ -57,7 +57,7 @@ func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (ma
return nil, err
}
return map[string]string{
"authorization": token.TokenType + " " + token.AccessToken,
"authorization": token.Type() + " " + token.AccessToken,
}, nil
}