mirror of
https://github.com/TECHNOFAB11/zfs-localpv.git
synced 2025-12-12 06:20:11 +01:00
feat(zfs-localpv): vendor packages for zfs-localpv
Signed-off-by: Pawan <pawan@mayadata.io>
This commit is contained in:
parent
8d81b8b9c6
commit
8a4ed4e7b8
2246 changed files with 950001 additions and 0 deletions
202
vendor/google.golang.org/appengine/LICENSE
generated
vendored
Normal file
202
vendor/google.golang.org/appengine/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
675
vendor/google.golang.org/appengine/internal/api.go
generated
vendored
Normal file
675
vendor/google.golang.org/appengine/internal/api.go
generated
vendored
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
// Copyright 2011 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 (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
apiPath = "/rpc_http"
|
||||
defaultTicketSuffix = "/default.20150612t184001.0"
|
||||
)
|
||||
|
||||
var (
|
||||
// Incoming headers.
|
||||
ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket")
|
||||
dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo")
|
||||
traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context")
|
||||
curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace")
|
||||
userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP")
|
||||
remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr")
|
||||
devRequestIdHeader = http.CanonicalHeaderKey("X-Appengine-Dev-Request-Id")
|
||||
|
||||
// Outgoing headers.
|
||||
apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint")
|
||||
apiEndpointHeaderValue = []string{"app-engine-apis"}
|
||||
apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method")
|
||||
apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"}
|
||||
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{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: limitDial,
|
||||
},
|
||||
}
|
||||
|
||||
defaultTicketOnce sync.Once
|
||||
defaultTicket string
|
||||
backgroundContextOnce sync.Once
|
||||
backgroundContext netcontext.Context
|
||||
)
|
||||
|
||||
func apiURL() *url.URL {
|
||||
host, port := "appengine.googleapis.internal", "10001"
|
||||
if h := os.Getenv("API_HOST"); h != "" {
|
||||
host = h
|
||||
}
|
||||
if p := os.Getenv("API_PORT"); p != "" {
|
||||
port = p
|
||||
}
|
||||
return &url.URL{
|
||||
Scheme: "http",
|
||||
Host: host + ":" + port,
|
||||
Path: apiPath,
|
||||
}
|
||||
}
|
||||
|
||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
c := &context{
|
||||
req: r,
|
||||
outHeader: w.Header(),
|
||||
apiURL: apiURL(),
|
||||
}
|
||||
r = r.WithContext(withContext(r.Context(), c))
|
||||
c.req = r
|
||||
|
||||
stopFlushing := make(chan int)
|
||||
|
||||
// Patch up RemoteAddr so it looks reasonable.
|
||||
if addr := r.Header.Get(userIPHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else {
|
||||
// Should not normally reach here, but pick a sensible default anyway.
|
||||
r.RemoteAddr = "127.0.0.1"
|
||||
}
|
||||
// The address in the headers will most likely be of these forms:
|
||||
// 123.123.123.123
|
||||
// 2001:db8::1
|
||||
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
|
||||
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
|
||||
// Assume the remote address is only a host; add a default port.
|
||||
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()
|
||||
flushed := make(chan struct{})
|
||||
go func() {
|
||||
defer close(flushed)
|
||||
// Force a log flush, because with very short requests we
|
||||
// may not ever flush logs.
|
||||
c.flushLog(true)
|
||||
}()
|
||||
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)
|
||||
}
|
||||
if c.outBody != nil {
|
||||
w.Write(c.outBody)
|
||||
}
|
||||
// Wait for the last flush to complete before returning,
|
||||
// otherwise the security ticket will not be valid.
|
||||
<-flushed
|
||||
}
|
||||
|
||||
func executeRequestSafely(c *context, r *http.Request) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
|
||||
c.outCode = 500
|
||||
}
|
||||
}()
|
||||
|
||||
http.DefaultServeMux.ServeHTTP(c, r)
|
||||
}
|
||||
|
||||
func renderPanic(x interface{}) string {
|
||||
buf := make([]byte, 16<<10) // 16 KB should be plenty
|
||||
buf = buf[:runtime.Stack(buf, false)]
|
||||
|
||||
// Remove the first few stack frames:
|
||||
// this func
|
||||
// the recover closure in the caller
|
||||
// That will root the stack trace at the site of the panic.
|
||||
const (
|
||||
skipStart = "internal.renderPanic"
|
||||
skipFrames = 2
|
||||
)
|
||||
start := bytes.Index(buf, []byte(skipStart))
|
||||
p := start
|
||||
for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ {
|
||||
p = bytes.IndexByte(buf[p+1:], '\n') + p + 1
|
||||
if p < 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if p >= 0 {
|
||||
// buf[start:p+1] is the block to remove.
|
||||
// Copy buf[p+1:] over buf[start:] and shrink buf.
|
||||
copy(buf[start:], buf[p+1:])
|
||||
buf = buf[:len(buf)-(p+1-start)]
|
||||
}
|
||||
|
||||
// Add panic heading.
|
||||
head := fmt.Sprintf("panic: %v\n\n", x)
|
||||
if len(head) > len(buf) {
|
||||
// Extremely unlikely to happen.
|
||||
return head
|
||||
}
|
||||
copy(buf[len(head):], buf)
|
||||
copy(buf, head)
|
||||
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
outCode int
|
||||
outHeader http.Header
|
||||
outBody []byte
|
||||
|
||||
pendingLogs struct {
|
||||
sync.Mutex
|
||||
lines []*logpb.UserAppLogLine
|
||||
flushes int
|
||||
}
|
||||
|
||||
apiURL *url.URL
|
||||
}
|
||||
|
||||
var contextKey = "holds a *context"
|
||||
|
||||
// jointContext joins two contexts in a superficial way.
|
||||
// It takes values and timeouts from a base context, and only values from another context.
|
||||
type jointContext struct {
|
||||
base netcontext.Context
|
||||
valuesOnly netcontext.Context
|
||||
}
|
||||
|
||||
func (c jointContext) Deadline() (time.Time, bool) {
|
||||
return c.base.Deadline()
|
||||
}
|
||||
|
||||
func (c jointContext) Done() <-chan struct{} {
|
||||
return c.base.Done()
|
||||
}
|
||||
|
||||
func (c jointContext) Err() error {
|
||||
return c.base.Err()
|
||||
}
|
||||
|
||||
func (c jointContext) Value(key interface{}) interface{} {
|
||||
if val := c.base.Value(key); val != nil {
|
||||
return val
|
||||
}
|
||||
return c.valuesOnly.Value(key)
|
||||
}
|
||||
|
||||
// fromContext returns the App Engine context or nil if ctx is not
|
||||
// derived from an App Engine context.
|
||||
func fromContext(ctx netcontext.Context) *context {
|
||||
c, _ := ctx.Value(&contextKey).(*context)
|
||||
return c
|
||||
}
|
||||
|
||||
func withContext(parent netcontext.Context, c *context) netcontext.Context {
|
||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
||||
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
|
||||
ctx = withNamespace(ctx, ns)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func toContext(c *context) netcontext.Context {
|
||||
return withContext(netcontext.Background(), c)
|
||||
}
|
||||
|
||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||
if c := fromContext(ctx); c != nil {
|
||||
return c.req.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReqContext(req *http.Request) netcontext.Context {
|
||||
return req.Context()
|
||||
}
|
||||
|
||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
||||
return jointContext{
|
||||
base: parent,
|
||||
valuesOnly: req.Context(),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultTicket returns a ticket used for background context or dev_appserver.
|
||||
func DefaultTicket() string {
|
||||
defaultTicketOnce.Do(func() {
|
||||
if IsDevAppServer() {
|
||||
defaultTicket = "testapp" + defaultTicketSuffix
|
||||
return
|
||||
}
|
||||
appID := partitionlessAppID()
|
||||
escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
|
||||
majVersion := VersionID(nil)
|
||||
if i := strings.Index(majVersion, "."); i > 0 {
|
||||
majVersion = majVersion[:i]
|
||||
}
|
||||
defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
|
||||
})
|
||||
return defaultTicket
|
||||
}
|
||||
|
||||
func BackgroundContext() netcontext.Context {
|
||||
backgroundContextOnce.Do(func() {
|
||||
// Compute background security ticket.
|
||||
ticket := DefaultTicket()
|
||||
|
||||
c := &context{
|
||||
req: &http.Request{
|
||||
Header: http.Header{
|
||||
ticketHeader: []string{ticket},
|
||||
},
|
||||
},
|
||||
apiURL: apiURL(),
|
||||
}
|
||||
backgroundContext = toContext(c)
|
||||
|
||||
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
|
||||
go c.logFlusher(make(chan int))
|
||||
})
|
||||
|
||||
return backgroundContext
|
||||
}
|
||||
|
||||
// RegisterTestRequest registers the HTTP request req for testing, such that
|
||||
// any API calls are sent to the provided URL. It returns a closure to delete
|
||||
// the registration.
|
||||
// It should only be used by aetest package.
|
||||
func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
|
||||
c := &context{
|
||||
req: req,
|
||||
apiURL: apiURL,
|
||||
}
|
||||
ctx := withContext(decorate(req.Context()), c)
|
||||
req = req.WithContext(ctx)
|
||||
c.req = req
|
||||
return req, func() {}
|
||||
}
|
||||
|
||||
var errTimeout = &CallError{
|
||||
Detail: "Deadline exceeded",
|
||||
Code: int32(remotepb.RpcError_CANCELLED),
|
||||
Timeout: true,
|
||||
}
|
||||
|
||||
func (c *context) Header() http.Header { return c.outHeader }
|
||||
|
||||
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
|
||||
// codes do not permit a response body (nor response entity headers such as
|
||||
// Content-Length, Content-Type, etc).
|
||||
func bodyAllowedForStatus(status int) bool {
|
||||
switch {
|
||||
case status >= 100 && status <= 199:
|
||||
return false
|
||||
case status == 204:
|
||||
return false
|
||||
case status == 304:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *context) Write(b []byte) (int, error) {
|
||||
if c.outCode == 0 {
|
||||
c.WriteHeader(http.StatusOK)
|
||||
}
|
||||
if len(b) > 0 && !bodyAllowedForStatus(c.outCode) {
|
||||
return 0, http.ErrBodyNotAllowed
|
||||
}
|
||||
c.outBody = append(c.outBody, b...)
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (c *context) WriteHeader(code int) {
|
||||
if c.outCode != 0 {
|
||||
logf(c, 3, "WriteHeader called multiple times on request.") // error level
|
||||
return
|
||||
}
|
||||
c.outCode = code
|
||||
}
|
||||
|
||||
func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
|
||||
hreq := &http.Request{
|
||||
Method: "POST",
|
||||
URL: c.apiURL,
|
||||
Header: http.Header{
|
||||
apiEndpointHeader: apiEndpointHeaderValue,
|
||||
apiMethodHeader: apiMethodHeaderValue,
|
||||
apiContentType: apiContentTypeValue,
|
||||
apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)},
|
||||
},
|
||||
Body: ioutil.NopCloser(bytes.NewReader(body)),
|
||||
ContentLength: int64(len(body)),
|
||||
Host: c.apiURL.Host,
|
||||
}
|
||||
if info := c.req.Header.Get(dapperHeader); info != "" {
|
||||
hreq.Header.Set(dapperHeader, info)
|
||||
}
|
||||
if info := c.req.Header.Get(traceHeader); info != "" {
|
||||
hreq.Header.Set(traceHeader, info)
|
||||
}
|
||||
|
||||
tr := apiHTTPClient.Transport.(*http.Transport)
|
||||
|
||||
var timedOut int32 // atomic; set to 1 if timed out
|
||||
t := time.AfterFunc(timeout, func() {
|
||||
atomic.StoreInt32(&timedOut, 1)
|
||||
tr.CancelRequest(hreq)
|
||||
})
|
||||
defer t.Stop()
|
||||
defer func() {
|
||||
// Check if timeout was exceeded.
|
||||
if atomic.LoadInt32(&timedOut) != 0 {
|
||||
err = errTimeout
|
||||
}
|
||||
}()
|
||||
|
||||
hresp, err := apiHTTPClient.Do(hreq)
|
||||
if err != nil {
|
||||
return nil, &CallError{
|
||||
Detail: fmt.Sprintf("service bridge HTTP failed: %v", err),
|
||||
Code: int32(remotepb.RpcError_UNKNOWN),
|
||||
}
|
||||
}
|
||||
defer hresp.Body.Close()
|
||||
hrespBody, err := ioutil.ReadAll(hresp.Body)
|
||||
if hresp.StatusCode != 200 {
|
||||
return nil, &CallError{
|
||||
Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody),
|
||||
Code: int32(remotepb.RpcError_UNKNOWN),
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, &CallError{
|
||||
Detail: fmt.Sprintf("service bridge response bad: %v", err),
|
||||
Code: int32(remotepb.RpcError_UNKNOWN),
|
||||
}
|
||||
}
|
||||
return hrespBody, nil
|
||||
}
|
||||
|
||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||
if fn, ok := NamespaceMods[service]; ok {
|
||||
fn(in, ns)
|
||||
}
|
||||
}
|
||||
|
||||
if f, ctx, ok := callOverrideFromContext(ctx); ok {
|
||||
return f(ctx, service, method, in, out)
|
||||
}
|
||||
|
||||
// Handle already-done contexts quickly.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
// Give a good error message rather than a panic lower down.
|
||||
return errNotAppEngineContext
|
||||
}
|
||||
|
||||
// Apply transaction modifications if we're in a transaction.
|
||||
if t := transactionFromContext(ctx); t != nil {
|
||||
if t.finished {
|
||||
return errors.New("transaction context has expired")
|
||||
}
|
||||
applyTransaction(in, &t.transaction)
|
||||
}
|
||||
|
||||
// Default RPC timeout is 60s.
|
||||
timeout := 60 * time.Second
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
timeout = deadline.Sub(time.Now())
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ticket := c.req.Header.Get(ticketHeader)
|
||||
// Use a test ticket under test environment.
|
||||
if ticket == "" {
|
||||
if appid := ctx.Value(&appIDOverrideKey); appid != nil {
|
||||
ticket = appid.(string) + defaultTicketSuffix
|
||||
}
|
||||
}
|
||||
// Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
|
||||
if ticket == "" {
|
||||
ticket = DefaultTicket()
|
||||
}
|
||||
if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" {
|
||||
ticket = dri
|
||||
}
|
||||
req := &remotepb.Request{
|
||||
ServiceName: &service,
|
||||
Method: &method,
|
||||
Request: data,
|
||||
RequestId: &ticket,
|
||||
}
|
||||
hreqBody, err := proto.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hrespBody, err := c.post(hreqBody, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res := &remotepb.Response{}
|
||||
if err := proto.Unmarshal(hrespBody, res); err != nil {
|
||||
return err
|
||||
}
|
||||
if res.RpcError != nil {
|
||||
ce := &CallError{
|
||||
Detail: res.RpcError.GetDetail(),
|
||||
Code: *res.RpcError.Code,
|
||||
}
|
||||
switch remotepb.RpcError_ErrorCode(ce.Code) {
|
||||
case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED:
|
||||
ce.Timeout = true
|
||||
}
|
||||
return ce
|
||||
}
|
||||
if res.ApplicationError != nil {
|
||||
return &APIError{
|
||||
Service: *req.ServiceName,
|
||||
Detail: res.ApplicationError.GetDetail(),
|
||||
Code: *res.ApplicationError.Code,
|
||||
}
|
||||
}
|
||||
if res.Exception != nil || res.JavaException != nil {
|
||||
// This shouldn't happen, but let's be defensive.
|
||||
return &CallError{
|
||||
Detail: "service bridge returned exception",
|
||||
Code: int32(remotepb.RpcError_UNKNOWN),
|
||||
}
|
||||
}
|
||||
return proto.Unmarshal(res.Response, out)
|
||||
}
|
||||
|
||||
func (c *context) Request() *http.Request {
|
||||
return c.req
|
||||
}
|
||||
|
||||
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{}) {
|
||||
if c == nil {
|
||||
panic("not an App Engine context")
|
||||
}
|
||||
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,
|
||||
})
|
||||
// Only duplicate log to stderr if not running on App Engine second generation
|
||||
if !IsSecondGen() {
|
||||
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})
|
||||
}
|
||||
169
vendor/google.golang.org/appengine/internal/api_classic.go
generated
vendored
Normal file
169
vendor/google.golang.org/appengine/internal/api_classic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright 2015 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"appengine"
|
||||
"appengine_internal"
|
||||
basepb "appengine_internal/base"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var contextKey = "holds an appengine.Context"
|
||||
|
||||
// fromContext returns the App Engine context or nil if ctx is not
|
||||
// derived from an App Engine context.
|
||||
func fromContext(ctx netcontext.Context) appengine.Context {
|
||||
c, _ := ctx.Value(&contextKey).(appengine.Context)
|
||||
return c
|
||||
}
|
||||
|
||||
// This is only for classic App Engine adapters.
|
||||
func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
return nil, errNotAppEngineContext
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
|
||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
||||
|
||||
s := &basepb.StringProto{}
|
||||
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
|
||||
if ns := s.GetValue(); ns != "" {
|
||||
ctx = NamespacedContext(ctx, ns)
|
||||
}
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||
if c := fromContext(ctx); c != nil {
|
||||
if req, ok := c.Request().(*http.Request); ok {
|
||||
return req.Header
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReqContext(req *http.Request) netcontext.Context {
|
||||
return WithContext(netcontext.Background(), req)
|
||||
}
|
||||
|
||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
||||
c := appengine.NewContext(req)
|
||||
return withContext(parent, c)
|
||||
}
|
||||
|
||||
type testingContext struct {
|
||||
appengine.Context
|
||||
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" }
|
||||
func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error {
|
||||
if service == "__go__" && method == "GetNamespace" {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("testingContext: unsupported Call")
|
||||
}
|
||||
func (t *testingContext) Request() interface{} { return t.req }
|
||||
|
||||
func ContextForTesting(req *http.Request) netcontext.Context {
|
||||
return withContext(netcontext.Background(), &testingContext{req: req})
|
||||
}
|
||||
|
||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||
if fn, ok := NamespaceMods[service]; ok {
|
||||
fn(in, ns)
|
||||
}
|
||||
}
|
||||
|
||||
if f, ctx, ok := callOverrideFromContext(ctx); ok {
|
||||
return f(ctx, service, method, in, out)
|
||||
}
|
||||
|
||||
// Handle already-done contexts quickly.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
// Give a good error message rather than a panic lower down.
|
||||
return errNotAppEngineContext
|
||||
}
|
||||
|
||||
// Apply transaction modifications if we're in a transaction.
|
||||
if t := transactionFromContext(ctx); t != nil {
|
||||
if t.finished {
|
||||
return errors.New("transaction context has expired")
|
||||
}
|
||||
applyTransaction(in, &t.transaction)
|
||||
}
|
||||
|
||||
var opts *appengine_internal.CallOptions
|
||||
if d, ok := ctx.Deadline(); ok {
|
||||
opts = &appengine_internal.CallOptions{
|
||||
Timeout: d.Sub(time.Now()),
|
||||
}
|
||||
}
|
||||
|
||||
err := c.Call(service, method, in, out, opts)
|
||||
switch v := err.(type) {
|
||||
case *appengine_internal.APIError:
|
||||
return &APIError{
|
||||
Service: v.Service,
|
||||
Detail: v.Detail,
|
||||
Code: v.Code,
|
||||
}
|
||||
case *appengine_internal.CallError:
|
||||
return &CallError{
|
||||
Detail: v.Detail,
|
||||
Code: v.Code,
|
||||
Timeout: v.Timeout,
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
panic("handleHTTP called; this should be impossible")
|
||||
}
|
||||
|
||||
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
|
||||
var fn func(format string, args ...interface{})
|
||||
switch level {
|
||||
case 0:
|
||||
fn = c.Debugf
|
||||
case 1:
|
||||
fn = c.Infof
|
||||
case 2:
|
||||
fn = c.Warningf
|
||||
case 3:
|
||||
fn = c.Errorf
|
||||
case 4:
|
||||
fn = c.Criticalf
|
||||
default:
|
||||
// This shouldn't happen.
|
||||
fn = c.Criticalf
|
||||
}
|
||||
fn(format, args...)
|
||||
}
|
||||
123
vendor/google.golang.org/appengine/internal/api_common.go
generated
vendored
Normal file
123
vendor/google.golang.org/appengine/internal/api_common.go
generated
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var errNotAppEngineContext = errors.New("not an App Engine context")
|
||||
|
||||
type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error
|
||||
|
||||
var callOverrideKey = "holds []CallOverrideFunc"
|
||||
|
||||
func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context {
|
||||
// We avoid appending to any existing call override
|
||||
// so we don't risk overwriting a popped stack below.
|
||||
var cofs []CallOverrideFunc
|
||||
if uf, ok := ctx.Value(&callOverrideKey).([]CallOverrideFunc); ok {
|
||||
cofs = append(cofs, uf...)
|
||||
}
|
||||
cofs = append(cofs, f)
|
||||
return netcontext.WithValue(ctx, &callOverrideKey, cofs)
|
||||
}
|
||||
|
||||
func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) {
|
||||
cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
|
||||
if len(cofs) == 0 {
|
||||
return nil, nil, false
|
||||
}
|
||||
// We found a list of overrides; grab the last, and reconstitute a
|
||||
// context that will hide it.
|
||||
f := cofs[len(cofs)-1]
|
||||
ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
|
||||
return f, ctx, true
|
||||
}
|
||||
|
||||
type logOverrideFunc func(level int64, format string, args ...interface{})
|
||||
|
||||
var logOverrideKey = "holds a logOverrideFunc"
|
||||
|
||||
func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &logOverrideKey, f)
|
||||
}
|
||||
|
||||
var appIDOverrideKey = "holds a string, being the full app ID"
|
||||
|
||||
func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &appIDOverrideKey, appID)
|
||||
}
|
||||
|
||||
var namespaceKey = "holds the namespace string"
|
||||
|
||||
func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &namespaceKey, ns)
|
||||
}
|
||||
|
||||
func NamespaceFromContext(ctx netcontext.Context) string {
|
||||
// If there's no namespace, return the empty string.
|
||||
ns, _ := ctx.Value(&namespaceKey).(string)
|
||||
return ns
|
||||
}
|
||||
|
||||
// FullyQualifiedAppID returns the fully-qualified application ID.
|
||||
// This may contain a partition prefix (e.g. "s~" for High Replication apps),
|
||||
// or a domain prefix (e.g. "example.com:").
|
||||
func FullyQualifiedAppID(ctx netcontext.Context) string {
|
||||
if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
|
||||
return id
|
||||
}
|
||||
return fullyQualifiedAppID(ctx)
|
||||
}
|
||||
|
||||
func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) {
|
||||
if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
|
||||
f(level, format, args...)
|
||||
return
|
||||
}
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
logf(c, level, format, args...)
|
||||
}
|
||||
|
||||
// NamespacedContext wraps a Context to support namespaces.
|
||||
func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
|
||||
return withNamespace(ctx, namespace)
|
||||
}
|
||||
|
||||
// SetTestEnv sets the env variables for testing background ticket in Flex.
|
||||
func SetTestEnv() func() {
|
||||
var environ = []struct {
|
||||
key, value string
|
||||
}{
|
||||
{"GAE_LONG_APP_ID", "my-app-id"},
|
||||
{"GAE_MINOR_VERSION", "067924799508853122"},
|
||||
{"GAE_MODULE_INSTANCE", "0"},
|
||||
{"GAE_MODULE_NAME", "default"},
|
||||
{"GAE_MODULE_VERSION", "20150612t184001"},
|
||||
}
|
||||
|
||||
for _, v := range environ {
|
||||
old := os.Getenv(v.key)
|
||||
os.Setenv(v.key, v.value)
|
||||
v.value = old
|
||||
}
|
||||
return func() { // Restore old environment after the test completes.
|
||||
for _, v := range environ {
|
||||
if v.value == "" {
|
||||
os.Unsetenv(v.key)
|
||||
continue
|
||||
}
|
||||
os.Setenv(v.key, v.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
28
vendor/google.golang.org/appengine/internal/app_id.go
generated
vendored
Normal file
28
vendor/google.golang.org/appengine/internal/app_id.go
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseFullAppID(appid string) (partition, domain, displayID string) {
|
||||
if i := strings.Index(appid, "~"); i != -1 {
|
||||
partition, appid = appid[:i], appid[i+1:]
|
||||
}
|
||||
if i := strings.Index(appid, ":"); i != -1 {
|
||||
domain, appid = appid[:i], appid[i+1:]
|
||||
}
|
||||
return partition, domain, appid
|
||||
}
|
||||
|
||||
// appID returns "appid" or "domain.com:appid".
|
||||
func appID(fullAppID string) string {
|
||||
_, dom, dis := parseFullAppID(fullAppID)
|
||||
if dom != "" {
|
||||
return dom + ":" + dis
|
||||
}
|
||||
return dis
|
||||
}
|
||||
308
vendor/google.golang.org/appengine/internal/base/api_base.pb.go
generated
vendored
Normal file
308
vendor/google.golang.org/appengine/internal/base/api_base.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google.golang.org/appengine/internal/base/api_base.proto
|
||||
|
||||
package base
|
||||
|
||||
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
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type StringProto struct {
|
||||
Value *string `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StringProto) Reset() { *m = StringProto{} }
|
||||
func (m *StringProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*StringProto) ProtoMessage() {}
|
||||
func (*StringProto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{0}
|
||||
}
|
||||
func (m *StringProto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StringProto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *StringProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_StringProto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *StringProto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_StringProto.Merge(dst, src)
|
||||
}
|
||||
func (m *StringProto) XXX_Size() int {
|
||||
return xxx_messageInfo_StringProto.Size(m)
|
||||
}
|
||||
func (m *StringProto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_StringProto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_StringProto proto.InternalMessageInfo
|
||||
|
||||
func (m *StringProto) GetValue() string {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Integer32Proto struct {
|
||||
Value *int32 `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Integer32Proto) Reset() { *m = Integer32Proto{} }
|
||||
func (m *Integer32Proto) String() string { return proto.CompactTextString(m) }
|
||||
func (*Integer32Proto) ProtoMessage() {}
|
||||
func (*Integer32Proto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{1}
|
||||
}
|
||||
func (m *Integer32Proto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Integer32Proto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Integer32Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Integer32Proto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Integer32Proto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Integer32Proto.Merge(dst, src)
|
||||
}
|
||||
func (m *Integer32Proto) XXX_Size() int {
|
||||
return xxx_messageInfo_Integer32Proto.Size(m)
|
||||
}
|
||||
func (m *Integer32Proto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Integer32Proto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Integer32Proto proto.InternalMessageInfo
|
||||
|
||||
func (m *Integer32Proto) GetValue() int32 {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Integer64Proto struct {
|
||||
Value *int64 `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Integer64Proto) Reset() { *m = Integer64Proto{} }
|
||||
func (m *Integer64Proto) String() string { return proto.CompactTextString(m) }
|
||||
func (*Integer64Proto) ProtoMessage() {}
|
||||
func (*Integer64Proto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{2}
|
||||
}
|
||||
func (m *Integer64Proto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Integer64Proto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Integer64Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Integer64Proto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Integer64Proto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Integer64Proto.Merge(dst, src)
|
||||
}
|
||||
func (m *Integer64Proto) XXX_Size() int {
|
||||
return xxx_messageInfo_Integer64Proto.Size(m)
|
||||
}
|
||||
func (m *Integer64Proto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Integer64Proto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Integer64Proto proto.InternalMessageInfo
|
||||
|
||||
func (m *Integer64Proto) GetValue() int64 {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type BoolProto struct {
|
||||
Value *bool `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *BoolProto) Reset() { *m = BoolProto{} }
|
||||
func (m *BoolProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*BoolProto) ProtoMessage() {}
|
||||
func (*BoolProto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{3}
|
||||
}
|
||||
func (m *BoolProto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_BoolProto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *BoolProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_BoolProto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *BoolProto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BoolProto.Merge(dst, src)
|
||||
}
|
||||
func (m *BoolProto) XXX_Size() int {
|
||||
return xxx_messageInfo_BoolProto.Size(m)
|
||||
}
|
||||
func (m *BoolProto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BoolProto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BoolProto proto.InternalMessageInfo
|
||||
|
||||
func (m *BoolProto) GetValue() bool {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type DoubleProto struct {
|
||||
Value *float64 `protobuf:"fixed64,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DoubleProto) Reset() { *m = DoubleProto{} }
|
||||
func (m *DoubleProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*DoubleProto) ProtoMessage() {}
|
||||
func (*DoubleProto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{4}
|
||||
}
|
||||
func (m *DoubleProto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DoubleProto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DoubleProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DoubleProto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *DoubleProto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DoubleProto.Merge(dst, src)
|
||||
}
|
||||
func (m *DoubleProto) XXX_Size() int {
|
||||
return xxx_messageInfo_DoubleProto.Size(m)
|
||||
}
|
||||
func (m *DoubleProto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DoubleProto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DoubleProto proto.InternalMessageInfo
|
||||
|
||||
func (m *DoubleProto) GetValue() float64 {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type BytesProto struct {
|
||||
Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *BytesProto) Reset() { *m = BytesProto{} }
|
||||
func (m *BytesProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*BytesProto) ProtoMessage() {}
|
||||
func (*BytesProto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{5}
|
||||
}
|
||||
func (m *BytesProto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_BytesProto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *BytesProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_BytesProto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *BytesProto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BytesProto.Merge(dst, src)
|
||||
}
|
||||
func (m *BytesProto) XXX_Size() int {
|
||||
return xxx_messageInfo_BytesProto.Size(m)
|
||||
}
|
||||
func (m *BytesProto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BytesProto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BytesProto proto.InternalMessageInfo
|
||||
|
||||
func (m *BytesProto) GetValue() []byte {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VoidProto struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *VoidProto) Reset() { *m = VoidProto{} }
|
||||
func (m *VoidProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*VoidProto) ProtoMessage() {}
|
||||
func (*VoidProto) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_api_base_9d49f8792e0c1140, []int{6}
|
||||
}
|
||||
func (m *VoidProto) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VoidProto.Unmarshal(m, b)
|
||||
}
|
||||
func (m *VoidProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_VoidProto.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *VoidProto) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_VoidProto.Merge(dst, src)
|
||||
}
|
||||
func (m *VoidProto) XXX_Size() int {
|
||||
return xxx_messageInfo_VoidProto.Size(m)
|
||||
}
|
||||
func (m *VoidProto) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_VoidProto.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_VoidProto proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*StringProto)(nil), "appengine.base.StringProto")
|
||||
proto.RegisterType((*Integer32Proto)(nil), "appengine.base.Integer32Proto")
|
||||
proto.RegisterType((*Integer64Proto)(nil), "appengine.base.Integer64Proto")
|
||||
proto.RegisterType((*BoolProto)(nil), "appengine.base.BoolProto")
|
||||
proto.RegisterType((*DoubleProto)(nil), "appengine.base.DoubleProto")
|
||||
proto.RegisterType((*BytesProto)(nil), "appengine.base.BytesProto")
|
||||
proto.RegisterType((*VoidProto)(nil), "appengine.base.VoidProto")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google.golang.org/appengine/internal/base/api_base.proto", fileDescriptor_api_base_9d49f8792e0c1140)
|
||||
}
|
||||
|
||||
var fileDescriptor_api_base_9d49f8792e0c1140 = []byte{
|
||||
// 199 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0x3f, 0x4b, 0xc6, 0x30,
|
||||
0x10, 0x06, 0x70, 0x5a, 0xad, 0xb4, 0x57, 0xe9, 0x20, 0x0e, 0x1d, 0xb5, 0x05, 0x71, 0x4a, 0x40,
|
||||
0x45, 0x9c, 0x83, 0x8b, 0x9b, 0x28, 0x38, 0xb8, 0x48, 0x8a, 0xc7, 0x11, 0x08, 0xb9, 0x90, 0xa6,
|
||||
0x82, 0xdf, 0x5e, 0xda, 0xd2, 0xfa, 0xc2, 0x9b, 0xed, 0xfe, 0xfc, 0xe0, 0xe1, 0x81, 0x27, 0x62,
|
||||
0x26, 0x8b, 0x82, 0xd8, 0x6a, 0x47, 0x82, 0x03, 0x49, 0xed, 0x3d, 0x3a, 0x32, 0x0e, 0xa5, 0x71,
|
||||
0x11, 0x83, 0xd3, 0x56, 0x0e, 0x7a, 0x44, 0xa9, 0xbd, 0xf9, 0x9a, 0x07, 0xe1, 0x03, 0x47, 0xbe,
|
||||
0x68, 0x76, 0x27, 0xe6, 0x6b, 0xd7, 0x43, 0xfd, 0x1e, 0x83, 0x71, 0xf4, 0xba, 0xbc, 0x2f, 0xa1,
|
||||
0xf8, 0xd1, 0x76, 0xc2, 0x36, 0xbb, 0xca, 0x6f, 0xab, 0xb7, 0x75, 0xe9, 0x6e, 0xa0, 0x79, 0x71,
|
||||
0x11, 0x09, 0xc3, 0xfd, 0x5d, 0xc2, 0x15, 0xc7, 0xee, 0xf1, 0x21, 0xe1, 0x4e, 0x36, 0x77, 0x0d,
|
||||
0x95, 0x62, 0xb6, 0x09, 0x52, 0x6e, 0xa4, 0x87, 0xfa, 0x99, 0xa7, 0xc1, 0x62, 0x02, 0x65, 0xff,
|
||||
0x79, 0xa0, 0x7e, 0x23, 0x8e, 0xab, 0x69, 0x0f, 0xcd, 0xb9, 0xca, 0xcb, 0xdd, 0xd5, 0x50, 0x7d,
|
||||
0xb0, 0xf9, 0x5e, 0x98, 0x3a, 0xfb, 0x3c, 0x9d, 0x9b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xba,
|
||||
0x37, 0x25, 0xea, 0x44, 0x01, 0x00, 0x00,
|
||||
}
|
||||
33
vendor/google.golang.org/appengine/internal/base/api_base.proto
generated
vendored
Normal file
33
vendor/google.golang.org/appengine/internal/base/api_base.proto
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Built-in base types for API calls. Primarily useful as return types.
|
||||
|
||||
syntax = "proto2";
|
||||
option go_package = "base";
|
||||
|
||||
package appengine.base;
|
||||
|
||||
message StringProto {
|
||||
required string value = 1;
|
||||
}
|
||||
|
||||
message Integer32Proto {
|
||||
required int32 value = 1;
|
||||
}
|
||||
|
||||
message Integer64Proto {
|
||||
required int64 value = 1;
|
||||
}
|
||||
|
||||
message BoolProto {
|
||||
required bool value = 1;
|
||||
}
|
||||
|
||||
message DoubleProto {
|
||||
required double value = 1;
|
||||
}
|
||||
|
||||
message BytesProto {
|
||||
required bytes value = 1 [ctype=CORD];
|
||||
}
|
||||
|
||||
message VoidProto {
|
||||
}
|
||||
4367
vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go
generated
vendored
Normal file
4367
vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
551
vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto
generated
vendored
Executable file
551
vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto
generated
vendored
Executable file
|
|
@ -0,0 +1,551 @@
|
|||
syntax = "proto2";
|
||||
option go_package = "datastore";
|
||||
|
||||
package appengine;
|
||||
|
||||
message Action{}
|
||||
|
||||
message PropertyValue {
|
||||
optional int64 int64Value = 1;
|
||||
optional bool booleanValue = 2;
|
||||
optional string stringValue = 3;
|
||||
optional double doubleValue = 4;
|
||||
|
||||
optional group PointValue = 5 {
|
||||
required double x = 6;
|
||||
required double y = 7;
|
||||
}
|
||||
|
||||
optional group UserValue = 8 {
|
||||
required string email = 9;
|
||||
required string auth_domain = 10;
|
||||
optional string nickname = 11;
|
||||
optional string federated_identity = 21;
|
||||
optional string federated_provider = 22;
|
||||
}
|
||||
|
||||
optional group ReferenceValue = 12 {
|
||||
required string app = 13;
|
||||
optional string name_space = 20;
|
||||
repeated group PathElement = 14 {
|
||||
required string type = 15;
|
||||
optional int64 id = 16;
|
||||
optional string name = 17;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message Property {
|
||||
enum Meaning {
|
||||
NO_MEANING = 0;
|
||||
BLOB = 14;
|
||||
TEXT = 15;
|
||||
BYTESTRING = 16;
|
||||
|
||||
ATOM_CATEGORY = 1;
|
||||
ATOM_LINK = 2;
|
||||
ATOM_TITLE = 3;
|
||||
ATOM_CONTENT = 4;
|
||||
ATOM_SUMMARY = 5;
|
||||
ATOM_AUTHOR = 6;
|
||||
|
||||
GD_WHEN = 7;
|
||||
GD_EMAIL = 8;
|
||||
GEORSS_POINT = 9;
|
||||
GD_IM = 10;
|
||||
|
||||
GD_PHONENUMBER = 11;
|
||||
GD_POSTALADDRESS = 12;
|
||||
|
||||
GD_RATING = 13;
|
||||
|
||||
BLOBKEY = 17;
|
||||
ENTITY_PROTO = 19;
|
||||
|
||||
INDEX_VALUE = 18;
|
||||
};
|
||||
|
||||
optional Meaning meaning = 1 [default = NO_MEANING];
|
||||
optional string meaning_uri = 2;
|
||||
|
||||
required string name = 3;
|
||||
|
||||
required PropertyValue value = 5;
|
||||
|
||||
required bool multiple = 4;
|
||||
|
||||
optional bool searchable = 6 [default=false];
|
||||
|
||||
enum FtsTokenizationOption {
|
||||
HTML = 1;
|
||||
ATOM = 2;
|
||||
}
|
||||
|
||||
optional FtsTokenizationOption fts_tokenization_option = 8;
|
||||
|
||||
optional string locale = 9 [default = "en"];
|
||||
}
|
||||
|
||||
message Path {
|
||||
repeated group Element = 1 {
|
||||
required string type = 2;
|
||||
optional int64 id = 3;
|
||||
optional string name = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message Reference {
|
||||
required string app = 13;
|
||||
optional string name_space = 20;
|
||||
required Path path = 14;
|
||||
}
|
||||
|
||||
message User {
|
||||
required string email = 1;
|
||||
required string auth_domain = 2;
|
||||
optional string nickname = 3;
|
||||
optional string federated_identity = 6;
|
||||
optional string federated_provider = 7;
|
||||
}
|
||||
|
||||
message EntityProto {
|
||||
required Reference key = 13;
|
||||
required Path entity_group = 16;
|
||||
optional User owner = 17;
|
||||
|
||||
enum Kind {
|
||||
GD_CONTACT = 1;
|
||||
GD_EVENT = 2;
|
||||
GD_MESSAGE = 3;
|
||||
}
|
||||
optional Kind kind = 4;
|
||||
optional string kind_uri = 5;
|
||||
|
||||
repeated Property property = 14;
|
||||
repeated Property raw_property = 15;
|
||||
|
||||
optional int32 rank = 18;
|
||||
}
|
||||
|
||||
message CompositeProperty {
|
||||
required int64 index_id = 1;
|
||||
repeated string value = 2;
|
||||
}
|
||||
|
||||
message Index {
|
||||
required string entity_type = 1;
|
||||
required bool ancestor = 5;
|
||||
repeated group Property = 2 {
|
||||
required string name = 3;
|
||||
enum Direction {
|
||||
ASCENDING = 1;
|
||||
DESCENDING = 2;
|
||||
}
|
||||
optional Direction direction = 4 [default = ASCENDING];
|
||||
}
|
||||
}
|
||||
|
||||
message CompositeIndex {
|
||||
required string app_id = 1;
|
||||
required int64 id = 2;
|
||||
required Index definition = 3;
|
||||
|
||||
enum State {
|
||||
WRITE_ONLY = 1;
|
||||
READ_WRITE = 2;
|
||||
DELETED = 3;
|
||||
ERROR = 4;
|
||||
}
|
||||
required State state = 4;
|
||||
|
||||
optional bool only_use_if_required = 6 [default = false];
|
||||
}
|
||||
|
||||
message IndexPostfix {
|
||||
message IndexValue {
|
||||
required string property_name = 1;
|
||||
required PropertyValue value = 2;
|
||||
}
|
||||
|
||||
repeated IndexValue index_value = 1;
|
||||
|
||||
optional Reference key = 2;
|
||||
|
||||
optional bool before = 3 [default=true];
|
||||
}
|
||||
|
||||
message IndexPosition {
|
||||
optional string key = 1;
|
||||
|
||||
optional bool before = 2 [default=true];
|
||||
}
|
||||
|
||||
message Snapshot {
|
||||
enum Status {
|
||||
INACTIVE = 0;
|
||||
ACTIVE = 1;
|
||||
}
|
||||
|
||||
required int64 ts = 1;
|
||||
}
|
||||
|
||||
message InternalHeader {
|
||||
optional string qos = 1;
|
||||
}
|
||||
|
||||
message Transaction {
|
||||
optional InternalHeader header = 4;
|
||||
required fixed64 handle = 1;
|
||||
required string app = 2;
|
||||
optional bool mark_changes = 3 [default = false];
|
||||
}
|
||||
|
||||
message Query {
|
||||
optional InternalHeader header = 39;
|
||||
|
||||
required string app = 1;
|
||||
optional string name_space = 29;
|
||||
|
||||
optional string kind = 3;
|
||||
optional Reference ancestor = 17;
|
||||
|
||||
repeated group Filter = 4 {
|
||||
enum Operator {
|
||||
LESS_THAN = 1;
|
||||
LESS_THAN_OR_EQUAL = 2;
|
||||
GREATER_THAN = 3;
|
||||
GREATER_THAN_OR_EQUAL = 4;
|
||||
EQUAL = 5;
|
||||
IN = 6;
|
||||
EXISTS = 7;
|
||||
}
|
||||
|
||||
required Operator op = 6;
|
||||
repeated Property property = 14;
|
||||
}
|
||||
|
||||
optional string search_query = 8;
|
||||
|
||||
repeated group Order = 9 {
|
||||
enum Direction {
|
||||
ASCENDING = 1;
|
||||
DESCENDING = 2;
|
||||
}
|
||||
|
||||
required string property = 10;
|
||||
optional Direction direction = 11 [default = ASCENDING];
|
||||
}
|
||||
|
||||
enum Hint {
|
||||
ORDER_FIRST = 1;
|
||||
ANCESTOR_FIRST = 2;
|
||||
FILTER_FIRST = 3;
|
||||
}
|
||||
optional Hint hint = 18;
|
||||
|
||||
optional int32 count = 23;
|
||||
|
||||
optional int32 offset = 12 [default = 0];
|
||||
|
||||
optional int32 limit = 16;
|
||||
|
||||
optional CompiledCursor compiled_cursor = 30;
|
||||
optional CompiledCursor end_compiled_cursor = 31;
|
||||
|
||||
repeated CompositeIndex composite_index = 19;
|
||||
|
||||
optional bool require_perfect_plan = 20 [default = false];
|
||||
|
||||
optional bool keys_only = 21 [default = false];
|
||||
|
||||
optional Transaction transaction = 22;
|
||||
|
||||
optional bool compile = 25 [default = false];
|
||||
|
||||
optional int64 failover_ms = 26;
|
||||
|
||||
optional bool strong = 32;
|
||||
|
||||
repeated string property_name = 33;
|
||||
|
||||
repeated string group_by_property_name = 34;
|
||||
|
||||
optional bool distinct = 24;
|
||||
|
||||
optional int64 min_safe_time_seconds = 35;
|
||||
|
||||
repeated string safe_replica_name = 36;
|
||||
|
||||
optional bool persist_offset = 37 [default=false];
|
||||
}
|
||||
|
||||
message CompiledQuery {
|
||||
required group PrimaryScan = 1 {
|
||||
optional string index_name = 2;
|
||||
|
||||
optional string start_key = 3;
|
||||
optional bool start_inclusive = 4;
|
||||
optional string end_key = 5;
|
||||
optional bool end_inclusive = 6;
|
||||
|
||||
repeated string start_postfix_value = 22;
|
||||
repeated string end_postfix_value = 23;
|
||||
|
||||
optional int64 end_unapplied_log_timestamp_us = 19;
|
||||
}
|
||||
|
||||
repeated group MergeJoinScan = 7 {
|
||||
required string index_name = 8;
|
||||
|
||||
repeated string prefix_value = 9;
|
||||
|
||||
optional bool value_prefix = 20 [default=false];
|
||||
}
|
||||
|
||||
optional Index index_def = 21;
|
||||
|
||||
optional int32 offset = 10 [default = 0];
|
||||
|
||||
optional int32 limit = 11;
|
||||
|
||||
required bool keys_only = 12;
|
||||
|
||||
repeated string property_name = 24;
|
||||
|
||||
optional int32 distinct_infix_size = 25;
|
||||
|
||||
optional group EntityFilter = 13 {
|
||||
optional bool distinct = 14 [default=false];
|
||||
|
||||
optional string kind = 17;
|
||||
optional Reference ancestor = 18;
|
||||
}
|
||||
}
|
||||
|
||||
message CompiledCursor {
|
||||
optional group Position = 2 {
|
||||
optional string start_key = 27;
|
||||
|
||||
repeated group IndexValue = 29 {
|
||||
optional string property = 30;
|
||||
required PropertyValue value = 31;
|
||||
}
|
||||
|
||||
optional Reference key = 32;
|
||||
|
||||
optional bool start_inclusive = 28 [default=true];
|
||||
}
|
||||
}
|
||||
|
||||
message Cursor {
|
||||
required fixed64 cursor = 1;
|
||||
|
||||
optional string app = 2;
|
||||
}
|
||||
|
||||
message Error {
|
||||
enum ErrorCode {
|
||||
BAD_REQUEST = 1;
|
||||
CONCURRENT_TRANSACTION = 2;
|
||||
INTERNAL_ERROR = 3;
|
||||
NEED_INDEX = 4;
|
||||
TIMEOUT = 5;
|
||||
PERMISSION_DENIED = 6;
|
||||
BIGTABLE_ERROR = 7;
|
||||
COMMITTED_BUT_STILL_APPLYING = 8;
|
||||
CAPABILITY_DISABLED = 9;
|
||||
TRY_ALTERNATE_BACKEND = 10;
|
||||
SAFE_TIME_TOO_OLD = 11;
|
||||
}
|
||||
}
|
||||
|
||||
message Cost {
|
||||
optional int32 index_writes = 1;
|
||||
optional int32 index_write_bytes = 2;
|
||||
optional int32 entity_writes = 3;
|
||||
optional int32 entity_write_bytes = 4;
|
||||
optional group CommitCost = 5 {
|
||||
optional int32 requested_entity_puts = 6;
|
||||
optional int32 requested_entity_deletes = 7;
|
||||
};
|
||||
optional int32 approximate_storage_delta = 8;
|
||||
optional int32 id_sequence_updates = 9;
|
||||
}
|
||||
|
||||
message GetRequest {
|
||||
optional InternalHeader header = 6;
|
||||
|
||||
repeated Reference key = 1;
|
||||
optional Transaction transaction = 2;
|
||||
|
||||
optional int64 failover_ms = 3;
|
||||
|
||||
optional bool strong = 4;
|
||||
|
||||
optional bool allow_deferred = 5 [default=false];
|
||||
}
|
||||
|
||||
message GetResponse {
|
||||
repeated group Entity = 1 {
|
||||
optional EntityProto entity = 2;
|
||||
optional Reference key = 4;
|
||||
|
||||
optional int64 version = 3;
|
||||
}
|
||||
|
||||
repeated Reference deferred = 5;
|
||||
|
||||
optional bool in_order = 6 [default=true];
|
||||
}
|
||||
|
||||
message PutRequest {
|
||||
optional InternalHeader header = 11;
|
||||
|
||||
repeated EntityProto entity = 1;
|
||||
optional Transaction transaction = 2;
|
||||
repeated CompositeIndex composite_index = 3;
|
||||
|
||||
optional bool trusted = 4 [default = false];
|
||||
|
||||
optional bool force = 7 [default = false];
|
||||
|
||||
optional bool mark_changes = 8 [default = false];
|
||||
repeated Snapshot snapshot = 9;
|
||||
|
||||
enum AutoIdPolicy {
|
||||
CURRENT = 0;
|
||||
SEQUENTIAL = 1;
|
||||
}
|
||||
optional AutoIdPolicy auto_id_policy = 10 [default = CURRENT];
|
||||
}
|
||||
|
||||
message PutResponse {
|
||||
repeated Reference key = 1;
|
||||
optional Cost cost = 2;
|
||||
repeated int64 version = 3;
|
||||
}
|
||||
|
||||
message TouchRequest {
|
||||
optional InternalHeader header = 10;
|
||||
|
||||
repeated Reference key = 1;
|
||||
repeated CompositeIndex composite_index = 2;
|
||||
optional bool force = 3 [default = false];
|
||||
repeated Snapshot snapshot = 9;
|
||||
}
|
||||
|
||||
message TouchResponse {
|
||||
optional Cost cost = 1;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
optional InternalHeader header = 10;
|
||||
|
||||
repeated Reference key = 6;
|
||||
optional Transaction transaction = 5;
|
||||
|
||||
optional bool trusted = 4 [default = false];
|
||||
|
||||
optional bool force = 7 [default = false];
|
||||
|
||||
optional bool mark_changes = 8 [default = false];
|
||||
repeated Snapshot snapshot = 9;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
optional Cost cost = 1;
|
||||
repeated int64 version = 3;
|
||||
}
|
||||
|
||||
message NextRequest {
|
||||
optional InternalHeader header = 5;
|
||||
|
||||
required Cursor cursor = 1;
|
||||
optional int32 count = 2;
|
||||
|
||||
optional int32 offset = 4 [default = 0];
|
||||
|
||||
optional bool compile = 3 [default = false];
|
||||
}
|
||||
|
||||
message QueryResult {
|
||||
optional Cursor cursor = 1;
|
||||
|
||||
repeated EntityProto result = 2;
|
||||
|
||||
optional int32 skipped_results = 7;
|
||||
|
||||
required bool more_results = 3;
|
||||
|
||||
optional bool keys_only = 4;
|
||||
|
||||
optional bool index_only = 9;
|
||||
|
||||
optional bool small_ops = 10;
|
||||
|
||||
optional CompiledQuery compiled_query = 5;
|
||||
|
||||
optional CompiledCursor compiled_cursor = 6;
|
||||
|
||||
repeated CompositeIndex index = 8;
|
||||
|
||||
repeated int64 version = 11;
|
||||
}
|
||||
|
||||
message AllocateIdsRequest {
|
||||
optional InternalHeader header = 4;
|
||||
|
||||
optional Reference model_key = 1;
|
||||
|
||||
optional int64 size = 2;
|
||||
|
||||
optional int64 max = 3;
|
||||
|
||||
repeated Reference reserve = 5;
|
||||
}
|
||||
|
||||
message AllocateIdsResponse {
|
||||
required int64 start = 1;
|
||||
required int64 end = 2;
|
||||
optional Cost cost = 3;
|
||||
}
|
||||
|
||||
message CompositeIndices {
|
||||
repeated CompositeIndex index = 1;
|
||||
}
|
||||
|
||||
message AddActionsRequest {
|
||||
optional InternalHeader header = 3;
|
||||
|
||||
required Transaction transaction = 1;
|
||||
repeated Action action = 2;
|
||||
}
|
||||
|
||||
message AddActionsResponse {
|
||||
}
|
||||
|
||||
message BeginTransactionRequest {
|
||||
optional InternalHeader header = 3;
|
||||
|
||||
required string app = 1;
|
||||
optional bool allow_multiple_eg = 2 [default = false];
|
||||
optional string database_id = 4;
|
||||
|
||||
enum TransactionMode {
|
||||
UNKNOWN = 0;
|
||||
READ_ONLY = 1;
|
||||
READ_WRITE = 2;
|
||||
}
|
||||
optional TransactionMode mode = 5 [default = UNKNOWN];
|
||||
|
||||
optional Transaction previous_transaction = 7;
|
||||
}
|
||||
|
||||
message CommitResponse {
|
||||
optional Cost cost = 1;
|
||||
|
||||
repeated group Version = 3 {
|
||||
required Reference root_entity_key = 4;
|
||||
required int64 version = 5;
|
||||
}
|
||||
}
|
||||
55
vendor/google.golang.org/appengine/internal/identity.go
generated
vendored
Normal file
55
vendor/google.golang.org/appengine/internal/identity.go
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var (
|
||||
// This is set to true in identity_classic.go, which is behind the appengine build tag.
|
||||
// The appengine build tag is set for the first generation runtimes (<= Go 1.9) but not
|
||||
// the second generation runtimes (>= Go 1.11), so this indicates whether we're on a
|
||||
// first-gen runtime. See IsStandard below for the second-gen check.
|
||||
appengineStandard bool
|
||||
|
||||
// This is set to true in identity_flex.go, which is behind the appenginevm build tag.
|
||||
appengineFlex bool
|
||||
)
|
||||
|
||||
// AppID is the implementation of the wrapper function of the same name in
|
||||
// ../identity.go. See that file for commentary.
|
||||
func AppID(c netcontext.Context) string {
|
||||
return appID(FullyQualifiedAppID(c))
|
||||
}
|
||||
|
||||
// IsStandard is the implementation of the wrapper function of the same name in
|
||||
// ../appengine.go. See that file for commentary.
|
||||
func IsStandard() bool {
|
||||
// appengineStandard will be true for first-gen runtimes (<= Go 1.9) but not
|
||||
// second-gen (>= Go 1.11).
|
||||
return appengineStandard || IsSecondGen()
|
||||
}
|
||||
|
||||
// IsStandard is the implementation of the wrapper function of the same name in
|
||||
// ../appengine.go. See that file for commentary.
|
||||
func IsSecondGen() bool {
|
||||
// Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime.
|
||||
return os.Getenv("GAE_ENV") == "standard"
|
||||
}
|
||||
|
||||
// IsFlex is the implementation of the wrapper function of the same name in
|
||||
// ../appengine.go. See that file for commentary.
|
||||
func IsFlex() bool {
|
||||
return appengineFlex
|
||||
}
|
||||
|
||||
// IsAppEngine is the implementation of the wrapper function of the same name in
|
||||
// ../appengine.go. See that file for commentary.
|
||||
func IsAppEngine() bool {
|
||||
return IsStandard() || IsFlex()
|
||||
}
|
||||
61
vendor/google.golang.org/appengine/internal/identity_classic.go
generated
vendored
Normal file
61
vendor/google.golang.org/appengine/internal/identity_classic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2015 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 (
|
||||
"appengine"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func init() {
|
||||
appengineStandard = true
|
||||
}
|
||||
|
||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return appengine.DefaultVersionHostname(c)
|
||||
}
|
||||
|
||||
func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() }
|
||||
func ServerSoftware() string { return appengine.ServerSoftware() }
|
||||
func InstanceID() string { return appengine.InstanceID() }
|
||||
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
|
||||
|
||||
func RequestID(ctx netcontext.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return appengine.RequestID(c)
|
||||
}
|
||||
|
||||
func ModuleName(ctx netcontext.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return appengine.ModuleName(c)
|
||||
}
|
||||
func VersionID(ctx netcontext.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return appengine.VersionID(c)
|
||||
}
|
||||
|
||||
func fullyQualifiedAppID(ctx netcontext.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return c.FullyQualifiedAppID()
|
||||
}
|
||||
11
vendor/google.golang.org/appengine/internal/identity_flex.go
generated
vendored
Normal file
11
vendor/google.golang.org/appengine/internal/identity_flex.go
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2018 Google LLC. 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 appenginevm
|
||||
|
||||
package internal
|
||||
|
||||
func init() {
|
||||
appengineFlex = true
|
||||
}
|
||||
134
vendor/google.golang.org/appengine/internal/identity_vm.go
generated
vendored
Normal file
134
vendor/google.golang.org/appengine/internal/identity_vm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2011 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 (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// These functions are implementations of the wrapper functions
|
||||
// in ../appengine/identity.go. See that file for commentary.
|
||||
|
||||
const (
|
||||
hDefaultVersionHostname = "X-AppEngine-Default-Version-Hostname"
|
||||
hRequestLogId = "X-AppEngine-Request-Log-Id"
|
||||
hDatacenter = "X-AppEngine-Datacenter"
|
||||
)
|
||||
|
||||
func ctxHeaders(ctx netcontext.Context) http.Header {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.Request().Header
|
||||
}
|
||||
|
||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||
return ctxHeaders(ctx).Get(hDefaultVersionHostname)
|
||||
}
|
||||
|
||||
func RequestID(ctx netcontext.Context) string {
|
||||
return ctxHeaders(ctx).Get(hRequestLogId)
|
||||
}
|
||||
|
||||
func Datacenter(ctx netcontext.Context) string {
|
||||
if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
|
||||
return dc
|
||||
}
|
||||
// If the header isn't set, read zone from the metadata service.
|
||||
// It has the format projects/[NUMERIC_PROJECT_ID]/zones/[ZONE]
|
||||
zone, err := getMetadata("instance/zone")
|
||||
if err != nil {
|
||||
log.Printf("Datacenter: %v", err)
|
||||
return ""
|
||||
}
|
||||
parts := strings.Split(string(zone), "/")
|
||||
if len(parts) == 0 {
|
||||
return ""
|
||||
}
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
func ServerSoftware() string {
|
||||
// TODO(dsymonds): Remove fallback when we've verified this.
|
||||
if s := os.Getenv("SERVER_SOFTWARE"); s != "" {
|
||||
return s
|
||||
}
|
||||
if s := os.Getenv("GAE_ENV"); s != "" {
|
||||
return s
|
||||
}
|
||||
return "Google App Engine/1.x.x"
|
||||
}
|
||||
|
||||
// TODO(dsymonds): Remove the metadata fetches.
|
||||
|
||||
func ModuleName(_ netcontext.Context) string {
|
||||
if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
|
||||
return s
|
||||
}
|
||||
if s := os.Getenv("GAE_SERVICE"); s != "" {
|
||||
return s
|
||||
}
|
||||
return string(mustGetMetadata("instance/attributes/gae_backend_name"))
|
||||
}
|
||||
|
||||
func VersionID(_ netcontext.Context) string {
|
||||
if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
|
||||
return s1 + "." + s2
|
||||
}
|
||||
if s1, s2 := os.Getenv("GAE_VERSION"), os.Getenv("GAE_DEPLOYMENT_ID"); s1 != "" && s2 != "" {
|
||||
return s1 + "." + s2
|
||||
}
|
||||
return string(mustGetMetadata("instance/attributes/gae_backend_version")) + "." + string(mustGetMetadata("instance/attributes/gae_backend_minor_version"))
|
||||
}
|
||||
|
||||
func InstanceID() string {
|
||||
if s := os.Getenv("GAE_MODULE_INSTANCE"); s != "" {
|
||||
return s
|
||||
}
|
||||
if s := os.Getenv("GAE_INSTANCE"); s != "" {
|
||||
return s
|
||||
}
|
||||
return string(mustGetMetadata("instance/attributes/gae_backend_instance"))
|
||||
}
|
||||
|
||||
func partitionlessAppID() string {
|
||||
// gae_project has everything except the partition prefix.
|
||||
if appID := os.Getenv("GAE_LONG_APP_ID"); appID != "" {
|
||||
return appID
|
||||
}
|
||||
if project := os.Getenv("GOOGLE_CLOUD_PROJECT"); project != "" {
|
||||
return project
|
||||
}
|
||||
return string(mustGetMetadata("instance/attributes/gae_project"))
|
||||
}
|
||||
|
||||
func fullyQualifiedAppID(_ netcontext.Context) string {
|
||||
if s := os.Getenv("GAE_APPLICATION"); s != "" {
|
||||
return s
|
||||
}
|
||||
appID := partitionlessAppID()
|
||||
|
||||
part := os.Getenv("GAE_PARTITION")
|
||||
if part == "" {
|
||||
part = string(mustGetMetadata("instance/attributes/gae_partition"))
|
||||
}
|
||||
|
||||
if part != "" {
|
||||
appID = part + "~" + appID
|
||||
}
|
||||
return appID
|
||||
}
|
||||
|
||||
func IsDevAppServer() bool {
|
||||
return os.Getenv("RUN_WITH_DEVAPPSERVER") != ""
|
||||
}
|
||||
110
vendor/google.golang.org/appengine/internal/internal.go
generated
vendored
Normal file
110
vendor/google.golang.org/appengine/internal/internal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
// Package internal provides support for package appengine.
|
||||
//
|
||||
// Programs should not use this package directly. Its API is not stable.
|
||||
// Use packages appengine and appengine/* instead.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
remotepb "google.golang.org/appengine/internal/remote_api"
|
||||
)
|
||||
|
||||
// errorCodeMaps is a map of service name to the error code map for the service.
|
||||
var errorCodeMaps = make(map[string]map[int32]string)
|
||||
|
||||
// RegisterErrorCodeMap is called from API implementations to register their
|
||||
// error code map. This should only be called from init functions.
|
||||
func RegisterErrorCodeMap(service string, m map[int32]string) {
|
||||
errorCodeMaps[service] = m
|
||||
}
|
||||
|
||||
type timeoutCodeKey struct {
|
||||
service string
|
||||
code int32
|
||||
}
|
||||
|
||||
// timeoutCodes is the set of service+code pairs that represent timeouts.
|
||||
var timeoutCodes = make(map[timeoutCodeKey]bool)
|
||||
|
||||
func RegisterTimeoutErrorCode(service string, code int32) {
|
||||
timeoutCodes[timeoutCodeKey{service, code}] = true
|
||||
}
|
||||
|
||||
// APIError is the type returned by appengine.Context's Call method
|
||||
// when an API call fails in an API-specific way. This may be, for instance,
|
||||
// a taskqueue API call failing with TaskQueueServiceError::UNKNOWN_QUEUE.
|
||||
type APIError struct {
|
||||
Service string
|
||||
Detail string
|
||||
Code int32 // API-specific error code
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
if e.Code == 0 {
|
||||
if e.Detail == "" {
|
||||
return "APIError <empty>"
|
||||
}
|
||||
return e.Detail
|
||||
}
|
||||
s := fmt.Sprintf("API error %d", e.Code)
|
||||
if m, ok := errorCodeMaps[e.Service]; ok {
|
||||
s += " (" + e.Service + ": " + m[e.Code] + ")"
|
||||
} else {
|
||||
// Shouldn't happen, but provide a bit more detail if it does.
|
||||
s = e.Service + " " + s
|
||||
}
|
||||
if e.Detail != "" {
|
||||
s += ": " + e.Detail
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (e *APIError) IsTimeout() bool {
|
||||
return timeoutCodes[timeoutCodeKey{e.Service, e.Code}]
|
||||
}
|
||||
|
||||
// CallError is the type returned by appengine.Context's Call method when an
|
||||
// API call fails in a generic way, such as RpcError::CAPABILITY_DISABLED.
|
||||
type CallError struct {
|
||||
Detail string
|
||||
Code int32
|
||||
// TODO: Remove this if we get a distinguishable error code.
|
||||
Timeout bool
|
||||
}
|
||||
|
||||
func (e *CallError) Error() string {
|
||||
var msg string
|
||||
switch remotepb.RpcError_ErrorCode(e.Code) {
|
||||
case remotepb.RpcError_UNKNOWN:
|
||||
return e.Detail
|
||||
case remotepb.RpcError_OVER_QUOTA:
|
||||
msg = "Over quota"
|
||||
case remotepb.RpcError_CAPABILITY_DISABLED:
|
||||
msg = "Capability disabled"
|
||||
case remotepb.RpcError_CANCELLED:
|
||||
msg = "Canceled"
|
||||
default:
|
||||
msg = fmt.Sprintf("Call error %d", e.Code)
|
||||
}
|
||||
s := msg + ": " + e.Detail
|
||||
if e.Timeout {
|
||||
s += " (timeout)"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (e *CallError) IsTimeout() bool {
|
||||
return e.Timeout
|
||||
}
|
||||
|
||||
// NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace.
|
||||
// The function should be prepared to be called on the same message more than once; it should only modify the
|
||||
// RPC request the first time.
|
||||
var NamespaceMods = make(map[string]func(m proto.Message, namespace string))
|
||||
1313
vendor/google.golang.org/appengine/internal/log/log_service.pb.go
generated
vendored
Normal file
1313
vendor/google.golang.org/appengine/internal/log/log_service.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
150
vendor/google.golang.org/appengine/internal/log/log_service.proto
generated
vendored
Normal file
150
vendor/google.golang.org/appengine/internal/log/log_service.proto
generated
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
syntax = "proto2";
|
||||
option go_package = "log";
|
||||
|
||||
package appengine;
|
||||
|
||||
message LogServiceError {
|
||||
enum ErrorCode {
|
||||
OK = 0;
|
||||
INVALID_REQUEST = 1;
|
||||
STORAGE_ERROR = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UserAppLogLine {
|
||||
required int64 timestamp_usec = 1;
|
||||
required int64 level = 2;
|
||||
required string message = 3;
|
||||
}
|
||||
|
||||
message UserAppLogGroup {
|
||||
repeated UserAppLogLine log_line = 2;
|
||||
}
|
||||
|
||||
message FlushRequest {
|
||||
optional bytes logs = 1;
|
||||
}
|
||||
|
||||
message SetStatusRequest {
|
||||
required string status = 1;
|
||||
}
|
||||
|
||||
|
||||
message LogOffset {
|
||||
optional bytes request_id = 1;
|
||||
}
|
||||
|
||||
message LogLine {
|
||||
required int64 time = 1;
|
||||
required int32 level = 2;
|
||||
required string log_message = 3;
|
||||
}
|
||||
|
||||
message RequestLog {
|
||||
required string app_id = 1;
|
||||
optional string module_id = 37 [default="default"];
|
||||
required string version_id = 2;
|
||||
required bytes request_id = 3;
|
||||
optional LogOffset offset = 35;
|
||||
required string ip = 4;
|
||||
optional string nickname = 5;
|
||||
required int64 start_time = 6;
|
||||
required int64 end_time = 7;
|
||||
required int64 latency = 8;
|
||||
required int64 mcycles = 9;
|
||||
required string method = 10;
|
||||
required string resource = 11;
|
||||
required string http_version = 12;
|
||||
required int32 status = 13;
|
||||
required int64 response_size = 14;
|
||||
optional string referrer = 15;
|
||||
optional string user_agent = 16;
|
||||
required string url_map_entry = 17;
|
||||
required string combined = 18;
|
||||
optional int64 api_mcycles = 19;
|
||||
optional string host = 20;
|
||||
optional double cost = 21;
|
||||
|
||||
optional string task_queue_name = 22;
|
||||
optional string task_name = 23;
|
||||
|
||||
optional bool was_loading_request = 24;
|
||||
optional int64 pending_time = 25;
|
||||
optional int32 replica_index = 26 [default = -1];
|
||||
optional bool finished = 27 [default = true];
|
||||
optional bytes clone_key = 28;
|
||||
|
||||
repeated LogLine line = 29;
|
||||
|
||||
optional bool lines_incomplete = 36;
|
||||
optional bytes app_engine_release = 38;
|
||||
|
||||
optional int32 exit_reason = 30;
|
||||
optional bool was_throttled_for_time = 31;
|
||||
optional bool was_throttled_for_requests = 32;
|
||||
optional int64 throttled_time = 33;
|
||||
|
||||
optional bytes server_name = 34;
|
||||
}
|
||||
|
||||
message LogModuleVersion {
|
||||
optional string module_id = 1 [default="default"];
|
||||
optional string version_id = 2;
|
||||
}
|
||||
|
||||
message LogReadRequest {
|
||||
required string app_id = 1;
|
||||
repeated string version_id = 2;
|
||||
repeated LogModuleVersion module_version = 19;
|
||||
|
||||
optional int64 start_time = 3;
|
||||
optional int64 end_time = 4;
|
||||
optional LogOffset offset = 5;
|
||||
repeated bytes request_id = 6;
|
||||
|
||||
optional int32 minimum_log_level = 7;
|
||||
optional bool include_incomplete = 8;
|
||||
optional int64 count = 9;
|
||||
|
||||
optional string combined_log_regex = 14;
|
||||
optional string host_regex = 15;
|
||||
optional int32 replica_index = 16;
|
||||
|
||||
optional bool include_app_logs = 10;
|
||||
optional int32 app_logs_per_request = 17;
|
||||
optional bool include_host = 11;
|
||||
optional bool include_all = 12;
|
||||
optional bool cache_iterator = 13;
|
||||
optional int32 num_shards = 18;
|
||||
}
|
||||
|
||||
message LogReadResponse {
|
||||
repeated RequestLog log = 1;
|
||||
optional LogOffset offset = 2;
|
||||
optional int64 last_end_time = 3;
|
||||
}
|
||||
|
||||
message LogUsageRecord {
|
||||
optional string version_id = 1;
|
||||
optional int32 start_time = 2;
|
||||
optional int32 end_time = 3;
|
||||
optional int64 count = 4;
|
||||
optional int64 total_size = 5;
|
||||
optional int32 records = 6;
|
||||
}
|
||||
|
||||
message LogUsageRequest {
|
||||
required string app_id = 1;
|
||||
repeated string version_id = 2;
|
||||
optional int32 start_time = 3;
|
||||
optional int32 end_time = 4;
|
||||
optional uint32 resolution_hours = 5 [default = 1];
|
||||
optional bool combine_versions = 6;
|
||||
optional int32 usage_version = 7;
|
||||
optional bool versions_only = 8;
|
||||
}
|
||||
|
||||
message LogUsageResponse {
|
||||
repeated LogUsageRecord usage = 1;
|
||||
optional LogUsageRecord summary = 2;
|
||||
}
|
||||
16
vendor/google.golang.org/appengine/internal/main.go
generated
vendored
Normal file
16
vendor/google.golang.org/appengine/internal/main.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2011 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 (
|
||||
"appengine_internal"
|
||||
)
|
||||
|
||||
func Main() {
|
||||
MainPath = ""
|
||||
appengine_internal.Main()
|
||||
}
|
||||
7
vendor/google.golang.org/appengine/internal/main_common.go
generated
vendored
Normal file
7
vendor/google.golang.org/appengine/internal/main_common.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package internal
|
||||
|
||||
// MainPath stores the file path of the main package. On App Engine Standard
|
||||
// using Go version 1.9 and below, this will be unset. On App Engine Flex and
|
||||
// App Engine Standard second-gen (Go 1.11 and above), this will be the
|
||||
// filepath to package main.
|
||||
var MainPath string
|
||||
69
vendor/google.golang.org/appengine/internal/main_vm.go
generated
vendored
Normal file
69
vendor/google.golang.org/appengine/internal/main_vm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2011 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 (
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func Main() {
|
||||
MainPath = filepath.Dir(findMainPath())
|
||||
installHealthChecker(http.DefaultServeMux)
|
||||
|
||||
port := "8080"
|
||||
if s := os.Getenv("PORT"); s != "" {
|
||||
port = s
|
||||
}
|
||||
|
||||
host := ""
|
||||
if IsDevAppServer() {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
|
||||
log.Fatalf("http.ListenAndServe: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the path to package main by looking at the root Caller.
|
||||
func findMainPath() string {
|
||||
pc := make([]uintptr, 100)
|
||||
n := runtime.Callers(2, pc)
|
||||
frames := runtime.CallersFrames(pc[:n])
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
// Tests won't have package main, instead they have testing.tRunner
|
||||
if frame.Function == "main.main" || frame.Function == "testing.tRunner" {
|
||||
return frame.File
|
||||
}
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func installHealthChecker(mux *http.ServeMux) {
|
||||
// If no health check handler has been installed by this point, add a trivial one.
|
||||
const healthPath = "/_ah/health"
|
||||
hreq := &http.Request{
|
||||
Method: "GET",
|
||||
URL: &url.URL{
|
||||
Path: healthPath,
|
||||
},
|
||||
}
|
||||
if _, pat := mux.Handler(hreq); pat != healthPath {
|
||||
mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, "ok")
|
||||
})
|
||||
}
|
||||
}
|
||||
60
vendor/google.golang.org/appengine/internal/metadata.go
generated
vendored
Normal file
60
vendor/google.golang.org/appengine/internal/metadata.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
package internal
|
||||
|
||||
// This file has code for accessing metadata.
|
||||
//
|
||||
// References:
|
||||
// https://cloud.google.com/compute/docs/metadata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
metadataHost = "metadata"
|
||||
metadataPath = "/computeMetadata/v1/"
|
||||
)
|
||||
|
||||
var (
|
||||
metadataRequestHeaders = http.Header{
|
||||
"Metadata-Flavor": []string{"Google"},
|
||||
}
|
||||
)
|
||||
|
||||
// TODO(dsymonds): Do we need to support default values, like Python?
|
||||
func mustGetMetadata(key string) []byte {
|
||||
b, err := getMetadata(key)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Metadata fetch failed for '%s': %v", key, err))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func getMetadata(key string) ([]byte, error) {
|
||||
// TODO(dsymonds): May need to use url.Parse to support keys with query args.
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
URL: &url.URL{
|
||||
Scheme: "http",
|
||||
Host: metadataHost,
|
||||
Path: metadataPath + key,
|
||||
},
|
||||
Header: metadataRequestHeaders,
|
||||
Host: metadataHost,
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("metadata server returned HTTP %d", resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
56
vendor/google.golang.org/appengine/internal/net.go
generated
vendored
Normal file
56
vendor/google.golang.org/appengine/internal/net.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
package internal
|
||||
|
||||
// This file implements a network dialer that limits the number of concurrent connections.
|
||||
// It is only used for API calls.
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable.
|
||||
|
||||
func limitRelease() {
|
||||
// non-blocking
|
||||
select {
|
||||
case <-limitSem:
|
||||
default:
|
||||
// This should not normally happen.
|
||||
log.Print("appengine: unbalanced limitSem release!")
|
||||
}
|
||||
}
|
||||
|
||||
func limitDial(network, addr string) (net.Conn, error) {
|
||||
limitSem <- 1
|
||||
|
||||
// Dial with a timeout in case the API host is MIA.
|
||||
// The connection should normally be very fast.
|
||||
conn, err := net.DialTimeout(network, addr, 500*time.Millisecond)
|
||||
if err != nil {
|
||||
limitRelease()
|
||||
return nil, err
|
||||
}
|
||||
lc := &limitConn{Conn: conn}
|
||||
runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
type limitConn struct {
|
||||
close sync.Once
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (lc *limitConn) Close() error {
|
||||
defer lc.close.Do(func() {
|
||||
limitRelease()
|
||||
runtime.SetFinalizer(lc, nil)
|
||||
})
|
||||
return lc.Conn.Close()
|
||||
}
|
||||
40
vendor/google.golang.org/appengine/internal/regen.sh
generated
vendored
Executable file
40
vendor/google.golang.org/appengine/internal/regen.sh
generated
vendored
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash -e
|
||||
#
|
||||
# This script rebuilds the generated code for the protocol buffers.
|
||||
# To run this you will need protoc and goprotobuf installed;
|
||||
# see https://github.com/golang/protobuf for instructions.
|
||||
|
||||
PKG=google.golang.org/appengine
|
||||
|
||||
function die() {
|
||||
echo 1>&2 $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Sanity check that the right tools are accessible.
|
||||
for tool in go protoc protoc-gen-go; do
|
||||
q=$(which $tool) || die "didn't find $tool"
|
||||
echo 1>&2 "$tool: $q"
|
||||
done
|
||||
|
||||
echo -n 1>&2 "finding package dir... "
|
||||
pkgdir=$(go list -f '{{.Dir}}' $PKG)
|
||||
echo 1>&2 $pkgdir
|
||||
base=$(echo $pkgdir | sed "s,/$PKG\$,,")
|
||||
echo 1>&2 "base: $base"
|
||||
cd $base
|
||||
|
||||
# Run protoc once per package.
|
||||
for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do
|
||||
echo 1>&2 "* $dir"
|
||||
protoc --go_out=. $dir/*.proto
|
||||
done
|
||||
|
||||
for f in $(find $PKG/internal -name '*.pb.go'); do
|
||||
# Remove proto.RegisterEnum calls.
|
||||
# These cause duplicate registration panics when these packages
|
||||
# are used on classic App Engine. proto.RegisterEnum only affects
|
||||
# parsing the text format; we don't care about that.
|
||||
# https://code.google.com/p/googleappengine/issues/detail?id=11670#c17
|
||||
sed -i '/proto.RegisterEnum/d' $f
|
||||
done
|
||||
361
vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go
generated
vendored
Normal file
361
vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google.golang.org/appengine/internal/remote_api/remote_api.proto
|
||||
|
||||
package remote_api
|
||||
|
||||
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
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type RpcError_ErrorCode int32
|
||||
|
||||
const (
|
||||
RpcError_UNKNOWN RpcError_ErrorCode = 0
|
||||
RpcError_CALL_NOT_FOUND RpcError_ErrorCode = 1
|
||||
RpcError_PARSE_ERROR RpcError_ErrorCode = 2
|
||||
RpcError_SECURITY_VIOLATION RpcError_ErrorCode = 3
|
||||
RpcError_OVER_QUOTA RpcError_ErrorCode = 4
|
||||
RpcError_REQUEST_TOO_LARGE RpcError_ErrorCode = 5
|
||||
RpcError_CAPABILITY_DISABLED RpcError_ErrorCode = 6
|
||||
RpcError_FEATURE_DISABLED RpcError_ErrorCode = 7
|
||||
RpcError_BAD_REQUEST RpcError_ErrorCode = 8
|
||||
RpcError_RESPONSE_TOO_LARGE RpcError_ErrorCode = 9
|
||||
RpcError_CANCELLED RpcError_ErrorCode = 10
|
||||
RpcError_REPLAY_ERROR RpcError_ErrorCode = 11
|
||||
RpcError_DEADLINE_EXCEEDED RpcError_ErrorCode = 12
|
||||
)
|
||||
|
||||
var RpcError_ErrorCode_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "CALL_NOT_FOUND",
|
||||
2: "PARSE_ERROR",
|
||||
3: "SECURITY_VIOLATION",
|
||||
4: "OVER_QUOTA",
|
||||
5: "REQUEST_TOO_LARGE",
|
||||
6: "CAPABILITY_DISABLED",
|
||||
7: "FEATURE_DISABLED",
|
||||
8: "BAD_REQUEST",
|
||||
9: "RESPONSE_TOO_LARGE",
|
||||
10: "CANCELLED",
|
||||
11: "REPLAY_ERROR",
|
||||
12: "DEADLINE_EXCEEDED",
|
||||
}
|
||||
var RpcError_ErrorCode_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"CALL_NOT_FOUND": 1,
|
||||
"PARSE_ERROR": 2,
|
||||
"SECURITY_VIOLATION": 3,
|
||||
"OVER_QUOTA": 4,
|
||||
"REQUEST_TOO_LARGE": 5,
|
||||
"CAPABILITY_DISABLED": 6,
|
||||
"FEATURE_DISABLED": 7,
|
||||
"BAD_REQUEST": 8,
|
||||
"RESPONSE_TOO_LARGE": 9,
|
||||
"CANCELLED": 10,
|
||||
"REPLAY_ERROR": 11,
|
||||
"DEADLINE_EXCEEDED": 12,
|
||||
}
|
||||
|
||||
func (x RpcError_ErrorCode) Enum() *RpcError_ErrorCode {
|
||||
p := new(RpcError_ErrorCode)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x RpcError_ErrorCode) String() string {
|
||||
return proto.EnumName(RpcError_ErrorCode_name, int32(x))
|
||||
}
|
||||
func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(RpcError_ErrorCode_value, data, "RpcError_ErrorCode")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = RpcError_ErrorCode(value)
|
||||
return nil
|
||||
}
|
||||
func (RpcError_ErrorCode) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_remote_api_1978114ec33a273d, []int{2, 0}
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
ServiceName *string `protobuf:"bytes,2,req,name=service_name,json=serviceName" json:"service_name,omitempty"`
|
||||
Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"`
|
||||
Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"`
|
||||
RequestId *string `protobuf:"bytes,5,opt,name=request_id,json=requestId" json:"request_id,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_remote_api_1978114ec33a273d, []int{0}
|
||||
}
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Request.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Request) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Request.Merge(dst, src)
|
||||
}
|
||||
func (m *Request) XXX_Size() int {
|
||||
return xxx_messageInfo_Request.Size(m)
|
||||
}
|
||||
func (m *Request) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Request.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Request proto.InternalMessageInfo
|
||||
|
||||
func (m *Request) GetServiceName() string {
|
||||
if m != nil && m.ServiceName != nil {
|
||||
return *m.ServiceName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetMethod() string {
|
||||
if m != nil && m.Method != nil {
|
||||
return *m.Method
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetRequest() []byte {
|
||||
if m != nil {
|
||||
return m.Request
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Request) GetRequestId() string {
|
||||
if m != nil && m.RequestId != nil {
|
||||
return *m.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ApplicationError struct {
|
||||
Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
|
||||
Detail *string `protobuf:"bytes,2,req,name=detail" json:"detail,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ApplicationError) Reset() { *m = ApplicationError{} }
|
||||
func (m *ApplicationError) String() string { return proto.CompactTextString(m) }
|
||||
func (*ApplicationError) ProtoMessage() {}
|
||||
func (*ApplicationError) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_remote_api_1978114ec33a273d, []int{1}
|
||||
}
|
||||
func (m *ApplicationError) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ApplicationError.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ApplicationError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ApplicationError.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *ApplicationError) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ApplicationError.Merge(dst, src)
|
||||
}
|
||||
func (m *ApplicationError) XXX_Size() int {
|
||||
return xxx_messageInfo_ApplicationError.Size(m)
|
||||
}
|
||||
func (m *ApplicationError) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ApplicationError.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ApplicationError proto.InternalMessageInfo
|
||||
|
||||
func (m *ApplicationError) GetCode() int32 {
|
||||
if m != nil && m.Code != nil {
|
||||
return *m.Code
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ApplicationError) GetDetail() string {
|
||||
if m != nil && m.Detail != nil {
|
||||
return *m.Detail
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RpcError struct {
|
||||
Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
|
||||
Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RpcError) Reset() { *m = RpcError{} }
|
||||
func (m *RpcError) String() string { return proto.CompactTextString(m) }
|
||||
func (*RpcError) ProtoMessage() {}
|
||||
func (*RpcError) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_remote_api_1978114ec33a273d, []int{2}
|
||||
}
|
||||
func (m *RpcError) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RpcError.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RpcError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RpcError.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *RpcError) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RpcError.Merge(dst, src)
|
||||
}
|
||||
func (m *RpcError) XXX_Size() int {
|
||||
return xxx_messageInfo_RpcError.Size(m)
|
||||
}
|
||||
func (m *RpcError) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RpcError.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RpcError proto.InternalMessageInfo
|
||||
|
||||
func (m *RpcError) GetCode() int32 {
|
||||
if m != nil && m.Code != nil {
|
||||
return *m.Code
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RpcError) GetDetail() string {
|
||||
if m != nil && m.Detail != nil {
|
||||
return *m.Detail
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
|
||||
Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"`
|
||||
ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error,json=applicationError" json:"application_error,omitempty"`
|
||||
JavaException []byte `protobuf:"bytes,4,opt,name=java_exception,json=javaException" json:"java_exception,omitempty"`
|
||||
RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error,json=rpcError" json:"rpc_error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Response) Reset() { *m = Response{} }
|
||||
func (m *Response) String() string { return proto.CompactTextString(m) }
|
||||
func (*Response) ProtoMessage() {}
|
||||
func (*Response) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_remote_api_1978114ec33a273d, []int{3}
|
||||
}
|
||||
func (m *Response) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Response.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Response) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Response.Merge(dst, src)
|
||||
}
|
||||
func (m *Response) XXX_Size() int {
|
||||
return xxx_messageInfo_Response.Size(m)
|
||||
}
|
||||
func (m *Response) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Response.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Response proto.InternalMessageInfo
|
||||
|
||||
func (m *Response) GetResponse() []byte {
|
||||
if m != nil {
|
||||
return m.Response
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Response) GetException() []byte {
|
||||
if m != nil {
|
||||
return m.Exception
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Response) GetApplicationError() *ApplicationError {
|
||||
if m != nil {
|
||||
return m.ApplicationError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Response) GetJavaException() []byte {
|
||||
if m != nil {
|
||||
return m.JavaException
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Response) GetRpcError() *RpcError {
|
||||
if m != nil {
|
||||
return m.RpcError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "remote_api.Request")
|
||||
proto.RegisterType((*ApplicationError)(nil), "remote_api.ApplicationError")
|
||||
proto.RegisterType((*RpcError)(nil), "remote_api.RpcError")
|
||||
proto.RegisterType((*Response)(nil), "remote_api.Response")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google.golang.org/appengine/internal/remote_api/remote_api.proto", fileDescriptor_remote_api_1978114ec33a273d)
|
||||
}
|
||||
|
||||
var fileDescriptor_remote_api_1978114ec33a273d = []byte{
|
||||
// 531 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x86, 0xb1, 0x9b, 0x34, 0xf1, 0xc4, 0x2d, 0xdb, 0xa5, 0x14, 0x0b, 0x15, 0x29, 0x44, 0x42,
|
||||
0xca, 0x53, 0x2a, 0x38, 0x00, 0x62, 0x63, 0x6f, 0x91, 0x85, 0x65, 0xa7, 0x6b, 0xbb, 0x50, 0x5e,
|
||||
0x56, 0x2b, 0x67, 0x65, 0x8c, 0x12, 0xaf, 0xd9, 0x98, 0x8a, 0x17, 0x6e, 0xc0, 0xb5, 0x38, 0x0c,
|
||||
0xb7, 0x40, 0x36, 0x6e, 0x63, 0xf5, 0x89, 0xb7, 0x7f, 0x7e, 0x7b, 0xe6, 0x1b, 0xcd, 0xcc, 0xc2,
|
||||
0xbb, 0x5c, 0xa9, 0x7c, 0x23, 0x17, 0xb9, 0xda, 0x88, 0x32, 0x5f, 0x28, 0x9d, 0x5f, 0x88, 0xaa,
|
||||
0x92, 0x65, 0x5e, 0x94, 0xf2, 0xa2, 0x28, 0x6b, 0xa9, 0x4b, 0xb1, 0xb9, 0xd0, 0x72, 0xab, 0x6a,
|
||||
0xc9, 0x45, 0x55, 0xf4, 0xe4, 0xa2, 0xd2, 0xaa, 0x56, 0x18, 0xf6, 0xce, 0xec, 0x27, 0x8c, 0x98,
|
||||
0xfc, 0xf6, 0x5d, 0xee, 0x6a, 0xfc, 0x12, 0xec, 0x9d, 0xd4, 0xb7, 0x45, 0x26, 0x79, 0x29, 0xb6,
|
||||
0xd2, 0x31, 0xa7, 0xe6, 0xdc, 0x62, 0x93, 0xce, 0x0b, 0xc5, 0x56, 0xe2, 0x33, 0x38, 0xdc, 0xca,
|
||||
0xfa, 0x8b, 0x5a, 0x3b, 0x07, 0xed, 0xc7, 0x2e, 0xc2, 0x0e, 0x8c, 0xf4, 0xbf, 0x2a, 0xce, 0x60,
|
||||
0x6a, 0xce, 0x6d, 0x76, 0x17, 0xe2, 0x17, 0x00, 0x9d, 0xe4, 0xc5, 0xda, 0x19, 0x4e, 0x8d, 0xb9,
|
||||
0xc5, 0xac, 0xce, 0xf1, 0xd7, 0xb3, 0xb7, 0x80, 0x48, 0x55, 0x6d, 0x8a, 0x4c, 0xd4, 0x85, 0x2a,
|
||||
0xa9, 0xd6, 0x4a, 0x63, 0x0c, 0x83, 0x4c, 0xad, 0xa5, 0x63, 0x4c, 0xcd, 0xf9, 0x90, 0xb5, 0xba,
|
||||
0x01, 0xaf, 0x65, 0x2d, 0x8a, 0x4d, 0xd7, 0x55, 0x17, 0xcd, 0x7e, 0x9b, 0x30, 0x66, 0x55, 0xf6,
|
||||
0x7f, 0x89, 0x46, 0x2f, 0xf1, 0x97, 0x09, 0x56, 0x9b, 0xe5, 0x36, 0x7f, 0x4d, 0x60, 0x94, 0x86,
|
||||
0x1f, 0xc2, 0xe8, 0x63, 0x88, 0x1e, 0x61, 0x0c, 0xc7, 0x2e, 0x09, 0x02, 0x1e, 0x46, 0x09, 0xbf,
|
||||
0x8c, 0xd2, 0xd0, 0x43, 0x06, 0x7e, 0x0c, 0x93, 0x15, 0x61, 0x31, 0xe5, 0x94, 0xb1, 0x88, 0x21,
|
||||
0x13, 0x9f, 0x01, 0x8e, 0xa9, 0x9b, 0x32, 0x3f, 0xb9, 0xe1, 0xd7, 0x7e, 0x14, 0x90, 0xc4, 0x8f,
|
||||
0x42, 0x74, 0x80, 0x8f, 0x01, 0xa2, 0x6b, 0xca, 0xf8, 0x55, 0x1a, 0x25, 0x04, 0x0d, 0xf0, 0x53,
|
||||
0x38, 0x61, 0xf4, 0x2a, 0xa5, 0x71, 0xc2, 0x93, 0x28, 0xe2, 0x01, 0x61, 0xef, 0x29, 0x1a, 0xe2,
|
||||
0x67, 0xf0, 0xc4, 0x25, 0x2b, 0xb2, 0xf4, 0x83, 0xa6, 0x80, 0xe7, 0xc7, 0x64, 0x19, 0x50, 0x0f,
|
||||
0x1d, 0xe2, 0x53, 0x40, 0x97, 0x94, 0x24, 0x29, 0xa3, 0x7b, 0x77, 0xd4, 0xe0, 0x97, 0xc4, 0xe3,
|
||||
0x5d, 0x25, 0x34, 0x6e, 0xf0, 0x8c, 0xc6, 0xab, 0x28, 0x8c, 0x69, 0xaf, 0xae, 0x85, 0x8f, 0xc0,
|
||||
0x72, 0x49, 0xe8, 0xd2, 0xa0, 0xc9, 0x03, 0x8c, 0xc0, 0x66, 0x74, 0x15, 0x90, 0x9b, 0xae, 0xef,
|
||||
0x49, 0xd3, 0x8f, 0x47, 0x89, 0x17, 0xf8, 0x21, 0xe5, 0xf4, 0x93, 0x4b, 0xa9, 0x47, 0x3d, 0x64,
|
||||
0xcf, 0xfe, 0x18, 0x30, 0x66, 0x72, 0x57, 0xa9, 0x72, 0x27, 0xf1, 0x73, 0x18, 0xeb, 0x4e, 0x3b,
|
||||
0xc6, 0xd4, 0x98, 0xdb, 0xec, 0x3e, 0xc6, 0xe7, 0x60, 0xc9, 0x1f, 0x99, 0xac, 0x9a, 0x75, 0xb5,
|
||||
0x23, 0xb5, 0xd9, 0xde, 0xc0, 0x3e, 0x9c, 0x88, 0xfd, 0x3a, 0xb9, 0x6c, 0x06, 0xec, 0x1c, 0x4c,
|
||||
0x8d, 0xf9, 0xe4, 0xcd, 0xf9, 0xa2, 0x77, 0x87, 0x0f, 0x77, 0xce, 0x90, 0x78, 0x78, 0x05, 0xaf,
|
||||
0xe0, 0xf8, 0xab, 0xb8, 0x15, 0x7c, 0x4f, 0x1b, 0xb4, 0xb4, 0xa3, 0xc6, 0xa5, 0xf7, 0xc4, 0xd7,
|
||||
0x60, 0xe9, 0x2a, 0xeb, 0x48, 0xc3, 0x96, 0x74, 0xda, 0x27, 0xdd, 0x1d, 0x07, 0x1b, 0xeb, 0x4e,
|
||||
0x2d, 0xed, 0xcf, 0xbd, 0x07, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xd1, 0x0f, 0x22, 0x4f,
|
||||
0x03, 0x00, 0x00,
|
||||
}
|
||||
44
vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto
generated
vendored
Normal file
44
vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
syntax = "proto2";
|
||||
option go_package = "remote_api";
|
||||
|
||||
package remote_api;
|
||||
|
||||
message Request {
|
||||
required string service_name = 2;
|
||||
required string method = 3;
|
||||
required bytes request = 4;
|
||||
optional string request_id = 5;
|
||||
}
|
||||
|
||||
message ApplicationError {
|
||||
required int32 code = 1;
|
||||
required string detail = 2;
|
||||
}
|
||||
|
||||
message RpcError {
|
||||
enum ErrorCode {
|
||||
UNKNOWN = 0;
|
||||
CALL_NOT_FOUND = 1;
|
||||
PARSE_ERROR = 2;
|
||||
SECURITY_VIOLATION = 3;
|
||||
OVER_QUOTA = 4;
|
||||
REQUEST_TOO_LARGE = 5;
|
||||
CAPABILITY_DISABLED = 6;
|
||||
FEATURE_DISABLED = 7;
|
||||
BAD_REQUEST = 8;
|
||||
RESPONSE_TOO_LARGE = 9;
|
||||
CANCELLED = 10;
|
||||
REPLAY_ERROR = 11;
|
||||
DEADLINE_EXCEEDED = 12;
|
||||
}
|
||||
required int32 code = 1;
|
||||
optional string detail = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
optional bytes response = 1;
|
||||
optional bytes exception = 2;
|
||||
optional ApplicationError application_error = 3;
|
||||
optional bytes java_exception = 4;
|
||||
optional RpcError rpc_error = 5;
|
||||
}
|
||||
115
vendor/google.golang.org/appengine/internal/transaction.go
generated
vendored
Normal file
115
vendor/google.golang.org/appengine/internal/transaction.go
generated
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
package internal
|
||||
|
||||
// This file implements hooks for applying datastore transactions.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
|
||||
basepb "google.golang.org/appengine/internal/base"
|
||||
pb "google.golang.org/appengine/internal/datastore"
|
||||
)
|
||||
|
||||
var transactionSetters = make(map[reflect.Type]reflect.Value)
|
||||
|
||||
// RegisterTransactionSetter registers a function that sets transaction information
|
||||
// in a protocol buffer message. f should be a function with two arguments,
|
||||
// the first being a protocol buffer type, and the second being *datastore.Transaction.
|
||||
func RegisterTransactionSetter(f interface{}) {
|
||||
v := reflect.ValueOf(f)
|
||||
transactionSetters[v.Type().In(0)] = v
|
||||
}
|
||||
|
||||
// applyTransaction applies the transaction t to message pb
|
||||
// by using the relevant setter passed to RegisterTransactionSetter.
|
||||
func applyTransaction(pb proto.Message, t *pb.Transaction) {
|
||||
v := reflect.ValueOf(pb)
|
||||
if f, ok := transactionSetters[v.Type()]; ok {
|
||||
f.Call([]reflect.Value{v, reflect.ValueOf(t)})
|
||||
}
|
||||
}
|
||||
|
||||
var transactionKey = "used for *Transaction"
|
||||
|
||||
func transactionFromContext(ctx netcontext.Context) *transaction {
|
||||
t, _ := ctx.Value(&transactionKey).(*transaction)
|
||||
return t
|
||||
}
|
||||
|
||||
func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &transactionKey, t)
|
||||
}
|
||||
|
||||
type transaction struct {
|
||||
transaction pb.Transaction
|
||||
finished bool
|
||||
}
|
||||
|
||||
var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
|
||||
|
||||
func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
|
||||
if transactionFromContext(c) != nil {
|
||||
return nil, errors.New("nested transactions are not supported")
|
||||
}
|
||||
|
||||
// Begin the transaction.
|
||||
t := &transaction{}
|
||||
req := &pb.BeginTransactionRequest{
|
||||
App: proto.String(FullyQualifiedAppID(c)),
|
||||
}
|
||||
if xg {
|
||||
req.AllowMultipleEg = proto.Bool(true)
|
||||
}
|
||||
if previousTransaction != nil {
|
||||
req.PreviousTransaction = previousTransaction
|
||||
}
|
||||
if readOnly {
|
||||
req.Mode = pb.BeginTransactionRequest_READ_ONLY.Enum()
|
||||
} else {
|
||||
req.Mode = pb.BeginTransactionRequest_READ_WRITE.Enum()
|
||||
}
|
||||
if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call f, rolling back the transaction if f returns a non-nil error, or panics.
|
||||
// The panic is not recovered.
|
||||
defer func() {
|
||||
if t.finished {
|
||||
return
|
||||
}
|
||||
t.finished = true
|
||||
// Ignore the error return value, since we are already returning a non-nil
|
||||
// error (or we're panicking).
|
||||
Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{})
|
||||
}()
|
||||
if err := f(withTransaction(c, t)); err != nil {
|
||||
return &t.transaction, err
|
||||
}
|
||||
t.finished = true
|
||||
|
||||
// Commit the transaction.
|
||||
res := &pb.CommitResponse{}
|
||||
err := Call(c, "datastore_v3", "Commit", &t.transaction, res)
|
||||
if ae, ok := err.(*APIError); ok {
|
||||
/* TODO: restore this conditional
|
||||
if appengine.IsDevAppServer() {
|
||||
*/
|
||||
// The Python Dev AppServer raises an ApplicationError with error code 2 (which is
|
||||
// Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.".
|
||||
if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." {
|
||||
return &t.transaction, ErrConcurrentTransaction
|
||||
}
|
||||
if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) {
|
||||
return &t.transaction, ErrConcurrentTransaction
|
||||
}
|
||||
}
|
||||
return &t.transaction, err
|
||||
}
|
||||
527
vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go
generated
vendored
Normal file
527
vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto
|
||||
|
||||
package urlfetch
|
||||
|
||||
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
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type URLFetchServiceError_ErrorCode int32
|
||||
|
||||
const (
|
||||
URLFetchServiceError_OK URLFetchServiceError_ErrorCode = 0
|
||||
URLFetchServiceError_INVALID_URL URLFetchServiceError_ErrorCode = 1
|
||||
URLFetchServiceError_FETCH_ERROR URLFetchServiceError_ErrorCode = 2
|
||||
URLFetchServiceError_UNSPECIFIED_ERROR URLFetchServiceError_ErrorCode = 3
|
||||
URLFetchServiceError_RESPONSE_TOO_LARGE URLFetchServiceError_ErrorCode = 4
|
||||
URLFetchServiceError_DEADLINE_EXCEEDED URLFetchServiceError_ErrorCode = 5
|
||||
URLFetchServiceError_SSL_CERTIFICATE_ERROR URLFetchServiceError_ErrorCode = 6
|
||||
URLFetchServiceError_DNS_ERROR URLFetchServiceError_ErrorCode = 7
|
||||
URLFetchServiceError_CLOSED URLFetchServiceError_ErrorCode = 8
|
||||
URLFetchServiceError_INTERNAL_TRANSIENT_ERROR URLFetchServiceError_ErrorCode = 9
|
||||
URLFetchServiceError_TOO_MANY_REDIRECTS URLFetchServiceError_ErrorCode = 10
|
||||
URLFetchServiceError_MALFORMED_REPLY URLFetchServiceError_ErrorCode = 11
|
||||
URLFetchServiceError_CONNECTION_ERROR URLFetchServiceError_ErrorCode = 12
|
||||
)
|
||||
|
||||
var URLFetchServiceError_ErrorCode_name = map[int32]string{
|
||||
0: "OK",
|
||||
1: "INVALID_URL",
|
||||
2: "FETCH_ERROR",
|
||||
3: "UNSPECIFIED_ERROR",
|
||||
4: "RESPONSE_TOO_LARGE",
|
||||
5: "DEADLINE_EXCEEDED",
|
||||
6: "SSL_CERTIFICATE_ERROR",
|
||||
7: "DNS_ERROR",
|
||||
8: "CLOSED",
|
||||
9: "INTERNAL_TRANSIENT_ERROR",
|
||||
10: "TOO_MANY_REDIRECTS",
|
||||
11: "MALFORMED_REPLY",
|
||||
12: "CONNECTION_ERROR",
|
||||
}
|
||||
var URLFetchServiceError_ErrorCode_value = map[string]int32{
|
||||
"OK": 0,
|
||||
"INVALID_URL": 1,
|
||||
"FETCH_ERROR": 2,
|
||||
"UNSPECIFIED_ERROR": 3,
|
||||
"RESPONSE_TOO_LARGE": 4,
|
||||
"DEADLINE_EXCEEDED": 5,
|
||||
"SSL_CERTIFICATE_ERROR": 6,
|
||||
"DNS_ERROR": 7,
|
||||
"CLOSED": 8,
|
||||
"INTERNAL_TRANSIENT_ERROR": 9,
|
||||
"TOO_MANY_REDIRECTS": 10,
|
||||
"MALFORMED_REPLY": 11,
|
||||
"CONNECTION_ERROR": 12,
|
||||
}
|
||||
|
||||
func (x URLFetchServiceError_ErrorCode) Enum() *URLFetchServiceError_ErrorCode {
|
||||
p := new(URLFetchServiceError_ErrorCode)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x URLFetchServiceError_ErrorCode) String() string {
|
||||
return proto.EnumName(URLFetchServiceError_ErrorCode_name, int32(x))
|
||||
}
|
||||
func (x *URLFetchServiceError_ErrorCode) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(URLFetchServiceError_ErrorCode_value, data, "URLFetchServiceError_ErrorCode")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = URLFetchServiceError_ErrorCode(value)
|
||||
return nil
|
||||
}
|
||||
func (URLFetchServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0, 0}
|
||||
}
|
||||
|
||||
type URLFetchRequest_RequestMethod int32
|
||||
|
||||
const (
|
||||
URLFetchRequest_GET URLFetchRequest_RequestMethod = 1
|
||||
URLFetchRequest_POST URLFetchRequest_RequestMethod = 2
|
||||
URLFetchRequest_HEAD URLFetchRequest_RequestMethod = 3
|
||||
URLFetchRequest_PUT URLFetchRequest_RequestMethod = 4
|
||||
URLFetchRequest_DELETE URLFetchRequest_RequestMethod = 5
|
||||
URLFetchRequest_PATCH URLFetchRequest_RequestMethod = 6
|
||||
)
|
||||
|
||||
var URLFetchRequest_RequestMethod_name = map[int32]string{
|
||||
1: "GET",
|
||||
2: "POST",
|
||||
3: "HEAD",
|
||||
4: "PUT",
|
||||
5: "DELETE",
|
||||
6: "PATCH",
|
||||
}
|
||||
var URLFetchRequest_RequestMethod_value = map[string]int32{
|
||||
"GET": 1,
|
||||
"POST": 2,
|
||||
"HEAD": 3,
|
||||
"PUT": 4,
|
||||
"DELETE": 5,
|
||||
"PATCH": 6,
|
||||
}
|
||||
|
||||
func (x URLFetchRequest_RequestMethod) Enum() *URLFetchRequest_RequestMethod {
|
||||
p := new(URLFetchRequest_RequestMethod)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x URLFetchRequest_RequestMethod) String() string {
|
||||
return proto.EnumName(URLFetchRequest_RequestMethod_name, int32(x))
|
||||
}
|
||||
func (x *URLFetchRequest_RequestMethod) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(URLFetchRequest_RequestMethod_value, data, "URLFetchRequest_RequestMethod")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = URLFetchRequest_RequestMethod(value)
|
||||
return nil
|
||||
}
|
||||
func (URLFetchRequest_RequestMethod) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0}
|
||||
}
|
||||
|
||||
type URLFetchServiceError struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} }
|
||||
func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) }
|
||||
func (*URLFetchServiceError) ProtoMessage() {}
|
||||
func (*URLFetchServiceError) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0}
|
||||
}
|
||||
func (m *URLFetchServiceError) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_URLFetchServiceError.Unmarshal(m, b)
|
||||
}
|
||||
func (m *URLFetchServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_URLFetchServiceError.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *URLFetchServiceError) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_URLFetchServiceError.Merge(dst, src)
|
||||
}
|
||||
func (m *URLFetchServiceError) XXX_Size() int {
|
||||
return xxx_messageInfo_URLFetchServiceError.Size(m)
|
||||
}
|
||||
func (m *URLFetchServiceError) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_URLFetchServiceError.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_URLFetchServiceError proto.InternalMessageInfo
|
||||
|
||||
type URLFetchRequest struct {
|
||||
Method *URLFetchRequest_RequestMethod `protobuf:"varint,1,req,name=Method,enum=appengine.URLFetchRequest_RequestMethod" json:"Method,omitempty"`
|
||||
Url *string `protobuf:"bytes,2,req,name=Url" json:"Url,omitempty"`
|
||||
Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"`
|
||||
Payload []byte `protobuf:"bytes,6,opt,name=Payload" json:"Payload,omitempty"`
|
||||
FollowRedirects *bool `protobuf:"varint,7,opt,name=FollowRedirects,def=1" json:"FollowRedirects,omitempty"`
|
||||
Deadline *float64 `protobuf:"fixed64,8,opt,name=Deadline" json:"Deadline,omitempty"`
|
||||
MustValidateServerCertificate *bool `protobuf:"varint,9,opt,name=MustValidateServerCertificate,def=1" json:"MustValidateServerCertificate,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} }
|
||||
func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*URLFetchRequest) ProtoMessage() {}
|
||||
func (*URLFetchRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1}
|
||||
}
|
||||
func (m *URLFetchRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_URLFetchRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *URLFetchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_URLFetchRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *URLFetchRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_URLFetchRequest.Merge(dst, src)
|
||||
}
|
||||
func (m *URLFetchRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_URLFetchRequest.Size(m)
|
||||
}
|
||||
func (m *URLFetchRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_URLFetchRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_URLFetchRequest proto.InternalMessageInfo
|
||||
|
||||
const Default_URLFetchRequest_FollowRedirects bool = true
|
||||
const Default_URLFetchRequest_MustValidateServerCertificate bool = true
|
||||
|
||||
func (m *URLFetchRequest) GetMethod() URLFetchRequest_RequestMethod {
|
||||
if m != nil && m.Method != nil {
|
||||
return *m.Method
|
||||
}
|
||||
return URLFetchRequest_GET
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetUrl() string {
|
||||
if m != nil && m.Url != nil {
|
||||
return *m.Url
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetHeader() []*URLFetchRequest_Header {
|
||||
if m != nil {
|
||||
return m.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetPayload() []byte {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetFollowRedirects() bool {
|
||||
if m != nil && m.FollowRedirects != nil {
|
||||
return *m.FollowRedirects
|
||||
}
|
||||
return Default_URLFetchRequest_FollowRedirects
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetDeadline() float64 {
|
||||
if m != nil && m.Deadline != nil {
|
||||
return *m.Deadline
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest) GetMustValidateServerCertificate() bool {
|
||||
if m != nil && m.MustValidateServerCertificate != nil {
|
||||
return *m.MustValidateServerCertificate
|
||||
}
|
||||
return Default_URLFetchRequest_MustValidateServerCertificate
|
||||
}
|
||||
|
||||
type URLFetchRequest_Header struct {
|
||||
Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"`
|
||||
Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} }
|
||||
func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) }
|
||||
func (*URLFetchRequest_Header) ProtoMessage() {}
|
||||
func (*URLFetchRequest_Header) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0}
|
||||
}
|
||||
func (m *URLFetchRequest_Header) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_URLFetchRequest_Header.Unmarshal(m, b)
|
||||
}
|
||||
func (m *URLFetchRequest_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_URLFetchRequest_Header.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *URLFetchRequest_Header) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_URLFetchRequest_Header.Merge(dst, src)
|
||||
}
|
||||
func (m *URLFetchRequest_Header) XXX_Size() int {
|
||||
return xxx_messageInfo_URLFetchRequest_Header.Size(m)
|
||||
}
|
||||
func (m *URLFetchRequest_Header) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_URLFetchRequest_Header.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_URLFetchRequest_Header proto.InternalMessageInfo
|
||||
|
||||
func (m *URLFetchRequest_Header) GetKey() string {
|
||||
if m != nil && m.Key != nil {
|
||||
return *m.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *URLFetchRequest_Header) GetValue() string {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type URLFetchResponse struct {
|
||||
Content []byte `protobuf:"bytes,1,opt,name=Content" json:"Content,omitempty"`
|
||||
StatusCode *int32 `protobuf:"varint,2,req,name=StatusCode" json:"StatusCode,omitempty"`
|
||||
Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"`
|
||||
ContentWasTruncated *bool `protobuf:"varint,6,opt,name=ContentWasTruncated,def=0" json:"ContentWasTruncated,omitempty"`
|
||||
ExternalBytesSent *int64 `protobuf:"varint,7,opt,name=ExternalBytesSent" json:"ExternalBytesSent,omitempty"`
|
||||
ExternalBytesReceived *int64 `protobuf:"varint,8,opt,name=ExternalBytesReceived" json:"ExternalBytesReceived,omitempty"`
|
||||
FinalUrl *string `protobuf:"bytes,9,opt,name=FinalUrl" json:"FinalUrl,omitempty"`
|
||||
ApiCpuMilliseconds *int64 `protobuf:"varint,10,opt,name=ApiCpuMilliseconds,def=0" json:"ApiCpuMilliseconds,omitempty"`
|
||||
ApiBytesSent *int64 `protobuf:"varint,11,opt,name=ApiBytesSent,def=0" json:"ApiBytesSent,omitempty"`
|
||||
ApiBytesReceived *int64 `protobuf:"varint,12,opt,name=ApiBytesReceived,def=0" json:"ApiBytesReceived,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} }
|
||||
func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*URLFetchResponse) ProtoMessage() {}
|
||||
func (*URLFetchResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2}
|
||||
}
|
||||
func (m *URLFetchResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_URLFetchResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *URLFetchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_URLFetchResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *URLFetchResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_URLFetchResponse.Merge(dst, src)
|
||||
}
|
||||
func (m *URLFetchResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_URLFetchResponse.Size(m)
|
||||
}
|
||||
func (m *URLFetchResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_URLFetchResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_URLFetchResponse proto.InternalMessageInfo
|
||||
|
||||
const Default_URLFetchResponse_ContentWasTruncated bool = false
|
||||
const Default_URLFetchResponse_ApiCpuMilliseconds int64 = 0
|
||||
const Default_URLFetchResponse_ApiBytesSent int64 = 0
|
||||
const Default_URLFetchResponse_ApiBytesReceived int64 = 0
|
||||
|
||||
func (m *URLFetchResponse) GetContent() []byte {
|
||||
if m != nil {
|
||||
return m.Content
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetStatusCode() int32 {
|
||||
if m != nil && m.StatusCode != nil {
|
||||
return *m.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetHeader() []*URLFetchResponse_Header {
|
||||
if m != nil {
|
||||
return m.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetContentWasTruncated() bool {
|
||||
if m != nil && m.ContentWasTruncated != nil {
|
||||
return *m.ContentWasTruncated
|
||||
}
|
||||
return Default_URLFetchResponse_ContentWasTruncated
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetExternalBytesSent() int64 {
|
||||
if m != nil && m.ExternalBytesSent != nil {
|
||||
return *m.ExternalBytesSent
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetExternalBytesReceived() int64 {
|
||||
if m != nil && m.ExternalBytesReceived != nil {
|
||||
return *m.ExternalBytesReceived
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetFinalUrl() string {
|
||||
if m != nil && m.FinalUrl != nil {
|
||||
return *m.FinalUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetApiCpuMilliseconds() int64 {
|
||||
if m != nil && m.ApiCpuMilliseconds != nil {
|
||||
return *m.ApiCpuMilliseconds
|
||||
}
|
||||
return Default_URLFetchResponse_ApiCpuMilliseconds
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetApiBytesSent() int64 {
|
||||
if m != nil && m.ApiBytesSent != nil {
|
||||
return *m.ApiBytesSent
|
||||
}
|
||||
return Default_URLFetchResponse_ApiBytesSent
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse) GetApiBytesReceived() int64 {
|
||||
if m != nil && m.ApiBytesReceived != nil {
|
||||
return *m.ApiBytesReceived
|
||||
}
|
||||
return Default_URLFetchResponse_ApiBytesReceived
|
||||
}
|
||||
|
||||
type URLFetchResponse_Header struct {
|
||||
Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"`
|
||||
Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} }
|
||||
func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) }
|
||||
func (*URLFetchResponse_Header) ProtoMessage() {}
|
||||
func (*URLFetchResponse_Header) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2, 0}
|
||||
}
|
||||
func (m *URLFetchResponse_Header) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_URLFetchResponse_Header.Unmarshal(m, b)
|
||||
}
|
||||
func (m *URLFetchResponse_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_URLFetchResponse_Header.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *URLFetchResponse_Header) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_URLFetchResponse_Header.Merge(dst, src)
|
||||
}
|
||||
func (m *URLFetchResponse_Header) XXX_Size() int {
|
||||
return xxx_messageInfo_URLFetchResponse_Header.Size(m)
|
||||
}
|
||||
func (m *URLFetchResponse_Header) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_URLFetchResponse_Header.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_URLFetchResponse_Header proto.InternalMessageInfo
|
||||
|
||||
func (m *URLFetchResponse_Header) GetKey() string {
|
||||
if m != nil && m.Key != nil {
|
||||
return *m.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *URLFetchResponse_Header) GetValue() string {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*URLFetchServiceError)(nil), "appengine.URLFetchServiceError")
|
||||
proto.RegisterType((*URLFetchRequest)(nil), "appengine.URLFetchRequest")
|
||||
proto.RegisterType((*URLFetchRequest_Header)(nil), "appengine.URLFetchRequest.Header")
|
||||
proto.RegisterType((*URLFetchResponse)(nil), "appengine.URLFetchResponse")
|
||||
proto.RegisterType((*URLFetchResponse_Header)(nil), "appengine.URLFetchResponse.Header")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto", fileDescriptor_urlfetch_service_b245a7065f33bced)
|
||||
}
|
||||
|
||||
var fileDescriptor_urlfetch_service_b245a7065f33bced = []byte{
|
||||
// 770 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xe3, 0x54,
|
||||
0x10, 0xc6, 0x76, 0x7e, 0xa7, 0x5d, 0x7a, 0x76, 0xb6, 0x45, 0x66, 0xb5, 0xa0, 0x10, 0x09, 0x29,
|
||||
0x17, 0x90, 0x2e, 0x2b, 0x24, 0x44, 0xaf, 0x70, 0xed, 0x93, 0xad, 0xa9, 0x63, 0x47, 0xc7, 0x4e,
|
||||
0x61, 0xb9, 0xb1, 0xac, 0x78, 0x9a, 0x5a, 0xb2, 0xec, 0x60, 0x9f, 0x2c, 0xf4, 0x35, 0x78, 0x0d,
|
||||
0xde, 0x87, 0xa7, 0xe1, 0x02, 0x9d, 0xc4, 0xc9, 0x6e, 0xbb, 0xd1, 0x4a, 0x5c, 0x65, 0xe6, 0x9b,
|
||||
0xef, 0xcc, 0x99, 0x7c, 0xdf, 0xf8, 0x80, 0xb3, 0x2c, 0xcb, 0x65, 0x4e, 0xe3, 0x65, 0x99, 0x27,
|
||||
0xc5, 0x72, 0x5c, 0x56, 0xcb, 0xf3, 0x64, 0xb5, 0xa2, 0x62, 0x99, 0x15, 0x74, 0x9e, 0x15, 0x92,
|
||||
0xaa, 0x22, 0xc9, 0xcf, 0xd7, 0x55, 0x7e, 0x4b, 0x72, 0x71, 0xb7, 0x0f, 0xe2, 0x9a, 0xaa, 0xb7,
|
||||
0xd9, 0x82, 0xc6, 0xab, 0xaa, 0x94, 0x25, 0xf6, 0xf7, 0x67, 0x86, 0x7f, 0xeb, 0x70, 0x3a, 0x17,
|
||||
0xde, 0x44, 0xb1, 0xc2, 0x2d, 0x89, 0x57, 0x55, 0x59, 0x0d, 0xff, 0xd2, 0xa1, 0xbf, 0x89, 0xec,
|
||||
0x32, 0x25, 0xec, 0x80, 0x1e, 0x5c, 0xb3, 0x4f, 0xf0, 0x04, 0x8e, 0x5c, 0xff, 0xc6, 0xf2, 0x5c,
|
||||
0x27, 0x9e, 0x0b, 0x8f, 0x69, 0x0a, 0x98, 0xf0, 0xc8, 0xbe, 0x8a, 0xb9, 0x10, 0x81, 0x60, 0x3a,
|
||||
0x9e, 0xc1, 0xd3, 0xb9, 0x1f, 0xce, 0xb8, 0xed, 0x4e, 0x5c, 0xee, 0x34, 0xb0, 0x81, 0x9f, 0x01,
|
||||
0x0a, 0x1e, 0xce, 0x02, 0x3f, 0xe4, 0x71, 0x14, 0x04, 0xb1, 0x67, 0x89, 0xd7, 0x9c, 0xb5, 0x14,
|
||||
0xdd, 0xe1, 0x96, 0xe3, 0xb9, 0x3e, 0x8f, 0xf9, 0xaf, 0x36, 0xe7, 0x0e, 0x77, 0x58, 0x1b, 0x3f,
|
||||
0x87, 0xb3, 0x30, 0xf4, 0x62, 0x9b, 0x8b, 0xc8, 0x9d, 0xb8, 0xb6, 0x15, 0xf1, 0xa6, 0x53, 0x07,
|
||||
0x9f, 0x40, 0xdf, 0xf1, 0xc3, 0x26, 0xed, 0x22, 0x40, 0xc7, 0xf6, 0x82, 0x90, 0x3b, 0xac, 0x87,
|
||||
0x2f, 0xc0, 0x74, 0xfd, 0x88, 0x0b, 0xdf, 0xf2, 0xe2, 0x48, 0x58, 0x7e, 0xe8, 0x72, 0x3f, 0x6a,
|
||||
0x98, 0x7d, 0x35, 0x82, 0xba, 0x79, 0x6a, 0xf9, 0x6f, 0x62, 0xc1, 0x1d, 0x57, 0x70, 0x3b, 0x0a,
|
||||
0x19, 0xe0, 0x33, 0x38, 0x99, 0x5a, 0xde, 0x24, 0x10, 0x53, 0xee, 0xc4, 0x82, 0xcf, 0xbc, 0x37,
|
||||
0xec, 0x08, 0x4f, 0x81, 0xd9, 0x81, 0xef, 0x73, 0x3b, 0x72, 0x03, 0xbf, 0x69, 0x71, 0x3c, 0xfc,
|
||||
0xc7, 0x80, 0x93, 0x9d, 0x5a, 0x82, 0x7e, 0x5f, 0x53, 0x2d, 0xf1, 0x27, 0xe8, 0x4c, 0x49, 0xde,
|
||||
0x95, 0xa9, 0xa9, 0x0d, 0xf4, 0xd1, 0xa7, 0xaf, 0x46, 0xe3, 0xbd, 0xba, 0xe3, 0x47, 0xdc, 0x71,
|
||||
0xf3, 0xbb, 0xe5, 0x8b, 0xe6, 0x1c, 0x32, 0x30, 0xe6, 0x55, 0x6e, 0xea, 0x03, 0x7d, 0xd4, 0x17,
|
||||
0x2a, 0xc4, 0x1f, 0xa1, 0x73, 0x47, 0x49, 0x4a, 0x95, 0x69, 0x0c, 0x8c, 0x11, 0xbc, 0xfa, 0xea,
|
||||
0x23, 0x3d, 0xaf, 0x36, 0x44, 0xd1, 0x1c, 0xc0, 0x17, 0xd0, 0x9d, 0x25, 0xf7, 0x79, 0x99, 0xa4,
|
||||
0x66, 0x67, 0xa0, 0x8d, 0x8e, 0x2f, 0xf5, 0x9e, 0x26, 0x76, 0x10, 0x8e, 0xe1, 0x64, 0x52, 0xe6,
|
||||
0x79, 0xf9, 0x87, 0xa0, 0x34, 0xab, 0x68, 0x21, 0x6b, 0xb3, 0x3b, 0xd0, 0x46, 0xbd, 0x8b, 0x96,
|
||||
0xac, 0xd6, 0x24, 0x1e, 0x17, 0xf1, 0x39, 0xf4, 0x1c, 0x4a, 0xd2, 0x3c, 0x2b, 0xc8, 0xec, 0x0d,
|
||||
0xb4, 0x91, 0x26, 0xf6, 0x39, 0xfe, 0x0c, 0x5f, 0x4c, 0xd7, 0xb5, 0xbc, 0x49, 0xf2, 0x2c, 0x4d,
|
||||
0x24, 0xa9, 0xed, 0xa1, 0xca, 0xa6, 0x4a, 0x66, 0xb7, 0xd9, 0x22, 0x91, 0x64, 0xf6, 0xdf, 0xeb,
|
||||
0xfc, 0x71, 0xea, 0xf3, 0x97, 0xd0, 0xd9, 0xfe, 0x0f, 0x25, 0xc6, 0x35, 0xdd, 0x9b, 0xad, 0xad,
|
||||
0x18, 0xd7, 0x74, 0x8f, 0xa7, 0xd0, 0xbe, 0x49, 0xf2, 0x35, 0x99, 0xed, 0x0d, 0xb6, 0x4d, 0x86,
|
||||
0x1e, 0x3c, 0x79, 0xa0, 0x26, 0x76, 0xc1, 0x78, 0xcd, 0x23, 0xa6, 0x61, 0x0f, 0x5a, 0xb3, 0x20,
|
||||
0x8c, 0x98, 0xae, 0xa2, 0x2b, 0x6e, 0x39, 0xcc, 0x50, 0xc5, 0xd9, 0x3c, 0x62, 0x2d, 0xb5, 0x2e,
|
||||
0x0e, 0xf7, 0x78, 0xc4, 0x59, 0x1b, 0xfb, 0xd0, 0x9e, 0x59, 0x91, 0x7d, 0xc5, 0x3a, 0xc3, 0x7f,
|
||||
0x0d, 0x60, 0xef, 0x84, 0xad, 0x57, 0x65, 0x51, 0x13, 0x9a, 0xd0, 0xb5, 0xcb, 0x42, 0x52, 0x21,
|
||||
0x4d, 0x4d, 0x49, 0x29, 0x76, 0x29, 0x7e, 0x09, 0x10, 0xca, 0x44, 0xae, 0x6b, 0xf5, 0x71, 0x6c,
|
||||
0x8c, 0x6b, 0x8b, 0xf7, 0x10, 0xbc, 0x78, 0xe4, 0xdf, 0xf0, 0xa0, 0x7f, 0xdb, 0x6b, 0x1e, 0x1b,
|
||||
0xf8, 0x03, 0x3c, 0x6b, 0xae, 0xf9, 0x25, 0xa9, 0xa3, 0x6a, 0x5d, 0x28, 0x81, 0xb6, 0x66, 0xf6,
|
||||
0x2e, 0xda, 0xb7, 0x49, 0x5e, 0x93, 0x38, 0xc4, 0xc0, 0x6f, 0xe0, 0x29, 0xff, 0x73, 0xfb, 0x02,
|
||||
0x5c, 0xde, 0x4b, 0xaa, 0x43, 0x35, 0xb8, 0x72, 0xd7, 0x10, 0x1f, 0x16, 0xf0, 0x7b, 0x38, 0x7b,
|
||||
0x00, 0x0a, 0x5a, 0x50, 0xf6, 0x96, 0xd2, 0x8d, 0xcd, 0x86, 0x38, 0x5c, 0x54, 0xfb, 0x30, 0xc9,
|
||||
0x8a, 0x24, 0x57, 0xfb, 0xaa, 0xec, 0xed, 0x8b, 0x7d, 0x8e, 0xdf, 0x01, 0x5a, 0xab, 0xcc, 0x5e,
|
||||
0xad, 0xa7, 0x59, 0x9e, 0x67, 0x35, 0x2d, 0xca, 0x22, 0xad, 0x4d, 0x50, 0xed, 0x2e, 0xb4, 0x97,
|
||||
0xe2, 0x40, 0x11, 0xbf, 0x86, 0x63, 0x6b, 0x95, 0xbd, 0x9b, 0xf6, 0x68, 0x47, 0x7e, 0x00, 0xe3,
|
||||
0xb7, 0xc0, 0x76, 0xf9, 0x7e, 0xcc, 0xe3, 0x1d, 0xf5, 0x83, 0xd2, 0xff, 0x5f, 0xa6, 0x4b, 0xf8,
|
||||
0xad, 0xb7, 0x7b, 0x2a, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x9f, 0x6d, 0x24, 0x63, 0x05,
|
||||
0x00, 0x00,
|
||||
}
|
||||
64
vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto
generated
vendored
Normal file
64
vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
syntax = "proto2";
|
||||
option go_package = "urlfetch";
|
||||
|
||||
package appengine;
|
||||
|
||||
message URLFetchServiceError {
|
||||
enum ErrorCode {
|
||||
OK = 0;
|
||||
INVALID_URL = 1;
|
||||
FETCH_ERROR = 2;
|
||||
UNSPECIFIED_ERROR = 3;
|
||||
RESPONSE_TOO_LARGE = 4;
|
||||
DEADLINE_EXCEEDED = 5;
|
||||
SSL_CERTIFICATE_ERROR = 6;
|
||||
DNS_ERROR = 7;
|
||||
CLOSED = 8;
|
||||
INTERNAL_TRANSIENT_ERROR = 9;
|
||||
TOO_MANY_REDIRECTS = 10;
|
||||
MALFORMED_REPLY = 11;
|
||||
CONNECTION_ERROR = 12;
|
||||
}
|
||||
}
|
||||
|
||||
message URLFetchRequest {
|
||||
enum RequestMethod {
|
||||
GET = 1;
|
||||
POST = 2;
|
||||
HEAD = 3;
|
||||
PUT = 4;
|
||||
DELETE = 5;
|
||||
PATCH = 6;
|
||||
}
|
||||
required RequestMethod Method = 1;
|
||||
required string Url = 2;
|
||||
repeated group Header = 3 {
|
||||
required string Key = 4;
|
||||
required string Value = 5;
|
||||
}
|
||||
optional bytes Payload = 6 [ctype=CORD];
|
||||
|
||||
optional bool FollowRedirects = 7 [default=true];
|
||||
|
||||
optional double Deadline = 8;
|
||||
|
||||
optional bool MustValidateServerCertificate = 9 [default=true];
|
||||
}
|
||||
|
||||
message URLFetchResponse {
|
||||
optional bytes Content = 1;
|
||||
required int32 StatusCode = 2;
|
||||
repeated group Header = 3 {
|
||||
required string Key = 4;
|
||||
required string Value = 5;
|
||||
}
|
||||
optional bool ContentWasTruncated = 6 [default=false];
|
||||
optional int64 ExternalBytesSent = 7;
|
||||
optional int64 ExternalBytesReceived = 8;
|
||||
|
||||
optional string FinalUrl = 9;
|
||||
|
||||
optional int64 ApiCpuMilliseconds = 10 [default=0];
|
||||
optional int64 ApiBytesSent = 11 [default=0];
|
||||
optional int64 ApiBytesReceived = 12 [default=0];
|
||||
}
|
||||
210
vendor/google.golang.org/appengine/urlfetch/urlfetch.go
generated
vendored
Normal file
210
vendor/google.golang.org/appengine/urlfetch/urlfetch.go
generated
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
// Package urlfetch provides an http.RoundTripper implementation
|
||||
// for fetching URLs via App Engine's urlfetch service.
|
||||
package urlfetch // import "google.golang.org/appengine/urlfetch"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"google.golang.org/appengine/internal"
|
||||
pb "google.golang.org/appengine/internal/urlfetch"
|
||||
)
|
||||
|
||||
// Transport is an implementation of http.RoundTripper for
|
||||
// App Engine. Users should generally create an http.Client using
|
||||
// this transport and use the Client rather than using this transport
|
||||
// directly.
|
||||
type Transport struct {
|
||||
Context context.Context
|
||||
|
||||
// Controls whether the application checks the validity of SSL certificates
|
||||
// over HTTPS connections. A value of false (the default) instructs the
|
||||
// application to send a request to the server only if the certificate is
|
||||
// valid and signed by a trusted certificate authority (CA), and also
|
||||
// includes a hostname that matches the certificate. A value of true
|
||||
// instructs the application to perform no certificate validation.
|
||||
AllowInvalidServerCertificate bool
|
||||
}
|
||||
|
||||
// Verify statically that *Transport implements http.RoundTripper.
|
||||
var _ http.RoundTripper = (*Transport)(nil)
|
||||
|
||||
// Client returns an *http.Client using a default urlfetch Transport. This
|
||||
// client will have the default deadline of 5 seconds, and will check the
|
||||
// validity of SSL certificates.
|
||||
//
|
||||
// Any deadline of the provided context will be used for requests through this client;
|
||||
// if the client does not have a deadline then a 5 second default is used.
|
||||
func Client(ctx context.Context) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &Transport{
|
||||
Context: ctx,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type bodyReader struct {
|
||||
content []byte
|
||||
truncated bool
|
||||
closed bool
|
||||
}
|
||||
|
||||
// ErrTruncatedBody is the error returned after the final Read() from a
|
||||
// response's Body if the body has been truncated by App Engine's proxy.
|
||||
var ErrTruncatedBody = errors.New("urlfetch: truncated body")
|
||||
|
||||
func statusCodeToText(code int) string {
|
||||
if t := http.StatusText(code); t != "" {
|
||||
return t
|
||||
}
|
||||
return strconv.Itoa(code)
|
||||
}
|
||||
|
||||
func (br *bodyReader) Read(p []byte) (n int, err error) {
|
||||
if br.closed {
|
||||
if br.truncated {
|
||||
return 0, ErrTruncatedBody
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(p, br.content)
|
||||
if n > 0 {
|
||||
br.content = br.content[n:]
|
||||
return
|
||||
}
|
||||
if br.truncated {
|
||||
br.closed = true
|
||||
return 0, ErrTruncatedBody
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (br *bodyReader) Close() error {
|
||||
br.closed = true
|
||||
br.content = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// A map of the URL Fetch-accepted methods that take a request body.
|
||||
var methodAcceptsRequestBody = map[string]bool{
|
||||
"POST": true,
|
||||
"PUT": true,
|
||||
"PATCH": true,
|
||||
}
|
||||
|
||||
// urlString returns a valid string given a URL. This function is necessary because
|
||||
// the String method of URL doesn't correctly handle URLs with non-empty Opaque values.
|
||||
// See http://code.google.com/p/go/issues/detail?id=4860.
|
||||
func urlString(u *url.URL) string {
|
||||
if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") {
|
||||
return u.String()
|
||||
}
|
||||
aux := *u
|
||||
aux.Opaque = "//" + aux.Host + aux.Opaque
|
||||
return aux.String()
|
||||
}
|
||||
|
||||
// RoundTrip issues a single HTTP request and returns its response. Per the
|
||||
// http.RoundTripper interface, RoundTrip only returns an error if there
|
||||
// was an unsupported request or the URL Fetch proxy fails.
|
||||
// Note that HTTP response codes such as 5xx, 403, 404, etc are not
|
||||
// errors as far as the transport is concerned and will be returned
|
||||
// with err set to nil.
|
||||
func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
|
||||
methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method)
|
||||
}
|
||||
|
||||
method := pb.URLFetchRequest_RequestMethod(methNum)
|
||||
|
||||
freq := &pb.URLFetchRequest{
|
||||
Method: &method,
|
||||
Url: proto.String(urlString(req.URL)),
|
||||
FollowRedirects: proto.Bool(false), // http.Client's responsibility
|
||||
MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
|
||||
}
|
||||
if deadline, ok := t.Context.Deadline(); ok {
|
||||
freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds())
|
||||
}
|
||||
|
||||
for k, vals := range req.Header {
|
||||
for _, val := range vals {
|
||||
freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
|
||||
Key: proto.String(k),
|
||||
Value: proto.String(val),
|
||||
})
|
||||
}
|
||||
}
|
||||
if methodAcceptsRequestBody[req.Method] && req.Body != nil {
|
||||
// Avoid a []byte copy if req.Body has a Bytes method.
|
||||
switch b := req.Body.(type) {
|
||||
case interface {
|
||||
Bytes() []byte
|
||||
}:
|
||||
freq.Payload = b.Bytes()
|
||||
default:
|
||||
freq.Payload, err = ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fres := &pb.URLFetchResponse{}
|
||||
if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &http.Response{}
|
||||
res.StatusCode = int(*fres.StatusCode)
|
||||
res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
|
||||
res.Header = make(http.Header)
|
||||
res.Request = req
|
||||
|
||||
// Faked:
|
||||
res.ProtoMajor = 1
|
||||
res.ProtoMinor = 1
|
||||
res.Proto = "HTTP/1.1"
|
||||
res.Close = true
|
||||
|
||||
for _, h := range fres.Header {
|
||||
hkey := http.CanonicalHeaderKey(*h.Key)
|
||||
hval := *h.Value
|
||||
if hkey == "Content-Length" {
|
||||
// Will get filled in below for all but HEAD requests.
|
||||
if req.Method == "HEAD" {
|
||||
res.ContentLength, _ = strconv.ParseInt(hval, 10, 64)
|
||||
}
|
||||
continue
|
||||
}
|
||||
res.Header.Add(hkey, hval)
|
||||
}
|
||||
|
||||
if req.Method != "HEAD" {
|
||||
res.ContentLength = int64(len(fres.Content))
|
||||
}
|
||||
|
||||
truncated := fres.GetContentWasTruncated()
|
||||
res.Body = &bodyReader{content: fres.Content, truncated: truncated}
|
||||
return
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name)
|
||||
internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED))
|
||||
}
|
||||
202
vendor/google.golang.org/genproto/LICENSE
generated
vendored
Normal file
202
vendor/google.golang.org/genproto/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
163
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
Normal file
163
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/rpc/status.proto
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
any "github.com/golang/protobuf/ptypes/any"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// The `Status` type defines a logical error model that is suitable for
|
||||
// different programming environments, including REST APIs and RPC APIs. It is
|
||||
// used by [gRPC](https://github.com/grpc). The error model is designed to be:
|
||||
//
|
||||
// - Simple to use and understand for most users
|
||||
// - Flexible enough to meet unexpected needs
|
||||
//
|
||||
// # Overview
|
||||
//
|
||||
// The `Status` message contains three pieces of data: error code, error
|
||||
// message, and error details. The error code should be an enum value of
|
||||
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
|
||||
// if needed. The error message should be a developer-facing English message
|
||||
// that helps developers *understand* and *resolve* the error. If a localized
|
||||
// user-facing error message is needed, put the localized message in the error
|
||||
// details or localize it in the client. The optional error details may contain
|
||||
// arbitrary information about the error. There is a predefined set of error
|
||||
// detail types in the package `google.rpc` that can be used for common error
|
||||
// conditions.
|
||||
//
|
||||
// # Language mapping
|
||||
//
|
||||
// The `Status` message is the logical representation of the error model, but it
|
||||
// is not necessarily the actual wire format. When the `Status` message is
|
||||
// exposed in different client libraries and different wire protocols, it can be
|
||||
// mapped differently. For example, it will likely be mapped to some exceptions
|
||||
// in Java, but more likely mapped to some error codes in C.
|
||||
//
|
||||
// # Other uses
|
||||
//
|
||||
// The error model and the `Status` message can be used in a variety of
|
||||
// environments, either with or without APIs, to provide a
|
||||
// consistent developer experience across different environments.
|
||||
//
|
||||
// Example uses of this error model include:
|
||||
//
|
||||
// - Partial errors. If a service needs to return partial errors to the client,
|
||||
// it may embed the `Status` in the normal response to indicate the partial
|
||||
// errors.
|
||||
//
|
||||
// - Workflow errors. A typical workflow has multiple steps. Each step may
|
||||
// have a `Status` message for error reporting.
|
||||
//
|
||||
// - Batch operations. If a client uses batch request and batch response, the
|
||||
// `Status` message should be used directly inside batch response, one for
|
||||
// each error sub-response.
|
||||
//
|
||||
// - Asynchronous operations. If an API call embeds asynchronous operation
|
||||
// results in its response, the status of those operations should be
|
||||
// represented directly using the `Status` message.
|
||||
//
|
||||
// - Logging. If some API errors are stored in logs, the message `Status` could
|
||||
// be used directly after any stripping needed for security/privacy reasons.
|
||||
type Status struct {
|
||||
// The status code, which should be an enum value of
|
||||
// [google.rpc.Code][google.rpc.Code].
|
||||
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||
// A developer-facing error message, which should be in English. Any
|
||||
// user-facing error message should be localized and sent in the
|
||||
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized
|
||||
// by the client.
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
// A list of messages that carry the error details. There is a common set of
|
||||
// message types for APIs to use.
|
||||
Details []*any.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Status) Reset() { *m = Status{} }
|
||||
func (m *Status) String() string { return proto.CompactTextString(m) }
|
||||
func (*Status) ProtoMessage() {}
|
||||
func (*Status) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_24d244abaf643bfe, []int{0}
|
||||
}
|
||||
|
||||
func (m *Status) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Status.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Status.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Status) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Status.Merge(m, src)
|
||||
}
|
||||
func (m *Status) XXX_Size() int {
|
||||
return xxx_messageInfo_Status.Size(m)
|
||||
}
|
||||
func (m *Status) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Status.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Status proto.InternalMessageInfo
|
||||
|
||||
func (m *Status) GetCode() int32 {
|
||||
if m != nil {
|
||||
return m.Code
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Status) GetMessage() string {
|
||||
if m != nil {
|
||||
return m.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Status) GetDetails() []*any.Any {
|
||||
if m != nil {
|
||||
return m.Details
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Status)(nil), "google.rpc.Status")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) }
|
||||
|
||||
var fileDescriptor_24d244abaf643bfe = []byte{
|
||||
// 209 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
|
||||
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
|
||||
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
|
||||
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
|
||||
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
|
||||
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
|
||||
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0x38, 0x2e, 0xbe, 0xe4, 0xfc, 0x5c, 0x3d, 0x84, 0xa3, 0x9c,
|
||||
0xb8, 0x21, 0xf6, 0x06, 0x80, 0x94, 0x07, 0x30, 0x46, 0x99, 0x43, 0xa5, 0xd2, 0xf3, 0x73, 0x12,
|
||||
0xf3, 0xd2, 0xf5, 0xf2, 0x8b, 0xd2, 0xf5, 0xd3, 0x53, 0xf3, 0xc0, 0x86, 0xe9, 0x43, 0xa4, 0x12,
|
||||
0x0b, 0x32, 0x8b, 0x91, 0xfc, 0x69, 0x0d, 0xa1, 0x16, 0x31, 0x31, 0x07, 0x05, 0x38, 0x27, 0xb1,
|
||||
0x81, 0x55, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x53, 0xf0, 0x7c, 0x10, 0x01, 0x00,
|
||||
0x00,
|
||||
}
|
||||
39
vendor/google.golang.org/grpc/.travis.yml
generated
vendored
Normal file
39
vendor/google.golang.org/grpc/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
language: go
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.12.x
|
||||
env: VET=1 GO111MODULE=on
|
||||
- go: 1.12.x
|
||||
env: RACE=1 GO111MODULE=on
|
||||
- go: 1.12.x
|
||||
env: RUN386=1
|
||||
- go: 1.12.x
|
||||
env: GRPC_GO_RETRY=on
|
||||
- go: 1.11.x
|
||||
env: GO111MODULE=on
|
||||
- go: 1.10.x
|
||||
- go: 1.9.x
|
||||
- go: 1.9.x
|
||||
env: GAE=1
|
||||
|
||||
go_import_path: google.golang.org/grpc
|
||||
|
||||
before_install:
|
||||
- if [[ "${GO111MODULE}" = "on" ]]; then mkdir "${HOME}/go"; export GOPATH="${HOME}/go"; fi
|
||||
- if [[ -n "${RUN386}" ]]; then export GOARCH=386; fi
|
||||
- if [[ "${TRAVIS_EVENT_TYPE}" = "cron" && -z "${RUN386}" ]]; then RACE=1; fi
|
||||
- if [[ "${TRAVIS_EVENT_TYPE}" != "cron" ]]; then VET_SKIP_PROTO=1; fi
|
||||
|
||||
install:
|
||||
- try3() { eval "$*" || eval "$*" || eval "$*"; }
|
||||
- try3 'if [[ "${GO111MODULE}" = "on" ]]; then go mod download; else make testdeps; fi'
|
||||
- if [[ "${GAE}" = 1 ]]; then source ./install_gae.sh; make testappenginedeps; fi
|
||||
- if [[ "${VET}" = 1 ]]; then ./vet.sh -install; fi
|
||||
|
||||
script:
|
||||
- set -e
|
||||
- if [[ "${VET}" = 1 ]]; then ./vet.sh; fi
|
||||
- if [[ "${GAE}" = 1 ]]; then make testappengine; exit 0; fi
|
||||
- if [[ "${RACE}" = 1 ]]; then make testrace; exit 0; fi
|
||||
- make test
|
||||
1
vendor/google.golang.org/grpc/AUTHORS
generated
vendored
Normal file
1
vendor/google.golang.org/grpc/AUTHORS
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Google Inc.
|
||||
60
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
Normal file
60
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# How to contribute
|
||||
|
||||
We definitely welcome your patches and contributions to gRPC!
|
||||
|
||||
If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/)
|
||||
|
||||
## Legal requirements
|
||||
|
||||
In order to protect both you and ourselves, you will need to sign the
|
||||
[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf).
|
||||
|
||||
## Guidelines for Pull Requests
|
||||
How to get your contributions merged smoothly and quickly.
|
||||
|
||||
- Create **small PRs** that are narrowly focused on **addressing a single
|
||||
concern**. We often times receive PRs that are trying to fix several things at
|
||||
a time, but only one fix is considered acceptable, nothing gets merged and
|
||||
both author's & review's time is wasted. Create more PRs to address different
|
||||
concerns and everyone will be happy.
|
||||
|
||||
- The grpc package should only depend on standard Go packages and a small number
|
||||
of exceptions. If your contribution introduces new dependencies which are NOT
|
||||
in the [list](https://godoc.org/google.golang.org/grpc?imports), you need a
|
||||
discussion with gRPC-Go authors and consultants.
|
||||
|
||||
- For speculative changes, consider opening an issue and discussing it first. If
|
||||
you are suggesting a behavioral or API change, consider starting with a [gRFC
|
||||
proposal](https://github.com/grpc/proposal).
|
||||
|
||||
- Provide a good **PR description** as a record of **what** change is being made
|
||||
and **why** it was made. Link to a github issue if it exists.
|
||||
|
||||
- Don't fix code style and formatting unless you are already changing that line
|
||||
to address an issue. PRs with irrelevant changes won't be merged. If you do
|
||||
want to fix formatting or style, do that in a separate PR.
|
||||
|
||||
- Unless your PR is trivial, you should expect there will be reviewer comments
|
||||
that you'll need to address before merging. We expect you to be reasonably
|
||||
responsive to those comments, otherwise the PR will be closed after 2-3 weeks
|
||||
of inactivity.
|
||||
|
||||
- Maintain **clean commit history** and use **meaningful commit messages**. PRs
|
||||
with messy commit history are difficult to review and won't be merged. Use
|
||||
`rebase -i upstream/master` to curate your commit history and/or to bring in
|
||||
latest changes from master (but avoid rebasing in the middle of a code
|
||||
review).
|
||||
|
||||
- Keep your PR up to date with upstream/master (if there are merge conflicts, we
|
||||
can't really merge your change).
|
||||
|
||||
- **All tests need to be passing** before your change can be merged. We
|
||||
recommend you **run tests locally** before creating your PR to catch breakages
|
||||
early on.
|
||||
- `make all` to test everything, OR
|
||||
- `make vet` to catch vet errors
|
||||
- `make test` to run the tests
|
||||
- `make testrace` to run tests in race mode
|
||||
- optional `make testappengine` to run tests with appengine
|
||||
|
||||
- Exceptions to the rules can be made if there's a compelling reason for doing so.
|
||||
202
vendor/google.golang.org/grpc/LICENSE
generated
vendored
Normal file
202
vendor/google.golang.org/grpc/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
60
vendor/google.golang.org/grpc/Makefile
generated
vendored
Normal file
60
vendor/google.golang.org/grpc/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
all: vet test testrace
|
||||
|
||||
build: deps
|
||||
go build google.golang.org/grpc/...
|
||||
|
||||
clean:
|
||||
go clean -i google.golang.org/grpc/...
|
||||
|
||||
deps:
|
||||
go get -d -v google.golang.org/grpc/...
|
||||
|
||||
proto:
|
||||
@ if ! which protoc > /dev/null; then \
|
||||
echo "error: protoc not installed" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
go generate google.golang.org/grpc/...
|
||||
|
||||
test: testdeps
|
||||
go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||
|
||||
testappengine: testappenginedeps
|
||||
goapp test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||
|
||||
testappenginedeps:
|
||||
goapp get -d -v -t -tags 'appengine appenginevm' google.golang.org/grpc/...
|
||||
|
||||
testdeps:
|
||||
go get -d -v -t google.golang.org/grpc/...
|
||||
|
||||
testrace: testdeps
|
||||
go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||
|
||||
updatedeps:
|
||||
go get -d -v -u -f google.golang.org/grpc/...
|
||||
|
||||
updatetestdeps:
|
||||
go get -d -v -t -u -f google.golang.org/grpc/...
|
||||
|
||||
vet: vetdeps
|
||||
./vet.sh
|
||||
|
||||
vetdeps:
|
||||
./vet.sh -install
|
||||
|
||||
.PHONY: \
|
||||
all \
|
||||
build \
|
||||
clean \
|
||||
deps \
|
||||
proto \
|
||||
test \
|
||||
testappengine \
|
||||
testappenginedeps \
|
||||
testdeps \
|
||||
testrace \
|
||||
updatedeps \
|
||||
updatetestdeps \
|
||||
vet \
|
||||
vetdeps
|
||||
121
vendor/google.golang.org/grpc/README.md
generated
vendored
Normal file
121
vendor/google.golang.org/grpc/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# gRPC-Go
|
||||
|
||||
[](https://travis-ci.org/grpc/grpc-go)
|
||||
[](https://godoc.org/google.golang.org/grpc)
|
||||
[](https://goreportcard.com/report/github.com/grpc/grpc-go)
|
||||
|
||||
The Go implementation of [gRPC](https://grpc.io/): A high performance, open
|
||||
source, general RPC framework that puts mobile and HTTP/2 first. For more
|
||||
information see the [gRPC Quick Start:
|
||||
Go](https://grpc.io/docs/quickstart/go.html) guide.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install this package, you need to install Go and setup your Go workspace on
|
||||
your computer. The simplest way to install the library is to run:
|
||||
|
||||
```
|
||||
$ go get -u google.golang.org/grpc
|
||||
```
|
||||
|
||||
With Go module support (Go 1.11+), simply `import "google.golang.org/grpc"` in
|
||||
your source code and `go [build|run|test]` will automatically download the
|
||||
necessary dependencies ([Go modules
|
||||
ref](https://github.com/golang/go/wiki/Modules)).
|
||||
|
||||
If you are trying to access grpc-go from within China, please see the
|
||||
[FAQ](#FAQ) below.
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
gRPC-Go requires Go 1.9 or later.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
- See [godoc](https://godoc.org/google.golang.org/grpc) for package and API
|
||||
descriptions.
|
||||
- Documentation on specific topics can be found in the [Documentation
|
||||
directory](Documentation/).
|
||||
- Examples can be found in the [examples directory](examples/).
|
||||
|
||||
Performance
|
||||
-----------
|
||||
Performance benchmark data for grpc-go and other languages is maintained in
|
||||
[this
|
||||
dashboard](https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5652536396611584&widget=490377658&container=1286539696).
|
||||
|
||||
Status
|
||||
------
|
||||
General Availability [Google Cloud Platform Launch
|
||||
Stages](https://cloud.google.com/terms/launch-stages).
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
#### I/O Timeout Errors
|
||||
|
||||
The `golang.org` domain may be blocked from some countries. `go get` usually
|
||||
produces an error like the following when this happens:
|
||||
|
||||
```
|
||||
$ go get -u google.golang.org/grpc
|
||||
package google.golang.org/grpc: unrecognized import path "google.golang.org/grpc" (https fetch: Get https://google.golang.org/grpc?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
|
||||
```
|
||||
|
||||
To build Go code, there are several options:
|
||||
|
||||
- Set up a VPN and access google.golang.org through that.
|
||||
|
||||
- Without Go module support: `git clone` the repo manually:
|
||||
|
||||
```
|
||||
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
|
||||
```
|
||||
|
||||
You will need to do the same for all of grpc's dependencies in `golang.org`,
|
||||
e.g. `golang.org/x/net`.
|
||||
|
||||
- With Go module support: it is possible to use the `replace` feature of `go
|
||||
mod` to create aliases for golang.org packages. In your project's directory:
|
||||
|
||||
```
|
||||
go mod edit -replace=google.golang.org/grpc=github.com/grpc/grpc-go@latest
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
go build -mod=vendor
|
||||
```
|
||||
|
||||
Again, this will need to be done for all transitive dependencies hosted on
|
||||
golang.org as well. Please refer to [this
|
||||
issue](https://github.com/golang/go/issues/28652) in the golang repo regarding
|
||||
this concern.
|
||||
|
||||
#### Compiling error, undefined: grpc.SupportPackageIsVersion
|
||||
|
||||
Please update proto package, gRPC package and rebuild the proto files:
|
||||
- `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`
|
||||
- `go get -u google.golang.org/grpc`
|
||||
- `protoc --go_out=plugins=grpc:. *.proto`
|
||||
|
||||
#### How to turn on logging
|
||||
|
||||
The default logger is controlled by the environment variables. Turn everything
|
||||
on by setting:
|
||||
|
||||
```
|
||||
GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info
|
||||
```
|
||||
|
||||
#### The RPC failed with error `"code = Unavailable desc = transport is closing"`
|
||||
|
||||
This error means the connection the RPC is using was closed, and there are many
|
||||
possible reasons, including:
|
||||
1. mis-configured transport credentials, connection failed on handshaking
|
||||
1. bytes disrupted, possibly by a proxy in between
|
||||
1. server shutdown
|
||||
|
||||
It can be tricky to debug this because the error happens on the client side but
|
||||
the root cause of the connection being closed is on the server side. Turn on
|
||||
logging on __both client and server__, and see if there are any transport
|
||||
errors.
|
||||
38
vendor/google.golang.org/grpc/backoff.go
generated
vendored
Normal file
38
vendor/google.golang.org/grpc/backoff.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// See internal/backoff package for the backoff implementation. This file is
|
||||
// kept for the exported types and API backward compatibility.
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultBackoffConfig uses values specified for backoff in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
var DefaultBackoffConfig = BackoffConfig{
|
||||
MaxDelay: 120 * time.Second,
|
||||
}
|
||||
|
||||
// BackoffConfig defines the parameters for the default gRPC backoff strategy.
|
||||
type BackoffConfig struct {
|
||||
// MaxDelay is the upper bound of backoff delay.
|
||||
MaxDelay time.Duration
|
||||
}
|
||||
391
vendor/google.golang.org/grpc/balancer.go
generated
vendored
Normal file
391
vendor/google.golang.org/grpc/balancer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/naming"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Address represents a server the client connects to.
|
||||
//
|
||||
// Deprecated: please use package balancer.
|
||||
type Address struct {
|
||||
// Addr is the server address on which a connection will be established.
|
||||
Addr string
|
||||
// Metadata is the information associated with Addr, which may be used
|
||||
// to make load balancing decision.
|
||||
Metadata interface{}
|
||||
}
|
||||
|
||||
// BalancerConfig specifies the configurations for Balancer.
|
||||
//
|
||||
// Deprecated: please use package balancer. May be removed in a future 1.x release.
|
||||
type BalancerConfig struct {
|
||||
// DialCreds is the transport credential the Balancer implementation can
|
||||
// use to dial to a remote load balancer server. The Balancer implementations
|
||||
// can ignore this if it does not need to talk to another party securely.
|
||||
DialCreds credentials.TransportCredentials
|
||||
// Dialer is the custom dialer the Balancer implementation can use to dial
|
||||
// to a remote load balancer server. The Balancer implementations
|
||||
// can ignore this if it doesn't need to talk to remote balancer.
|
||||
Dialer func(context.Context, string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// BalancerGetOptions configures a Get call.
|
||||
//
|
||||
// Deprecated: please use package balancer. May be removed in a future 1.x release.
|
||||
type BalancerGetOptions struct {
|
||||
// BlockingWait specifies whether Get should block when there is no
|
||||
// connected address.
|
||||
BlockingWait bool
|
||||
}
|
||||
|
||||
// Balancer chooses network addresses for RPCs.
|
||||
//
|
||||
// Deprecated: please use package balancer. May be removed in a future 1.x release.
|
||||
type Balancer interface {
|
||||
// Start does the initialization work to bootstrap a Balancer. For example,
|
||||
// this function may start the name resolution and watch the updates. It will
|
||||
// be called when dialing.
|
||||
Start(target string, config BalancerConfig) error
|
||||
// Up informs the Balancer that gRPC has a connection to the server at
|
||||
// addr. It returns down which is called once the connection to addr gets
|
||||
// lost or closed.
|
||||
// TODO: It is not clear how to construct and take advantage of the meaningful error
|
||||
// parameter for down. Need realistic demands to guide.
|
||||
Up(addr Address) (down func(error))
|
||||
// Get gets the address of a server for the RPC corresponding to ctx.
|
||||
// i) If it returns a connected address, gRPC internals issues the RPC on the
|
||||
// connection to this address;
|
||||
// ii) If it returns an address on which the connection is under construction
|
||||
// (initiated by Notify(...)) but not connected, gRPC internals
|
||||
// * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or
|
||||
// Shutdown state;
|
||||
// or
|
||||
// * issues RPC on the connection otherwise.
|
||||
// iii) If it returns an address on which the connection does not exist, gRPC
|
||||
// internals treats it as an error and will fail the corresponding RPC.
|
||||
//
|
||||
// Therefore, the following is the recommended rule when writing a custom Balancer.
|
||||
// If opts.BlockingWait is true, it should return a connected address or
|
||||
// block if there is no connected address. It should respect the timeout or
|
||||
// cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast
|
||||
// RPCs), it should return an address it has notified via Notify(...) immediately
|
||||
// instead of blocking.
|
||||
//
|
||||
// The function returns put which is called once the rpc has completed or failed.
|
||||
// put can collect and report RPC stats to a remote load balancer.
|
||||
//
|
||||
// This function should only return the errors Balancer cannot recover by itself.
|
||||
// gRPC internals will fail the RPC if an error is returned.
|
||||
Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)
|
||||
// Notify returns a channel that is used by gRPC internals to watch the addresses
|
||||
// gRPC needs to connect. The addresses might be from a name resolver or remote
|
||||
// load balancer. gRPC internals will compare it with the existing connected
|
||||
// addresses. If the address Balancer notified is not in the existing connected
|
||||
// addresses, gRPC starts to connect the address. If an address in the existing
|
||||
// connected addresses is not in the notification list, the corresponding connection
|
||||
// is shutdown gracefully. Otherwise, there are no operations to take. Note that
|
||||
// the Address slice must be the full list of the Addresses which should be connected.
|
||||
// It is NOT delta.
|
||||
Notify() <-chan []Address
|
||||
// Close shuts down the balancer.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch
|
||||
// the name resolution updates and updates the addresses available correspondingly.
|
||||
//
|
||||
// Deprecated: please use package balancer/roundrobin. May be removed in a future 1.x release.
|
||||
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
|
||||
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 {
|
||||
updates, err := rr.w.Next()
|
||||
if err != nil {
|
||||
grpclog.Warningf("grpc: the naming watcher stops working due to %v.", err)
|
||||
return err
|
||||
}
|
||||
rr.mu.Lock()
|
||||
defer rr.mu.Unlock()
|
||||
for _, update := range updates {
|
||||
addr := Address{
|
||||
Addr: update.Addr,
|
||||
Metadata: update.Metadata,
|
||||
}
|
||||
switch update.Op {
|
||||
case naming.Add:
|
||||
var exist bool
|
||||
for _, v := range rr.addrs {
|
||||
if addr == v.addr {
|
||||
exist = true
|
||||
grpclog.Infoln("grpc: The name resolver wanted to add an existing address: ", addr)
|
||||
break
|
||||
}
|
||||
}
|
||||
if exist {
|
||||
continue
|
||||
}
|
||||
rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
|
||||
case naming.Delete:
|
||||
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
|
||||
}
|
||||
}
|
||||
default:
|
||||
grpclog.Errorln("Unknown update.Op ", update.Op)
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
select {
|
||||
case <-rr.addrCh:
|
||||
default:
|
||||
}
|
||||
rr.addrCh <- open
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rr *roundRobin) Start(target string, config BalancerConfig) error {
|
||||
rr.mu.Lock()
|
||||
defer rr.mu.Unlock()
|
||||
if rr.done {
|
||||
return ErrClientConnClosing
|
||||
}
|
||||
if rr.r == nil {
|
||||
// If there is no name resolver installed, it is not needed to
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rr.w = w
|
||||
rr.addrCh = make(chan []Address, 1)
|
||||
go func() {
|
||||
for {
|
||||
if err := rr.watchAddrUpdates(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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()
|
||||
var cnt int
|
||||
for _, a := range rr.addrs {
|
||||
if a.addr == addr {
|
||||
if a.connected {
|
||||
return nil
|
||||
}
|
||||
a.connected = true
|
||||
}
|
||||
if a.connected {
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
// 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 unsets the connected state of addr.
|
||||
func (rr *roundRobin) down(addr Address, err error) {
|
||||
rr.mu.Lock()
|
||||
defer rr.mu.Unlock()
|
||||
for _, a := range rr.addrs {
|
||||
if addr == a.addr {
|
||||
a.connected = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the next addr in the rotation.
|
||||
func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
|
||||
var ch chan struct{}
|
||||
rr.mu.Lock()
|
||||
if rr.done {
|
||||
rr.mu.Unlock()
|
||||
err = ErrClientConnClosing
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
if !opts.BlockingWait {
|
||||
if len(rr.addrs) == 0 {
|
||||
rr.mu.Unlock()
|
||||
err = status.Errorf(codes.Unavailable, "there is no address available")
|
||||
return
|
||||
}
|
||||
// Returns the next addr on rr.addrs for failfast RPCs.
|
||||
addr = rr.addrs[rr.next].addr
|
||||
rr.next++
|
||||
rr.mu.Unlock()
|
||||
return
|
||||
}
|
||||
// Wait on rr.waitCh for non-failfast RPCs.
|
||||
if rr.waitCh == nil {
|
||||
ch = make(chan struct{})
|
||||
rr.waitCh = ch
|
||||
} else {
|
||||
ch = rr.waitCh
|
||||
}
|
||||
rr.mu.Unlock()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
return
|
||||
case <-ch:
|
||||
rr.mu.Lock()
|
||||
if rr.done {
|
||||
rr.mu.Unlock()
|
||||
err = ErrClientConnClosing
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
// The newly added addr got removed by Down() again.
|
||||
if rr.waitCh == nil {
|
||||
ch = make(chan struct{})
|
||||
rr.waitCh = ch
|
||||
} else {
|
||||
ch = rr.waitCh
|
||||
}
|
||||
rr.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rr *roundRobin) Notify() <-chan []Address {
|
||||
return rr.addrCh
|
||||
}
|
||||
|
||||
func (rr *roundRobin) Close() error {
|
||||
rr.mu.Lock()
|
||||
defer rr.mu.Unlock()
|
||||
if rr.done {
|
||||
return errBalancerClosed
|
||||
}
|
||||
rr.done = true
|
||||
if rr.w != nil {
|
||||
rr.w.Close()
|
||||
}
|
||||
if rr.waitCh != nil {
|
||||
close(rr.waitCh)
|
||||
rr.waitCh = nil
|
||||
}
|
||||
if rr.addrCh != nil {
|
||||
close(rr.addrCh)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// pickFirst is used to test multi-addresses in one addrConn in which all addresses share the same addrConn.
|
||||
// It is a wrapper around roundRobin balancer. The logic of all methods works fine because balancer.Get()
|
||||
// returns the only address Up by resetTransport().
|
||||
type pickFirst struct {
|
||||
*roundRobin
|
||||
}
|
||||
364
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
Normal file
364
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package balancer defines APIs for load balancing in gRPC.
|
||||
// All APIs in this package are experimental.
|
||||
package balancer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
// m is a map from name to balancer builder.
|
||||
m = make(map[string]Builder)
|
||||
)
|
||||
|
||||
// Register registers the balancer builder to the balancer map. b.Name
|
||||
// (lowercased) will be used as the name registered with this builder. If the
|
||||
// Builder implements ConfigParser, ParseConfig will be called when new service
|
||||
// configs are received by the resolver, and the result will be provided to the
|
||||
// Balancer in UpdateClientConnState.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Balancers are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func Register(b Builder) {
|
||||
m[strings.ToLower(b.Name())] = b
|
||||
}
|
||||
|
||||
// unregisterForTesting deletes the balancer with the given name from the
|
||||
// balancer map.
|
||||
//
|
||||
// This function is not thread-safe.
|
||||
func unregisterForTesting(name string) {
|
||||
delete(m, name)
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.BalancerUnregister = unregisterForTesting
|
||||
}
|
||||
|
||||
// Get returns the resolver builder registered with the given name.
|
||||
// Note that the compare is done in a case-insensitive fashion.
|
||||
// If no builder is register with the name, nil will be returned.
|
||||
func Get(name string) Builder {
|
||||
if b, ok := m[strings.ToLower(name)]; ok {
|
||||
return b
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubConn represents a gRPC sub connection.
|
||||
// Each sub connection contains a list of addresses. gRPC will
|
||||
// try to connect to them (in sequence), and stop trying the
|
||||
// remainder once one connection is successful.
|
||||
//
|
||||
// The reconnect backoff will be applied on the list, not a single address.
|
||||
// For example, try_on_all_addresses -> backoff -> try_on_all_addresses.
|
||||
//
|
||||
// All SubConns start in IDLE, and will not try to connect. To trigger
|
||||
// the connecting, Balancers must call Connect.
|
||||
// When the connection encounters an error, it will reconnect immediately.
|
||||
// When the connection becomes IDLE, it will not reconnect unless Connect is
|
||||
// called.
|
||||
//
|
||||
// This interface is to be implemented by gRPC. Users should not need a
|
||||
// brand new implementation of this interface. For the situations like
|
||||
// testing, the new implementation should embed this interface. This allows
|
||||
// gRPC to add new methods to this interface.
|
||||
type SubConn interface {
|
||||
// UpdateAddresses updates the addresses used in this SubConn.
|
||||
// gRPC checks if currently-connected address is still in the new list.
|
||||
// If it's in the list, the connection will be kept.
|
||||
// If it's not in the list, the connection will gracefully closed, and
|
||||
// a new connection will be created.
|
||||
//
|
||||
// This will trigger a state transition for the SubConn.
|
||||
UpdateAddresses([]resolver.Address)
|
||||
// Connect starts the connecting for this SubConn.
|
||||
Connect()
|
||||
}
|
||||
|
||||
// NewSubConnOptions contains options to create new SubConn.
|
||||
type NewSubConnOptions struct {
|
||||
// CredsBundle is the credentials bundle that will be used in the created
|
||||
// SubConn. If it's nil, the original creds from grpc DialOptions will be
|
||||
// used.
|
||||
CredsBundle credentials.Bundle
|
||||
// HealthCheckEnabled indicates whether health check service should be
|
||||
// enabled on this SubConn
|
||||
HealthCheckEnabled bool
|
||||
}
|
||||
|
||||
// ClientConn represents a gRPC ClientConn.
|
||||
//
|
||||
// This interface is to be implemented by gRPC. Users should not need a
|
||||
// brand new implementation of this interface. For the situations like
|
||||
// testing, the new implementation should embed this interface. This allows
|
||||
// gRPC to add new methods to this interface.
|
||||
type ClientConn interface {
|
||||
// NewSubConn is called by balancer to create a new SubConn.
|
||||
// It doesn't block and wait for the connections to be established.
|
||||
// Behaviors of the SubConn can be controlled by options.
|
||||
NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
|
||||
// RemoveSubConn removes the SubConn from ClientConn.
|
||||
// The SubConn will be shutdown.
|
||||
RemoveSubConn(SubConn)
|
||||
|
||||
// UpdateBalancerState is called by balancer to notify gRPC that some internal
|
||||
// state in balancer has changed.
|
||||
//
|
||||
// gRPC will update the connectivity state of the ClientConn, and will call pick
|
||||
// on the new picker to pick new SubConn.
|
||||
UpdateBalancerState(s connectivity.State, p Picker)
|
||||
|
||||
// ResolveNow is called by balancer to notify gRPC to do a name resolving.
|
||||
ResolveNow(resolver.ResolveNowOption)
|
||||
|
||||
// Target returns the dial target for this ClientConn.
|
||||
//
|
||||
// Deprecated: Use the Target field in the BuildOptions instead.
|
||||
Target() string
|
||||
}
|
||||
|
||||
// BuildOptions contains additional information for Build.
|
||||
type BuildOptions struct {
|
||||
// DialCreds is the transport credential the Balancer implementation can
|
||||
// use to dial to a remote load balancer server. The Balancer implementations
|
||||
// can ignore this if it does not need to talk to another party securely.
|
||||
DialCreds credentials.TransportCredentials
|
||||
// CredsBundle is the credentials bundle that the Balancer can use.
|
||||
CredsBundle credentials.Bundle
|
||||
// Dialer is the custom dialer the Balancer implementation can use to dial
|
||||
// to a remote load balancer server. The Balancer implementations
|
||||
// can ignore this if it doesn't need to talk to remote balancer.
|
||||
Dialer func(context.Context, string) (net.Conn, error)
|
||||
// ChannelzParentID is the entity parent's channelz unique identification number.
|
||||
ChannelzParentID int64
|
||||
// Target contains the parsed address info of the dial target. It is the same resolver.Target as
|
||||
// passed to the resolver.
|
||||
// See the documentation for the resolver.Target type for details about what it contains.
|
||||
Target resolver.Target
|
||||
}
|
||||
|
||||
// Builder creates a balancer.
|
||||
type Builder interface {
|
||||
// Build creates a new balancer with the ClientConn.
|
||||
Build(cc ClientConn, opts BuildOptions) Balancer
|
||||
// Name returns the name of balancers built by this builder.
|
||||
// It will be used to pick balancers (for example in service config).
|
||||
Name() string
|
||||
}
|
||||
|
||||
// ConfigParser parses load balancer configs.
|
||||
type ConfigParser interface {
|
||||
// ParseConfig parses the JSON load balancer config provided into an
|
||||
// internal form or returns an error if the config is invalid. For future
|
||||
// compatibility reasons, unknown fields in the config should be ignored.
|
||||
ParseConfig(LoadBalancingConfigJSON json.RawMessage) (serviceconfig.LoadBalancingConfig, error)
|
||||
}
|
||||
|
||||
// PickOptions contains addition information for the Pick operation.
|
||||
type PickOptions struct {
|
||||
// FullMethodName is the method name that NewClientStream() is called
|
||||
// with. The canonical format is /service/Method.
|
||||
FullMethodName string
|
||||
}
|
||||
|
||||
// DoneInfo contains additional information for done.
|
||||
type DoneInfo struct {
|
||||
// Err is the rpc error the RPC finished with. It could be nil.
|
||||
Err error
|
||||
// Trailer contains the metadata from the RPC's trailer, if present.
|
||||
Trailer metadata.MD
|
||||
// BytesSent indicates if any bytes have been sent to the server.
|
||||
BytesSent bool
|
||||
// BytesReceived indicates if any byte has been received from the server.
|
||||
BytesReceived bool
|
||||
// ServerLoad is the load received from server. It's usually sent as part of
|
||||
// trailing metadata.
|
||||
//
|
||||
// The only supported type now is *orca_v1.LoadReport.
|
||||
ServerLoad interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrNoSubConnAvailable indicates no SubConn is available for pick().
|
||||
// gRPC will block the RPC until a new picker is available via UpdateBalancerState().
|
||||
ErrNoSubConnAvailable = errors.New("no SubConn is available")
|
||||
// ErrTransientFailure indicates all SubConns are in TransientFailure.
|
||||
// WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
|
||||
ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
|
||||
)
|
||||
|
||||
// Picker is used by gRPC to pick a SubConn to send an RPC.
|
||||
// Balancer is expected to generate a new picker from its snapshot every time its
|
||||
// internal state has changed.
|
||||
//
|
||||
// The pickers used by gRPC can be updated by ClientConn.UpdateBalancerState().
|
||||
type Picker interface {
|
||||
// Pick returns the SubConn to be used to send the RPC.
|
||||
// The returned SubConn must be one returned by NewSubConn().
|
||||
//
|
||||
// This functions is expected to return:
|
||||
// - a SubConn that is known to be READY;
|
||||
// - ErrNoSubConnAvailable if no SubConn is available, but progress is being
|
||||
// made (for example, some SubConn is in CONNECTING mode);
|
||||
// - other errors if no active connecting is happening (for example, all SubConn
|
||||
// are in TRANSIENT_FAILURE mode).
|
||||
//
|
||||
// If a SubConn is returned:
|
||||
// - If it is READY, gRPC will send the RPC on it;
|
||||
// - If it is not ready, or becomes not ready after it's returned, gRPC will
|
||||
// block until UpdateBalancerState() is called and will call pick on the
|
||||
// new picker. The done function returned from Pick(), if not nil, will be
|
||||
// called with nil error, no bytes sent and no bytes received.
|
||||
//
|
||||
// If the returned error is not nil:
|
||||
// - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState()
|
||||
// - If the error is ErrTransientFailure:
|
||||
// - If the RPC is wait-for-ready, gRPC will block until UpdateBalancerState()
|
||||
// is called to pick again;
|
||||
// - Otherwise, RPC will fail with unavailable error.
|
||||
// - Else (error is other non-nil error):
|
||||
// - The RPC will fail with unavailable error.
|
||||
//
|
||||
// The returned done() function will be called once the rpc has finished,
|
||||
// with the final status of that RPC. If the SubConn returned is not a
|
||||
// valid SubConn type, done may not be called. done may be nil if balancer
|
||||
// doesn't care about the RPC status.
|
||||
Pick(ctx context.Context, opts PickOptions) (conn SubConn, done func(DoneInfo), err error)
|
||||
}
|
||||
|
||||
// Balancer takes input from gRPC, manages SubConns, and collects and aggregates
|
||||
// the connectivity states.
|
||||
//
|
||||
// It also generates and updates the Picker used by gRPC to pick SubConns for RPCs.
|
||||
//
|
||||
// HandleSubConnectionStateChange, HandleResolvedAddrs and Close are guaranteed
|
||||
// to be called synchronously from the same goroutine.
|
||||
// There's no guarantee on picker.Pick, it may be called anytime.
|
||||
type Balancer interface {
|
||||
// HandleSubConnStateChange is called by gRPC when the connectivity state
|
||||
// of sc has changed.
|
||||
// Balancer is expected to aggregate all the state of SubConn and report
|
||||
// that back to gRPC.
|
||||
// Balancer should also generate and update Pickers when its internal state has
|
||||
// been changed by the new state.
|
||||
//
|
||||
// Deprecated: if V2Balancer is implemented by the Balancer,
|
||||
// UpdateSubConnState will be called instead.
|
||||
HandleSubConnStateChange(sc SubConn, state connectivity.State)
|
||||
// HandleResolvedAddrs is called by gRPC to send updated resolved addresses to
|
||||
// balancers.
|
||||
// Balancer can create new SubConn or remove SubConn with the addresses.
|
||||
// An empty address slice and a non-nil error will be passed if the resolver returns
|
||||
// non-nil error to gRPC.
|
||||
//
|
||||
// Deprecated: if V2Balancer is implemented by the Balancer,
|
||||
// UpdateClientConnState will be called instead.
|
||||
HandleResolvedAddrs([]resolver.Address, error)
|
||||
// Close closes the balancer. The balancer is not required to call
|
||||
// ClientConn.RemoveSubConn for its existing SubConns.
|
||||
Close()
|
||||
}
|
||||
|
||||
// SubConnState describes the state of a SubConn.
|
||||
type SubConnState struct {
|
||||
ConnectivityState connectivity.State
|
||||
// TODO: add last connection error
|
||||
}
|
||||
|
||||
// ClientConnState describes the state of a ClientConn relevant to the
|
||||
// balancer.
|
||||
type ClientConnState struct {
|
||||
ResolverState resolver.State
|
||||
// The parsed load balancing configuration returned by the builder's
|
||||
// ParseConfig method, if implemented.
|
||||
BalancerConfig serviceconfig.LoadBalancingConfig
|
||||
}
|
||||
|
||||
// V2Balancer is defined for documentation purposes. If a Balancer also
|
||||
// implements V2Balancer, its UpdateClientConnState method will be called
|
||||
// instead of HandleResolvedAddrs and its UpdateSubConnState will be called
|
||||
// instead of HandleSubConnStateChange.
|
||||
type V2Balancer interface {
|
||||
// UpdateClientConnState is called by gRPC when the state of the ClientConn
|
||||
// changes.
|
||||
UpdateClientConnState(ClientConnState)
|
||||
// UpdateSubConnState is called by gRPC when the state of a SubConn
|
||||
// changes.
|
||||
UpdateSubConnState(SubConn, SubConnState)
|
||||
// Close closes the balancer. The balancer is not required to call
|
||||
// ClientConn.RemoveSubConn for its existing SubConns.
|
||||
Close()
|
||||
}
|
||||
|
||||
// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
|
||||
// and returns one aggregated connectivity state.
|
||||
//
|
||||
// It's not thread safe.
|
||||
type ConnectivityStateEvaluator struct {
|
||||
numReady uint64 // Number of addrConns in ready state.
|
||||
numConnecting uint64 // Number of addrConns in connecting state.
|
||||
numTransientFailure uint64 // Number of addrConns in transientFailure.
|
||||
}
|
||||
|
||||
// RecordTransition records state change happening in subConn and based on that
|
||||
// it evaluates what aggregated state should be.
|
||||
//
|
||||
// - If at least one SubConn in Ready, the aggregated state is Ready;
|
||||
// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
|
||||
// - Else the aggregated state is TransientFailure.
|
||||
//
|
||||
// Idle and Shutdown are not considered.
|
||||
func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
|
||||
// Update counters.
|
||||
for idx, state := range []connectivity.State{oldState, newState} {
|
||||
updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
|
||||
switch state {
|
||||
case connectivity.Ready:
|
||||
cse.numReady += updateVal
|
||||
case connectivity.Connecting:
|
||||
cse.numConnecting += updateVal
|
||||
case connectivity.TransientFailure:
|
||||
cse.numTransientFailure += updateVal
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate.
|
||||
if cse.numReady > 0 {
|
||||
return connectivity.Ready
|
||||
}
|
||||
if cse.numConnecting > 0 {
|
||||
return connectivity.Connecting
|
||||
}
|
||||
return connectivity.TransientFailure
|
||||
}
|
||||
184
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
Normal file
184
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
type baseBuilder struct {
|
||||
name string
|
||||
pickerBuilder PickerBuilder
|
||||
config Config
|
||||
}
|
||||
|
||||
func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
|
||||
return &baseBalancer{
|
||||
cc: cc,
|
||||
pickerBuilder: bb.pickerBuilder,
|
||||
|
||||
subConns: make(map[resolver.Address]balancer.SubConn),
|
||||
scStates: make(map[balancer.SubConn]connectivity.State),
|
||||
csEvltr: &balancer.ConnectivityStateEvaluator{},
|
||||
// Initialize picker to a picker that always return
|
||||
// ErrNoSubConnAvailable, because when state of a SubConn changes, we
|
||||
// may call UpdateBalancerState with this picker.
|
||||
picker: NewErrPicker(balancer.ErrNoSubConnAvailable),
|
||||
config: bb.config,
|
||||
}
|
||||
}
|
||||
|
||||
func (bb *baseBuilder) Name() string {
|
||||
return bb.name
|
||||
}
|
||||
|
||||
type baseBalancer struct {
|
||||
cc balancer.ClientConn
|
||||
pickerBuilder PickerBuilder
|
||||
|
||||
csEvltr *balancer.ConnectivityStateEvaluator
|
||||
state connectivity.State
|
||||
|
||||
subConns map[resolver.Address]balancer.SubConn
|
||||
scStates map[balancer.SubConn]connectivity.State
|
||||
picker balancer.Picker
|
||||
config Config
|
||||
}
|
||||
|
||||
func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) {
|
||||
// TODO: handle s.ResolverState.Err (log if not nil) once implemented.
|
||||
// TODO: handle s.ResolverState.ServiceConfig?
|
||||
if grpclog.V(2) {
|
||||
grpclog.Infoln("base.baseBalancer: got new ClientConn state: ", s)
|
||||
}
|
||||
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
|
||||
addrsSet := make(map[resolver.Address]struct{})
|
||||
for _, a := range s.ResolverState.Addresses {
|
||||
addrsSet[a] = struct{}{}
|
||||
if _, ok := b.subConns[a]; !ok {
|
||||
// a is a new address (not existing in b.subConns).
|
||||
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
|
||||
if err != nil {
|
||||
grpclog.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
|
||||
continue
|
||||
}
|
||||
b.subConns[a] = sc
|
||||
b.scStates[sc] = connectivity.Idle
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
for a, sc := range b.subConns {
|
||||
// a was removed by resolver.
|
||||
if _, ok := addrsSet[a]; !ok {
|
||||
b.cc.RemoveSubConn(sc)
|
||||
delete(b.subConns, a)
|
||||
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
||||
// The entry will be deleted in HandleSubConnStateChange.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// regeneratePicker takes a snapshot of the balancer, and generates a picker
|
||||
// from it. The picker is
|
||||
// - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
|
||||
// - built by the pickerBuilder with all READY SubConns otherwise.
|
||||
func (b *baseBalancer) regeneratePicker() {
|
||||
if b.state == connectivity.TransientFailure {
|
||||
b.picker = NewErrPicker(balancer.ErrTransientFailure)
|
||||
return
|
||||
}
|
||||
readySCs := make(map[resolver.Address]balancer.SubConn)
|
||||
|
||||
// Filter out all ready SCs from full subConn map.
|
||||
for addr, sc := range b.subConns {
|
||||
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
|
||||
readySCs[addr] = sc
|
||||
}
|
||||
}
|
||||
b.picker = b.pickerBuilder.Build(readySCs)
|
||||
}
|
||||
|
||||
func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
s := state.ConnectivityState
|
||||
if grpclog.V(2) {
|
||||
grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
|
||||
}
|
||||
oldS, ok := b.scStates[sc]
|
||||
if !ok {
|
||||
if grpclog.V(2) {
|
||||
grpclog.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
|
||||
}
|
||||
return
|
||||
}
|
||||
b.scStates[sc] = s
|
||||
switch s {
|
||||
case connectivity.Idle:
|
||||
sc.Connect()
|
||||
case connectivity.Shutdown:
|
||||
// When an address was removed by resolver, b called RemoveSubConn but
|
||||
// kept the sc's state in scStates. Remove state for this sc here.
|
||||
delete(b.scStates, sc)
|
||||
}
|
||||
|
||||
oldAggrState := b.state
|
||||
b.state = b.csEvltr.RecordTransition(oldS, s)
|
||||
|
||||
// Regenerate picker when one of the following happens:
|
||||
// - this sc became ready from not-ready
|
||||
// - this sc became not-ready from ready
|
||||
// - the aggregated state of balancer became TransientFailure from non-TransientFailure
|
||||
// - the aggregated state of balancer became non-TransientFailure from TransientFailure
|
||||
if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
|
||||
(b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
|
||||
b.regeneratePicker()
|
||||
}
|
||||
|
||||
b.cc.UpdateBalancerState(b.state, b.picker)
|
||||
}
|
||||
|
||||
// Close is a nop because base balancer doesn't have internal state to clean up,
|
||||
// and it doesn't need to call RemoveSubConn for the SubConns.
|
||||
func (b *baseBalancer) Close() {
|
||||
}
|
||||
|
||||
// NewErrPicker returns a picker that always returns err on Pick().
|
||||
func NewErrPicker(err error) balancer.Picker {
|
||||
return &errPicker{err: err}
|
||||
}
|
||||
|
||||
type errPicker struct {
|
||||
err error // Pick() always returns this err.
|
||||
}
|
||||
|
||||
func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
|
||||
return nil, nil, p.err
|
||||
}
|
||||
64
vendor/google.golang.org/grpc/balancer/base/base.go
generated
vendored
Normal file
64
vendor/google.golang.org/grpc/balancer/base/base.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package base defines a balancer base that can be used to build balancers with
|
||||
// different picking algorithms.
|
||||
//
|
||||
// The base balancer creates a new SubConn for each resolved address. The
|
||||
// provided picker will only be notified about READY SubConns.
|
||||
//
|
||||
// This package is the base of round_robin balancer, its purpose is to be used
|
||||
// to build round_robin like balancers with complex picking algorithms.
|
||||
// Balancers with more complicated logic should try to implement a balancer
|
||||
// builder from scratch.
|
||||
//
|
||||
// All APIs in this package are experimental.
|
||||
package base
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// PickerBuilder creates balancer.Picker.
|
||||
type PickerBuilder interface {
|
||||
// Build takes a slice of ready SubConns, and returns a picker that will be
|
||||
// used by gRPC to pick a SubConn.
|
||||
Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker
|
||||
}
|
||||
|
||||
// NewBalancerBuilder returns a balancer builder. The balancers
|
||||
// built by this builder will use the picker builder to build pickers.
|
||||
func NewBalancerBuilder(name string, pb PickerBuilder) balancer.Builder {
|
||||
return NewBalancerBuilderWithConfig(name, pb, Config{})
|
||||
}
|
||||
|
||||
// Config contains the config info about the base balancer builder.
|
||||
type Config struct {
|
||||
// HealthCheck indicates whether health checking should be enabled for this specific balancer.
|
||||
HealthCheck bool
|
||||
}
|
||||
|
||||
// NewBalancerBuilderWithConfig returns a base balancer builder configured by the provided config.
|
||||
func NewBalancerBuilderWithConfig(name string, pb PickerBuilder, config Config) balancer.Builder {
|
||||
return &baseBuilder{
|
||||
name: name,
|
||||
pickerBuilder: pb,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
83
vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
generated
vendored
Normal file
83
vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
|
||||
// installed as one of the default balancers in gRPC, users don't need to
|
||||
// explicitly install this balancer.
|
||||
package roundrobin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/balancer/base"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// Name is the name of round_robin balancer.
|
||||
const Name = "round_robin"
|
||||
|
||||
// newBuilder creates a new roundrobin balancer builder.
|
||||
func newBuilder() balancer.Builder {
|
||||
return base.NewBalancerBuilderWithConfig(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true})
|
||||
}
|
||||
|
||||
func init() {
|
||||
balancer.Register(newBuilder())
|
||||
}
|
||||
|
||||
type rrPickerBuilder struct{}
|
||||
|
||||
func (*rrPickerBuilder) Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker {
|
||||
grpclog.Infof("roundrobinPicker: newPicker called with readySCs: %v", readySCs)
|
||||
if len(readySCs) == 0 {
|
||||
return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||
}
|
||||
var scs []balancer.SubConn
|
||||
for _, sc := range readySCs {
|
||||
scs = append(scs, sc)
|
||||
}
|
||||
return &rrPicker{
|
||||
subConns: scs,
|
||||
// Start at a random index, as the same RR balancer rebuilds a new
|
||||
// picker when SubConn states change, and we don't want to apply excess
|
||||
// load to the first server in the list.
|
||||
next: grpcrand.Intn(len(scs)),
|
||||
}
|
||||
}
|
||||
|
||||
type rrPicker struct {
|
||||
// subConns is the snapshot of the roundrobin balancer when this picker was
|
||||
// created. The slice is immutable. Each Get() will do a round robin
|
||||
// selection from it and return the selected SubConn.
|
||||
subConns []balancer.SubConn
|
||||
|
||||
mu sync.Mutex
|
||||
next int
|
||||
}
|
||||
|
||||
func (p *rrPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
|
||||
p.mu.Lock()
|
||||
sc := p.subConns[p.next]
|
||||
p.next = (p.next + 1) % len(p.subConns)
|
||||
p.mu.Unlock()
|
||||
return sc, nil, nil
|
||||
}
|
||||
318
vendor/google.golang.org/grpc/balancer_conn_wrappers.go
generated
vendored
Normal file
318
vendor/google.golang.org/grpc/balancer_conn_wrappers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// scStateUpdate contains the subConn and the new state it changed to.
|
||||
type scStateUpdate struct {
|
||||
sc balancer.SubConn
|
||||
state connectivity.State
|
||||
}
|
||||
|
||||
// scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
|
||||
// TODO make a general purpose buffer that uses interface{}.
|
||||
type scStateUpdateBuffer struct {
|
||||
c chan *scStateUpdate
|
||||
mu sync.Mutex
|
||||
backlog []*scStateUpdate
|
||||
}
|
||||
|
||||
func newSCStateUpdateBuffer() *scStateUpdateBuffer {
|
||||
return &scStateUpdateBuffer{
|
||||
c: make(chan *scStateUpdate, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if len(b.backlog) == 0 {
|
||||
select {
|
||||
case b.c <- t:
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.backlog = append(b.backlog, t)
|
||||
}
|
||||
|
||||
func (b *scStateUpdateBuffer) load() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if len(b.backlog) > 0 {
|
||||
select {
|
||||
case b.c <- b.backlog[0]:
|
||||
b.backlog[0] = nil
|
||||
b.backlog = b.backlog[1:]
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get returns the channel that the scStateUpdate will be sent to.
|
||||
//
|
||||
// Upon receiving, the caller should call load to send another
|
||||
// scStateChangeTuple onto the channel if there is any.
|
||||
func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
|
||||
return b.c
|
||||
}
|
||||
|
||||
// ccBalancerWrapper is a wrapper on top of cc for balancers.
|
||||
// It implements balancer.ClientConn interface.
|
||||
type ccBalancerWrapper struct {
|
||||
cc *ClientConn
|
||||
balancer balancer.Balancer
|
||||
stateChangeQueue *scStateUpdateBuffer
|
||||
ccUpdateCh chan *balancer.ClientConnState
|
||||
done chan struct{}
|
||||
|
||||
mu sync.Mutex
|
||||
subConns map[*acBalancerWrapper]struct{}
|
||||
}
|
||||
|
||||
func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
|
||||
ccb := &ccBalancerWrapper{
|
||||
cc: cc,
|
||||
stateChangeQueue: newSCStateUpdateBuffer(),
|
||||
ccUpdateCh: make(chan *balancer.ClientConnState, 1),
|
||||
done: make(chan struct{}),
|
||||
subConns: make(map[*acBalancerWrapper]struct{}),
|
||||
}
|
||||
go ccb.watcher()
|
||||
ccb.balancer = b.Build(ccb, bopts)
|
||||
return ccb
|
||||
}
|
||||
|
||||
// watcher balancer functions sequentially, so the balancer can be implemented
|
||||
// lock-free.
|
||||
func (ccb *ccBalancerWrapper) watcher() {
|
||||
for {
|
||||
select {
|
||||
case t := <-ccb.stateChangeQueue.get():
|
||||
ccb.stateChangeQueue.load()
|
||||
select {
|
||||
case <-ccb.done:
|
||||
ccb.balancer.Close()
|
||||
return
|
||||
default:
|
||||
}
|
||||
if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
|
||||
ub.UpdateSubConnState(t.sc, balancer.SubConnState{ConnectivityState: t.state})
|
||||
} else {
|
||||
ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
|
||||
}
|
||||
case s := <-ccb.ccUpdateCh:
|
||||
select {
|
||||
case <-ccb.done:
|
||||
ccb.balancer.Close()
|
||||
return
|
||||
default:
|
||||
}
|
||||
if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
|
||||
ub.UpdateClientConnState(*s)
|
||||
} else {
|
||||
ccb.balancer.HandleResolvedAddrs(s.ResolverState.Addresses, nil)
|
||||
}
|
||||
case <-ccb.done:
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ccb.done:
|
||||
ccb.balancer.Close()
|
||||
ccb.mu.Lock()
|
||||
scs := ccb.subConns
|
||||
ccb.subConns = nil
|
||||
ccb.mu.Unlock()
|
||||
for acbw := range scs {
|
||||
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
|
||||
}
|
||||
ccb.UpdateBalancerState(connectivity.Connecting, nil)
|
||||
return
|
||||
default:
|
||||
}
|
||||
ccb.cc.firstResolveEvent.Fire()
|
||||
}
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) close() {
|
||||
close(ccb.done)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
|
||||
// When updating addresses for a SubConn, if the address in use is not in
|
||||
// the new addresses, the old ac will be tearDown() and a new ac will be
|
||||
// created. tearDown() generates a state change with Shutdown state, we
|
||||
// don't want the balancer to receive this state change. So before
|
||||
// tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
|
||||
// this function will be called with (nil, Shutdown). We don't need to call
|
||||
// balancer method in this case.
|
||||
if sc == nil {
|
||||
return
|
||||
}
|
||||
ccb.stateChangeQueue.put(&scStateUpdate{
|
||||
sc: sc,
|
||||
state: s,
|
||||
})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) {
|
||||
if ccb.cc.curBalancerName != grpclbName {
|
||||
// Filter any grpclb addresses since we don't have the grpclb balancer.
|
||||
s := &ccs.ResolverState
|
||||
for i := 0; i < len(s.Addresses); {
|
||||
if s.Addresses[i].Type == resolver.GRPCLB {
|
||||
copy(s.Addresses[i:], s.Addresses[i+1:])
|
||||
s.Addresses = s.Addresses[:len(s.Addresses)-1]
|
||||
continue
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-ccb.ccUpdateCh:
|
||||
default:
|
||||
}
|
||||
ccb.ccUpdateCh <- ccs
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
if len(addrs) <= 0 {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
|
||||
}
|
||||
ccb.mu.Lock()
|
||||
defer ccb.mu.Unlock()
|
||||
if ccb.subConns == nil {
|
||||
return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
|
||||
}
|
||||
ac, err := ccb.cc.newAddrConn(addrs, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acbw := &acBalancerWrapper{ac: ac}
|
||||
acbw.ac.mu.Lock()
|
||||
ac.acbw = acbw
|
||||
acbw.ac.mu.Unlock()
|
||||
ccb.subConns[acbw] = struct{}{}
|
||||
return acbw, nil
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ccb.mu.Lock()
|
||||
defer ccb.mu.Unlock()
|
||||
if ccb.subConns == nil {
|
||||
return
|
||||
}
|
||||
delete(ccb.subConns, acbw)
|
||||
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
|
||||
ccb.mu.Lock()
|
||||
defer ccb.mu.Unlock()
|
||||
if ccb.subConns == nil {
|
||||
return
|
||||
}
|
||||
// Update picker before updating state. Even though the ordering here does
|
||||
// not matter, it can lead to multiple calls of Pick in the common start-up
|
||||
// case where we wait for ready and then perform an RPC. If the picker is
|
||||
// updated later, we could call the "connecting" picker when the state is
|
||||
// updated, and then call the "ready" picker after the picker gets updated.
|
||||
ccb.cc.blockingpicker.updatePicker(p)
|
||||
ccb.cc.csMgr.updateState(s)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {
|
||||
ccb.cc.resolveNow(o)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) Target() string {
|
||||
return ccb.cc.target
|
||||
}
|
||||
|
||||
// acBalancerWrapper is a wrapper on top of ac for balancers.
|
||||
// It implements balancer.SubConn interface.
|
||||
type acBalancerWrapper struct {
|
||||
mu sync.Mutex
|
||||
ac *addrConn
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
if len(addrs) <= 0 {
|
||||
acbw.ac.tearDown(errConnDrain)
|
||||
return
|
||||
}
|
||||
if !acbw.ac.tryUpdateAddrs(addrs) {
|
||||
cc := acbw.ac.cc
|
||||
opts := acbw.ac.scopts
|
||||
acbw.ac.mu.Lock()
|
||||
// Set old ac.acbw to nil so the Shutdown state update will be ignored
|
||||
// by balancer.
|
||||
//
|
||||
// TODO(bar) the state transition could be wrong when tearDown() old ac
|
||||
// and creating new ac, fix the transition.
|
||||
acbw.ac.acbw = nil
|
||||
acbw.ac.mu.Unlock()
|
||||
acState := acbw.ac.getState()
|
||||
acbw.ac.tearDown(errConnDrain)
|
||||
|
||||
if acState == connectivity.Shutdown {
|
||||
return
|
||||
}
|
||||
|
||||
ac, err := cc.newAddrConn(addrs, opts)
|
||||
if err != nil {
|
||||
grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
|
||||
return
|
||||
}
|
||||
acbw.ac = ac
|
||||
ac.mu.Lock()
|
||||
ac.acbw = acbw
|
||||
ac.mu.Unlock()
|
||||
if acState != connectivity.Idle {
|
||||
ac.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Connect() {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
acbw.ac.connect()
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
return acbw.ac
|
||||
}
|
||||
334
vendor/google.golang.org/grpc/balancer_v1_wrapper.go
generated
vendored
Normal file
334
vendor/google.golang.org/grpc/balancer_v1_wrapper.go
generated
vendored
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
type balancerWrapperBuilder struct {
|
||||
b Balancer // The v1 balancer.
|
||||
}
|
||||
|
||||
func (bwb *balancerWrapperBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
|
||||
bwb.b.Start(opts.Target.Endpoint, BalancerConfig{
|
||||
DialCreds: opts.DialCreds,
|
||||
Dialer: opts.Dialer,
|
||||
})
|
||||
_, pickfirst := bwb.b.(*pickFirst)
|
||||
bw := &balancerWrapper{
|
||||
balancer: bwb.b,
|
||||
pickfirst: pickfirst,
|
||||
cc: cc,
|
||||
targetAddr: opts.Target.Endpoint,
|
||||
startCh: make(chan struct{}),
|
||||
conns: make(map[resolver.Address]balancer.SubConn),
|
||||
connSt: make(map[balancer.SubConn]*scState),
|
||||
csEvltr: &balancer.ConnectivityStateEvaluator{},
|
||||
state: connectivity.Idle,
|
||||
}
|
||||
cc.UpdateBalancerState(connectivity.Idle, bw)
|
||||
go bw.lbWatcher()
|
||||
return bw
|
||||
}
|
||||
|
||||
func (bwb *balancerWrapperBuilder) Name() string {
|
||||
return "wrapper"
|
||||
}
|
||||
|
||||
type scState struct {
|
||||
addr Address // The v1 address type.
|
||||
s connectivity.State
|
||||
down func(error)
|
||||
}
|
||||
|
||||
type balancerWrapper struct {
|
||||
balancer Balancer // The v1 balancer.
|
||||
pickfirst bool
|
||||
|
||||
cc balancer.ClientConn
|
||||
targetAddr string // Target without the scheme.
|
||||
|
||||
mu sync.Mutex
|
||||
conns map[resolver.Address]balancer.SubConn
|
||||
connSt map[balancer.SubConn]*scState
|
||||
// This channel is closed when handling the first resolver result.
|
||||
// lbWatcher blocks until this is closed, to avoid race between
|
||||
// - NewSubConn is created, cc wants to notify balancer of state changes;
|
||||
// - Build hasn't return, cc doesn't have access to balancer.
|
||||
startCh chan struct{}
|
||||
|
||||
// To aggregate the connectivity state.
|
||||
csEvltr *balancer.ConnectivityStateEvaluator
|
||||
state connectivity.State
|
||||
}
|
||||
|
||||
// lbWatcher watches the Notify channel of the balancer and manages
|
||||
// connections accordingly.
|
||||
func (bw *balancerWrapper) lbWatcher() {
|
||||
<-bw.startCh
|
||||
notifyCh := bw.balancer.Notify()
|
||||
if notifyCh == nil {
|
||||
// There's no resolver in the balancer. Connect directly.
|
||||
a := resolver.Address{
|
||||
Addr: bw.targetAddr,
|
||||
Type: resolver.Backend,
|
||||
}
|
||||
sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
|
||||
if err != nil {
|
||||
grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
|
||||
} else {
|
||||
bw.mu.Lock()
|
||||
bw.conns[a] = sc
|
||||
bw.connSt[sc] = &scState{
|
||||
addr: Address{Addr: bw.targetAddr},
|
||||
s: connectivity.Idle,
|
||||
}
|
||||
bw.mu.Unlock()
|
||||
sc.Connect()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for addrs := range notifyCh {
|
||||
grpclog.Infof("balancerWrapper: got update addr from Notify: %v", addrs)
|
||||
if bw.pickfirst {
|
||||
var (
|
||||
oldA resolver.Address
|
||||
oldSC balancer.SubConn
|
||||
)
|
||||
bw.mu.Lock()
|
||||
for oldA, oldSC = range bw.conns {
|
||||
break
|
||||
}
|
||||
bw.mu.Unlock()
|
||||
if len(addrs) <= 0 {
|
||||
if oldSC != nil {
|
||||
// Teardown old sc.
|
||||
bw.mu.Lock()
|
||||
delete(bw.conns, oldA)
|
||||
delete(bw.connSt, oldSC)
|
||||
bw.mu.Unlock()
|
||||
bw.cc.RemoveSubConn(oldSC)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
var newAddrs []resolver.Address
|
||||
for _, a := range addrs {
|
||||
newAddr := resolver.Address{
|
||||
Addr: a.Addr,
|
||||
Type: resolver.Backend, // All addresses from balancer are all backends.
|
||||
ServerName: "",
|
||||
Metadata: a.Metadata,
|
||||
}
|
||||
newAddrs = append(newAddrs, newAddr)
|
||||
}
|
||||
if oldSC == nil {
|
||||
// Create new sc.
|
||||
sc, err := bw.cc.NewSubConn(newAddrs, balancer.NewSubConnOptions{})
|
||||
if err != nil {
|
||||
grpclog.Warningf("Error creating connection to %v. Err: %v", newAddrs, err)
|
||||
} else {
|
||||
bw.mu.Lock()
|
||||
// For pickfirst, there should be only one SubConn, so the
|
||||
// address doesn't matter. All states updating (up and down)
|
||||
// and picking should all happen on that only SubConn.
|
||||
bw.conns[resolver.Address{}] = sc
|
||||
bw.connSt[sc] = &scState{
|
||||
addr: addrs[0], // Use the first address.
|
||||
s: connectivity.Idle,
|
||||
}
|
||||
bw.mu.Unlock()
|
||||
sc.Connect()
|
||||
}
|
||||
} else {
|
||||
bw.mu.Lock()
|
||||
bw.connSt[oldSC].addr = addrs[0]
|
||||
bw.mu.Unlock()
|
||||
oldSC.UpdateAddresses(newAddrs)
|
||||
}
|
||||
} else {
|
||||
var (
|
||||
add []resolver.Address // Addresses need to setup connections.
|
||||
del []balancer.SubConn // Connections need to tear down.
|
||||
)
|
||||
resAddrs := make(map[resolver.Address]Address)
|
||||
for _, a := range addrs {
|
||||
resAddrs[resolver.Address{
|
||||
Addr: a.Addr,
|
||||
Type: resolver.Backend, // All addresses from balancer are all backends.
|
||||
ServerName: "",
|
||||
Metadata: a.Metadata,
|
||||
}] = a
|
||||
}
|
||||
bw.mu.Lock()
|
||||
for a := range resAddrs {
|
||||
if _, ok := bw.conns[a]; !ok {
|
||||
add = append(add, a)
|
||||
}
|
||||
}
|
||||
for a, c := range bw.conns {
|
||||
if _, ok := resAddrs[a]; !ok {
|
||||
del = append(del, c)
|
||||
delete(bw.conns, a)
|
||||
// Keep the state of this sc in bw.connSt until its state becomes Shutdown.
|
||||
}
|
||||
}
|
||||
bw.mu.Unlock()
|
||||
for _, a := range add {
|
||||
sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
|
||||
if err != nil {
|
||||
grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
|
||||
} else {
|
||||
bw.mu.Lock()
|
||||
bw.conns[a] = sc
|
||||
bw.connSt[sc] = &scState{
|
||||
addr: resAddrs[a],
|
||||
s: connectivity.Idle,
|
||||
}
|
||||
bw.mu.Unlock()
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
for _, c := range del {
|
||||
bw.cc.RemoveSubConn(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
|
||||
bw.mu.Lock()
|
||||
defer bw.mu.Unlock()
|
||||
scSt, ok := bw.connSt[sc]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if s == connectivity.Idle {
|
||||
sc.Connect()
|
||||
}
|
||||
oldS := scSt.s
|
||||
scSt.s = s
|
||||
if oldS != connectivity.Ready && s == connectivity.Ready {
|
||||
scSt.down = bw.balancer.Up(scSt.addr)
|
||||
} else if oldS == connectivity.Ready && s != connectivity.Ready {
|
||||
if scSt.down != nil {
|
||||
scSt.down(errConnClosing)
|
||||
}
|
||||
}
|
||||
sa := bw.csEvltr.RecordTransition(oldS, s)
|
||||
if bw.state != sa {
|
||||
bw.state = sa
|
||||
}
|
||||
bw.cc.UpdateBalancerState(bw.state, bw)
|
||||
if s == connectivity.Shutdown {
|
||||
// Remove state for this sc.
|
||||
delete(bw.connSt, sc)
|
||||
}
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) HandleResolvedAddrs([]resolver.Address, error) {
|
||||
bw.mu.Lock()
|
||||
defer bw.mu.Unlock()
|
||||
select {
|
||||
case <-bw.startCh:
|
||||
default:
|
||||
close(bw.startCh)
|
||||
}
|
||||
// There should be a resolver inside the balancer.
|
||||
// All updates here, if any, are ignored.
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) Close() {
|
||||
bw.mu.Lock()
|
||||
defer bw.mu.Unlock()
|
||||
select {
|
||||
case <-bw.startCh:
|
||||
default:
|
||||
close(bw.startCh)
|
||||
}
|
||||
bw.balancer.Close()
|
||||
}
|
||||
|
||||
// The picker is the balancerWrapper itself.
|
||||
// It either blocks or returns error, consistent with v1 balancer Get().
|
||||
func (bw *balancerWrapper) Pick(ctx context.Context, opts balancer.PickOptions) (sc balancer.SubConn, done func(balancer.DoneInfo), err error) {
|
||||
failfast := true // Default failfast is true.
|
||||
if ss, ok := rpcInfoFromContext(ctx); ok {
|
||||
failfast = ss.failfast
|
||||
}
|
||||
a, p, err := bw.balancer.Get(ctx, BalancerGetOptions{BlockingWait: !failfast})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if p != nil {
|
||||
done = func(balancer.DoneInfo) { p() }
|
||||
defer func() {
|
||||
if err != nil {
|
||||
p()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
bw.mu.Lock()
|
||||
defer bw.mu.Unlock()
|
||||
if bw.pickfirst {
|
||||
// Get the first sc in conns.
|
||||
for _, sc := range bw.conns {
|
||||
return sc, done, nil
|
||||
}
|
||||
return nil, nil, balancer.ErrNoSubConnAvailable
|
||||
}
|
||||
sc, ok1 := bw.conns[resolver.Address{
|
||||
Addr: a.Addr,
|
||||
Type: resolver.Backend,
|
||||
ServerName: "",
|
||||
Metadata: a.Metadata,
|
||||
}]
|
||||
s, ok2 := bw.connSt[sc]
|
||||
if !ok1 || !ok2 {
|
||||
// This can only happen due to a race where Get() returned an address
|
||||
// that was subsequently removed by Notify. In this case we should
|
||||
// retry always.
|
||||
return nil, nil, balancer.ErrNoSubConnAvailable
|
||||
}
|
||||
switch s.s {
|
||||
case connectivity.Ready, connectivity.Idle:
|
||||
return sc, done, nil
|
||||
case connectivity.Shutdown, connectivity.TransientFailure:
|
||||
// If the returned sc has been shut down or is in transient failure,
|
||||
// return error, and this RPC will fail or wait for another picker (if
|
||||
// non-failfast).
|
||||
return nil, nil, balancer.ErrTransientFailure
|
||||
default:
|
||||
// For other states (connecting or unknown), the v1 balancer would
|
||||
// traditionally wait until ready and then issue the RPC. Returning
|
||||
// ErrNoSubConnAvailable will be a slight improvement in that it will
|
||||
// allow the balancer to choose another address in case others are
|
||||
// connected.
|
||||
return nil, nil, balancer.ErrNoSubConnAvailable
|
||||
}
|
||||
}
|
||||
900
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
Normal file
900
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,900 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: grpc/binarylog/grpc_binarylog_v1/binarylog.proto
|
||||
|
||||
package grpc_binarylog_v1 // import "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import duration "github.com/golang/protobuf/ptypes/duration"
|
||||
import timestamp "github.com/golang/protobuf/ptypes/timestamp"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Enumerates the type of event
|
||||
// Note the terminology is different from the RPC semantics
|
||||
// definition, but the same meaning is expressed here.
|
||||
type GrpcLogEntry_EventType int32
|
||||
|
||||
const (
|
||||
GrpcLogEntry_EVENT_TYPE_UNKNOWN GrpcLogEntry_EventType = 0
|
||||
// Header sent from client to server
|
||||
GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER GrpcLogEntry_EventType = 1
|
||||
// Header sent from server to client
|
||||
GrpcLogEntry_EVENT_TYPE_SERVER_HEADER GrpcLogEntry_EventType = 2
|
||||
// Message sent from client to server
|
||||
GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE GrpcLogEntry_EventType = 3
|
||||
// Message sent from server to client
|
||||
GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE GrpcLogEntry_EventType = 4
|
||||
// A signal that client is done sending
|
||||
GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE GrpcLogEntry_EventType = 5
|
||||
// Trailer indicates the end of the RPC.
|
||||
// On client side, this event means a trailer was either received
|
||||
// from the network or the gRPC library locally generated a status
|
||||
// to inform the application about a failure.
|
||||
// On server side, this event means the server application requested
|
||||
// to send a trailer. Note: EVENT_TYPE_CANCEL may still arrive after
|
||||
// this due to races on server side.
|
||||
GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER GrpcLogEntry_EventType = 6
|
||||
// A signal that the RPC is cancelled. On client side, this
|
||||
// indicates the client application requests a cancellation.
|
||||
// On server side, this indicates that cancellation was detected.
|
||||
// Note: This marks the end of the RPC. Events may arrive after
|
||||
// this due to races. For example, on client side a trailer
|
||||
// may arrive even though the application requested to cancel the RPC.
|
||||
GrpcLogEntry_EVENT_TYPE_CANCEL GrpcLogEntry_EventType = 7
|
||||
)
|
||||
|
||||
var GrpcLogEntry_EventType_name = map[int32]string{
|
||||
0: "EVENT_TYPE_UNKNOWN",
|
||||
1: "EVENT_TYPE_CLIENT_HEADER",
|
||||
2: "EVENT_TYPE_SERVER_HEADER",
|
||||
3: "EVENT_TYPE_CLIENT_MESSAGE",
|
||||
4: "EVENT_TYPE_SERVER_MESSAGE",
|
||||
5: "EVENT_TYPE_CLIENT_HALF_CLOSE",
|
||||
6: "EVENT_TYPE_SERVER_TRAILER",
|
||||
7: "EVENT_TYPE_CANCEL",
|
||||
}
|
||||
var GrpcLogEntry_EventType_value = map[string]int32{
|
||||
"EVENT_TYPE_UNKNOWN": 0,
|
||||
"EVENT_TYPE_CLIENT_HEADER": 1,
|
||||
"EVENT_TYPE_SERVER_HEADER": 2,
|
||||
"EVENT_TYPE_CLIENT_MESSAGE": 3,
|
||||
"EVENT_TYPE_SERVER_MESSAGE": 4,
|
||||
"EVENT_TYPE_CLIENT_HALF_CLOSE": 5,
|
||||
"EVENT_TYPE_SERVER_TRAILER": 6,
|
||||
"EVENT_TYPE_CANCEL": 7,
|
||||
}
|
||||
|
||||
func (x GrpcLogEntry_EventType) String() string {
|
||||
return proto.EnumName(GrpcLogEntry_EventType_name, int32(x))
|
||||
}
|
||||
func (GrpcLogEntry_EventType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 0}
|
||||
}
|
||||
|
||||
// Enumerates the entity that generates the log entry
|
||||
type GrpcLogEntry_Logger int32
|
||||
|
||||
const (
|
||||
GrpcLogEntry_LOGGER_UNKNOWN GrpcLogEntry_Logger = 0
|
||||
GrpcLogEntry_LOGGER_CLIENT GrpcLogEntry_Logger = 1
|
||||
GrpcLogEntry_LOGGER_SERVER GrpcLogEntry_Logger = 2
|
||||
)
|
||||
|
||||
var GrpcLogEntry_Logger_name = map[int32]string{
|
||||
0: "LOGGER_UNKNOWN",
|
||||
1: "LOGGER_CLIENT",
|
||||
2: "LOGGER_SERVER",
|
||||
}
|
||||
var GrpcLogEntry_Logger_value = map[string]int32{
|
||||
"LOGGER_UNKNOWN": 0,
|
||||
"LOGGER_CLIENT": 1,
|
||||
"LOGGER_SERVER": 2,
|
||||
}
|
||||
|
||||
func (x GrpcLogEntry_Logger) String() string {
|
||||
return proto.EnumName(GrpcLogEntry_Logger_name, int32(x))
|
||||
}
|
||||
func (GrpcLogEntry_Logger) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 1}
|
||||
}
|
||||
|
||||
type Address_Type int32
|
||||
|
||||
const (
|
||||
Address_TYPE_UNKNOWN Address_Type = 0
|
||||
// address is in 1.2.3.4 form
|
||||
Address_TYPE_IPV4 Address_Type = 1
|
||||
// address is in IPv6 canonical form (RFC5952 section 4)
|
||||
// The scope is NOT included in the address string.
|
||||
Address_TYPE_IPV6 Address_Type = 2
|
||||
// address is UDS string
|
||||
Address_TYPE_UNIX Address_Type = 3
|
||||
)
|
||||
|
||||
var Address_Type_name = map[int32]string{
|
||||
0: "TYPE_UNKNOWN",
|
||||
1: "TYPE_IPV4",
|
||||
2: "TYPE_IPV6",
|
||||
3: "TYPE_UNIX",
|
||||
}
|
||||
var Address_Type_value = map[string]int32{
|
||||
"TYPE_UNKNOWN": 0,
|
||||
"TYPE_IPV4": 1,
|
||||
"TYPE_IPV6": 2,
|
||||
"TYPE_UNIX": 3,
|
||||
}
|
||||
|
||||
func (x Address_Type) String() string {
|
||||
return proto.EnumName(Address_Type_name, int32(x))
|
||||
}
|
||||
func (Address_Type) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{7, 0}
|
||||
}
|
||||
|
||||
// Log entry we store in binary logs
|
||||
type GrpcLogEntry struct {
|
||||
// The timestamp of the binary log message
|
||||
Timestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||
// Uniquely identifies a call. The value must not be 0 in order to disambiguate
|
||||
// from an unset value.
|
||||
// Each call may have several log entries, they will all have the same call_id.
|
||||
// Nothing is guaranteed about their value other than they are unique across
|
||||
// different RPCs in the same gRPC process.
|
||||
CallId uint64 `protobuf:"varint,2,opt,name=call_id,json=callId,proto3" json:"call_id,omitempty"`
|
||||
// The entry sequence id for this call. The first GrpcLogEntry has a
|
||||
// value of 1, to disambiguate from an unset value. The purpose of
|
||||
// this field is to detect missing entries in environments where
|
||||
// durability or ordering is not guaranteed.
|
||||
SequenceIdWithinCall uint64 `protobuf:"varint,3,opt,name=sequence_id_within_call,json=sequenceIdWithinCall,proto3" json:"sequence_id_within_call,omitempty"`
|
||||
Type GrpcLogEntry_EventType `protobuf:"varint,4,opt,name=type,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_EventType" json:"type,omitempty"`
|
||||
Logger GrpcLogEntry_Logger `protobuf:"varint,5,opt,name=logger,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_Logger" json:"logger,omitempty"`
|
||||
// The logger uses one of the following fields to record the payload,
|
||||
// according to the type of the log entry.
|
||||
//
|
||||
// Types that are valid to be assigned to Payload:
|
||||
// *GrpcLogEntry_ClientHeader
|
||||
// *GrpcLogEntry_ServerHeader
|
||||
// *GrpcLogEntry_Message
|
||||
// *GrpcLogEntry_Trailer
|
||||
Payload isGrpcLogEntry_Payload `protobuf_oneof:"payload"`
|
||||
// true if payload does not represent the full message or metadata.
|
||||
PayloadTruncated bool `protobuf:"varint,10,opt,name=payload_truncated,json=payloadTruncated,proto3" json:"payload_truncated,omitempty"`
|
||||
// Peer address information, will only be recorded on the first
|
||||
// incoming event. On client side, peer is logged on
|
||||
// EVENT_TYPE_SERVER_HEADER normally or EVENT_TYPE_SERVER_TRAILER in
|
||||
// the case of trailers-only. On server side, peer is always
|
||||
// logged on EVENT_TYPE_CLIENT_HEADER.
|
||||
Peer *Address `protobuf:"bytes,11,opt,name=peer,proto3" json:"peer,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) Reset() { *m = GrpcLogEntry{} }
|
||||
func (m *GrpcLogEntry) String() string { return proto.CompactTextString(m) }
|
||||
func (*GrpcLogEntry) ProtoMessage() {}
|
||||
func (*GrpcLogEntry) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{0}
|
||||
}
|
||||
func (m *GrpcLogEntry) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GrpcLogEntry.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GrpcLogEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GrpcLogEntry.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *GrpcLogEntry) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GrpcLogEntry.Merge(dst, src)
|
||||
}
|
||||
func (m *GrpcLogEntry) XXX_Size() int {
|
||||
return xxx_messageInfo_GrpcLogEntry.Size(m)
|
||||
}
|
||||
func (m *GrpcLogEntry) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GrpcLogEntry.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GrpcLogEntry proto.InternalMessageInfo
|
||||
|
||||
func (m *GrpcLogEntry) GetTimestamp() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.Timestamp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetCallId() uint64 {
|
||||
if m != nil {
|
||||
return m.CallId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetSequenceIdWithinCall() uint64 {
|
||||
if m != nil {
|
||||
return m.SequenceIdWithinCall
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetType() GrpcLogEntry_EventType {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return GrpcLogEntry_EVENT_TYPE_UNKNOWN
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetLogger() GrpcLogEntry_Logger {
|
||||
if m != nil {
|
||||
return m.Logger
|
||||
}
|
||||
return GrpcLogEntry_LOGGER_UNKNOWN
|
||||
}
|
||||
|
||||
type isGrpcLogEntry_Payload interface {
|
||||
isGrpcLogEntry_Payload()
|
||||
}
|
||||
|
||||
type GrpcLogEntry_ClientHeader struct {
|
||||
ClientHeader *ClientHeader `protobuf:"bytes,6,opt,name=client_header,json=clientHeader,proto3,oneof"`
|
||||
}
|
||||
|
||||
type GrpcLogEntry_ServerHeader struct {
|
||||
ServerHeader *ServerHeader `protobuf:"bytes,7,opt,name=server_header,json=serverHeader,proto3,oneof"`
|
||||
}
|
||||
|
||||
type GrpcLogEntry_Message struct {
|
||||
Message *Message `protobuf:"bytes,8,opt,name=message,proto3,oneof"`
|
||||
}
|
||||
|
||||
type GrpcLogEntry_Trailer struct {
|
||||
Trailer *Trailer `protobuf:"bytes,9,opt,name=trailer,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*GrpcLogEntry_ClientHeader) isGrpcLogEntry_Payload() {}
|
||||
|
||||
func (*GrpcLogEntry_ServerHeader) isGrpcLogEntry_Payload() {}
|
||||
|
||||
func (*GrpcLogEntry_Message) isGrpcLogEntry_Payload() {}
|
||||
|
||||
func (*GrpcLogEntry_Trailer) isGrpcLogEntry_Payload() {}
|
||||
|
||||
func (m *GrpcLogEntry) GetPayload() isGrpcLogEntry_Payload {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetClientHeader() *ClientHeader {
|
||||
if x, ok := m.GetPayload().(*GrpcLogEntry_ClientHeader); ok {
|
||||
return x.ClientHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetServerHeader() *ServerHeader {
|
||||
if x, ok := m.GetPayload().(*GrpcLogEntry_ServerHeader); ok {
|
||||
return x.ServerHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetMessage() *Message {
|
||||
if x, ok := m.GetPayload().(*GrpcLogEntry_Message); ok {
|
||||
return x.Message
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetTrailer() *Trailer {
|
||||
if x, ok := m.GetPayload().(*GrpcLogEntry_Trailer); ok {
|
||||
return x.Trailer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetPayloadTruncated() bool {
|
||||
if m != nil {
|
||||
return m.PayloadTruncated
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *GrpcLogEntry) GetPeer() *Address {
|
||||
if m != nil {
|
||||
return m.Peer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// XXX_OneofFuncs is for the internal use of the proto package.
|
||||
func (*GrpcLogEntry) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
||||
return _GrpcLogEntry_OneofMarshaler, _GrpcLogEntry_OneofUnmarshaler, _GrpcLogEntry_OneofSizer, []interface{}{
|
||||
(*GrpcLogEntry_ClientHeader)(nil),
|
||||
(*GrpcLogEntry_ServerHeader)(nil),
|
||||
(*GrpcLogEntry_Message)(nil),
|
||||
(*GrpcLogEntry_Trailer)(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func _GrpcLogEntry_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
|
||||
m := msg.(*GrpcLogEntry)
|
||||
// payload
|
||||
switch x := m.Payload.(type) {
|
||||
case *GrpcLogEntry_ClientHeader:
|
||||
b.EncodeVarint(6<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.ClientHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
case *GrpcLogEntry_ServerHeader:
|
||||
b.EncodeVarint(7<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.ServerHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
case *GrpcLogEntry_Message:
|
||||
b.EncodeVarint(8<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.Message); err != nil {
|
||||
return err
|
||||
}
|
||||
case *GrpcLogEntry_Trailer:
|
||||
b.EncodeVarint(9<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.Trailer); err != nil {
|
||||
return err
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
return fmt.Errorf("GrpcLogEntry.Payload has unexpected type %T", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _GrpcLogEntry_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
|
||||
m := msg.(*GrpcLogEntry)
|
||||
switch tag {
|
||||
case 6: // payload.client_header
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(ClientHeader)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Payload = &GrpcLogEntry_ClientHeader{msg}
|
||||
return true, err
|
||||
case 7: // payload.server_header
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(ServerHeader)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Payload = &GrpcLogEntry_ServerHeader{msg}
|
||||
return true, err
|
||||
case 8: // payload.message
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(Message)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Payload = &GrpcLogEntry_Message{msg}
|
||||
return true, err
|
||||
case 9: // payload.trailer
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(Trailer)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Payload = &GrpcLogEntry_Trailer{msg}
|
||||
return true, err
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func _GrpcLogEntry_OneofSizer(msg proto.Message) (n int) {
|
||||
m := msg.(*GrpcLogEntry)
|
||||
// payload
|
||||
switch x := m.Payload.(type) {
|
||||
case *GrpcLogEntry_ClientHeader:
|
||||
s := proto.Size(x.ClientHeader)
|
||||
n += 1 // tag and wire
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case *GrpcLogEntry_ServerHeader:
|
||||
s := proto.Size(x.ServerHeader)
|
||||
n += 1 // tag and wire
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case *GrpcLogEntry_Message:
|
||||
s := proto.Size(x.Message)
|
||||
n += 1 // tag and wire
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case *GrpcLogEntry_Trailer:
|
||||
s := proto.Size(x.Trailer)
|
||||
n += 1 // tag and wire
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case nil:
|
||||
default:
|
||||
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type ClientHeader struct {
|
||||
// This contains only the metadata from the application.
|
||||
Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
// The name of the RPC method, which looks something like:
|
||||
// /<service>/<method>
|
||||
// Note the leading "/" character.
|
||||
MethodName string `protobuf:"bytes,2,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"`
|
||||
// A single process may be used to run multiple virtual
|
||||
// servers with different identities.
|
||||
// The authority is the name of such a server identitiy.
|
||||
// It is typically a portion of the URI in the form of
|
||||
// <host> or <host>:<port> .
|
||||
Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"`
|
||||
// the RPC timeout
|
||||
Timeout *duration.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ClientHeader) Reset() { *m = ClientHeader{} }
|
||||
func (m *ClientHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*ClientHeader) ProtoMessage() {}
|
||||
func (*ClientHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{1}
|
||||
}
|
||||
func (m *ClientHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClientHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ClientHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ClientHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *ClientHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ClientHeader.Merge(dst, src)
|
||||
}
|
||||
func (m *ClientHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_ClientHeader.Size(m)
|
||||
}
|
||||
func (m *ClientHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ClientHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ClientHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *ClientHeader) GetMetadata() *Metadata {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ClientHeader) GetMethodName() string {
|
||||
if m != nil {
|
||||
return m.MethodName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ClientHeader) GetAuthority() string {
|
||||
if m != nil {
|
||||
return m.Authority
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ClientHeader) GetTimeout() *duration.Duration {
|
||||
if m != nil {
|
||||
return m.Timeout
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerHeader struct {
|
||||
// This contains only the metadata from the application.
|
||||
Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ServerHeader) Reset() { *m = ServerHeader{} }
|
||||
func (m *ServerHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*ServerHeader) ProtoMessage() {}
|
||||
func (*ServerHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{2}
|
||||
}
|
||||
func (m *ServerHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ServerHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ServerHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ServerHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *ServerHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ServerHeader.Merge(dst, src)
|
||||
}
|
||||
func (m *ServerHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_ServerHeader.Size(m)
|
||||
}
|
||||
func (m *ServerHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ServerHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ServerHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *ServerHeader) GetMetadata() *Metadata {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Trailer struct {
|
||||
// This contains only the metadata from the application.
|
||||
Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
// The gRPC status code.
|
||||
StatusCode uint32 `protobuf:"varint,2,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
|
||||
// An original status message before any transport specific
|
||||
// encoding.
|
||||
StatusMessage string `protobuf:"bytes,3,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"`
|
||||
// The value of the 'grpc-status-details-bin' metadata key. If
|
||||
// present, this is always an encoded 'google.rpc.Status' message.
|
||||
StatusDetails []byte `protobuf:"bytes,4,opt,name=status_details,json=statusDetails,proto3" json:"status_details,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Trailer) Reset() { *m = Trailer{} }
|
||||
func (m *Trailer) String() string { return proto.CompactTextString(m) }
|
||||
func (*Trailer) ProtoMessage() {}
|
||||
func (*Trailer) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{3}
|
||||
}
|
||||
func (m *Trailer) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Trailer.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Trailer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Trailer.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Trailer) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Trailer.Merge(dst, src)
|
||||
}
|
||||
func (m *Trailer) XXX_Size() int {
|
||||
return xxx_messageInfo_Trailer.Size(m)
|
||||
}
|
||||
func (m *Trailer) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Trailer.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Trailer proto.InternalMessageInfo
|
||||
|
||||
func (m *Trailer) GetMetadata() *Metadata {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Trailer) GetStatusCode() uint32 {
|
||||
if m != nil {
|
||||
return m.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Trailer) GetStatusMessage() string {
|
||||
if m != nil {
|
||||
return m.StatusMessage
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Trailer) GetStatusDetails() []byte {
|
||||
if m != nil {
|
||||
return m.StatusDetails
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Message payload, used by CLIENT_MESSAGE and SERVER_MESSAGE
|
||||
type Message struct {
|
||||
// Length of the message. It may not be the same as the length of the
|
||||
// data field, as the logging payload can be truncated or omitted.
|
||||
Length uint32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
|
||||
// May be truncated or omitted.
|
||||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{4}
|
||||
}
|
||||
func (m *Message) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Message.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Message) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Message.Merge(dst, src)
|
||||
}
|
||||
func (m *Message) XXX_Size() int {
|
||||
return xxx_messageInfo_Message.Size(m)
|
||||
}
|
||||
func (m *Message) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Message.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Message proto.InternalMessageInfo
|
||||
|
||||
func (m *Message) GetLength() uint32 {
|
||||
if m != nil {
|
||||
return m.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Message) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A list of metadata pairs, used in the payload of client header,
|
||||
// server header, and server trailer.
|
||||
// Implementations may omit some entries to honor the header limits
|
||||
// of GRPC_BINARY_LOG_CONFIG.
|
||||
//
|
||||
// Header keys added by gRPC are omitted. To be more specific,
|
||||
// implementations will not log the following entries, and this is
|
||||
// not to be treated as a truncation:
|
||||
// - entries handled by grpc that are not user visible, such as those
|
||||
// that begin with 'grpc-' (with exception of grpc-trace-bin)
|
||||
// or keys like 'lb-token'
|
||||
// - transport specific entries, including but not limited to:
|
||||
// ':path', ':authority', 'content-encoding', 'user-agent', 'te', etc
|
||||
// - entries added for call credentials
|
||||
//
|
||||
// Implementations must always log grpc-trace-bin if it is present.
|
||||
// Practically speaking it will only be visible on server side because
|
||||
// grpc-trace-bin is managed by low level client side mechanisms
|
||||
// inaccessible from the application level. On server side, the
|
||||
// header is just a normal metadata key.
|
||||
// The pair will not count towards the size limit.
|
||||
type Metadata struct {
|
||||
Entry []*MetadataEntry `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Metadata) Reset() { *m = Metadata{} }
|
||||
func (m *Metadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*Metadata) ProtoMessage() {}
|
||||
func (*Metadata) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{5}
|
||||
}
|
||||
func (m *Metadata) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Metadata.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Metadata) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Metadata.Merge(dst, src)
|
||||
}
|
||||
func (m *Metadata) XXX_Size() int {
|
||||
return xxx_messageInfo_Metadata.Size(m)
|
||||
}
|
||||
func (m *Metadata) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Metadata.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Metadata proto.InternalMessageInfo
|
||||
|
||||
func (m *Metadata) GetEntry() []*MetadataEntry {
|
||||
if m != nil {
|
||||
return m.Entry
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A metadata key value pair
|
||||
type MetadataEntry struct {
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MetadataEntry) Reset() { *m = MetadataEntry{} }
|
||||
func (m *MetadataEntry) String() string { return proto.CompactTextString(m) }
|
||||
func (*MetadataEntry) ProtoMessage() {}
|
||||
func (*MetadataEntry) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{6}
|
||||
}
|
||||
func (m *MetadataEntry) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MetadataEntry.Unmarshal(m, b)
|
||||
}
|
||||
func (m *MetadataEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_MetadataEntry.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *MetadataEntry) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MetadataEntry.Merge(dst, src)
|
||||
}
|
||||
func (m *MetadataEntry) XXX_Size() int {
|
||||
return xxx_messageInfo_MetadataEntry.Size(m)
|
||||
}
|
||||
func (m *MetadataEntry) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MetadataEntry.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MetadataEntry proto.InternalMessageInfo
|
||||
|
||||
func (m *MetadataEntry) GetKey() string {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MetadataEntry) GetValue() []byte {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Address information
|
||||
type Address struct {
|
||||
Type Address_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.binarylog.v1.Address_Type" json:"type,omitempty"`
|
||||
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
|
||||
// only for TYPE_IPV4 and TYPE_IPV6
|
||||
IpPort uint32 `protobuf:"varint,3,opt,name=ip_port,json=ipPort,proto3" json:"ip_port,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Address) Reset() { *m = Address{} }
|
||||
func (m *Address) String() string { return proto.CompactTextString(m) }
|
||||
func (*Address) ProtoMessage() {}
|
||||
func (*Address) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_binarylog_264c8c9c551ce911, []int{7}
|
||||
}
|
||||
func (m *Address) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Address.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Address.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Address) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Address.Merge(dst, src)
|
||||
}
|
||||
func (m *Address) XXX_Size() int {
|
||||
return xxx_messageInfo_Address.Size(m)
|
||||
}
|
||||
func (m *Address) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Address.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Address proto.InternalMessageInfo
|
||||
|
||||
func (m *Address) GetType() Address_Type {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return Address_TYPE_UNKNOWN
|
||||
}
|
||||
|
||||
func (m *Address) GetAddress() string {
|
||||
if m != nil {
|
||||
return m.Address
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetIpPort() uint32 {
|
||||
if m != nil {
|
||||
return m.IpPort
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GrpcLogEntry)(nil), "grpc.binarylog.v1.GrpcLogEntry")
|
||||
proto.RegisterType((*ClientHeader)(nil), "grpc.binarylog.v1.ClientHeader")
|
||||
proto.RegisterType((*ServerHeader)(nil), "grpc.binarylog.v1.ServerHeader")
|
||||
proto.RegisterType((*Trailer)(nil), "grpc.binarylog.v1.Trailer")
|
||||
proto.RegisterType((*Message)(nil), "grpc.binarylog.v1.Message")
|
||||
proto.RegisterType((*Metadata)(nil), "grpc.binarylog.v1.Metadata")
|
||||
proto.RegisterType((*MetadataEntry)(nil), "grpc.binarylog.v1.MetadataEntry")
|
||||
proto.RegisterType((*Address)(nil), "grpc.binarylog.v1.Address")
|
||||
proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_EventType", GrpcLogEntry_EventType_name, GrpcLogEntry_EventType_value)
|
||||
proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_Logger", GrpcLogEntry_Logger_name, GrpcLogEntry_Logger_value)
|
||||
proto.RegisterEnum("grpc.binarylog.v1.Address_Type", Address_Type_name, Address_Type_value)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("grpc/binarylog/grpc_binarylog_v1/binarylog.proto", fileDescriptor_binarylog_264c8c9c551ce911)
|
||||
}
|
||||
|
||||
var fileDescriptor_binarylog_264c8c9c551ce911 = []byte{
|
||||
// 900 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x51, 0x6f, 0xe3, 0x44,
|
||||
0x10, 0x3e, 0x37, 0x69, 0xdc, 0x4c, 0x92, 0xca, 0x5d, 0x95, 0x3b, 0x5f, 0x29, 0x34, 0xb2, 0x04,
|
||||
0x0a, 0x42, 0x72, 0xb9, 0x94, 0xeb, 0xf1, 0x02, 0x52, 0x92, 0xfa, 0xd2, 0x88, 0x5c, 0x1a, 0x6d,
|
||||
0x72, 0x3d, 0x40, 0x48, 0xd6, 0x36, 0x5e, 0x1c, 0x0b, 0xc7, 0x6b, 0xd6, 0x9b, 0xa0, 0xfc, 0x2c,
|
||||
0xde, 0x90, 0xee, 0x77, 0xf1, 0x8e, 0xbc, 0x6b, 0x27, 0xa6, 0x69, 0x0f, 0x09, 0xde, 0x3c, 0xdf,
|
||||
0x7c, 0xf3, 0xcd, 0xee, 0x78, 0x66, 0x16, 0xbe, 0xf2, 0x79, 0x3c, 0x3b, 0xbf, 0x0b, 0x22, 0xc2,
|
||||
0xd7, 0x21, 0xf3, 0xcf, 0x53, 0xd3, 0xdd, 0x98, 0xee, 0xea, 0xc5, 0xd6, 0x67, 0xc7, 0x9c, 0x09,
|
||||
0x86, 0x8e, 0x52, 0x8a, 0xbd, 0x45, 0x57, 0x2f, 0x4e, 0x3e, 0xf5, 0x19, 0xf3, 0x43, 0x7a, 0x2e,
|
||||
0x09, 0x77, 0xcb, 0x5f, 0xce, 0xbd, 0x25, 0x27, 0x22, 0x60, 0x91, 0x0a, 0x39, 0x39, 0xbb, 0xef,
|
||||
0x17, 0xc1, 0x82, 0x26, 0x82, 0x2c, 0x62, 0x45, 0xb0, 0xde, 0xeb, 0x50, 0xef, 0xf3, 0x78, 0x36,
|
||||
0x64, 0xbe, 0x13, 0x09, 0xbe, 0x46, 0xdf, 0x40, 0x75, 0xc3, 0x31, 0xb5, 0xa6, 0xd6, 0xaa, 0xb5,
|
||||
0x4f, 0x6c, 0xa5, 0x62, 0xe7, 0x2a, 0xf6, 0x34, 0x67, 0xe0, 0x2d, 0x19, 0x3d, 0x03, 0x7d, 0x46,
|
||||
0xc2, 0xd0, 0x0d, 0x3c, 0x73, 0xaf, 0xa9, 0xb5, 0xca, 0xb8, 0x92, 0x9a, 0x03, 0x0f, 0xbd, 0x84,
|
||||
0x67, 0x09, 0xfd, 0x6d, 0x49, 0xa3, 0x19, 0x75, 0x03, 0xcf, 0xfd, 0x3d, 0x10, 0xf3, 0x20, 0x72,
|
||||
0x53, 0xa7, 0x59, 0x92, 0xc4, 0xe3, 0xdc, 0x3d, 0xf0, 0xde, 0x49, 0x67, 0x8f, 0x84, 0x21, 0xfa,
|
||||
0x16, 0xca, 0x62, 0x1d, 0x53, 0xb3, 0xdc, 0xd4, 0x5a, 0x87, 0xed, 0x2f, 0xec, 0x9d, 0xdb, 0xdb,
|
||||
0xc5, 0x83, 0xdb, 0xce, 0x8a, 0x46, 0x62, 0xba, 0x8e, 0x29, 0x96, 0x61, 0xe8, 0x3b, 0xa8, 0x84,
|
||||
0xcc, 0xf7, 0x29, 0x37, 0xf7, 0xa5, 0xc0, 0xe7, 0xff, 0x26, 0x30, 0x94, 0x6c, 0x9c, 0x45, 0xa1,
|
||||
0xd7, 0xd0, 0x98, 0x85, 0x01, 0x8d, 0x84, 0x3b, 0xa7, 0xc4, 0xa3, 0xdc, 0xac, 0xc8, 0x62, 0x9c,
|
||||
0x3d, 0x20, 0xd3, 0x93, 0xbc, 0x6b, 0x49, 0xbb, 0x7e, 0x82, 0xeb, 0xb3, 0x82, 0x9d, 0xea, 0x24,
|
||||
0x94, 0xaf, 0x28, 0xcf, 0x75, 0xf4, 0x47, 0x75, 0x26, 0x92, 0xb7, 0xd5, 0x49, 0x0a, 0x36, 0xba,
|
||||
0x04, 0x7d, 0x41, 0x93, 0x84, 0xf8, 0xd4, 0x3c, 0xc8, 0x7f, 0xcb, 0x8e, 0xc2, 0x1b, 0xc5, 0xb8,
|
||||
0x7e, 0x82, 0x73, 0x72, 0x1a, 0x27, 0x38, 0x09, 0x42, 0xca, 0xcd, 0xea, 0xa3, 0x71, 0x53, 0xc5,
|
||||
0x48, 0xe3, 0x32, 0x32, 0xfa, 0x12, 0x8e, 0x62, 0xb2, 0x0e, 0x19, 0xf1, 0x5c, 0xc1, 0x97, 0xd1,
|
||||
0x8c, 0x08, 0xea, 0x99, 0xd0, 0xd4, 0x5a, 0x07, 0xd8, 0xc8, 0x1c, 0xd3, 0x1c, 0x47, 0x36, 0x94,
|
||||
0x63, 0x4a, 0xb9, 0x59, 0x7b, 0x34, 0x43, 0xc7, 0xf3, 0x38, 0x4d, 0x12, 0x2c, 0x79, 0xd6, 0x5f,
|
||||
0x1a, 0x54, 0x37, 0x3f, 0x0c, 0x3d, 0x05, 0xe4, 0xdc, 0x3a, 0xa3, 0xa9, 0x3b, 0xfd, 0x71, 0xec,
|
||||
0xb8, 0x6f, 0x47, 0xdf, 0x8f, 0x6e, 0xde, 0x8d, 0x8c, 0x27, 0xe8, 0x14, 0xcc, 0x02, 0xde, 0x1b,
|
||||
0x0e, 0xd2, 0xef, 0x6b, 0xa7, 0x73, 0xe5, 0x60, 0x43, 0xbb, 0xe7, 0x9d, 0x38, 0xf8, 0xd6, 0xc1,
|
||||
0xb9, 0x77, 0x0f, 0x7d, 0x02, 0xcf, 0x77, 0x63, 0xdf, 0x38, 0x93, 0x49, 0xa7, 0xef, 0x18, 0xa5,
|
||||
0x7b, 0xee, 0x2c, 0x38, 0x77, 0x97, 0x51, 0x13, 0x4e, 0x1f, 0xc8, 0xdc, 0x19, 0xbe, 0x76, 0x7b,
|
||||
0xc3, 0x9b, 0x89, 0x63, 0xec, 0x3f, 0x2c, 0x30, 0xc5, 0x9d, 0xc1, 0xd0, 0xc1, 0x46, 0x05, 0x7d,
|
||||
0x04, 0x47, 0x45, 0x81, 0xce, 0xa8, 0xe7, 0x0c, 0x0d, 0xdd, 0xea, 0x42, 0x45, 0xb5, 0x19, 0x42,
|
||||
0x70, 0x38, 0xbc, 0xe9, 0xf7, 0x1d, 0x5c, 0xb8, 0xef, 0x11, 0x34, 0x32, 0x4c, 0x65, 0x34, 0xb4,
|
||||
0x02, 0xa4, 0x52, 0x18, 0x7b, 0xdd, 0x2a, 0xe8, 0x59, 0xfd, 0xad, 0xf7, 0x1a, 0xd4, 0x8b, 0xcd,
|
||||
0x87, 0x5e, 0xc1, 0xc1, 0x82, 0x0a, 0xe2, 0x11, 0x41, 0xb2, 0xe1, 0xfd, 0xf8, 0xc1, 0x2e, 0x51,
|
||||
0x14, 0xbc, 0x21, 0xa3, 0x33, 0xa8, 0x2d, 0xa8, 0x98, 0x33, 0xcf, 0x8d, 0xc8, 0x82, 0xca, 0x01,
|
||||
0xae, 0x62, 0x50, 0xd0, 0x88, 0x2c, 0x28, 0x3a, 0x85, 0x2a, 0x59, 0x8a, 0x39, 0xe3, 0x81, 0x58,
|
||||
0xcb, 0xb1, 0xad, 0xe2, 0x2d, 0x80, 0x2e, 0x40, 0x4f, 0x17, 0x01, 0x5b, 0x0a, 0x39, 0xae, 0xb5,
|
||||
0xf6, 0xf3, 0x9d, 0x9d, 0x71, 0x95, 0x6d, 0x26, 0x9c, 0x33, 0xad, 0x3e, 0xd4, 0x8b, 0x1d, 0xff,
|
||||
0x9f, 0x0f, 0x6f, 0xfd, 0xa1, 0x81, 0x9e, 0x75, 0xf0, 0xff, 0xaa, 0x40, 0x22, 0x88, 0x58, 0x26,
|
||||
0xee, 0x8c, 0x79, 0xaa, 0x02, 0x0d, 0x0c, 0x0a, 0xea, 0x31, 0x8f, 0xa2, 0xcf, 0xe0, 0x30, 0x23,
|
||||
0xe4, 0x73, 0xa8, 0xca, 0xd0, 0x50, 0x68, 0x36, 0x7a, 0x05, 0x9a, 0x47, 0x05, 0x09, 0xc2, 0x44,
|
||||
0x56, 0xa4, 0x9e, 0xd3, 0xae, 0x14, 0x68, 0xbd, 0x04, 0x3d, 0x8f, 0x78, 0x0a, 0x95, 0x90, 0x46,
|
||||
0xbe, 0x98, 0xcb, 0x03, 0x37, 0x70, 0x66, 0x21, 0x04, 0x65, 0x79, 0x8d, 0x3d, 0x19, 0x2f, 0xbf,
|
||||
0xad, 0x2e, 0x1c, 0xe4, 0x67, 0x47, 0x97, 0xb0, 0x4f, 0xd3, 0xcd, 0x65, 0x6a, 0xcd, 0x52, 0xab,
|
||||
0xd6, 0x6e, 0x7e, 0xe0, 0x9e, 0x72, 0xc3, 0x61, 0x45, 0xb7, 0x5e, 0x41, 0xe3, 0x1f, 0x38, 0x32,
|
||||
0xa0, 0xf4, 0x2b, 0x5d, 0xcb, 0xec, 0x55, 0x9c, 0x7e, 0xa2, 0x63, 0xd8, 0x5f, 0x91, 0x70, 0x49,
|
||||
0xb3, 0xdc, 0xca, 0xb0, 0xfe, 0xd4, 0x40, 0xcf, 0xe6, 0x18, 0x5d, 0x64, 0xdb, 0x59, 0x93, 0xcb,
|
||||
0xf5, 0xec, 0xf1, 0x89, 0xb7, 0x0b, 0x3b, 0xd9, 0x04, 0x9d, 0x28, 0x34, 0xeb, 0xb0, 0xdc, 0x4c,
|
||||
0x1f, 0x8f, 0x20, 0x76, 0x63, 0xc6, 0x85, 0xac, 0x6a, 0x03, 0x57, 0x82, 0x78, 0xcc, 0xb8, 0xb0,
|
||||
0x1c, 0x28, 0xcb, 0x1d, 0x61, 0x40, 0xfd, 0xde, 0x76, 0x68, 0x40, 0x55, 0x22, 0x83, 0xf1, 0xed,
|
||||
0xd7, 0x86, 0x56, 0x34, 0x2f, 0x8d, 0xbd, 0x8d, 0xf9, 0x76, 0x34, 0xf8, 0xc1, 0x28, 0x75, 0x7f,
|
||||
0x86, 0xe3, 0x80, 0xed, 0x1e, 0xb2, 0x7b, 0xd8, 0x95, 0xd6, 0x90, 0xf9, 0xe3, 0xb4, 0x51, 0xc7,
|
||||
0xda, 0x4f, 0xed, 0xac, 0x71, 0x7d, 0x16, 0x92, 0xc8, 0xb7, 0x19, 0x57, 0x4f, 0xf3, 0x87, 0x5e,
|
||||
0xea, 0xbb, 0x8a, 0xec, 0xf2, 0x8b, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xf6, 0x4b, 0x50,
|
||||
0xd4, 0x07, 0x00, 0x00,
|
||||
}
|
||||
74
vendor/google.golang.org/grpc/call.go
generated
vendored
Normal file
74
vendor/google.golang.org/grpc/call.go
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Invoke sends the RPC request on the wire and returns after response is
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// All errors returned by Invoke are compatible with the status package.
|
||||
func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
|
||||
// allow interceptor to see all applicable call options, which means those
|
||||
// configured as defaults from dial option as well as per-call options
|
||||
opts = combine(cc.dopts.callOptions, opts)
|
||||
|
||||
if cc.dopts.unaryInt != nil {
|
||||
return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
|
||||
}
|
||||
return invoke(ctx, method, args, reply, cc, opts...)
|
||||
}
|
||||
|
||||
func combine(o1 []CallOption, o2 []CallOption) []CallOption {
|
||||
// we don't use append because o1 could have extra capacity whose
|
||||
// elements would be overwritten, which could cause inadvertent
|
||||
// sharing (and race conditions) between concurrent calls
|
||||
if len(o1) == 0 {
|
||||
return o2
|
||||
} else if len(o2) == 0 {
|
||||
return o1
|
||||
}
|
||||
ret := make([]CallOption, len(o1)+len(o2))
|
||||
copy(ret, o1)
|
||||
copy(ret[len(o1):], o2)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Invoke sends the RPC request on the wire and returns after response is
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// DEPRECATED: Use ClientConn.Invoke instead.
|
||||
func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
|
||||
return cc.Invoke(ctx, method, args, reply, opts...)
|
||||
}
|
||||
|
||||
var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
|
||||
|
||||
func invoke(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
|
||||
cs, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.SendMsg(req); err != nil {
|
||||
return err
|
||||
}
|
||||
return cs.RecvMsg(reply)
|
||||
}
|
||||
1447
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
Normal file
1447
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
50
vendor/google.golang.org/grpc/codec.go
generated
vendored
Normal file
50
vendor/google.golang.org/grpc/codec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/encoding"
|
||||
_ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
|
||||
)
|
||||
|
||||
// baseCodec contains the functionality of both Codec and encoding.Codec, but
|
||||
// omits the name/string, which vary between the two and are not needed for
|
||||
// anything besides the registry in the encoding package.
|
||||
type baseCodec interface {
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
}
|
||||
|
||||
var _ baseCodec = Codec(nil)
|
||||
var _ baseCodec = encoding.Codec(nil)
|
||||
|
||||
// Codec defines the interface gRPC uses to encode and decode messages.
|
||||
// Note that implementations of this interface must be thread safe;
|
||||
// a Codec's methods can be called from concurrent goroutines.
|
||||
//
|
||||
// Deprecated: use encoding.Codec instead.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
// String returns the name of the Codec implementation. This is unused by
|
||||
// gRPC.
|
||||
String() string
|
||||
}
|
||||
17
vendor/google.golang.org/grpc/codegen.sh
generated
vendored
Executable file
17
vendor/google.golang.org/grpc/codegen.sh
generated
vendored
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This script serves as an example to demonstrate how to generate the gRPC-Go
|
||||
# interface and the related messages from .proto file.
|
||||
#
|
||||
# It assumes the installation of i) Google proto buffer compiler at
|
||||
# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen
|
||||
# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have
|
||||
# not, please install them first.
|
||||
#
|
||||
# We recommend running this script at $GOPATH/src.
|
||||
#
|
||||
# If this is not what you need, feel free to make your own scripts. Again, this
|
||||
# script is for demonstration purpose.
|
||||
#
|
||||
proto=$1
|
||||
protoc --go_out=plugins=grpc:. $proto
|
||||
62
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
Normal file
62
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package codes
|
||||
|
||||
import "strconv"
|
||||
|
||||
func (c Code) String() string {
|
||||
switch c {
|
||||
case OK:
|
||||
return "OK"
|
||||
case Canceled:
|
||||
return "Canceled"
|
||||
case Unknown:
|
||||
return "Unknown"
|
||||
case InvalidArgument:
|
||||
return "InvalidArgument"
|
||||
case DeadlineExceeded:
|
||||
return "DeadlineExceeded"
|
||||
case NotFound:
|
||||
return "NotFound"
|
||||
case AlreadyExists:
|
||||
return "AlreadyExists"
|
||||
case PermissionDenied:
|
||||
return "PermissionDenied"
|
||||
case ResourceExhausted:
|
||||
return "ResourceExhausted"
|
||||
case FailedPrecondition:
|
||||
return "FailedPrecondition"
|
||||
case Aborted:
|
||||
return "Aborted"
|
||||
case OutOfRange:
|
||||
return "OutOfRange"
|
||||
case Unimplemented:
|
||||
return "Unimplemented"
|
||||
case Internal:
|
||||
return "Internal"
|
||||
case Unavailable:
|
||||
return "Unavailable"
|
||||
case DataLoss:
|
||||
return "DataLoss"
|
||||
case Unauthenticated:
|
||||
return "Unauthenticated"
|
||||
default:
|
||||
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
||||
198
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
Normal file
198
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package codes defines the canonical error codes used by gRPC. It is
|
||||
// consistent across various languages.
|
||||
package codes // import "google.golang.org/grpc/codes"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
|
||||
type Code uint32
|
||||
|
||||
const (
|
||||
// OK is returned on success.
|
||||
OK Code = 0
|
||||
|
||||
// Canceled indicates the operation was canceled (typically by the caller).
|
||||
Canceled Code = 1
|
||||
|
||||
// Unknown error. An example of where this error may be returned is
|
||||
// if a Status value received from another address space belongs to
|
||||
// an error-space that is not known in this address space. Also
|
||||
// errors raised by APIs that do not return enough error information
|
||||
// may be converted to this error.
|
||||
Unknown Code = 2
|
||||
|
||||
// InvalidArgument indicates client specified an invalid argument.
|
||||
// Note that this differs from FailedPrecondition. It indicates arguments
|
||||
// that are problematic regardless of the state of the system
|
||||
// (e.g., a malformed file name).
|
||||
InvalidArgument Code = 3
|
||||
|
||||
// DeadlineExceeded means operation expired before completion.
|
||||
// For operations that change the state of the system, this error may be
|
||||
// returned even if the operation has completed successfully. For
|
||||
// example, a successful response from a server could have been delayed
|
||||
// long enough for the deadline to expire.
|
||||
DeadlineExceeded Code = 4
|
||||
|
||||
// NotFound means some requested entity (e.g., file or directory) was
|
||||
// not found.
|
||||
NotFound Code = 5
|
||||
|
||||
// AlreadyExists means an attempt to create an entity failed because one
|
||||
// already exists.
|
||||
AlreadyExists Code = 6
|
||||
|
||||
// PermissionDenied indicates the caller does not have permission to
|
||||
// execute the specified operation. It must not be used for rejections
|
||||
// caused by exhausting some resource (use ResourceExhausted
|
||||
// instead for those errors). It must not be
|
||||
// used if the caller cannot be identified (use Unauthenticated
|
||||
// instead for those errors).
|
||||
PermissionDenied Code = 7
|
||||
|
||||
// ResourceExhausted indicates some resource has been exhausted, perhaps
|
||||
// a per-user quota, or perhaps the entire file system is out of space.
|
||||
ResourceExhausted Code = 8
|
||||
|
||||
// FailedPrecondition indicates operation was rejected because the
|
||||
// system is not in a state required for the operation's execution.
|
||||
// For example, directory to be deleted may be non-empty, an rmdir
|
||||
// operation is applied to a non-directory, etc.
|
||||
//
|
||||
// A litmus test that may help a service implementor in deciding
|
||||
// between FailedPrecondition, Aborted, and Unavailable:
|
||||
// (a) Use Unavailable if the client can retry just the failing call.
|
||||
// (b) Use Aborted if the client should retry at a higher-level
|
||||
// (e.g., restarting a read-modify-write sequence).
|
||||
// (c) Use FailedPrecondition if the client should not retry until
|
||||
// the system state has been explicitly fixed. E.g., if an "rmdir"
|
||||
// fails because the directory is non-empty, FailedPrecondition
|
||||
// should be returned since the client should not retry unless
|
||||
// they have first fixed up the directory by deleting files from it.
|
||||
// (d) Use FailedPrecondition if the client performs conditional
|
||||
// REST Get/Update/Delete on a resource and the resource on the
|
||||
// server does not match the condition. E.g., conflicting
|
||||
// read-modify-write on the same resource.
|
||||
FailedPrecondition Code = 9
|
||||
|
||||
// Aborted indicates the operation was aborted, typically due to a
|
||||
// concurrency issue like sequencer check failures, transaction aborts,
|
||||
// etc.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
Aborted Code = 10
|
||||
|
||||
// OutOfRange means operation was attempted past the valid range.
|
||||
// E.g., seeking or reading past end of file.
|
||||
//
|
||||
// Unlike InvalidArgument, this error indicates a problem that may
|
||||
// be fixed if the system state changes. For example, a 32-bit file
|
||||
// system will generate InvalidArgument if asked to read at an
|
||||
// offset that is not in the range [0,2^32-1], but it will generate
|
||||
// OutOfRange if asked to read from an offset past the current
|
||||
// file size.
|
||||
//
|
||||
// There is a fair bit of overlap between FailedPrecondition and
|
||||
// OutOfRange. We recommend using OutOfRange (the more specific
|
||||
// error) when it applies so that callers who are iterating through
|
||||
// a space can easily look for an OutOfRange error to detect when
|
||||
// they are done.
|
||||
OutOfRange Code = 11
|
||||
|
||||
// Unimplemented indicates operation is not implemented or not
|
||||
// supported/enabled in this service.
|
||||
Unimplemented Code = 12
|
||||
|
||||
// Internal errors. Means some invariants expected by underlying
|
||||
// system has been broken. If you see one of these errors,
|
||||
// something is very broken.
|
||||
Internal Code = 13
|
||||
|
||||
// Unavailable indicates the service is currently unavailable.
|
||||
// This is a most likely a transient condition and may be corrected
|
||||
// by retrying with a backoff. Note that it is not always safe to retry
|
||||
// non-idempotent operations.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
Unavailable Code = 14
|
||||
|
||||
// DataLoss indicates unrecoverable data loss or corruption.
|
||||
DataLoss Code = 15
|
||||
|
||||
// Unauthenticated indicates the request does not have valid
|
||||
// authentication credentials for the operation.
|
||||
Unauthenticated Code = 16
|
||||
|
||||
_maxCode = 17
|
||||
)
|
||||
|
||||
var strToCode = map[string]Code{
|
||||
`"OK"`: OK,
|
||||
`"CANCELLED"`:/* [sic] */ Canceled,
|
||||
`"UNKNOWN"`: Unknown,
|
||||
`"INVALID_ARGUMENT"`: InvalidArgument,
|
||||
`"DEADLINE_EXCEEDED"`: DeadlineExceeded,
|
||||
`"NOT_FOUND"`: NotFound,
|
||||
`"ALREADY_EXISTS"`: AlreadyExists,
|
||||
`"PERMISSION_DENIED"`: PermissionDenied,
|
||||
`"RESOURCE_EXHAUSTED"`: ResourceExhausted,
|
||||
`"FAILED_PRECONDITION"`: FailedPrecondition,
|
||||
`"ABORTED"`: Aborted,
|
||||
`"OUT_OF_RANGE"`: OutOfRange,
|
||||
`"UNIMPLEMENTED"`: Unimplemented,
|
||||
`"INTERNAL"`: Internal,
|
||||
`"UNAVAILABLE"`: Unavailable,
|
||||
`"DATA_LOSS"`: DataLoss,
|
||||
`"UNAUTHENTICATED"`: Unauthenticated,
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals b into the Code.
|
||||
func (c *Code) UnmarshalJSON(b []byte) error {
|
||||
// From json.Unmarshaler: By convention, to approximate the behavior of
|
||||
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
|
||||
// a no-op.
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
if c == nil {
|
||||
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
|
||||
}
|
||||
|
||||
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
|
||||
if ci >= _maxCode {
|
||||
return fmt.Errorf("invalid code: %q", ci)
|
||||
}
|
||||
|
||||
*c = Code(ci)
|
||||
return nil
|
||||
}
|
||||
|
||||
if jc, ok := strToCode[string(b)]; ok {
|
||||
*c = jc
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid code: %q", string(b))
|
||||
}
|
||||
73
vendor/google.golang.org/grpc/connectivity/connectivity.go
generated
vendored
Normal file
73
vendor/google.golang.org/grpc/connectivity/connectivity.go
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package connectivity defines connectivity semantics.
|
||||
// For details, see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md.
|
||||
// All APIs in this package are experimental.
|
||||
package connectivity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// State indicates the state of connectivity.
|
||||
// It can be the state of a ClientConn or SubConn.
|
||||
type State int
|
||||
|
||||
func (s State) String() string {
|
||||
switch s {
|
||||
case Idle:
|
||||
return "IDLE"
|
||||
case Connecting:
|
||||
return "CONNECTING"
|
||||
case Ready:
|
||||
return "READY"
|
||||
case TransientFailure:
|
||||
return "TRANSIENT_FAILURE"
|
||||
case Shutdown:
|
||||
return "SHUTDOWN"
|
||||
default:
|
||||
grpclog.Errorf("unknown connectivity state: %d", s)
|
||||
return "Invalid-State"
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// Idle indicates the ClientConn is idle.
|
||||
Idle State = iota
|
||||
// Connecting indicates the ClientConn is connecting.
|
||||
Connecting
|
||||
// Ready indicates the ClientConn is ready for work.
|
||||
Ready
|
||||
// TransientFailure indicates the ClientConn has seen a failure but expects to recover.
|
||||
TransientFailure
|
||||
// Shutdown indicates the ClientConn has started shutting down.
|
||||
Shutdown
|
||||
)
|
||||
|
||||
// Reporter reports the connectivity states.
|
||||
type Reporter interface {
|
||||
// CurrentState returns the current state of the reporter.
|
||||
CurrentState() State
|
||||
// WaitForStateChange blocks until the reporter's state is different from the given state,
|
||||
// and returns true.
|
||||
// It returns false if <-ctx.Done() can proceed (ctx got timeout or got canceled).
|
||||
WaitForStateChange(context.Context, State) bool
|
||||
}
|
||||
336
vendor/google.golang.org/grpc/credentials/credentials.go
generated
vendored
Normal file
336
vendor/google.golang.org/grpc/credentials/credentials.go
generated
vendored
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package credentials implements various credentials supported by gRPC library,
|
||||
// which encapsulate all the state needed by a client to authenticate with a
|
||||
// server and make various assertions, e.g., about the client's identity, role,
|
||||
// or whether it is authorized to make a particular call.
|
||||
package credentials // import "google.golang.org/grpc/credentials"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/grpc/credentials/internal"
|
||||
)
|
||||
|
||||
// PerRPCCredentials defines the common interface for the credentials which need to
|
||||
// attach security information to every RPC (e.g., oauth2).
|
||||
type PerRPCCredentials interface {
|
||||
// GetRequestMetadata gets the current request metadata, refreshing
|
||||
// tokens if required. This should be called by the transport layer on
|
||||
// each request, and the data should be populated in headers or other
|
||||
// context. If a status code is returned, it will be used as the status
|
||||
// for the RPC. uri is the URI of the entry point for the request.
|
||||
// When supported by the underlying implementation, ctx can be used for
|
||||
// timeout and cancellation.
|
||||
// TODO(zhaoq): Define the set of the qualified keys instead of leaving
|
||||
// it as an arbitrary string.
|
||||
GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
|
||||
// RequireTransportSecurity indicates whether the credentials requires
|
||||
// transport security.
|
||||
RequireTransportSecurity() bool
|
||||
}
|
||||
|
||||
// ProtocolInfo provides information regarding the gRPC wire protocol version,
|
||||
// security protocol, security protocol version in use, server name, etc.
|
||||
type ProtocolInfo struct {
|
||||
// ProtocolVersion is the gRPC wire protocol version.
|
||||
ProtocolVersion string
|
||||
// SecurityProtocol is the security protocol in use.
|
||||
SecurityProtocol string
|
||||
// SecurityVersion is the security protocol version.
|
||||
SecurityVersion string
|
||||
// ServerName is the user-configured server name.
|
||||
ServerName string
|
||||
}
|
||||
|
||||
// AuthInfo defines the common interface for the auth information the users are interested in.
|
||||
type AuthInfo interface {
|
||||
AuthType() string
|
||||
}
|
||||
|
||||
// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
|
||||
// and the caller should not close rawConn.
|
||||
var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
|
||||
|
||||
// TransportCredentials defines the common interface for all the live gRPC wire
|
||||
// protocols and supported transport security protocols (e.g., TLS, SSL).
|
||||
type TransportCredentials interface {
|
||||
// ClientHandshake does the authentication handshake specified by the corresponding
|
||||
// authentication protocol on rawConn for clients. It returns the authenticated
|
||||
// connection and the corresponding auth information about the connection.
|
||||
// Implementations must use the provided context to implement timely cancellation.
|
||||
// gRPC will try to reconnect if the error returned is a temporary error
|
||||
// (io.EOF, context.DeadlineExceeded or err.Temporary() == true).
|
||||
// If the returned error is a wrapper error, implementations should make sure that
|
||||
// the error implements Temporary() to have the correct retry behaviors.
|
||||
//
|
||||
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
||||
ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
|
||||
// ServerHandshake does the authentication handshake for servers. It returns
|
||||
// the authenticated connection and the corresponding auth information about
|
||||
// the connection.
|
||||
//
|
||||
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
||||
ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
|
||||
// Info provides the ProtocolInfo of this TransportCredentials.
|
||||
Info() ProtocolInfo
|
||||
// Clone makes a copy of this TransportCredentials.
|
||||
Clone() TransportCredentials
|
||||
// OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
|
||||
// gRPC internals also use it to override the virtual hosting name if it is set.
|
||||
// It must be called before dialing. Currently, this is only used by grpclb.
|
||||
OverrideServerName(string) error
|
||||
}
|
||||
|
||||
// Bundle is a combination of TransportCredentials and PerRPCCredentials.
|
||||
//
|
||||
// It also contains a mode switching method, so it can be used as a combination
|
||||
// of different credential policies.
|
||||
//
|
||||
// Bundle cannot be used together with individual TransportCredentials.
|
||||
// PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
|
||||
//
|
||||
// This API is experimental.
|
||||
type Bundle interface {
|
||||
TransportCredentials() TransportCredentials
|
||||
PerRPCCredentials() PerRPCCredentials
|
||||
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
|
||||
// existing Bundle may cause races.
|
||||
//
|
||||
// NewWithMode returns nil if the requested mode is not supported.
|
||||
NewWithMode(mode string) (Bundle, error)
|
||||
}
|
||||
|
||||
// TLSInfo contains the auth information for a TLS authenticated connection.
|
||||
// It implements the AuthInfo interface.
|
||||
type TLSInfo struct {
|
||||
State tls.ConnectionState
|
||||
}
|
||||
|
||||
// AuthType returns the type of TLSInfo as a string.
|
||||
func (t TLSInfo) AuthType() string {
|
||||
return "tls"
|
||||
}
|
||||
|
||||
// GetSecurityValue returns security info requested by channelz.
|
||||
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
|
||||
v := &TLSChannelzSecurityValue{
|
||||
StandardName: cipherSuiteLookup[t.State.CipherSuite],
|
||||
}
|
||||
// Currently there's no way to get LocalCertificate info from tls package.
|
||||
if len(t.State.PeerCertificates) > 0 {
|
||||
v.RemoteCertificate = t.State.PeerCertificates[0].Raw
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// tlsCreds is the credentials required for authenticating a connection using TLS.
|
||||
type tlsCreds struct {
|
||||
// TLS configuration
|
||||
config *tls.Config
|
||||
}
|
||||
|
||||
func (c tlsCreds) Info() ProtocolInfo {
|
||||
return ProtocolInfo{
|
||||
SecurityProtocol: "tls",
|
||||
SecurityVersion: "1.2",
|
||||
ServerName: c.config.ServerName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
|
||||
// use local cfg to avoid clobbering ServerName if using multiple endpoints
|
||||
cfg := cloneTLSConfig(c.config)
|
||||
if cfg.ServerName == "" {
|
||||
colonPos := strings.LastIndex(authority, ":")
|
||||
if colonPos == -1 {
|
||||
colonPos = len(authority)
|
||||
}
|
||||
cfg.ServerName = authority[:colonPos]
|
||||
}
|
||||
conn := tls.Client(rawConn, cfg)
|
||||
errChannel := make(chan error, 1)
|
||||
go func() {
|
||||
errChannel <- conn.Handshake()
|
||||
}()
|
||||
select {
|
||||
case err := <-errChannel:
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return nil, nil, ctx.Err()
|
||||
}
|
||||
return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
|
||||
}
|
||||
|
||||
func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
|
||||
conn := tls.Server(rawConn, c.config)
|
||||
if err := conn.Handshake(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
|
||||
}
|
||||
|
||||
func (c *tlsCreds) Clone() TransportCredentials {
|
||||
return NewTLS(c.config)
|
||||
}
|
||||
|
||||
func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
|
||||
c.config.ServerName = serverNameOverride
|
||||
return nil
|
||||
}
|
||||
|
||||
const alpnProtoStrH2 = "h2"
|
||||
|
||||
func appendH2ToNextProtos(ps []string) []string {
|
||||
for _, p := range ps {
|
||||
if p == alpnProtoStrH2 {
|
||||
return ps
|
||||
}
|
||||
}
|
||||
ret := make([]string, 0, len(ps)+1)
|
||||
ret = append(ret, ps...)
|
||||
return append(ret, alpnProtoStrH2)
|
||||
}
|
||||
|
||||
// NewTLS uses c to construct a TransportCredentials based on TLS.
|
||||
func NewTLS(c *tls.Config) TransportCredentials {
|
||||
tc := &tlsCreds{cloneTLSConfig(c)}
|
||||
tc.config.NextProtos = appendH2ToNextProtos(tc.config.NextProtos)
|
||||
return tc
|
||||
}
|
||||
|
||||
// NewClientTLSFromCert constructs TLS credentials from the input certificate for client.
|
||||
// serverNameOverride is for testing only. If set to a non empty string,
|
||||
// it will override the virtual host name of authority (e.g. :authority header field) in requests.
|
||||
func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
|
||||
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
|
||||
}
|
||||
|
||||
// NewClientTLSFromFile constructs TLS credentials from the input certificate file for client.
|
||||
// serverNameOverride is for testing only. If set to a non empty string,
|
||||
// it will override the virtual host name of authority (e.g. :authority header field) in requests.
|
||||
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
|
||||
b, err := ioutil.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cp := x509.NewCertPool()
|
||||
if !cp.AppendCertsFromPEM(b) {
|
||||
return nil, fmt.Errorf("credentials: failed to append certificates")
|
||||
}
|
||||
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
|
||||
}
|
||||
|
||||
// NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
|
||||
func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
|
||||
return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
|
||||
}
|
||||
|
||||
// NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
|
||||
// file for server.
|
||||
func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
|
||||
}
|
||||
|
||||
// ChannelzSecurityInfo defines the interface that security protocols should implement
|
||||
// in order to provide security info to channelz.
|
||||
type ChannelzSecurityInfo interface {
|
||||
GetSecurityValue() ChannelzSecurityValue
|
||||
}
|
||||
|
||||
// ChannelzSecurityValue defines the interface that GetSecurityValue() return value
|
||||
// should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
|
||||
// and *OtherChannelzSecurityValue.
|
||||
type ChannelzSecurityValue interface {
|
||||
isChannelzSecurityValue()
|
||||
}
|
||||
|
||||
// TLSChannelzSecurityValue defines the struct that TLS protocol should return
|
||||
// from GetSecurityValue(), containing security info like cipher and certificate used.
|
||||
type TLSChannelzSecurityValue struct {
|
||||
ChannelzSecurityValue
|
||||
StandardName string
|
||||
LocalCertificate []byte
|
||||
RemoteCertificate []byte
|
||||
}
|
||||
|
||||
// OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
|
||||
// from GetSecurityValue(), which contains protocol specific security info. Note
|
||||
// the Value field will be sent to users of channelz requesting channel info, and
|
||||
// thus sensitive info should better be avoided.
|
||||
type OtherChannelzSecurityValue struct {
|
||||
ChannelzSecurityValue
|
||||
Name string
|
||||
Value proto.Message
|
||||
}
|
||||
|
||||
var cipherSuiteLookup = map[uint16]string{
|
||||
tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
}
|
||||
|
||||
// cloneTLSConfig returns a shallow clone of the exported
|
||||
// fields of cfg, ignoring the unexported sync.Once, which
|
||||
// contains a mutex and must not be copied.
|
||||
//
|
||||
// If cfg is nil, a new zero tls.Config is returned.
|
||||
//
|
||||
// TODO: inline this function if possible.
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
|
||||
return cfg.Clone()
|
||||
}
|
||||
61
vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
generated
vendored
Normal file
61
vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// +build !appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package internal contains credentials-internal code.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type sysConn = syscall.Conn
|
||||
|
||||
// syscallConn keeps reference of rawConn to support syscall.Conn for channelz.
|
||||
// SyscallConn() (the method in interface syscall.Conn) is explicitly
|
||||
// implemented on this type,
|
||||
//
|
||||
// Interface syscall.Conn is implemented by most net.Conn implementations (e.g.
|
||||
// TCPConn, UnixConn), but is not part of net.Conn interface. So wrapper conns
|
||||
// that embed net.Conn don't implement syscall.Conn. (Side note: tls.Conn
|
||||
// doesn't embed net.Conn, so even if syscall.Conn is part of net.Conn, it won't
|
||||
// help here).
|
||||
type syscallConn struct {
|
||||
net.Conn
|
||||
// sysConn is a type alias of syscall.Conn. It's necessary because the name
|
||||
// `Conn` collides with `net.Conn`.
|
||||
sysConn
|
||||
}
|
||||
|
||||
// WrapSyscallConn tries to wrap rawConn and newConn into a net.Conn that
|
||||
// implements syscall.Conn. rawConn will be used to support syscall, and newConn
|
||||
// will be used for read/write.
|
||||
//
|
||||
// This function returns newConn if rawConn doesn't implement syscall.Conn.
|
||||
func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
|
||||
sysConn, ok := rawConn.(syscall.Conn)
|
||||
if !ok {
|
||||
return newConn
|
||||
}
|
||||
return &syscallConn{
|
||||
Conn: newConn,
|
||||
sysConn: sysConn,
|
||||
}
|
||||
}
|
||||
30
vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
generated
vendored
Normal file
30
vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// +build appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// WrapSyscallConn returns newConn on appengine.
|
||||
func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
|
||||
return newConn
|
||||
}
|
||||
30
vendor/google.golang.org/grpc/credentials/tls13.go
generated
vendored
Normal file
30
vendor/google.golang.org/grpc/credentials/tls13.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// +build go1.12
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package credentials
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// This init function adds cipher suite constants only defined in Go 1.12.
|
||||
func init() {
|
||||
cipherSuiteLookup[tls.TLS_AES_128_GCM_SHA256] = "TLS_AES_128_GCM_SHA256"
|
||||
cipherSuiteLookup[tls.TLS_AES_256_GCM_SHA384] = "TLS_AES_256_GCM_SHA384"
|
||||
cipherSuiteLookup[tls.TLS_CHACHA20_POLY1305_SHA256] = "TLS_CHACHA20_POLY1305_SHA256"
|
||||
}
|
||||
554
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
Normal file
554
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
"google.golang.org/grpc/internal/transport"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/stats"
|
||||
)
|
||||
|
||||
// dialOptions configure a Dial call. dialOptions are set by the DialOption
|
||||
// values passed to Dial.
|
||||
type dialOptions struct {
|
||||
unaryInt UnaryClientInterceptor
|
||||
streamInt StreamClientInterceptor
|
||||
|
||||
chainUnaryInts []UnaryClientInterceptor
|
||||
chainStreamInts []StreamClientInterceptor
|
||||
|
||||
cp Compressor
|
||||
dc Decompressor
|
||||
bs backoff.Strategy
|
||||
block bool
|
||||
insecure bool
|
||||
timeout time.Duration
|
||||
scChan <-chan ServiceConfig
|
||||
authority string
|
||||
copts transport.ConnectOptions
|
||||
callOptions []CallOption
|
||||
// This is used by v1 balancer dial option WithBalancer to support v1
|
||||
// balancer, and also by WithBalancerName dial option.
|
||||
balancerBuilder balancer.Builder
|
||||
// This is to support grpclb.
|
||||
resolverBuilder resolver.Builder
|
||||
channelzParentID int64
|
||||
disableServiceConfig bool
|
||||
disableRetry bool
|
||||
disableHealthCheck bool
|
||||
healthCheckFunc internal.HealthChecker
|
||||
minConnectTimeout func() time.Duration
|
||||
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
|
||||
defaultServiceConfigRawJSON *string
|
||||
}
|
||||
|
||||
// DialOption configures how we set up the connection.
|
||||
type DialOption interface {
|
||||
apply(*dialOptions)
|
||||
}
|
||||
|
||||
// EmptyDialOption does not alter the dial configuration. It can be embedded in
|
||||
// another structure to build custom dial options.
|
||||
//
|
||||
// This API is EXPERIMENTAL.
|
||||
type EmptyDialOption struct{}
|
||||
|
||||
func (EmptyDialOption) apply(*dialOptions) {}
|
||||
|
||||
// funcDialOption wraps a function that modifies dialOptions into an
|
||||
// implementation of the DialOption interface.
|
||||
type funcDialOption struct {
|
||||
f func(*dialOptions)
|
||||
}
|
||||
|
||||
func (fdo *funcDialOption) apply(do *dialOptions) {
|
||||
fdo.f(do)
|
||||
}
|
||||
|
||||
func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
|
||||
return &funcDialOption{
|
||||
f: f,
|
||||
}
|
||||
}
|
||||
|
||||
// WithWriteBufferSize determines how much data can be batched before doing a
|
||||
// write on the wire. The corresponding memory allocation for this buffer will
|
||||
// be twice the size to keep syscalls low. The default value for this buffer is
|
||||
// 32KB.
|
||||
//
|
||||
// Zero will disable the write buffer such that each write will be on underlying
|
||||
// connection. Note: A Send call may not directly translate to a write.
|
||||
func WithWriteBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.WriteBufferSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithReadBufferSize lets you set the size of read buffer, this determines how
|
||||
// much data can be read at most for each read syscall.
|
||||
//
|
||||
// The default value for this buffer is 32KB. Zero will disable read buffer for
|
||||
// a connection so data framer can access the underlying conn directly.
|
||||
func WithReadBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.ReadBufferSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithInitialWindowSize returns a DialOption which sets the value for initial
|
||||
// window size on a stream. The lower bound for window size is 64K and any value
|
||||
// smaller than that will be ignored.
|
||||
func WithInitialWindowSize(s int32) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.InitialWindowSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithInitialConnWindowSize returns a DialOption which sets the value for
|
||||
// initial window size on a connection. The lower bound for window size is 64K
|
||||
// and any value smaller than that will be ignored.
|
||||
func WithInitialConnWindowSize(s int32) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.InitialConnWindowSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithMaxMsgSize returns a DialOption which sets the maximum message size the
|
||||
// client can receive.
|
||||
//
|
||||
// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead. Will
|
||||
// be supported throughout 1.x.
|
||||
func WithMaxMsgSize(s int) DialOption {
|
||||
return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
|
||||
}
|
||||
|
||||
// WithDefaultCallOptions returns a DialOption which sets the default
|
||||
// CallOptions for calls over the connection.
|
||||
func WithDefaultCallOptions(cos ...CallOption) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.callOptions = append(o.callOptions, cos...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithCodec returns a DialOption which sets a codec for message marshaling and
|
||||
// unmarshaling.
|
||||
//
|
||||
// Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead. Will be
|
||||
// supported throughout 1.x.
|
||||
func WithCodec(c Codec) DialOption {
|
||||
return WithDefaultCallOptions(CallCustomCodec(c))
|
||||
}
|
||||
|
||||
// WithCompressor returns a DialOption which sets a Compressor to use for
|
||||
// message compression. It has lower priority than the compressor set by the
|
||||
// UseCompressor CallOption.
|
||||
//
|
||||
// Deprecated: use UseCompressor instead. Will be supported throughout 1.x.
|
||||
func WithCompressor(cp Compressor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.cp = cp
|
||||
})
|
||||
}
|
||||
|
||||
// WithDecompressor returns a DialOption which sets a Decompressor to use for
|
||||
// incoming message decompression. If incoming response messages are encoded
|
||||
// using the decompressor's Type(), it will be used. Otherwise, the message
|
||||
// encoding will be used to look up the compressor registered via
|
||||
// encoding.RegisterCompressor, which will then be used to decompress the
|
||||
// message. If no compressor is registered for the encoding, an Unimplemented
|
||||
// status error will be returned.
|
||||
//
|
||||
// Deprecated: use encoding.RegisterCompressor instead. Will be supported
|
||||
// throughout 1.x.
|
||||
func WithDecompressor(dc Decompressor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.dc = dc
|
||||
})
|
||||
}
|
||||
|
||||
// WithBalancer returns a DialOption which sets a load balancer with the v1 API.
|
||||
// Name resolver will be ignored if this DialOption is specified.
|
||||
//
|
||||
// Deprecated: use the new balancer APIs in balancer package and
|
||||
// WithBalancerName. Will be removed in a future 1.x release.
|
||||
func WithBalancer(b Balancer) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.balancerBuilder = &balancerWrapperBuilder{
|
||||
b: b,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WithBalancerName sets the balancer that the ClientConn will be initialized
|
||||
// with. Balancer registered with balancerName will be used. This function
|
||||
// panics if no balancer was registered by balancerName.
|
||||
//
|
||||
// The balancer cannot be overridden by balancer option specified by service
|
||||
// config.
|
||||
//
|
||||
// Deprecated: use WithDefaultServiceConfig and WithDisableServiceConfig
|
||||
// instead. Will be removed in a future 1.x release.
|
||||
func WithBalancerName(balancerName string) DialOption {
|
||||
builder := balancer.Get(balancerName)
|
||||
if builder == nil {
|
||||
panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
|
||||
}
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.balancerBuilder = builder
|
||||
})
|
||||
}
|
||||
|
||||
// withResolverBuilder is only for grpclb.
|
||||
func withResolverBuilder(b resolver.Builder) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.resolverBuilder = b
|
||||
})
|
||||
}
|
||||
|
||||
// WithServiceConfig returns a DialOption which has a channel to read the
|
||||
// service configuration.
|
||||
//
|
||||
// Deprecated: service config should be received through name resolver or via
|
||||
// WithDefaultServiceConfig, as specified at
|
||||
// https://github.com/grpc/grpc/blob/master/doc/service_config.md. Will be
|
||||
// removed in a future 1.x release.
|
||||
func WithServiceConfig(c <-chan ServiceConfig) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.scChan = c
|
||||
})
|
||||
}
|
||||
|
||||
// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
|
||||
// when backing off after failed connection attempts.
|
||||
func WithBackoffMaxDelay(md time.Duration) DialOption {
|
||||
return WithBackoffConfig(BackoffConfig{MaxDelay: md})
|
||||
}
|
||||
|
||||
// WithBackoffConfig configures the dialer to use the provided backoff
|
||||
// parameters after connection failures.
|
||||
//
|
||||
// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
|
||||
// for use.
|
||||
func WithBackoffConfig(b BackoffConfig) DialOption {
|
||||
return withBackoff(backoff.Exponential{
|
||||
MaxDelay: b.MaxDelay,
|
||||
})
|
||||
}
|
||||
|
||||
// withBackoff sets the backoff strategy used for connectRetryNum after a failed
|
||||
// connection attempt.
|
||||
//
|
||||
// This can be exported if arbitrary backoff strategies are allowed by gRPC.
|
||||
func withBackoff(bs backoff.Strategy) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.bs = bs
|
||||
})
|
||||
}
|
||||
|
||||
// WithBlock returns a DialOption which makes caller of Dial blocks until the
|
||||
// underlying connection is up. Without this, Dial returns immediately and
|
||||
// connecting the server happens in background.
|
||||
func WithBlock() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.block = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithInsecure returns a DialOption which disables transport security for this
|
||||
// ClientConn. Note that transport security is required unless WithInsecure is
|
||||
// set.
|
||||
func WithInsecure() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.insecure = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithTransportCredentials returns a DialOption which configures a connection
|
||||
// level security credentials (e.g., TLS/SSL). This should not be used together
|
||||
// with WithCredentialsBundle.
|
||||
func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.TransportCredentials = creds
|
||||
})
|
||||
}
|
||||
|
||||
// WithPerRPCCredentials returns a DialOption which sets credentials and places
|
||||
// auth state on each outbound RPC.
|
||||
func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
|
||||
})
|
||||
}
|
||||
|
||||
// WithCredentialsBundle returns a DialOption to set a credentials bundle for
|
||||
// the ClientConn.WithCreds. This should not be used together with
|
||||
// WithTransportCredentials.
|
||||
//
|
||||
// This API is experimental.
|
||||
func WithCredentialsBundle(b credentials.Bundle) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.CredsBundle = b
|
||||
})
|
||||
}
|
||||
|
||||
// WithTimeout returns a DialOption that configures a timeout for dialing a
|
||||
// ClientConn initially. This is valid if and only if WithBlock() is present.
|
||||
//
|
||||
// Deprecated: use DialContext and context.WithTimeout instead. Will be
|
||||
// supported throughout 1.x.
|
||||
func WithTimeout(d time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.timeout = d
|
||||
})
|
||||
}
|
||||
|
||||
// WithContextDialer returns a DialOption that sets a dialer to create
|
||||
// connections. If FailOnNonTempDialError() is set to true, and an error is
|
||||
// returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.Dialer = f
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.WithResolverBuilder = withResolverBuilder
|
||||
internal.WithHealthCheckFunc = withHealthCheckFunc
|
||||
}
|
||||
|
||||
// WithDialer returns a DialOption that specifies a function to use for dialing
|
||||
// network addresses. If FailOnNonTempDialError() is set to true, and an error
|
||||
// is returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
//
|
||||
// Deprecated: use WithContextDialer instead. Will be supported throughout
|
||||
// 1.x.
|
||||
func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
|
||||
return WithContextDialer(
|
||||
func(ctx context.Context, addr string) (net.Conn, error) {
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
return f(addr, time.Until(deadline))
|
||||
}
|
||||
return f(addr, 0)
|
||||
})
|
||||
}
|
||||
|
||||
// WithStatsHandler returns a DialOption that specifies the stats handler for
|
||||
// all the RPCs and underlying network connections in this ClientConn.
|
||||
func WithStatsHandler(h stats.Handler) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.StatsHandler = h
|
||||
})
|
||||
}
|
||||
|
||||
// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
|
||||
// non-temporary dial errors. If f is true, and dialer returns a non-temporary
|
||||
// error, gRPC will fail the connection to the network address and won't try to
|
||||
// reconnect. The default value of FailOnNonTempDialError is false.
|
||||
//
|
||||
// FailOnNonTempDialError only affects the initial dial, and does not do
|
||||
// anything useful unless you are also using WithBlock().
|
||||
//
|
||||
// This is an EXPERIMENTAL API.
|
||||
func FailOnNonTempDialError(f bool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.FailOnNonTempDialError = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithUserAgent returns a DialOption that specifies a user agent string for all
|
||||
// the RPCs.
|
||||
func WithUserAgent(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.UserAgent = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
|
||||
// for the client transport.
|
||||
func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
|
||||
if kp.Time < internal.KeepaliveMinPingTime {
|
||||
grpclog.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
|
||||
kp.Time = internal.KeepaliveMinPingTime
|
||||
}
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.KeepaliveParams = kp
|
||||
})
|
||||
}
|
||||
|
||||
// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
|
||||
// unary RPCs.
|
||||
func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.unaryInt = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithChainUnaryInterceptor returns a DialOption that specifies the chained
|
||||
// interceptor for unary RPCs. The first interceptor will be the outer most,
|
||||
// while the last interceptor will be the inner most wrapper around the real call.
|
||||
// All interceptors added by this method will be chained, and the interceptor
|
||||
// defined by WithUnaryInterceptor will always be prepended to the chain.
|
||||
func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithStreamInterceptor returns a DialOption that specifies the interceptor for
|
||||
// streaming RPCs.
|
||||
func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.streamInt = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithChainStreamInterceptor returns a DialOption that specifies the chained
|
||||
// interceptor for unary RPCs. The first interceptor will be the outer most,
|
||||
// while the last interceptor will be the inner most wrapper around the real call.
|
||||
// All interceptors added by this method will be chained, and the interceptor
|
||||
// defined by WithStreamInterceptor will always be prepended to the chain.
|
||||
func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.chainStreamInts = append(o.chainStreamInts, interceptors...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithAuthority returns a DialOption that specifies the value to be used as the
|
||||
// :authority pseudo-header. This value only works with WithInsecure and has no
|
||||
// effect if TransportCredentials are present.
|
||||
func WithAuthority(a string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.authority = a
|
||||
})
|
||||
}
|
||||
|
||||
// WithChannelzParentID returns a DialOption that specifies the channelz ID of
|
||||
// current ClientConn's parent. This function is used in nested channel creation
|
||||
// (e.g. grpclb dial).
|
||||
func WithChannelzParentID(id int64) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.channelzParentID = id
|
||||
})
|
||||
}
|
||||
|
||||
// WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
|
||||
// service config provided by the resolver and provides a hint to the resolver
|
||||
// to not fetch service configs.
|
||||
//
|
||||
// Note that this dial option only disables service config from resolver. If
|
||||
// default service config is provided, gRPC will use the default service config.
|
||||
func WithDisableServiceConfig() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableServiceConfig = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithDefaultServiceConfig returns a DialOption that configures the default
|
||||
// service config, which will be used in cases where:
|
||||
//
|
||||
// 1. WithDisableServiceConfig is also used.
|
||||
// 2. Resolver does not return a service config or if the resolver returns an
|
||||
// invalid service config.
|
||||
//
|
||||
// This API is EXPERIMENTAL.
|
||||
func WithDefaultServiceConfig(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.defaultServiceConfigRawJSON = &s
|
||||
})
|
||||
}
|
||||
|
||||
// WithDisableRetry returns a DialOption that disables retries, even if the
|
||||
// service config enables them. This does not impact transparent retries, which
|
||||
// will happen automatically if no data is written to the wire or if the RPC is
|
||||
// unprocessed by the remote server.
|
||||
//
|
||||
// Retry support is currently disabled by default, but will be enabled by
|
||||
// default in the future. Until then, it may be enabled by setting the
|
||||
// environment variable "GRPC_GO_RETRY" to "on".
|
||||
//
|
||||
// This API is EXPERIMENTAL.
|
||||
func WithDisableRetry() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableRetry = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithMaxHeaderListSize returns a DialOption that specifies the maximum
|
||||
// (uncompressed) size of header list that the client is prepared to accept.
|
||||
func WithMaxHeaderListSize(s uint32) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.MaxHeaderListSize = &s
|
||||
})
|
||||
}
|
||||
|
||||
// WithDisableHealthCheck disables the LB channel health checking for all
|
||||
// SubConns of this ClientConn.
|
||||
//
|
||||
// This API is EXPERIMENTAL.
|
||||
func WithDisableHealthCheck() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableHealthCheck = true
|
||||
})
|
||||
}
|
||||
|
||||
// withHealthCheckFunc replaces the default health check function with the
|
||||
// provided one. It makes tests easier to change the health check function.
|
||||
//
|
||||
// For testing purpose only.
|
||||
func withHealthCheckFunc(f internal.HealthChecker) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.healthCheckFunc = f
|
||||
})
|
||||
}
|
||||
|
||||
func defaultDialOptions() dialOptions {
|
||||
return dialOptions{
|
||||
disableRetry: !envconfig.Retry,
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
copts: transport.ConnectOptions{
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// withGetMinConnectDeadline specifies the function that clientconn uses to
|
||||
// get minConnectDeadline. This can be used to make connection attempts happen
|
||||
// faster/slower.
|
||||
//
|
||||
// For testing purpose only.
|
||||
func withMinConnectDeadline(f func() time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.minConnectTimeout = f
|
||||
})
|
||||
}
|
||||
24
vendor/google.golang.org/grpc/doc.go
generated
vendored
Normal file
24
vendor/google.golang.org/grpc/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Package grpc implements an RPC system called gRPC.
|
||||
|
||||
See grpc.io for more information about gRPC.
|
||||
*/
|
||||
package grpc // import "google.golang.org/grpc"
|
||||
118
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
Normal file
118
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package encoding defines the interface for the compressor and codec, and
|
||||
// functions to register and retrieve compressors and codecs.
|
||||
//
|
||||
// This package is EXPERIMENTAL.
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Identity specifies the optional encoding for uncompressed streams.
|
||||
// It is intended for grpc internal use only.
|
||||
const Identity = "identity"
|
||||
|
||||
// Compressor is used for compressing and decompressing when sending or
|
||||
// receiving messages.
|
||||
type Compressor interface {
|
||||
// Compress writes the data written to wc to w after compressing it. If an
|
||||
// error occurs while initializing the compressor, that error is returned
|
||||
// instead.
|
||||
Compress(w io.Writer) (io.WriteCloser, error)
|
||||
// Decompress reads data from r, decompresses it, and provides the
|
||||
// uncompressed data via the returned io.Reader. If an error occurs while
|
||||
// initializing the decompressor, that error is returned instead.
|
||||
Decompress(r io.Reader) (io.Reader, error)
|
||||
// Name is the name of the compression codec and is used to set the content
|
||||
// coding header. The result must be static; the result cannot change
|
||||
// between calls.
|
||||
Name() string
|
||||
}
|
||||
|
||||
var registeredCompressor = make(map[string]Compressor)
|
||||
|
||||
// RegisterCompressor registers the compressor with gRPC by its name. It can
|
||||
// be activated when sending an RPC via grpc.UseCompressor(). It will be
|
||||
// automatically accessed when receiving a message based on the content coding
|
||||
// header. Servers also use it to send a response with the same encoding as
|
||||
// the request.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Compressors are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func RegisterCompressor(c Compressor) {
|
||||
registeredCompressor[c.Name()] = c
|
||||
}
|
||||
|
||||
// GetCompressor returns Compressor for the given compressor name.
|
||||
func GetCompressor(name string) Compressor {
|
||||
return registeredCompressor[name]
|
||||
}
|
||||
|
||||
// Codec defines the interface gRPC uses to encode and decode messages. Note
|
||||
// that implementations of this interface must be thread safe; a Codec's
|
||||
// methods can be called from concurrent goroutines.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
Name() string
|
||||
}
|
||||
|
||||
var registeredCodecs = make(map[string]Codec)
|
||||
|
||||
// RegisterCodec registers the provided Codec for use with all gRPC clients and
|
||||
// servers.
|
||||
//
|
||||
// The Codec will be stored and looked up by result of its Name() method, which
|
||||
// should match the content-subtype of the encoding handled by the Codec. This
|
||||
// is case-insensitive, and is stored and looked up as lowercase. If the
|
||||
// result of calling Name() is an empty string, RegisterCodec will panic. See
|
||||
// Content-Type on
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||
// more details.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Compressors are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func RegisterCodec(codec Codec) {
|
||||
if codec == nil {
|
||||
panic("cannot register a nil Codec")
|
||||
}
|
||||
if codec.Name() == "" {
|
||||
panic("cannot register Codec with empty string result for Name()")
|
||||
}
|
||||
contentSubtype := strings.ToLower(codec.Name())
|
||||
registeredCodecs[contentSubtype] = codec
|
||||
}
|
||||
|
||||
// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
|
||||
// registered for the content-subtype.
|
||||
//
|
||||
// The content-subtype is expected to be lowercase.
|
||||
func GetCodec(contentSubtype string) Codec {
|
||||
return registeredCodecs[contentSubtype]
|
||||
}
|
||||
110
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
Normal file
110
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package proto defines the protobuf codec. Importing this package will
|
||||
// register the codec.
|
||||
package proto
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/grpc/encoding"
|
||||
)
|
||||
|
||||
// Name is the name registered for the proto compressor.
|
||||
const Name = "proto"
|
||||
|
||||
func init() {
|
||||
encoding.RegisterCodec(codec{})
|
||||
}
|
||||
|
||||
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
||||
type codec struct{}
|
||||
|
||||
type cachedProtoBuffer struct {
|
||||
lastMarshaledSize uint32
|
||||
proto.Buffer
|
||||
}
|
||||
|
||||
func capToMaxInt32(val int) uint32 {
|
||||
if val > math.MaxInt32 {
|
||||
return uint32(math.MaxInt32)
|
||||
}
|
||||
return uint32(val)
|
||||
}
|
||||
|
||||
func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
|
||||
protoMsg := v.(proto.Message)
|
||||
newSlice := make([]byte, 0, cb.lastMarshaledSize)
|
||||
|
||||
cb.SetBuf(newSlice)
|
||||
cb.Reset()
|
||||
if err := cb.Marshal(protoMsg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := cb.Bytes()
|
||||
cb.lastMarshaledSize = capToMaxInt32(len(out))
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (codec) Marshal(v interface{}) ([]byte, error) {
|
||||
if pm, ok := v.(proto.Marshaler); ok {
|
||||
// object can marshal itself, no need for buffer
|
||||
return pm.Marshal()
|
||||
}
|
||||
|
||||
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
||||
out, err := marshal(v, cb)
|
||||
|
||||
// put back buffer and lose the ref to the slice
|
||||
cb.SetBuf(nil)
|
||||
protoBufferPool.Put(cb)
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (codec) Unmarshal(data []byte, v interface{}) error {
|
||||
protoMsg := v.(proto.Message)
|
||||
protoMsg.Reset()
|
||||
|
||||
if pu, ok := protoMsg.(proto.Unmarshaler); ok {
|
||||
// object can unmarshal itself, no need for buffer
|
||||
return pu.Unmarshal(data)
|
||||
}
|
||||
|
||||
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
||||
cb.SetBuf(data)
|
||||
err := cb.Unmarshal(protoMsg)
|
||||
cb.SetBuf(nil)
|
||||
protoBufferPool.Put(cb)
|
||||
return err
|
||||
}
|
||||
|
||||
func (codec) Name() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
var protoBufferPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &cachedProtoBuffer{
|
||||
Buffer: proto.Buffer{},
|
||||
lastMarshaledSize: 16,
|
||||
}
|
||||
},
|
||||
}
|
||||
19
vendor/google.golang.org/grpc/go.mod
generated
vendored
Normal file
19
vendor/google.golang.org/grpc/go.mod
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
module google.golang.org/grpc
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.26.0 // indirect
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/client9/misspell v0.3.4
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/golang/mock v1.1.1
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/google/go-cmp v0.2.0
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135
|
||||
google.golang.org/appengine v1.1.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc
|
||||
)
|
||||
37
vendor/google.golang.org/grpc/go.sum
generated
vendored
Normal file
37
vendor/google.golang.org/grpc/go.sum
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
126
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
Normal file
126
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpclog defines logging for grpc.
|
||||
//
|
||||
// All logs in transport and grpclb packages only go to verbose level 2.
|
||||
// All logs in other packages in grpc are logged in spite of the verbosity level.
|
||||
//
|
||||
// In the default logger,
|
||||
// severity level can be set by environment variable GRPC_GO_LOG_SEVERITY_LEVEL,
|
||||
// verbosity level can be set by GRPC_GO_LOG_VERBOSITY_LEVEL.
|
||||
package grpclog // import "google.golang.org/grpc/grpclog"
|
||||
|
||||
import "os"
|
||||
|
||||
var logger = newLoggerV2()
|
||||
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
func V(l int) bool {
|
||||
return logger.V(l)
|
||||
}
|
||||
|
||||
// Info logs to the INFO log.
|
||||
func Info(args ...interface{}) {
|
||||
logger.Info(args...)
|
||||
}
|
||||
|
||||
// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Infof(format string, args ...interface{}) {
|
||||
logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
func Infoln(args ...interface{}) {
|
||||
logger.Infoln(args...)
|
||||
}
|
||||
|
||||
// Warning logs to the WARNING log.
|
||||
func Warning(args ...interface{}) {
|
||||
logger.Warning(args...)
|
||||
}
|
||||
|
||||
// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Warningf(format string, args ...interface{}) {
|
||||
logger.Warningf(format, args...)
|
||||
}
|
||||
|
||||
// Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
func Warningln(args ...interface{}) {
|
||||
logger.Warningln(args...)
|
||||
}
|
||||
|
||||
// Error logs to the ERROR log.
|
||||
func Error(args ...interface{}) {
|
||||
logger.Error(args...)
|
||||
}
|
||||
|
||||
// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
logger.Errorf(format, args...)
|
||||
}
|
||||
|
||||
// Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
func Errorln(args ...interface{}) {
|
||||
logger.Errorln(args...)
|
||||
}
|
||||
|
||||
// Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print.
|
||||
// It calls os.Exit() with exit code 1.
|
||||
func Fatal(args ...interface{}) {
|
||||
logger.Fatal(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf.
|
||||
// It calles os.Exit() with exit code 1.
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
logger.Fatalf(format, args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalln logs to the FATAL log. Arguments are handled in the manner of fmt.Println.
|
||||
// It calle os.Exit()) with exit code 1.
|
||||
func Fatalln(args ...interface{}) {
|
||||
logger.Fatalln(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
|
||||
//
|
||||
// Deprecated: use Info.
|
||||
func Print(args ...interface{}) {
|
||||
logger.Info(args...)
|
||||
}
|
||||
|
||||
// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
|
||||
//
|
||||
// Deprecated: use Infof.
|
||||
func Printf(format string, args ...interface{}) {
|
||||
logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
|
||||
//
|
||||
// Deprecated: use Infoln.
|
||||
func Println(args ...interface{}) {
|
||||
logger.Infoln(args...)
|
||||
}
|
||||
85
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
Normal file
85
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclog
|
||||
|
||||
// Logger mimics golang's standard Logger as an interface.
|
||||
//
|
||||
// Deprecated: use LoggerV2.
|
||||
type Logger interface {
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Fatalln(args ...interface{})
|
||||
Print(args ...interface{})
|
||||
Printf(format string, args ...interface{})
|
||||
Println(args ...interface{})
|
||||
}
|
||||
|
||||
// SetLogger sets the logger that is used in grpc. Call only from
|
||||
// init() functions.
|
||||
//
|
||||
// Deprecated: use SetLoggerV2.
|
||||
func SetLogger(l Logger) {
|
||||
logger = &loggerWrapper{Logger: l}
|
||||
}
|
||||
|
||||
// loggerWrapper wraps Logger into a LoggerV2.
|
||||
type loggerWrapper struct {
|
||||
Logger
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Info(args ...interface{}) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infoln(args ...interface{}) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infof(format string, args ...interface{}) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warning(args ...interface{}) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningln(args ...interface{}) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningf(format string, args ...interface{}) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Error(args ...interface{}) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorln(args ...interface{}) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorf(format string, args ...interface{}) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) V(l int) bool {
|
||||
// Returns true for all verbose level.
|
||||
return true
|
||||
}
|
||||
195
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
Normal file
195
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// LoggerV2 does underlying logging work for grpclog.
|
||||
type LoggerV2 interface {
|
||||
// Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
|
||||
Info(args ...interface{})
|
||||
// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
Infoln(args ...interface{})
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...interface{})
|
||||
// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
|
||||
Warning(args ...interface{})
|
||||
// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
Warningln(args ...interface{})
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...interface{})
|
||||
// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
Error(args ...interface{})
|
||||
// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
Errorln(args ...interface{})
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...interface{})
|
||||
// Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatal(args ...interface{})
|
||||
// Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalln(args ...interface{})
|
||||
// Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalf(format string, args ...interface{})
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
V(l int) bool
|
||||
}
|
||||
|
||||
// SetLoggerV2 sets logger that is used in grpc to a V2 logger.
|
||||
// Not mutex-protected, should be called before any gRPC functions.
|
||||
func SetLoggerV2(l LoggerV2) {
|
||||
logger = l
|
||||
}
|
||||
|
||||
const (
|
||||
// infoLog indicates Info severity.
|
||||
infoLog int = iota
|
||||
// warningLog indicates Warning severity.
|
||||
warningLog
|
||||
// errorLog indicates Error severity.
|
||||
errorLog
|
||||
// fatalLog indicates Fatal severity.
|
||||
fatalLog
|
||||
)
|
||||
|
||||
// severityName contains the string representation of each severity.
|
||||
var severityName = []string{
|
||||
infoLog: "INFO",
|
||||
warningLog: "WARNING",
|
||||
errorLog: "ERROR",
|
||||
fatalLog: "FATAL",
|
||||
}
|
||||
|
||||
// loggerT is the default logger used by grpclog.
|
||||
type loggerT struct {
|
||||
m []*log.Logger
|
||||
v int
|
||||
}
|
||||
|
||||
// NewLoggerV2 creates a loggerV2 with the provided writers.
|
||||
// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1).
|
||||
// Error logs will be written to errorW, warningW and infoW.
|
||||
// Warning logs will be written to warningW and infoW.
|
||||
// Info logs will be written to infoW.
|
||||
func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
|
||||
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, 0)
|
||||
}
|
||||
|
||||
// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
|
||||
// verbosity level.
|
||||
func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
|
||||
var m []*log.Logger
|
||||
m = append(m, log.New(infoW, severityName[infoLog]+": ", log.LstdFlags))
|
||||
m = append(m, log.New(io.MultiWriter(infoW, warningW), severityName[warningLog]+": ", log.LstdFlags))
|
||||
ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
|
||||
m = append(m, log.New(ew, severityName[errorLog]+": ", log.LstdFlags))
|
||||
m = append(m, log.New(ew, severityName[fatalLog]+": ", log.LstdFlags))
|
||||
return &loggerT{m: m, v: v}
|
||||
}
|
||||
|
||||
// newLoggerV2 creates a loggerV2 to be used as default logger.
|
||||
// All logs are written to stderr.
|
||||
func newLoggerV2() LoggerV2 {
|
||||
errorW := ioutil.Discard
|
||||
warningW := ioutil.Discard
|
||||
infoW := ioutil.Discard
|
||||
|
||||
logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
|
||||
switch logLevel {
|
||||
case "", "ERROR", "error": // If env is unset, set level to ERROR.
|
||||
errorW = os.Stderr
|
||||
case "WARNING", "warning":
|
||||
warningW = os.Stderr
|
||||
case "INFO", "info":
|
||||
infoW = os.Stderr
|
||||
}
|
||||
|
||||
var v int
|
||||
vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
|
||||
if vl, err := strconv.Atoi(vLevel); err == nil {
|
||||
v = vl
|
||||
}
|
||||
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, v)
|
||||
}
|
||||
|
||||
func (g *loggerT) Info(args ...interface{}) {
|
||||
g.m[infoLog].Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Infoln(args ...interface{}) {
|
||||
g.m[infoLog].Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Infof(format string, args ...interface{}) {
|
||||
g.m[infoLog].Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Warning(args ...interface{}) {
|
||||
g.m[warningLog].Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningln(args ...interface{}) {
|
||||
g.m[warningLog].Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningf(format string, args ...interface{}) {
|
||||
g.m[warningLog].Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Error(args ...interface{}) {
|
||||
g.m[errorLog].Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorln(args ...interface{}) {
|
||||
g.m[errorLog].Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorf(format string, args ...interface{}) {
|
||||
g.m[errorLog].Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatal(args ...interface{}) {
|
||||
g.m[fatalLog].Fatal(args...)
|
||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalln(args ...interface{}) {
|
||||
g.m[fatalLog].Fatalln(args...)
|
||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalf(format string, args ...interface{}) {
|
||||
g.m[fatalLog].Fatalf(format, args...)
|
||||
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
|
||||
}
|
||||
|
||||
func (g *loggerT) V(l int) bool {
|
||||
return l <= g.v
|
||||
}
|
||||
6
vendor/google.golang.org/grpc/install_gae.sh
generated
vendored
Executable file
6
vendor/google.golang.org/grpc/install_gae.sh
generated
vendored
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
TMP=$(mktemp -d /tmp/sdk.XXX) \
|
||||
&& curl -o $TMP.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" \
|
||||
&& unzip -q $TMP.zip -d $TMP \
|
||||
&& export PATH="$PATH:$TMP/go_appengine"
|
||||
77
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
Normal file
77
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
|
||||
type UnaryInvoker func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
|
||||
|
||||
// UnaryClientInterceptor intercepts the execution of a unary RPC on the client. invoker is the handler to complete the RPC
|
||||
// and it is the responsibility of the interceptor to call it.
|
||||
// This is an EXPERIMENTAL API.
|
||||
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
||||
|
||||
// Streamer is called by StreamClientInterceptor to create a ClientStream.
|
||||
type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
|
||||
|
||||
// StreamClientInterceptor intercepts the creation of ClientStream. It may return a custom ClientStream to intercept all I/O
|
||||
// operations. streamer is the handler to create a ClientStream and it is the responsibility of the interceptor to call it.
|
||||
// This is an EXPERIMENTAL API.
|
||||
type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
|
||||
|
||||
// UnaryServerInfo consists of various information about a unary RPC on
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
type UnaryServerInfo struct {
|
||||
// Server is the service implementation the user provides. This is read-only.
|
||||
Server interface{}
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
}
|
||||
|
||||
// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
|
||||
// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the
|
||||
// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as
|
||||
// the status message of the RPC.
|
||||
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
|
||||
|
||||
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
|
||||
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
|
||||
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
|
||||
// to complete the RPC.
|
||||
type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
|
||||
|
||||
// StreamServerInfo consists of various information about a streaming RPC on
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
type StreamServerInfo struct {
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
// IsClientStream indicates whether the RPC is a client streaming RPC.
|
||||
IsClientStream bool
|
||||
// IsServerStream indicates whether the RPC is a server streaming RPC.
|
||||
IsServerStream bool
|
||||
}
|
||||
|
||||
// StreamServerInterceptor provides a hook to intercept the execution of a streaming RPC on the server.
|
||||
// info contains all the information of this RPC the interceptor can operate on. And handler is the
|
||||
// service method implementation. It is the responsibility of the interceptor to invoke handler to
|
||||
// complete the RPC.
|
||||
type StreamServerInterceptor func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
|
||||
78
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
Normal file
78
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package backoff implement the backoff strategy for gRPC.
|
||||
//
|
||||
// This is kept in internal until the gRPC project decides whether or not to
|
||||
// allow alternative backoff strategies.
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
)
|
||||
|
||||
// Strategy defines the methodology for backing off after a grpc connection
|
||||
// failure.
|
||||
//
|
||||
type Strategy interface {
|
||||
// Backoff returns the amount of time to wait before the next retry given
|
||||
// the number of consecutive failures.
|
||||
Backoff(retries int) time.Duration
|
||||
}
|
||||
|
||||
const (
|
||||
// baseDelay is the amount of time to wait before retrying after the first
|
||||
// failure.
|
||||
baseDelay = 1.0 * time.Second
|
||||
// factor is applied to the backoff after each retry.
|
||||
factor = 1.6
|
||||
// jitter provides a range to randomize backoff delays.
|
||||
jitter = 0.2
|
||||
)
|
||||
|
||||
// Exponential implements exponential backoff algorithm as defined in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
type Exponential struct {
|
||||
// MaxDelay is the upper bound of backoff delay.
|
||||
MaxDelay time.Duration
|
||||
}
|
||||
|
||||
// Backoff returns the amount of time to wait before the next retry given the
|
||||
// number of retries.
|
||||
func (bc Exponential) Backoff(retries int) time.Duration {
|
||||
if retries == 0 {
|
||||
return baseDelay
|
||||
}
|
||||
backoff, max := float64(baseDelay), float64(bc.MaxDelay)
|
||||
for backoff < max && retries > 0 {
|
||||
backoff *= factor
|
||||
retries--
|
||||
}
|
||||
if backoff > max {
|
||||
backoff = max
|
||||
}
|
||||
// Randomize backoff delays so that if a cluster of requests start at
|
||||
// the same time, they won't operate in lockstep.
|
||||
backoff *= 1 + jitter*(grpcrand.Float64()*2-1)
|
||||
if backoff < 0 {
|
||||
return 0
|
||||
}
|
||||
return time.Duration(backoff)
|
||||
}
|
||||
46
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
Normal file
46
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package balancerload defines APIs to parse server loads in trailers. The
|
||||
// parsed loads are sent to balancers in DoneInfo.
|
||||
package balancerload
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// Parser converts loads from metadata into a concrete type.
|
||||
type Parser interface {
|
||||
// Parse parses loads from metadata.
|
||||
Parse(md metadata.MD) interface{}
|
||||
}
|
||||
|
||||
var parser Parser
|
||||
|
||||
// SetParser sets the load parser.
|
||||
//
|
||||
// Not mutex-protected, should be called before any gRPC functions.
|
||||
func SetParser(lr Parser) {
|
||||
parser = lr
|
||||
}
|
||||
|
||||
// Parse calls parser.Read().
|
||||
func Parse(md metadata.MD) interface{} {
|
||||
if parser == nil {
|
||||
return nil
|
||||
}
|
||||
return parser.Parse(md)
|
||||
}
|
||||
167
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
Normal file
167
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package binarylog implementation binary logging as defined in
|
||||
// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// Logger is the global binary logger. It can be used to get binary logger for
|
||||
// each method.
|
||||
type Logger interface {
|
||||
getMethodLogger(methodName string) *MethodLogger
|
||||
}
|
||||
|
||||
// binLogger is the global binary logger for the binary. One of this should be
|
||||
// built at init time from the configuration (environment varialbe or flags).
|
||||
//
|
||||
// It is used to get a methodLogger for each individual method.
|
||||
var binLogger Logger
|
||||
|
||||
// SetLogger sets the binarg logger.
|
||||
//
|
||||
// Only call this at init time.
|
||||
func SetLogger(l Logger) {
|
||||
binLogger = l
|
||||
}
|
||||
|
||||
// GetMethodLogger returns the methodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each methodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func GetMethodLogger(methodName string) *MethodLogger {
|
||||
if binLogger == nil {
|
||||
return nil
|
||||
}
|
||||
return binLogger.getMethodLogger(methodName)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const envStr = "GRPC_BINARY_LOG_FILTER"
|
||||
configStr := os.Getenv(envStr)
|
||||
binLogger = NewLoggerFromConfigString(configStr)
|
||||
}
|
||||
|
||||
type methodLoggerConfig struct {
|
||||
// Max length of header and message.
|
||||
hdr, msg uint64
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
all *methodLoggerConfig
|
||||
services map[string]*methodLoggerConfig
|
||||
methods map[string]*methodLoggerConfig
|
||||
|
||||
blacklist map[string]struct{}
|
||||
}
|
||||
|
||||
// newEmptyLogger creates an empty logger. The map fields need to be filled in
|
||||
// using the set* functions.
|
||||
func newEmptyLogger() *logger {
|
||||
return &logger{}
|
||||
}
|
||||
|
||||
// Set method logger for "*".
|
||||
func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
|
||||
if l.all != nil {
|
||||
return fmt.Errorf("conflicting global rules found")
|
||||
}
|
||||
l.all = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set method logger for "service/*".
|
||||
//
|
||||
// New methodLogger with same service overrides the old one.
|
||||
func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
|
||||
if _, ok := l.services[service]; ok {
|
||||
return fmt.Errorf("conflicting rules for service %v found", service)
|
||||
}
|
||||
if l.services == nil {
|
||||
l.services = make(map[string]*methodLoggerConfig)
|
||||
}
|
||||
l.services[service] = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set method logger for "service/method".
|
||||
//
|
||||
// New methodLogger with same method overrides the old one.
|
||||
func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
|
||||
if _, ok := l.blacklist[method]; ok {
|
||||
return fmt.Errorf("conflicting rules for method %v found", method)
|
||||
}
|
||||
if _, ok := l.methods[method]; ok {
|
||||
return fmt.Errorf("conflicting rules for method %v found", method)
|
||||
}
|
||||
if l.methods == nil {
|
||||
l.methods = make(map[string]*methodLoggerConfig)
|
||||
}
|
||||
l.methods[method] = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set blacklist method for "-service/method".
|
||||
func (l *logger) setBlacklist(method string) error {
|
||||
if _, ok := l.blacklist[method]; ok {
|
||||
return fmt.Errorf("conflicting rules for method %v found", method)
|
||||
}
|
||||
if _, ok := l.methods[method]; ok {
|
||||
return fmt.Errorf("conflicting rules for method %v found", method)
|
||||
}
|
||||
if l.blacklist == nil {
|
||||
l.blacklist = make(map[string]struct{})
|
||||
}
|
||||
l.blacklist[method] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getMethodLogger returns the methodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each methodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func (l *logger) getMethodLogger(methodName string) *MethodLogger {
|
||||
s, m, err := parseMethodName(methodName)
|
||||
if err != nil {
|
||||
grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
|
||||
return nil
|
||||
}
|
||||
if ml, ok := l.methods[s+"/"+m]; ok {
|
||||
return newMethodLogger(ml.hdr, ml.msg)
|
||||
}
|
||||
if _, ok := l.blacklist[s+"/"+m]; ok {
|
||||
return nil
|
||||
}
|
||||
if ml, ok := l.services[s]; ok {
|
||||
return newMethodLogger(ml.hdr, ml.msg)
|
||||
}
|
||||
if l.all == nil {
|
||||
return nil
|
||||
}
|
||||
return newMethodLogger(l.all.hdr, l.all.msg)
|
||||
}
|
||||
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file contains exported variables/functions that are exported for testing
|
||||
// only.
|
||||
//
|
||||
// An ideal way for this would be to put those in a *_test.go but in binarylog
|
||||
// package. But this doesn't work with staticcheck with go module. Error was:
|
||||
// "MdToMetadataProto not declared by package binarylog". This could be caused
|
||||
// by the way staticcheck looks for files for a certain package, which doesn't
|
||||
// support *_test.go files.
|
||||
//
|
||||
// Move those to binary_test.go when staticcheck is fixed.
|
||||
|
||||
package binarylog
|
||||
|
||||
var (
|
||||
// AllLogger is a logger that logs all headers/messages for all RPCs. It's
|
||||
// for testing only.
|
||||
AllLogger = NewLoggerFromConfigString("*")
|
||||
// MdToMetadataProto converts metadata to a binary logging proto message.
|
||||
// It's for testing only.
|
||||
MdToMetadataProto = mdToMetadataProto
|
||||
// AddrToProto converts an address to a binary logging proto message. It's
|
||||
// for testing only.
|
||||
AddrToProto = addrToProto
|
||||
)
|
||||
210
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
Normal file
210
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// NewLoggerFromConfigString reads the string and build a logger. It can be used
|
||||
// to build a new logger and assign it to binarylog.Logger.
|
||||
//
|
||||
// Example filter config strings:
|
||||
// - "" Nothing will be logged
|
||||
// - "*" All headers and messages will be fully logged.
|
||||
// - "*{h}" Only headers will be logged.
|
||||
// - "*{m:256}" Only the first 256 bytes of each message will be logged.
|
||||
// - "Foo/*" Logs every method in service Foo
|
||||
// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar
|
||||
// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method
|
||||
// /Foo/Bar, logs all headers and messages in every other method in service
|
||||
// Foo.
|
||||
//
|
||||
// If two configs exist for one certain method or service, the one specified
|
||||
// later overrides the privous config.
|
||||
func NewLoggerFromConfigString(s string) Logger {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
l := newEmptyLogger()
|
||||
methods := strings.Split(s, ",")
|
||||
for _, method := range methods {
|
||||
if err := l.fillMethodLoggerWithConfigString(method); err != nil {
|
||||
grpclog.Warningf("failed to parse binary log config: %v", err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// fillMethodLoggerWithConfigString parses config, creates methodLogger and adds
|
||||
// it to the right map in the logger.
|
||||
func (l *logger) fillMethodLoggerWithConfigString(config string) error {
|
||||
// "" is invalid.
|
||||
if config == "" {
|
||||
return errors.New("empty string is not a valid method binary logging config")
|
||||
}
|
||||
|
||||
// "-service/method", blacklist, no * or {} allowed.
|
||||
if config[0] == '-' {
|
||||
s, m, suffix, err := parseMethodConfigAndSuffix(config[1:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
if m == "*" {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, "* not allowd in blacklist config")
|
||||
}
|
||||
if suffix != "" {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, "header/message limit not allowed in blacklist config")
|
||||
}
|
||||
if err := l.setBlacklist(s + "/" + m); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// "*{h:256;m:256}"
|
||||
if config[0] == '*' {
|
||||
hdr, msg, err := parseHeaderMessageLengthConfig(config[1:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
if err := l.setDefaultMethodLogger(&methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
s, m, suffix, err := parseMethodConfigAndSuffix(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
hdr, msg, err := parseHeaderMessageLengthConfig(suffix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
|
||||
}
|
||||
if m == "*" {
|
||||
if err := l.setServiceMethodLogger(s, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := l.setMethodMethodLogger(s+"/"+m, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// TODO: this const is only used by env_config now. But could be useful for
|
||||
// other config. Move to binarylog.go if necessary.
|
||||
maxUInt = ^uint64(0)
|
||||
|
||||
// For "p.s/m" plus any suffix. Suffix will be parsed again. See test for
|
||||
// expected output.
|
||||
longMethodConfigRegexpStr = `^([\w./]+)/((?:\w+)|[*])(.+)?$`
|
||||
|
||||
// For suffix from above, "{h:123,m:123}". See test for expected output.
|
||||
optionalLengthRegexpStr = `(?::(\d+))?` // Optional ":123".
|
||||
headerConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `}$`
|
||||
messageConfigRegexpStr = `^{m` + optionalLengthRegexpStr + `}$`
|
||||
headerMessageConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `;m` + optionalLengthRegexpStr + `}$`
|
||||
)
|
||||
|
||||
var (
|
||||
longMethodConfigRegexp = regexp.MustCompile(longMethodConfigRegexpStr)
|
||||
headerConfigRegexp = regexp.MustCompile(headerConfigRegexpStr)
|
||||
messageConfigRegexp = regexp.MustCompile(messageConfigRegexpStr)
|
||||
headerMessageConfigRegexp = regexp.MustCompile(headerMessageConfigRegexpStr)
|
||||
)
|
||||
|
||||
// Turn "service/method{h;m}" into "service", "method", "{h;m}".
|
||||
func parseMethodConfigAndSuffix(c string) (service, method, suffix string, _ error) {
|
||||
// Regexp result:
|
||||
//
|
||||
// in: "p.s/m{h:123,m:123}",
|
||||
// out: []string{"p.s/m{h:123,m:123}", "p.s", "m", "{h:123,m:123}"},
|
||||
match := longMethodConfigRegexp.FindStringSubmatch(c)
|
||||
if match == nil {
|
||||
return "", "", "", fmt.Errorf("%q contains invalid substring", c)
|
||||
}
|
||||
service = match[1]
|
||||
method = match[2]
|
||||
suffix = match[3]
|
||||
return
|
||||
}
|
||||
|
||||
// Turn "{h:123;m:345}" into 123, 345.
|
||||
//
|
||||
// Return maxUInt if length is unspecified.
|
||||
func parseHeaderMessageLengthConfig(c string) (hdrLenStr, msgLenStr uint64, err error) {
|
||||
if c == "" {
|
||||
return maxUInt, maxUInt, nil
|
||||
}
|
||||
// Header config only.
|
||||
if match := headerConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
if s := match[1]; s != "" {
|
||||
hdrLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
return hdrLenStr, 0, nil
|
||||
}
|
||||
return maxUInt, 0, nil
|
||||
}
|
||||
|
||||
// Message config only.
|
||||
if match := messageConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
if s := match[1]; s != "" {
|
||||
msgLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
return 0, msgLenStr, nil
|
||||
}
|
||||
return 0, maxUInt, nil
|
||||
}
|
||||
|
||||
// Header and message config both.
|
||||
if match := headerMessageConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
// Both hdr and msg are specified, but one or two of them might be empty.
|
||||
hdrLenStr = maxUInt
|
||||
msgLenStr = maxUInt
|
||||
if s := match[1]; s != "" {
|
||||
hdrLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
}
|
||||
if s := match[2]; s != "" {
|
||||
msgLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
}
|
||||
return hdrLenStr, msgLenStr, nil
|
||||
}
|
||||
return 0, 0, fmt.Errorf("%q contains invalid substring", c)
|
||||
}
|
||||
423
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
Normal file
423
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type callIDGenerator struct {
|
||||
id uint64
|
||||
}
|
||||
|
||||
func (g *callIDGenerator) next() uint64 {
|
||||
id := atomic.AddUint64(&g.id, 1)
|
||||
return id
|
||||
}
|
||||
|
||||
// reset is for testing only, and doesn't need to be thread safe.
|
||||
func (g *callIDGenerator) reset() {
|
||||
g.id = 0
|
||||
}
|
||||
|
||||
var idGen callIDGenerator
|
||||
|
||||
// MethodLogger is the sub-logger for each method.
|
||||
type MethodLogger struct {
|
||||
headerMaxLen, messageMaxLen uint64
|
||||
|
||||
callID uint64
|
||||
idWithinCallGen *callIDGenerator
|
||||
|
||||
sink Sink // TODO(blog): make this plugable.
|
||||
}
|
||||
|
||||
func newMethodLogger(h, m uint64) *MethodLogger {
|
||||
return &MethodLogger{
|
||||
headerMaxLen: h,
|
||||
messageMaxLen: m,
|
||||
|
||||
callID: idGen.next(),
|
||||
idWithinCallGen: &callIDGenerator{},
|
||||
|
||||
sink: defaultSink, // TODO(blog): make it plugable.
|
||||
}
|
||||
}
|
||||
|
||||
// Log creates a proto binary log entry, and logs it to the sink.
|
||||
func (ml *MethodLogger) Log(c LogEntryConfig) {
|
||||
m := c.toProto()
|
||||
timestamp, _ := ptypes.TimestampProto(time.Now())
|
||||
m.Timestamp = timestamp
|
||||
m.CallId = ml.callID
|
||||
m.SequenceIdWithinCall = ml.idWithinCallGen.next()
|
||||
|
||||
switch pay := m.Payload.(type) {
|
||||
case *pb.GrpcLogEntry_ClientHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
|
||||
case *pb.GrpcLogEntry_ServerHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
|
||||
case *pb.GrpcLogEntry_Message:
|
||||
m.PayloadTruncated = ml.truncateMessage(pay.Message)
|
||||
}
|
||||
|
||||
ml.sink.Write(m)
|
||||
}
|
||||
|
||||
func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
|
||||
if ml.headerMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
var (
|
||||
bytesLimit = ml.headerMaxLen
|
||||
index int
|
||||
)
|
||||
// At the end of the loop, index will be the first entry where the total
|
||||
// size is greater than the limit:
|
||||
//
|
||||
// len(entry[:index]) <= ml.hdr && len(entry[:index+1]) > ml.hdr.
|
||||
for ; index < len(mdPb.Entry); index++ {
|
||||
entry := mdPb.Entry[index]
|
||||
if entry.Key == "grpc-trace-bin" {
|
||||
// "grpc-trace-bin" is a special key. It's kept in the log entry,
|
||||
// but not counted towards the size limit.
|
||||
continue
|
||||
}
|
||||
currentEntryLen := uint64(len(entry.Value))
|
||||
if currentEntryLen > bytesLimit {
|
||||
break
|
||||
}
|
||||
bytesLimit -= currentEntryLen
|
||||
}
|
||||
truncated = index < len(mdPb.Entry)
|
||||
mdPb.Entry = mdPb.Entry[:index]
|
||||
return truncated
|
||||
}
|
||||
|
||||
func (ml *MethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
|
||||
if ml.messageMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
if ml.messageMaxLen >= uint64(len(msgPb.Data)) {
|
||||
return false
|
||||
}
|
||||
msgPb.Data = msgPb.Data[:ml.messageMaxLen]
|
||||
return true
|
||||
}
|
||||
|
||||
// LogEntryConfig represents the configuration for binary log entry.
|
||||
type LogEntryConfig interface {
|
||||
toProto() *pb.GrpcLogEntry
|
||||
}
|
||||
|
||||
// ClientHeader configs the binary log entry to be a ClientHeader entry.
|
||||
type ClientHeader struct {
|
||||
OnClientSide bool
|
||||
Header metadata.MD
|
||||
MethodName string
|
||||
Authority string
|
||||
Timeout time.Duration
|
||||
// PeerAddr is required only when it's on server side.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
|
||||
// This function doesn't need to set all the fields (e.g. seq ID). The Log
|
||||
// function will set the fields when necessary.
|
||||
clientHeader := &pb.ClientHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
MethodName: c.MethodName,
|
||||
Authority: c.Authority,
|
||||
}
|
||||
if c.Timeout > 0 {
|
||||
clientHeader.Timeout = ptypes.DurationProto(c.Timeout)
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
|
||||
Payload: &pb.GrpcLogEntry_ClientHeader{
|
||||
ClientHeader: clientHeader,
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerHeader configs the binary log entry to be a ServerHeader entry.
|
||||
type ServerHeader struct {
|
||||
OnClientSide bool
|
||||
Header metadata.MD
|
||||
// PeerAddr is required only when it's on client side.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerHeader) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
|
||||
Payload: &pb.GrpcLogEntry_ServerHeader{
|
||||
ServerHeader: &pb.ServerHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ClientMessage configs the binary log entry to be a ClientMessage entry.
|
||||
type ClientMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
}
|
||||
|
||||
func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
if m, ok := c.Message.(proto.Message); ok {
|
||||
data, err = proto.Marshal(m)
|
||||
if err != nil {
|
||||
grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
} else if b, ok := c.Message.([]byte); ok {
|
||||
data = b
|
||||
} else {
|
||||
grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
|
||||
Payload: &pb.GrpcLogEntry_Message{
|
||||
Message: &pb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerMessage configs the binary log entry to be a ServerMessage entry.
|
||||
type ServerMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
}
|
||||
|
||||
func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
if m, ok := c.Message.(proto.Message); ok {
|
||||
data, err = proto.Marshal(m)
|
||||
if err != nil {
|
||||
grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
} else if b, ok := c.Message.([]byte); ok {
|
||||
data = b
|
||||
} else {
|
||||
grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
|
||||
Payload: &pb.GrpcLogEntry_Message{
|
||||
Message: &pb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ClientHalfClose configs the binary log entry to be a ClientHalfClose entry.
|
||||
type ClientHalfClose struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
|
||||
Payload: nil, // No payload here.
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerTrailer configs the binary log entry to be a ServerTrailer entry.
|
||||
type ServerTrailer struct {
|
||||
OnClientSide bool
|
||||
Trailer metadata.MD
|
||||
// Err is the status error.
|
||||
Err error
|
||||
// PeerAddr is required only when it's on client side and the RPC is trailer
|
||||
// only.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
|
||||
st, ok := status.FromError(c.Err)
|
||||
if !ok {
|
||||
grpclog.Info("binarylogging: error in trailer is not a status error")
|
||||
}
|
||||
var (
|
||||
detailsBytes []byte
|
||||
err error
|
||||
)
|
||||
stProto := st.Proto()
|
||||
if stProto != nil && len(stProto.Details) != 0 {
|
||||
detailsBytes, err = proto.Marshal(stProto)
|
||||
if err != nil {
|
||||
grpclog.Infof("binarylogging: failed to marshal status proto: %v", err)
|
||||
}
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
|
||||
Payload: &pb.GrpcLogEntry_Trailer{
|
||||
Trailer: &pb.Trailer{
|
||||
Metadata: mdToMetadataProto(c.Trailer),
|
||||
StatusCode: uint32(st.Code()),
|
||||
StatusMessage: st.Message(),
|
||||
StatusDetails: detailsBytes,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Cancel configs the binary log entry to be a Cancel entry.
|
||||
type Cancel struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *Cancel) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL,
|
||||
Payload: nil,
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// metadataKeyOmit returns whether the metadata entry with this key should be
|
||||
// omitted.
|
||||
func metadataKeyOmit(key string) bool {
|
||||
switch key {
|
||||
case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te":
|
||||
return true
|
||||
case "grpc-trace-bin": // grpc-trace-bin is special because it's visiable to users.
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(key, "grpc-")
|
||||
}
|
||||
|
||||
func mdToMetadataProto(md metadata.MD) *pb.Metadata {
|
||||
ret := &pb.Metadata{}
|
||||
for k, vv := range md {
|
||||
if metadataKeyOmit(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
ret.Entry = append(ret.Entry,
|
||||
&pb.MetadataEntry{
|
||||
Key: k,
|
||||
Value: []byte(v),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func addrToProto(addr net.Addr) *pb.Address {
|
||||
ret := &pb.Address{}
|
||||
switch a := addr.(type) {
|
||||
case *net.TCPAddr:
|
||||
if a.IP.To4() != nil {
|
||||
ret.Type = pb.Address_TYPE_IPV4
|
||||
} else if a.IP.To16() != nil {
|
||||
ret.Type = pb.Address_TYPE_IPV6
|
||||
} else {
|
||||
ret.Type = pb.Address_TYPE_UNKNOWN
|
||||
// Do not set address and port fields.
|
||||
break
|
||||
}
|
||||
ret.Address = a.IP.String()
|
||||
ret.IpPort = uint32(a.Port)
|
||||
case *net.UnixAddr:
|
||||
ret.Type = pb.Address_TYPE_UNIX
|
||||
ret.Address = a.String()
|
||||
default:
|
||||
ret.Type = pb.Address_TYPE_UNKNOWN
|
||||
}
|
||||
return ret
|
||||
}
|
||||
33
vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
generated
vendored
Executable file
33
vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
generated
vendored
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2018 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
|
||||
function finish {
|
||||
rm -rf "$TMP"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
pushd "$TMP"
|
||||
mkdir -p grpc/binarylog/grpc_binarylog_v1
|
||||
curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/binlog/v1/binarylog.proto > grpc/binarylog/grpc_binarylog_v1/binarylog.proto
|
||||
|
||||
protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/binarylog/grpc_binarylog_v1/*.proto
|
||||
popd
|
||||
rm -f ./grpc_binarylog_v1/*.pb.go
|
||||
cp "$TMP"/grpc/binarylog/grpc_binarylog_v1/*.pb.go ../../binarylog/grpc_binarylog_v1/
|
||||
|
||||
162
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
Normal file
162
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultSink Sink = &noopSink{} // TODO(blog): change this default (file in /tmp).
|
||||
)
|
||||
|
||||
// SetDefaultSink sets the sink where binary logs will be written to.
|
||||
//
|
||||
// Not thread safe. Only set during initialization.
|
||||
func SetDefaultSink(s Sink) {
|
||||
if defaultSink != nil {
|
||||
defaultSink.Close()
|
||||
}
|
||||
defaultSink = s
|
||||
}
|
||||
|
||||
// Sink writes log entry into the binary log sink.
|
||||
type Sink interface {
|
||||
// Write will be called to write the log entry into the sink.
|
||||
//
|
||||
// It should be thread-safe so it can be called in parallel.
|
||||
Write(*pb.GrpcLogEntry) error
|
||||
// Close will be called when the Sink is replaced by a new Sink.
|
||||
Close() error
|
||||
}
|
||||
|
||||
type noopSink struct{}
|
||||
|
||||
func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil }
|
||||
func (ns *noopSink) Close() error { return nil }
|
||||
|
||||
// newWriterSink creates a binary log sink with the given writer.
|
||||
//
|
||||
// Write() marshalls the proto message and writes it to the given writer. Each
|
||||
// message is prefixed with a 4 byte big endian unsigned integer as the length.
|
||||
//
|
||||
// No buffer is done, Close() doesn't try to close the writer.
|
||||
func newWriterSink(w io.Writer) *writerSink {
|
||||
return &writerSink{out: w}
|
||||
}
|
||||
|
||||
type writerSink struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (ws *writerSink) Write(e *pb.GrpcLogEntry) error {
|
||||
b, err := proto.Marshal(e)
|
||||
if err != nil {
|
||||
grpclog.Infof("binary logging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
hdr := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(hdr, uint32(len(b)))
|
||||
if _, err := ws.out.Write(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := ws.out.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ws *writerSink) Close() error { return nil }
|
||||
|
||||
type bufWriteCloserSink struct {
|
||||
mu sync.Mutex
|
||||
closer io.Closer
|
||||
out *writerSink // out is built on buf.
|
||||
buf *bufio.Writer // buf is kept for flush.
|
||||
|
||||
writeStartOnce sync.Once
|
||||
writeTicker *time.Ticker
|
||||
}
|
||||
|
||||
func (fs *bufWriteCloserSink) Write(e *pb.GrpcLogEntry) error {
|
||||
// Start the write loop when Write is called.
|
||||
fs.writeStartOnce.Do(fs.startFlushGoroutine)
|
||||
fs.mu.Lock()
|
||||
if err := fs.out.Write(e); err != nil {
|
||||
fs.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
fs.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
bufFlushDuration = 60 * time.Second
|
||||
)
|
||||
|
||||
func (fs *bufWriteCloserSink) startFlushGoroutine() {
|
||||
fs.writeTicker = time.NewTicker(bufFlushDuration)
|
||||
go func() {
|
||||
for range fs.writeTicker.C {
|
||||
fs.mu.Lock()
|
||||
fs.buf.Flush()
|
||||
fs.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (fs *bufWriteCloserSink) Close() error {
|
||||
if fs.writeTicker != nil {
|
||||
fs.writeTicker.Stop()
|
||||
}
|
||||
fs.mu.Lock()
|
||||
fs.buf.Flush()
|
||||
fs.closer.Close()
|
||||
fs.out.Close()
|
||||
fs.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func newBufWriteCloserSink(o io.WriteCloser) Sink {
|
||||
bufW := bufio.NewWriter(o)
|
||||
return &bufWriteCloserSink{
|
||||
closer: o,
|
||||
out: newWriterSink(bufW),
|
||||
buf: bufW,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTempFileSink creates a temp file and returns a Sink that writes to this
|
||||
// file.
|
||||
func NewTempFileSink() (Sink, error) {
|
||||
tempFile, err := ioutil.TempFile("/tmp", "grpcgo_binarylog_*.txt")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create temp file: %v", err)
|
||||
}
|
||||
return newBufWriteCloserSink(tempFile), nil
|
||||
}
|
||||
41
vendor/google.golang.org/grpc/internal/binarylog/util.go
generated
vendored
Normal file
41
vendor/google.golang.org/grpc/internal/binarylog/util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// parseMethodName splits service and method from the input. It expects format
|
||||
// "/service/method".
|
||||
//
|
||||
// TODO: move to internal/grpcutil.
|
||||
func parseMethodName(methodName string) (service, method string, _ error) {
|
||||
if !strings.HasPrefix(methodName, "/") {
|
||||
return "", "", errors.New("invalid method name: should start with /")
|
||||
}
|
||||
methodName = methodName[1:]
|
||||
|
||||
pos := strings.LastIndex(methodName, "/")
|
||||
if pos < 0 {
|
||||
return "", "", errors.New("invalid method name: suffix /method is missing")
|
||||
}
|
||||
return methodName[:pos], methodName[pos+1:], nil
|
||||
}
|
||||
727
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
Normal file
727
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package channelz defines APIs for enabling channelz service, entry
|
||||
// registration/deletion, and accessing channelz data. It also defines channelz
|
||||
// metric struct formats.
|
||||
//
|
||||
// All APIs in this package are experimental.
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxTraceEntry int32 = 30
|
||||
)
|
||||
|
||||
var (
|
||||
db dbWrapper
|
||||
idGen idGenerator
|
||||
// EntryPerPage defines the number of channelz entries to be shown on a web page.
|
||||
EntryPerPage = int64(50)
|
||||
curState int32
|
||||
maxTraceEntry = defaultMaxTraceEntry
|
||||
)
|
||||
|
||||
// TurnOn turns on channelz data collection.
|
||||
func TurnOn() {
|
||||
if !IsOn() {
|
||||
NewChannelzStorage()
|
||||
atomic.StoreInt32(&curState, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// IsOn returns whether channelz data collection is on.
|
||||
func IsOn() bool {
|
||||
return atomic.CompareAndSwapInt32(&curState, 1, 1)
|
||||
}
|
||||
|
||||
// SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
|
||||
// Setting it to 0 will disable channel tracing.
|
||||
func SetMaxTraceEntry(i int32) {
|
||||
atomic.StoreInt32(&maxTraceEntry, i)
|
||||
}
|
||||
|
||||
// ResetMaxTraceEntryToDefault resets the maximum number of trace entry per entity to default.
|
||||
func ResetMaxTraceEntryToDefault() {
|
||||
atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
|
||||
}
|
||||
|
||||
func getMaxTraceEntry() int {
|
||||
i := atomic.LoadInt32(&maxTraceEntry)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
// dbWarpper wraps around a reference to internal channelz data storage, and
|
||||
// provide synchronized functionality to set and get the reference.
|
||||
type dbWrapper struct {
|
||||
mu sync.RWMutex
|
||||
DB *channelMap
|
||||
}
|
||||
|
||||
func (d *dbWrapper) set(db *channelMap) {
|
||||
d.mu.Lock()
|
||||
d.DB = db
|
||||
d.mu.Unlock()
|
||||
}
|
||||
|
||||
func (d *dbWrapper) get() *channelMap {
|
||||
d.mu.RLock()
|
||||
defer d.mu.RUnlock()
|
||||
return d.DB
|
||||
}
|
||||
|
||||
// NewChannelzStorage initializes channelz data storage and id generator.
|
||||
//
|
||||
// This function returns a cleanup function to wait for all channelz state to be reset by the
|
||||
// grpc goroutines when those entities get closed. By using this cleanup function, we make sure tests
|
||||
// don't mess up each other, i.e. lingering goroutine from previous test doing entity removal happen
|
||||
// to remove some entity just register by the new test, since the id space is the same.
|
||||
//
|
||||
// Note: This function is exported for testing purpose only. User should not call
|
||||
// it in most cases.
|
||||
func NewChannelzStorage() (cleanup func() error) {
|
||||
db.set(&channelMap{
|
||||
topLevelChannels: make(map[int64]struct{}),
|
||||
channels: make(map[int64]*channel),
|
||||
listenSockets: make(map[int64]*listenSocket),
|
||||
normalSockets: make(map[int64]*normalSocket),
|
||||
servers: make(map[int64]*server),
|
||||
subChannels: make(map[int64]*subChannel),
|
||||
})
|
||||
idGen.reset()
|
||||
return func() error {
|
||||
var err error
|
||||
cm := db.get()
|
||||
if cm == nil {
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < 1000; i++ {
|
||||
cm.mu.Lock()
|
||||
if len(cm.topLevelChannels) == 0 && len(cm.servers) == 0 && len(cm.channels) == 0 && len(cm.subChannels) == 0 && len(cm.listenSockets) == 0 && len(cm.normalSockets) == 0 {
|
||||
cm.mu.Unlock()
|
||||
// all things stored in the channelz map have been cleared.
|
||||
return nil
|
||||
}
|
||||
cm.mu.Unlock()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
cm.mu.Lock()
|
||||
err = fmt.Errorf("after 10s the channelz map has not been cleaned up yet, topchannels: %d, servers: %d, channels: %d, subchannels: %d, listen sockets: %d, normal sockets: %d", len(cm.topLevelChannels), len(cm.servers), len(cm.channels), len(cm.subChannels), len(cm.listenSockets), len(cm.normalSockets))
|
||||
cm.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// GetTopChannels returns a slice of top channel's ChannelMetric, along with a
|
||||
// boolean indicating whether there's more top channels to be queried for.
|
||||
//
|
||||
// The arg id specifies that only top channel with id at or above it will be included
|
||||
// in the result. The returned slice is up to a length of the arg maxResults or
|
||||
// EntryPerPage if maxResults is zero, and is sorted in ascending id order.
|
||||
func GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
|
||||
return db.get().GetTopChannels(id, maxResults)
|
||||
}
|
||||
|
||||
// GetServers returns a slice of server's ServerMetric, along with a
|
||||
// boolean indicating whether there's more servers to be queried for.
|
||||
//
|
||||
// The arg id specifies that only server with id at or above it will be included
|
||||
// in the result. The returned slice is up to a length of the arg maxResults or
|
||||
// EntryPerPage if maxResults is zero, and is sorted in ascending id order.
|
||||
func GetServers(id int64, maxResults int64) ([]*ServerMetric, bool) {
|
||||
return db.get().GetServers(id, maxResults)
|
||||
}
|
||||
|
||||
// GetServerSockets returns a slice of server's (identified by id) normal socket's
|
||||
// SocketMetric, along with a boolean indicating whether there's more sockets to
|
||||
// be queried for.
|
||||
//
|
||||
// The arg startID specifies that only sockets with id at or above it will be
|
||||
// included in the result. The returned slice is up to a length of the arg maxResults
|
||||
// or EntryPerPage if maxResults is zero, and is sorted in ascending id order.
|
||||
func GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
|
||||
return db.get().GetServerSockets(id, startID, maxResults)
|
||||
}
|
||||
|
||||
// GetChannel returns the ChannelMetric for the channel (identified by id).
|
||||
func GetChannel(id int64) *ChannelMetric {
|
||||
return db.get().GetChannel(id)
|
||||
}
|
||||
|
||||
// GetSubChannel returns the SubChannelMetric for the subchannel (identified by id).
|
||||
func GetSubChannel(id int64) *SubChannelMetric {
|
||||
return db.get().GetSubChannel(id)
|
||||
}
|
||||
|
||||
// GetSocket returns the SocketInternalMetric for the socket (identified by id).
|
||||
func GetSocket(id int64) *SocketMetric {
|
||||
return db.get().GetSocket(id)
|
||||
}
|
||||
|
||||
// GetServer returns the ServerMetric for the server (identified by id).
|
||||
func GetServer(id int64) *ServerMetric {
|
||||
return db.get().GetServer(id)
|
||||
}
|
||||
|
||||
// RegisterChannel registers the given channel c in channelz database with ref
|
||||
// as its reference name, and add it to the child list of its parent (identified
|
||||
// by pid). pid = 0 means no parent. It returns the unique channelz tracking id
|
||||
// assigned to this channel.
|
||||
func RegisterChannel(c Channel, pid int64, ref string) int64 {
|
||||
id := idGen.genID()
|
||||
cn := &channel{
|
||||
refName: ref,
|
||||
c: c,
|
||||
subChans: make(map[int64]string),
|
||||
nestedChans: make(map[int64]string),
|
||||
id: id,
|
||||
pid: pid,
|
||||
trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
|
||||
}
|
||||
if pid == 0 {
|
||||
db.get().addChannel(id, cn, true, pid, ref)
|
||||
} else {
|
||||
db.get().addChannel(id, cn, false, pid, ref)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// RegisterSubChannel registers the given channel c in channelz database with ref
|
||||
// as its reference name, and add it to the child list of its parent (identified
|
||||
// by pid). It returns the unique channelz tracking id assigned to this subchannel.
|
||||
func RegisterSubChannel(c Channel, pid int64, ref string) int64 {
|
||||
if pid == 0 {
|
||||
grpclog.Error("a SubChannel's parent id cannot be 0")
|
||||
return 0
|
||||
}
|
||||
id := idGen.genID()
|
||||
sc := &subChannel{
|
||||
refName: ref,
|
||||
c: c,
|
||||
sockets: make(map[int64]string),
|
||||
id: id,
|
||||
pid: pid,
|
||||
trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
|
||||
}
|
||||
db.get().addSubChannel(id, sc, pid, ref)
|
||||
return id
|
||||
}
|
||||
|
||||
// RegisterServer registers the given server s in channelz database. It returns
|
||||
// the unique channelz tracking id assigned to this server.
|
||||
func RegisterServer(s Server, ref string) int64 {
|
||||
id := idGen.genID()
|
||||
svr := &server{
|
||||
refName: ref,
|
||||
s: s,
|
||||
sockets: make(map[int64]string),
|
||||
listenSockets: make(map[int64]string),
|
||||
id: id,
|
||||
}
|
||||
db.get().addServer(id, svr)
|
||||
return id
|
||||
}
|
||||
|
||||
// RegisterListenSocket registers the given listen socket s in channelz database
|
||||
// with ref as its reference name, and add it to the child list of its parent
|
||||
// (identified by pid). It returns the unique channelz tracking id assigned to
|
||||
// this listen socket.
|
||||
func RegisterListenSocket(s Socket, pid int64, ref string) int64 {
|
||||
if pid == 0 {
|
||||
grpclog.Error("a ListenSocket's parent id cannot be 0")
|
||||
return 0
|
||||
}
|
||||
id := idGen.genID()
|
||||
ls := &listenSocket{refName: ref, s: s, id: id, pid: pid}
|
||||
db.get().addListenSocket(id, ls, pid, ref)
|
||||
return id
|
||||
}
|
||||
|
||||
// RegisterNormalSocket registers the given normal socket s in channelz database
|
||||
// with ref as its reference name, and add it to the child list of its parent
|
||||
// (identified by pid). It returns the unique channelz tracking id assigned to
|
||||
// this normal socket.
|
||||
func RegisterNormalSocket(s Socket, pid int64, ref string) int64 {
|
||||
if pid == 0 {
|
||||
grpclog.Error("a NormalSocket's parent id cannot be 0")
|
||||
return 0
|
||||
}
|
||||
id := idGen.genID()
|
||||
ns := &normalSocket{refName: ref, s: s, id: id, pid: pid}
|
||||
db.get().addNormalSocket(id, ns, pid, ref)
|
||||
return id
|
||||
}
|
||||
|
||||
// RemoveEntry removes an entry with unique channelz trakcing id to be id from
|
||||
// channelz database.
|
||||
func RemoveEntry(id int64) {
|
||||
db.get().removeEntry(id)
|
||||
}
|
||||
|
||||
// TraceEventDesc is what the caller of AddTraceEvent should provide to describe the event to be added
|
||||
// to the channel trace.
|
||||
// The Parent field is optional. It is used for event that will be recorded in the entity's parent
|
||||
// trace also.
|
||||
type TraceEventDesc struct {
|
||||
Desc string
|
||||
Severity Severity
|
||||
Parent *TraceEventDesc
|
||||
}
|
||||
|
||||
// AddTraceEvent adds trace related to the entity with specified id, using the provided TraceEventDesc.
|
||||
func AddTraceEvent(id int64, desc *TraceEventDesc) {
|
||||
if getMaxTraceEntry() == 0 {
|
||||
return
|
||||
}
|
||||
db.get().traceEvent(id, desc)
|
||||
}
|
||||
|
||||
// channelMap is the storage data structure for channelz.
|
||||
// Methods of channelMap can be divided in two two categories with respect to locking.
|
||||
// 1. Methods acquire the global lock.
|
||||
// 2. Methods that can only be called when global lock is held.
|
||||
// A second type of method need always to be called inside a first type of method.
|
||||
type channelMap struct {
|
||||
mu sync.RWMutex
|
||||
topLevelChannels map[int64]struct{}
|
||||
servers map[int64]*server
|
||||
channels map[int64]*channel
|
||||
subChannels map[int64]*subChannel
|
||||
listenSockets map[int64]*listenSocket
|
||||
normalSockets map[int64]*normalSocket
|
||||
}
|
||||
|
||||
func (c *channelMap) addServer(id int64, s *server) {
|
||||
c.mu.Lock()
|
||||
s.cm = c
|
||||
c.servers[id] = s
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64, ref string) {
|
||||
c.mu.Lock()
|
||||
cn.cm = c
|
||||
cn.trace.cm = c
|
||||
c.channels[id] = cn
|
||||
if isTopChannel {
|
||||
c.topLevelChannels[id] = struct{}{}
|
||||
} else {
|
||||
c.findEntry(pid).addChild(id, cn)
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64, ref string) {
|
||||
c.mu.Lock()
|
||||
sc.cm = c
|
||||
sc.trace.cm = c
|
||||
c.subChannels[id] = sc
|
||||
c.findEntry(pid).addChild(id, sc)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64, ref string) {
|
||||
c.mu.Lock()
|
||||
ls.cm = c
|
||||
c.listenSockets[id] = ls
|
||||
c.findEntry(pid).addChild(id, ls)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64, ref string) {
|
||||
c.mu.Lock()
|
||||
ns.cm = c
|
||||
c.normalSockets[id] = ns
|
||||
c.findEntry(pid).addChild(id, ns)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// removeEntry triggers the removal of an entry, which may not indeed delete the entry, if it has to
|
||||
// wait on the deletion of its children and until no other entity's channel trace references it.
|
||||
// It may lead to a chain of entry deletion. For example, deleting the last socket of a gracefully
|
||||
// shutting down server will lead to the server being also deleted.
|
||||
func (c *channelMap) removeEntry(id int64) {
|
||||
c.mu.Lock()
|
||||
c.findEntry(id).triggerDelete()
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller
|
||||
func (c *channelMap) decrTraceRefCount(id int64) {
|
||||
e := c.findEntry(id)
|
||||
if v, ok := e.(tracedChannel); ok {
|
||||
v.decrTraceRefCount()
|
||||
e.deleteSelfIfReady()
|
||||
}
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller.
|
||||
func (c *channelMap) findEntry(id int64) entry {
|
||||
var v entry
|
||||
var ok bool
|
||||
if v, ok = c.channels[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok = c.subChannels[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok = c.servers[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok = c.listenSockets[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok = c.normalSockets[id]; ok {
|
||||
return v
|
||||
}
|
||||
return &dummyEntry{idNotFound: id}
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller
|
||||
// deleteEntry simply deletes an entry from the channelMap. Before calling this
|
||||
// method, caller must check this entry is ready to be deleted, i.e removeEntry()
|
||||
// has been called on it, and no children still exist.
|
||||
// Conditionals are ordered by the expected frequency of deletion of each entity
|
||||
// type, in order to optimize performance.
|
||||
func (c *channelMap) deleteEntry(id int64) {
|
||||
var ok bool
|
||||
if _, ok = c.normalSockets[id]; ok {
|
||||
delete(c.normalSockets, id)
|
||||
return
|
||||
}
|
||||
if _, ok = c.subChannels[id]; ok {
|
||||
delete(c.subChannels, id)
|
||||
return
|
||||
}
|
||||
if _, ok = c.channels[id]; ok {
|
||||
delete(c.channels, id)
|
||||
delete(c.topLevelChannels, id)
|
||||
return
|
||||
}
|
||||
if _, ok = c.listenSockets[id]; ok {
|
||||
delete(c.listenSockets, id)
|
||||
return
|
||||
}
|
||||
if _, ok = c.servers[id]; ok {
|
||||
delete(c.servers, id)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (c *channelMap) traceEvent(id int64, desc *TraceEventDesc) {
|
||||
c.mu.Lock()
|
||||
child := c.findEntry(id)
|
||||
childTC, ok := child.(tracedChannel)
|
||||
if !ok {
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
childTC.getChannelTrace().append(&TraceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
|
||||
if desc.Parent != nil {
|
||||
parent := c.findEntry(child.getParentID())
|
||||
var chanType RefChannelType
|
||||
switch child.(type) {
|
||||
case *channel:
|
||||
chanType = RefChannel
|
||||
case *subChannel:
|
||||
chanType = RefSubChannel
|
||||
}
|
||||
if parentTC, ok := parent.(tracedChannel); ok {
|
||||
parentTC.getChannelTrace().append(&TraceEvent{
|
||||
Desc: desc.Parent.Desc,
|
||||
Severity: desc.Parent.Severity,
|
||||
Timestamp: time.Now(),
|
||||
RefID: id,
|
||||
RefName: childTC.getRefName(),
|
||||
RefType: chanType,
|
||||
})
|
||||
childTC.incrTraceRefCount()
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
type int64Slice []int64
|
||||
|
||||
func (s int64Slice) Len() int { return len(s) }
|
||||
func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
|
||||
|
||||
func copyMap(m map[int64]string) map[int64]string {
|
||||
n := make(map[int64]string)
|
||||
for k, v := range m {
|
||||
n[k] = v
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func min(a, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *channelMap) GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntryPerPage
|
||||
}
|
||||
c.mu.RLock()
|
||||
l := int64(len(c.topLevelChannels))
|
||||
ids := make([]int64, 0, l)
|
||||
cns := make([]*channel, 0, min(l, maxResults))
|
||||
|
||||
for k := range c.topLevelChannels {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
|
||||
count := int64(0)
|
||||
var end bool
|
||||
var t []*ChannelMetric
|
||||
for i, v := range ids[idx:] {
|
||||
if count == maxResults {
|
||||
break
|
||||
}
|
||||
if cn, ok := c.channels[v]; ok {
|
||||
cns = append(cns, cn)
|
||||
t = append(t, &ChannelMetric{
|
||||
NestedChans: copyMap(cn.nestedChans),
|
||||
SubChans: copyMap(cn.subChans),
|
||||
})
|
||||
count++
|
||||
}
|
||||
if i == len(ids[idx:])-1 {
|
||||
end = true
|
||||
break
|
||||
}
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
if count == 0 {
|
||||
end = true
|
||||
}
|
||||
|
||||
for i, cn := range cns {
|
||||
t[i].ChannelData = cn.c.ChannelzMetric()
|
||||
t[i].ID = cn.id
|
||||
t[i].RefName = cn.refName
|
||||
t[i].Trace = cn.trace.dumpData()
|
||||
}
|
||||
return t, end
|
||||
}
|
||||
|
||||
func (c *channelMap) GetServers(id, maxResults int64) ([]*ServerMetric, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntryPerPage
|
||||
}
|
||||
c.mu.RLock()
|
||||
l := int64(len(c.servers))
|
||||
ids := make([]int64, 0, l)
|
||||
ss := make([]*server, 0, min(l, maxResults))
|
||||
for k := range c.servers {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
|
||||
count := int64(0)
|
||||
var end bool
|
||||
var s []*ServerMetric
|
||||
for i, v := range ids[idx:] {
|
||||
if count == maxResults {
|
||||
break
|
||||
}
|
||||
if svr, ok := c.servers[v]; ok {
|
||||
ss = append(ss, svr)
|
||||
s = append(s, &ServerMetric{
|
||||
ListenSockets: copyMap(svr.listenSockets),
|
||||
})
|
||||
count++
|
||||
}
|
||||
if i == len(ids[idx:])-1 {
|
||||
end = true
|
||||
break
|
||||
}
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
if count == 0 {
|
||||
end = true
|
||||
}
|
||||
|
||||
for i, svr := range ss {
|
||||
s[i].ServerData = svr.s.ChannelzMetric()
|
||||
s[i].ID = svr.id
|
||||
s[i].RefName = svr.refName
|
||||
}
|
||||
return s, end
|
||||
}
|
||||
|
||||
func (c *channelMap) GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntryPerPage
|
||||
}
|
||||
var svr *server
|
||||
var ok bool
|
||||
c.mu.RLock()
|
||||
if svr, ok = c.servers[id]; !ok {
|
||||
// server with id doesn't exist.
|
||||
c.mu.RUnlock()
|
||||
return nil, true
|
||||
}
|
||||
svrskts := svr.sockets
|
||||
l := int64(len(svrskts))
|
||||
ids := make([]int64, 0, l)
|
||||
sks := make([]*normalSocket, 0, min(l, maxResults))
|
||||
for k := range svrskts {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
|
||||
count := int64(0)
|
||||
var end bool
|
||||
for i, v := range ids[idx:] {
|
||||
if count == maxResults {
|
||||
break
|
||||
}
|
||||
if ns, ok := c.normalSockets[v]; ok {
|
||||
sks = append(sks, ns)
|
||||
count++
|
||||
}
|
||||
if i == len(ids[idx:])-1 {
|
||||
end = true
|
||||
break
|
||||
}
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
if count == 0 {
|
||||
end = true
|
||||
}
|
||||
var s []*SocketMetric
|
||||
for _, ns := range sks {
|
||||
sm := &SocketMetric{}
|
||||
sm.SocketData = ns.s.ChannelzMetric()
|
||||
sm.ID = ns.id
|
||||
sm.RefName = ns.refName
|
||||
s = append(s, sm)
|
||||
}
|
||||
return s, end
|
||||
}
|
||||
|
||||
func (c *channelMap) GetChannel(id int64) *ChannelMetric {
|
||||
cm := &ChannelMetric{}
|
||||
var cn *channel
|
||||
var ok bool
|
||||
c.mu.RLock()
|
||||
if cn, ok = c.channels[id]; !ok {
|
||||
// channel with id doesn't exist.
|
||||
c.mu.RUnlock()
|
||||
return nil
|
||||
}
|
||||
cm.NestedChans = copyMap(cn.nestedChans)
|
||||
cm.SubChans = copyMap(cn.subChans)
|
||||
// cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
|
||||
// holding the lock to prevent potential data race.
|
||||
chanCopy := cn.c
|
||||
c.mu.RUnlock()
|
||||
cm.ChannelData = chanCopy.ChannelzMetric()
|
||||
cm.ID = cn.id
|
||||
cm.RefName = cn.refName
|
||||
cm.Trace = cn.trace.dumpData()
|
||||
return cm
|
||||
}
|
||||
|
||||
func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
|
||||
cm := &SubChannelMetric{}
|
||||
var sc *subChannel
|
||||
var ok bool
|
||||
c.mu.RLock()
|
||||
if sc, ok = c.subChannels[id]; !ok {
|
||||
// subchannel with id doesn't exist.
|
||||
c.mu.RUnlock()
|
||||
return nil
|
||||
}
|
||||
cm.Sockets = copyMap(sc.sockets)
|
||||
// sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
|
||||
// holding the lock to prevent potential data race.
|
||||
chanCopy := sc.c
|
||||
c.mu.RUnlock()
|
||||
cm.ChannelData = chanCopy.ChannelzMetric()
|
||||
cm.ID = sc.id
|
||||
cm.RefName = sc.refName
|
||||
cm.Trace = sc.trace.dumpData()
|
||||
return cm
|
||||
}
|
||||
|
||||
func (c *channelMap) GetSocket(id int64) *SocketMetric {
|
||||
sm := &SocketMetric{}
|
||||
c.mu.RLock()
|
||||
if ls, ok := c.listenSockets[id]; ok {
|
||||
c.mu.RUnlock()
|
||||
sm.SocketData = ls.s.ChannelzMetric()
|
||||
sm.ID = ls.id
|
||||
sm.RefName = ls.refName
|
||||
return sm
|
||||
}
|
||||
if ns, ok := c.normalSockets[id]; ok {
|
||||
c.mu.RUnlock()
|
||||
sm.SocketData = ns.s.ChannelzMetric()
|
||||
sm.ID = ns.id
|
||||
sm.RefName = ns.refName
|
||||
return sm
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *channelMap) GetServer(id int64) *ServerMetric {
|
||||
sm := &ServerMetric{}
|
||||
var svr *server
|
||||
var ok bool
|
||||
c.mu.RLock()
|
||||
if svr, ok = c.servers[id]; !ok {
|
||||
c.mu.RUnlock()
|
||||
return nil
|
||||
}
|
||||
sm.ListenSockets = copyMap(svr.listenSockets)
|
||||
c.mu.RUnlock()
|
||||
sm.ID = svr.id
|
||||
sm.RefName = svr.refName
|
||||
sm.ServerData = svr.s.ChannelzMetric()
|
||||
return sm
|
||||
}
|
||||
|
||||
type idGenerator struct {
|
||||
id int64
|
||||
}
|
||||
|
||||
func (i *idGenerator) reset() {
|
||||
atomic.StoreInt64(&i.id, 0)
|
||||
}
|
||||
|
||||
func (i *idGenerator) genID() int64 {
|
||||
return atomic.AddInt64(&i.id, 1)
|
||||
}
|
||||
702
vendor/google.golang.org/grpc/internal/channelz/types.go
generated
vendored
Normal file
702
vendor/google.golang.org/grpc/internal/channelz/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,702 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// entry represents a node in the channelz database.
|
||||
type entry interface {
|
||||
// addChild adds a child e, whose channelz id is id to child list
|
||||
addChild(id int64, e entry)
|
||||
// deleteChild deletes a child with channelz id to be id from child list
|
||||
deleteChild(id int64)
|
||||
// triggerDelete tries to delete self from channelz database. However, if child
|
||||
// list is not empty, then deletion from the database is on hold until the last
|
||||
// child is deleted from database.
|
||||
triggerDelete()
|
||||
// deleteSelfIfReady check whether triggerDelete() has been called before, and whether child
|
||||
// list is now empty. If both conditions are met, then delete self from database.
|
||||
deleteSelfIfReady()
|
||||
// getParentID returns parent ID of the entry. 0 value parent ID means no parent.
|
||||
getParentID() int64
|
||||
}
|
||||
|
||||
// dummyEntry is a fake entry to handle entry not found case.
|
||||
type dummyEntry struct {
|
||||
idNotFound int64
|
||||
}
|
||||
|
||||
func (d *dummyEntry) addChild(id int64, e entry) {
|
||||
// Note: It is possible for a normal program to reach here under race condition.
|
||||
// For example, there could be a race between ClientConn.Close() info being propagated
|
||||
// to addrConn and http2Client. ClientConn.Close() cancel the context and result
|
||||
// in http2Client to error. The error info is then caught by transport monitor
|
||||
// and before addrConn.tearDown() is called in side ClientConn.Close(). Therefore,
|
||||
// the addrConn will create a new transport. And when registering the new transport in
|
||||
// channelz, its parent addrConn could have already been torn down and deleted
|
||||
// from channelz tracking, and thus reach the code here.
|
||||
grpclog.Infof("attempt to add child of type %T with id %d to a parent (id=%d) that doesn't currently exist", e, id, d.idNotFound)
|
||||
}
|
||||
|
||||
func (d *dummyEntry) deleteChild(id int64) {
|
||||
// It is possible for a normal program to reach here under race condition.
|
||||
// Refer to the example described in addChild().
|
||||
grpclog.Infof("attempt to delete child with id %d from a parent (id=%d) that doesn't currently exist", id, d.idNotFound)
|
||||
}
|
||||
|
||||
func (d *dummyEntry) triggerDelete() {
|
||||
grpclog.Warningf("attempt to delete an entry (id=%d) that doesn't currently exist", d.idNotFound)
|
||||
}
|
||||
|
||||
func (*dummyEntry) deleteSelfIfReady() {
|
||||
// code should not reach here. deleteSelfIfReady is always called on an existing entry.
|
||||
}
|
||||
|
||||
func (*dummyEntry) getParentID() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ChannelMetric defines the info channelz provides for a specific Channel, which
|
||||
// includes ChannelInternalMetric and channelz-specific data, such as channelz id,
|
||||
// child list, etc.
|
||||
type ChannelMetric struct {
|
||||
// ID is the channelz id of this channel.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this channel.
|
||||
RefName string
|
||||
// ChannelData contains channel internal metric reported by the channel through
|
||||
// ChannelzMetric().
|
||||
ChannelData *ChannelInternalMetric
|
||||
// NestedChans tracks the nested channel type children of this channel in the format of
|
||||
// a map from nested channel channelz id to corresponding reference string.
|
||||
NestedChans map[int64]string
|
||||
// SubChans tracks the subchannel type children of this channel in the format of a
|
||||
// map from subchannel channelz id to corresponding reference string.
|
||||
SubChans map[int64]string
|
||||
// Sockets tracks the socket type children of this channel in the format of a map
|
||||
// from socket channelz id to corresponding reference string.
|
||||
// Note current grpc implementation doesn't allow channel having sockets directly,
|
||||
// therefore, this is field is unused.
|
||||
Sockets map[int64]string
|
||||
// Trace contains the most recent traced events.
|
||||
Trace *ChannelTrace
|
||||
}
|
||||
|
||||
// SubChannelMetric defines the info channelz provides for a specific SubChannel,
|
||||
// which includes ChannelInternalMetric and channelz-specific data, such as
|
||||
// channelz id, child list, etc.
|
||||
type SubChannelMetric struct {
|
||||
// ID is the channelz id of this subchannel.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this subchannel.
|
||||
RefName string
|
||||
// ChannelData contains subchannel internal metric reported by the subchannel
|
||||
// through ChannelzMetric().
|
||||
ChannelData *ChannelInternalMetric
|
||||
// NestedChans tracks the nested channel type children of this subchannel in the format of
|
||||
// a map from nested channel channelz id to corresponding reference string.
|
||||
// Note current grpc implementation doesn't allow subchannel to have nested channels
|
||||
// as children, therefore, this field is unused.
|
||||
NestedChans map[int64]string
|
||||
// SubChans tracks the subchannel type children of this subchannel in the format of a
|
||||
// map from subchannel channelz id to corresponding reference string.
|
||||
// Note current grpc implementation doesn't allow subchannel to have subchannels
|
||||
// as children, therefore, this field is unused.
|
||||
SubChans map[int64]string
|
||||
// Sockets tracks the socket type children of this subchannel in the format of a map
|
||||
// from socket channelz id to corresponding reference string.
|
||||
Sockets map[int64]string
|
||||
// Trace contains the most recent traced events.
|
||||
Trace *ChannelTrace
|
||||
}
|
||||
|
||||
// ChannelInternalMetric defines the struct that the implementor of Channel interface
|
||||
// should return from ChannelzMetric().
|
||||
type ChannelInternalMetric struct {
|
||||
// current connectivity state of the channel.
|
||||
State connectivity.State
|
||||
// The target this channel originally tried to connect to. May be absent
|
||||
Target string
|
||||
// The number of calls started on the channel.
|
||||
CallsStarted int64
|
||||
// The number of calls that have completed with an OK status.
|
||||
CallsSucceeded int64
|
||||
// The number of calls that have a completed with a non-OK status.
|
||||
CallsFailed int64
|
||||
// The last time a call was started on the channel.
|
||||
LastCallStartedTimestamp time.Time
|
||||
}
|
||||
|
||||
// ChannelTrace stores traced events on a channel/subchannel and related info.
|
||||
type ChannelTrace struct {
|
||||
// EventNum is the number of events that ever got traced (i.e. including those that have been deleted)
|
||||
EventNum int64
|
||||
// CreationTime is the creation time of the trace.
|
||||
CreationTime time.Time
|
||||
// Events stores the most recent trace events (up to $maxTraceEntry, newer event will overwrite the
|
||||
// oldest one)
|
||||
Events []*TraceEvent
|
||||
}
|
||||
|
||||
// TraceEvent represent a single trace event
|
||||
type TraceEvent struct {
|
||||
// Desc is a simple description of the trace event.
|
||||
Desc string
|
||||
// Severity states the severity of this trace event.
|
||||
Severity Severity
|
||||
// Timestamp is the event time.
|
||||
Timestamp time.Time
|
||||
// RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
|
||||
// involved in this event.
|
||||
// e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
|
||||
RefID int64
|
||||
// RefName is the reference name for the entity that gets referenced in the event.
|
||||
RefName string
|
||||
// RefType indicates the referenced entity type, i.e Channel or SubChannel.
|
||||
RefType RefChannelType
|
||||
}
|
||||
|
||||
// Channel is the interface that should be satisfied in order to be tracked by
|
||||
// channelz as Channel or SubChannel.
|
||||
type Channel interface {
|
||||
ChannelzMetric() *ChannelInternalMetric
|
||||
}
|
||||
|
||||
type dummyChannel struct{}
|
||||
|
||||
func (d *dummyChannel) ChannelzMetric() *ChannelInternalMetric {
|
||||
return &ChannelInternalMetric{}
|
||||
}
|
||||
|
||||
type channel struct {
|
||||
refName string
|
||||
c Channel
|
||||
closeCalled bool
|
||||
nestedChans map[int64]string
|
||||
subChans map[int64]string
|
||||
id int64
|
||||
pid int64
|
||||
cm *channelMap
|
||||
trace *channelTrace
|
||||
// traceRefCount is the number of trace events that reference this channel.
|
||||
// Non-zero traceRefCount means the trace of this channel cannot be deleted.
|
||||
traceRefCount int32
|
||||
}
|
||||
|
||||
func (c *channel) addChild(id int64, e entry) {
|
||||
switch v := e.(type) {
|
||||
case *subChannel:
|
||||
c.subChans[id] = v.refName
|
||||
case *channel:
|
||||
c.nestedChans[id] = v.refName
|
||||
default:
|
||||
grpclog.Errorf("cannot add a child (id = %d) of type %T to a channel", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *channel) deleteChild(id int64) {
|
||||
delete(c.subChans, id)
|
||||
delete(c.nestedChans, id)
|
||||
c.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (c *channel) triggerDelete() {
|
||||
c.closeCalled = true
|
||||
c.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (c *channel) getParentID() int64 {
|
||||
return c.pid
|
||||
}
|
||||
|
||||
// deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means
|
||||
// deleting the channel reference from its parent's child list.
|
||||
//
|
||||
// In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the
|
||||
// corresponding grpc object has been invoked, and the channel does not have any children left.
|
||||
//
|
||||
// The returned boolean value indicates whether the channel has been successfully deleted from tree.
|
||||
func (c *channel) deleteSelfFromTree() (deleted bool) {
|
||||
if !c.closeCalled || len(c.subChans)+len(c.nestedChans) != 0 {
|
||||
return false
|
||||
}
|
||||
// not top channel
|
||||
if c.pid != 0 {
|
||||
c.cm.findEntry(c.pid).deleteChild(c.id)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means
|
||||
// deleting the channel from channelz's tracking entirely. Users can no longer use id to query the
|
||||
// channel, and its memory will be garbage collected.
|
||||
//
|
||||
// The trace reference count of the channel must be 0 in order to be deleted from the map. This is
|
||||
// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
|
||||
// the trace of the referenced entity must not be deleted. In order to release the resource allocated
|
||||
// by grpc, the reference to the grpc object is reset to a dummy object.
|
||||
//
|
||||
// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
|
||||
//
|
||||
// It returns a bool to indicate whether the channel can be safely deleted from map.
|
||||
func (c *channel) deleteSelfFromMap() (delete bool) {
|
||||
if c.getTraceRefCount() != 0 {
|
||||
c.c = &dummyChannel{}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfIfReady tries to delete the channel itself from the channelz database.
|
||||
// The delete process includes two steps:
|
||||
// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its
|
||||
// parent's child list.
|
||||
// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id
|
||||
// will return entry not found error.
|
||||
func (c *channel) deleteSelfIfReady() {
|
||||
if !c.deleteSelfFromTree() {
|
||||
return
|
||||
}
|
||||
if !c.deleteSelfFromMap() {
|
||||
return
|
||||
}
|
||||
c.cm.deleteEntry(c.id)
|
||||
c.trace.clear()
|
||||
}
|
||||
|
||||
func (c *channel) getChannelTrace() *channelTrace {
|
||||
return c.trace
|
||||
}
|
||||
|
||||
func (c *channel) incrTraceRefCount() {
|
||||
atomic.AddInt32(&c.traceRefCount, 1)
|
||||
}
|
||||
|
||||
func (c *channel) decrTraceRefCount() {
|
||||
atomic.AddInt32(&c.traceRefCount, -1)
|
||||
}
|
||||
|
||||
func (c *channel) getTraceRefCount() int {
|
||||
i := atomic.LoadInt32(&c.traceRefCount)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
func (c *channel) getRefName() string {
|
||||
return c.refName
|
||||
}
|
||||
|
||||
type subChannel struct {
|
||||
refName string
|
||||
c Channel
|
||||
closeCalled bool
|
||||
sockets map[int64]string
|
||||
id int64
|
||||
pid int64
|
||||
cm *channelMap
|
||||
trace *channelTrace
|
||||
traceRefCount int32
|
||||
}
|
||||
|
||||
func (sc *subChannel) addChild(id int64, e entry) {
|
||||
if v, ok := e.(*normalSocket); ok {
|
||||
sc.sockets[id] = v.refName
|
||||
} else {
|
||||
grpclog.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *subChannel) deleteChild(id int64) {
|
||||
delete(sc.sockets, id)
|
||||
sc.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (sc *subChannel) triggerDelete() {
|
||||
sc.closeCalled = true
|
||||
sc.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (sc *subChannel) getParentID() int64 {
|
||||
return sc.pid
|
||||
}
|
||||
|
||||
// deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
|
||||
// means deleting the subchannel reference from its parent's child list.
|
||||
//
|
||||
// In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
|
||||
// the corresponding grpc object has been invoked, and the subchannel does not have any children left.
|
||||
//
|
||||
// The returned boolean value indicates whether the channel has been successfully deleted from tree.
|
||||
func (sc *subChannel) deleteSelfFromTree() (deleted bool) {
|
||||
if !sc.closeCalled || len(sc.sockets) != 0 {
|
||||
return false
|
||||
}
|
||||
sc.cm.findEntry(sc.pid).deleteChild(sc.id)
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
|
||||
// deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
|
||||
// the subchannel, and its memory will be garbage collected.
|
||||
//
|
||||
// The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
|
||||
// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
|
||||
// the trace of the referenced entity must not be deleted. In order to release the resource allocated
|
||||
// by grpc, the reference to the grpc object is reset to a dummy object.
|
||||
//
|
||||
// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
|
||||
//
|
||||
// It returns a bool to indicate whether the channel can be safely deleted from map.
|
||||
func (sc *subChannel) deleteSelfFromMap() (delete bool) {
|
||||
if sc.getTraceRefCount() != 0 {
|
||||
// free the grpc struct (i.e. addrConn)
|
||||
sc.c = &dummyChannel{}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
|
||||
// The delete process includes two steps:
|
||||
// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
|
||||
// its parent's child list.
|
||||
// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
|
||||
// by id will return entry not found error.
|
||||
func (sc *subChannel) deleteSelfIfReady() {
|
||||
if !sc.deleteSelfFromTree() {
|
||||
return
|
||||
}
|
||||
if !sc.deleteSelfFromMap() {
|
||||
return
|
||||
}
|
||||
sc.cm.deleteEntry(sc.id)
|
||||
sc.trace.clear()
|
||||
}
|
||||
|
||||
func (sc *subChannel) getChannelTrace() *channelTrace {
|
||||
return sc.trace
|
||||
}
|
||||
|
||||
func (sc *subChannel) incrTraceRefCount() {
|
||||
atomic.AddInt32(&sc.traceRefCount, 1)
|
||||
}
|
||||
|
||||
func (sc *subChannel) decrTraceRefCount() {
|
||||
atomic.AddInt32(&sc.traceRefCount, -1)
|
||||
}
|
||||
|
||||
func (sc *subChannel) getTraceRefCount() int {
|
||||
i := atomic.LoadInt32(&sc.traceRefCount)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
func (sc *subChannel) getRefName() string {
|
||||
return sc.refName
|
||||
}
|
||||
|
||||
// SocketMetric defines the info channelz provides for a specific Socket, which
|
||||
// includes SocketInternalMetric and channelz-specific data, such as channelz id, etc.
|
||||
type SocketMetric struct {
|
||||
// ID is the channelz id of this socket.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this socket.
|
||||
RefName string
|
||||
// SocketData contains socket internal metric reported by the socket through
|
||||
// ChannelzMetric().
|
||||
SocketData *SocketInternalMetric
|
||||
}
|
||||
|
||||
// SocketInternalMetric defines the struct that the implementor of Socket interface
|
||||
// should return from ChannelzMetric().
|
||||
type SocketInternalMetric struct {
|
||||
// The number of streams that have been started.
|
||||
StreamsStarted int64
|
||||
// The number of streams that have ended successfully:
|
||||
// On client side, receiving frame with eos bit set.
|
||||
// On server side, sending frame with eos bit set.
|
||||
StreamsSucceeded int64
|
||||
// The number of streams that have ended unsuccessfully:
|
||||
// On client side, termination without receiving frame with eos bit set.
|
||||
// On server side, termination without sending frame with eos bit set.
|
||||
StreamsFailed int64
|
||||
// The number of messages successfully sent on this socket.
|
||||
MessagesSent int64
|
||||
MessagesReceived int64
|
||||
// The number of keep alives sent. This is typically implemented with HTTP/2
|
||||
// ping messages.
|
||||
KeepAlivesSent int64
|
||||
// The last time a stream was created by this endpoint. Usually unset for
|
||||
// servers.
|
||||
LastLocalStreamCreatedTimestamp time.Time
|
||||
// The last time a stream was created by the remote endpoint. Usually unset
|
||||
// for clients.
|
||||
LastRemoteStreamCreatedTimestamp time.Time
|
||||
// The last time a message was sent by this endpoint.
|
||||
LastMessageSentTimestamp time.Time
|
||||
// The last time a message was received by this endpoint.
|
||||
LastMessageReceivedTimestamp time.Time
|
||||
// The amount of window, granted to the local endpoint by the remote endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
LocalFlowControlWindow int64
|
||||
// The amount of window, granted to the remote endpoint by the local endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
RemoteFlowControlWindow int64
|
||||
// The locally bound address.
|
||||
LocalAddr net.Addr
|
||||
// The remote bound address. May be absent.
|
||||
RemoteAddr net.Addr
|
||||
// Optional, represents the name of the remote endpoint, if different than
|
||||
// the original target name.
|
||||
RemoteName string
|
||||
SocketOptions *SocketOptionData
|
||||
Security credentials.ChannelzSecurityValue
|
||||
}
|
||||
|
||||
// Socket is the interface that should be satisfied in order to be tracked by
|
||||
// channelz as Socket.
|
||||
type Socket interface {
|
||||
ChannelzMetric() *SocketInternalMetric
|
||||
}
|
||||
|
||||
type listenSocket struct {
|
||||
refName string
|
||||
s Socket
|
||||
id int64
|
||||
pid int64
|
||||
cm *channelMap
|
||||
}
|
||||
|
||||
func (ls *listenSocket) addChild(id int64, e entry) {
|
||||
grpclog.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e)
|
||||
}
|
||||
|
||||
func (ls *listenSocket) deleteChild(id int64) {
|
||||
grpclog.Errorf("cannot delete a child (id = %d) from a listen socket", id)
|
||||
}
|
||||
|
||||
func (ls *listenSocket) triggerDelete() {
|
||||
ls.cm.deleteEntry(ls.id)
|
||||
ls.cm.findEntry(ls.pid).deleteChild(ls.id)
|
||||
}
|
||||
|
||||
func (ls *listenSocket) deleteSelfIfReady() {
|
||||
grpclog.Errorf("cannot call deleteSelfIfReady on a listen socket")
|
||||
}
|
||||
|
||||
func (ls *listenSocket) getParentID() int64 {
|
||||
return ls.pid
|
||||
}
|
||||
|
||||
type normalSocket struct {
|
||||
refName string
|
||||
s Socket
|
||||
id int64
|
||||
pid int64
|
||||
cm *channelMap
|
||||
}
|
||||
|
||||
func (ns *normalSocket) addChild(id int64, e entry) {
|
||||
grpclog.Errorf("cannot add a child (id = %d) of type %T to a normal socket", id, e)
|
||||
}
|
||||
|
||||
func (ns *normalSocket) deleteChild(id int64) {
|
||||
grpclog.Errorf("cannot delete a child (id = %d) from a normal socket", id)
|
||||
}
|
||||
|
||||
func (ns *normalSocket) triggerDelete() {
|
||||
ns.cm.deleteEntry(ns.id)
|
||||
ns.cm.findEntry(ns.pid).deleteChild(ns.id)
|
||||
}
|
||||
|
||||
func (ns *normalSocket) deleteSelfIfReady() {
|
||||
grpclog.Errorf("cannot call deleteSelfIfReady on a normal socket")
|
||||
}
|
||||
|
||||
func (ns *normalSocket) getParentID() int64 {
|
||||
return ns.pid
|
||||
}
|
||||
|
||||
// ServerMetric defines the info channelz provides for a specific Server, which
|
||||
// includes ServerInternalMetric and channelz-specific data, such as channelz id,
|
||||
// child list, etc.
|
||||
type ServerMetric struct {
|
||||
// ID is the channelz id of this server.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this server.
|
||||
RefName string
|
||||
// ServerData contains server internal metric reported by the server through
|
||||
// ChannelzMetric().
|
||||
ServerData *ServerInternalMetric
|
||||
// ListenSockets tracks the listener socket type children of this server in the
|
||||
// format of a map from socket channelz id to corresponding reference string.
|
||||
ListenSockets map[int64]string
|
||||
}
|
||||
|
||||
// ServerInternalMetric defines the struct that the implementor of Server interface
|
||||
// should return from ChannelzMetric().
|
||||
type ServerInternalMetric struct {
|
||||
// The number of incoming calls started on the server.
|
||||
CallsStarted int64
|
||||
// The number of incoming calls that have completed with an OK status.
|
||||
CallsSucceeded int64
|
||||
// The number of incoming calls that have a completed with a non-OK status.
|
||||
CallsFailed int64
|
||||
// The last time a call was started on the server.
|
||||
LastCallStartedTimestamp time.Time
|
||||
}
|
||||
|
||||
// Server is the interface to be satisfied in order to be tracked by channelz as
|
||||
// Server.
|
||||
type Server interface {
|
||||
ChannelzMetric() *ServerInternalMetric
|
||||
}
|
||||
|
||||
type server struct {
|
||||
refName string
|
||||
s Server
|
||||
closeCalled bool
|
||||
sockets map[int64]string
|
||||
listenSockets map[int64]string
|
||||
id int64
|
||||
cm *channelMap
|
||||
}
|
||||
|
||||
func (s *server) addChild(id int64, e entry) {
|
||||
switch v := e.(type) {
|
||||
case *normalSocket:
|
||||
s.sockets[id] = v.refName
|
||||
case *listenSocket:
|
||||
s.listenSockets[id] = v.refName
|
||||
default:
|
||||
grpclog.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) deleteChild(id int64) {
|
||||
delete(s.sockets, id)
|
||||
delete(s.listenSockets, id)
|
||||
s.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (s *server) triggerDelete() {
|
||||
s.closeCalled = true
|
||||
s.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (s *server) deleteSelfIfReady() {
|
||||
if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
|
||||
return
|
||||
}
|
||||
s.cm.deleteEntry(s.id)
|
||||
}
|
||||
|
||||
func (s *server) getParentID() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type tracedChannel interface {
|
||||
getChannelTrace() *channelTrace
|
||||
incrTraceRefCount()
|
||||
decrTraceRefCount()
|
||||
getRefName() string
|
||||
}
|
||||
|
||||
type channelTrace struct {
|
||||
cm *channelMap
|
||||
createdTime time.Time
|
||||
eventCount int64
|
||||
mu sync.Mutex
|
||||
events []*TraceEvent
|
||||
}
|
||||
|
||||
func (c *channelTrace) append(e *TraceEvent) {
|
||||
c.mu.Lock()
|
||||
if len(c.events) == getMaxTraceEntry() {
|
||||
del := c.events[0]
|
||||
c.events = c.events[1:]
|
||||
if del.RefID != 0 {
|
||||
// start recursive cleanup in a goroutine to not block the call originated from grpc.
|
||||
go func() {
|
||||
// need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
|
||||
c.cm.mu.Lock()
|
||||
c.cm.decrTraceRefCount(del.RefID)
|
||||
c.cm.mu.Unlock()
|
||||
}()
|
||||
}
|
||||
}
|
||||
e.Timestamp = time.Now()
|
||||
c.events = append(c.events, e)
|
||||
c.eventCount++
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *channelTrace) clear() {
|
||||
c.mu.Lock()
|
||||
for _, e := range c.events {
|
||||
if e.RefID != 0 {
|
||||
// caller should have already held the c.cm.mu lock.
|
||||
c.cm.decrTraceRefCount(e.RefID)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// Severity is the severity level of a trace event.
|
||||
// The canonical enumeration of all valid values is here:
|
||||
// https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
|
||||
type Severity int
|
||||
|
||||
const (
|
||||
// CtUNKNOWN indicates unknown severity of a trace event.
|
||||
CtUNKNOWN Severity = iota
|
||||
// CtINFO indicates info level severity of a trace event.
|
||||
CtINFO
|
||||
// CtWarning indicates warning level severity of a trace event.
|
||||
CtWarning
|
||||
// CtError indicates error level severity of a trace event.
|
||||
CtError
|
||||
)
|
||||
|
||||
// RefChannelType is the type of the entity being referenced in a trace event.
|
||||
type RefChannelType int
|
||||
|
||||
const (
|
||||
// RefChannel indicates the referenced entity is a Channel.
|
||||
RefChannel RefChannelType = iota
|
||||
// RefSubChannel indicates the referenced entity is a SubChannel.
|
||||
RefSubChannel
|
||||
)
|
||||
|
||||
func (c *channelTrace) dumpData() *ChannelTrace {
|
||||
c.mu.Lock()
|
||||
ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime}
|
||||
ct.Events = c.events[:len(c.events)]
|
||||
c.mu.Unlock()
|
||||
return ct
|
||||
}
|
||||
53
vendor/google.golang.org/grpc/internal/channelz/types_linux.go
generated
vendored
Normal file
53
vendor/google.golang.org/grpc/internal/channelz/types_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// +build !appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SocketOptionData defines the struct to hold socket option data, and related
|
||||
// getter function to obtain info from fd.
|
||||
type SocketOptionData struct {
|
||||
Linger *unix.Linger
|
||||
RecvTimeout *unix.Timeval
|
||||
SendTimeout *unix.Timeval
|
||||
TCPInfo *unix.TCPInfo
|
||||
}
|
||||
|
||||
// Getsockopt defines the function to get socket options requested by channelz.
|
||||
// It is to be passed to syscall.RawConn.Control().
|
||||
func (s *SocketOptionData) Getsockopt(fd uintptr) {
|
||||
if v, err := unix.GetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER); err == nil {
|
||||
s.Linger = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO); err == nil {
|
||||
s.RecvTimeout = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO); err == nil {
|
||||
s.SendTimeout = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTCPInfo(int(fd), syscall.SOL_TCP, syscall.TCP_INFO); err == nil {
|
||||
s.TCPInfo = v
|
||||
}
|
||||
}
|
||||
44
vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
generated
vendored
Normal file
44
vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
|
||||
// SocketOptionData defines the struct to hold socket option data, and related
|
||||
// getter function to obtain info from fd.
|
||||
// Windows OS doesn't support Socket Option
|
||||
type SocketOptionData struct {
|
||||
}
|
||||
|
||||
// Getsockopt defines the function to get socket options requested by channelz.
|
||||
// It is to be passed to syscall.RawConn.Control().
|
||||
// Windows OS doesn't support Socket Option
|
||||
func (s *SocketOptionData) Getsockopt(fd uintptr) {
|
||||
once.Do(func() {
|
||||
grpclog.Warningln("Channelz: socket options are not supported on non-linux os and appengine.")
|
||||
})
|
||||
}
|
||||
39
vendor/google.golang.org/grpc/internal/channelz/util_linux.go
generated
vendored
Normal file
39
vendor/google.golang.org/grpc/internal/channelz/util_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// +build linux,!appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(socket interface{}) *SocketOptionData {
|
||||
c, ok := socket.(syscall.Conn)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
data := &SocketOptionData{}
|
||||
if rawConn, err := c.SyscallConn(); err == nil {
|
||||
rawConn.Control(data.Getsockopt)
|
||||
return data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
26
vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
generated
vendored
Normal file
26
vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(c interface{}) *SocketOptionData {
|
||||
return nil
|
||||
}
|
||||
35
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
Normal file
35
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package envconfig contains grpc settings configured by environment variables.
|
||||
package envconfig
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = "GRPC_GO_"
|
||||
retryStr = prefix + "RETRY"
|
||||
)
|
||||
|
||||
var (
|
||||
// Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
|
||||
Retry = strings.EqualFold(os.Getenv(retryStr), "on")
|
||||
)
|
||||
56
vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
generated
vendored
Normal file
56
vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpcrand implements math/rand functions in a concurrent-safe way
|
||||
// with a global random source, independent of math/rand's global source.
|
||||
package grpcrand
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
// Int63n implements rand.Int63n on the grpcrand global source.
|
||||
func Int63n(n int64) int64 {
|
||||
mu.Lock()
|
||||
res := r.Int63n(n)
|
||||
mu.Unlock()
|
||||
return res
|
||||
}
|
||||
|
||||
// Intn implements rand.Intn on the grpcrand global source.
|
||||
func Intn(n int) int {
|
||||
mu.Lock()
|
||||
res := r.Intn(n)
|
||||
mu.Unlock()
|
||||
return res
|
||||
}
|
||||
|
||||
// Float64 implements rand.Float64 on the grpcrand global source.
|
||||
func Float64() float64 {
|
||||
mu.Lock()
|
||||
res := r.Float64()
|
||||
mu.Unlock()
|
||||
return res
|
||||
}
|
||||
61
vendor/google.golang.org/grpc/internal/grpcsync/event.go
generated
vendored
Normal file
61
vendor/google.golang.org/grpc/internal/grpcsync/event.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpcsync implements additional synchronization primitives built upon
|
||||
// the sync package.
|
||||
package grpcsync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Event represents a one-time event that may occur in the future.
|
||||
type Event struct {
|
||||
fired int32
|
||||
c chan struct{}
|
||||
o sync.Once
|
||||
}
|
||||
|
||||
// Fire causes e to complete. It is safe to call multiple times, and
|
||||
// concurrently. It returns true iff this call to Fire caused the signaling
|
||||
// channel returned by Done to close.
|
||||
func (e *Event) Fire() bool {
|
||||
ret := false
|
||||
e.o.Do(func() {
|
||||
atomic.StoreInt32(&e.fired, 1)
|
||||
close(e.c)
|
||||
ret = true
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
// Done returns a channel that will be closed when Fire is called.
|
||||
func (e *Event) Done() <-chan struct{} {
|
||||
return e.c
|
||||
}
|
||||
|
||||
// HasFired returns true if Fire has been called.
|
||||
func (e *Event) HasFired() bool {
|
||||
return atomic.LoadInt32(&e.fired) == 1
|
||||
}
|
||||
|
||||
// NewEvent returns a new, ready-to-use Event.
|
||||
func NewEvent() *Event {
|
||||
return &Event{c: make(chan struct{})}
|
||||
}
|
||||
71
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
Normal file
71
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package internal contains gRPC-internal code, to avoid polluting
|
||||
// the godoc of the top-level grpc package. It must not import any grpc
|
||||
// symbols to avoid circular dependencies.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/connectivity"
|
||||
)
|
||||
|
||||
var (
|
||||
// WithResolverBuilder is exported by dialoptions.go
|
||||
WithResolverBuilder interface{} // func (resolver.Builder) grpc.DialOption
|
||||
// WithHealthCheckFunc is not exported by dialoptions.go
|
||||
WithHealthCheckFunc interface{} // func (HealthChecker) DialOption
|
||||
// HealthCheckFunc is used to provide client-side LB channel health checking
|
||||
HealthCheckFunc HealthChecker
|
||||
// BalancerUnregister is exported by package balancer to unregister a balancer.
|
||||
BalancerUnregister func(name string)
|
||||
// KeepaliveMinPingTime is the minimum ping interval. This must be 10s by
|
||||
// default, but tests may wish to set it lower for convenience.
|
||||
KeepaliveMinPingTime = 10 * time.Second
|
||||
// ParseServiceConfig is a function to parse JSON service configs into
|
||||
// opaque data structures.
|
||||
ParseServiceConfig func(sc string) (interface{}, error)
|
||||
// StatusRawProto is exported by status/status.go. This func returns a
|
||||
// pointer to the wrapped Status proto for a given status.Status without a
|
||||
// call to proto.Clone(). The returned Status proto should not be mutated by
|
||||
// the caller.
|
||||
StatusRawProto interface{} // func (*status.Status) *spb.Status
|
||||
)
|
||||
|
||||
// HealthChecker defines the signature of the client-side LB channel health checking function.
|
||||
//
|
||||
// The implementation is expected to create a health checking RPC stream by
|
||||
// calling newStream(), watch for the health status of serviceName, and report
|
||||
// it's health back by calling setConnectivityState().
|
||||
//
|
||||
// The health checking protocol is defined at:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/health-checking.md
|
||||
type HealthChecker func(ctx context.Context, newStream func(string) (interface{}, error), setConnectivityState func(connectivity.State), serviceName string) error
|
||||
|
||||
const (
|
||||
// CredsBundleModeFallback switches GoogleDefaultCreds to fallback mode.
|
||||
CredsBundleModeFallback = "fallback"
|
||||
// CredsBundleModeBalancer switches GoogleDefaultCreds to grpclb balancer
|
||||
// mode.
|
||||
CredsBundleModeBalancer = "balancer"
|
||||
// CredsBundleModeBackendFromBalancer switches GoogleDefaultCreds to mode
|
||||
// that supports backend returned by grpclb balancer.
|
||||
CredsBundleModeBackendFromBalancer = "backend-from-balancer"
|
||||
)
|
||||
114
vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
generated
vendored
Normal file
114
vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// +build !appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package syscall provides functionalities that grpc uses to get low-level operating system
|
||||
// stats/info.
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// GetCPUTime returns the how much CPU time has passed since the start of this process.
|
||||
func GetCPUTime() int64 {
|
||||
var ts unix.Timespec
|
||||
if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil {
|
||||
grpclog.Fatal(err)
|
||||
}
|
||||
return ts.Nano()
|
||||
}
|
||||
|
||||
// Rusage is an alias for syscall.Rusage under linux non-appengine environment.
|
||||
type Rusage syscall.Rusage
|
||||
|
||||
// GetRusage returns the resource usage of current process.
|
||||
func GetRusage() (rusage *Rusage) {
|
||||
rusage = new(Rusage)
|
||||
syscall.Getrusage(syscall.RUSAGE_SELF, (*syscall.Rusage)(rusage))
|
||||
return
|
||||
}
|
||||
|
||||
// CPUTimeDiff returns the differences of user CPU time and system CPU time used
|
||||
// between two Rusage structs.
|
||||
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
||||
f := (*syscall.Rusage)(first)
|
||||
l := (*syscall.Rusage)(latest)
|
||||
var (
|
||||
utimeDiffs = l.Utime.Sec - f.Utime.Sec
|
||||
utimeDiffus = l.Utime.Usec - f.Utime.Usec
|
||||
stimeDiffs = l.Stime.Sec - f.Stime.Sec
|
||||
stimeDiffus = l.Stime.Usec - f.Stime.Usec
|
||||
)
|
||||
|
||||
uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
|
||||
sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6
|
||||
|
||||
return uTimeElapsed, sTimeElapsed
|
||||
}
|
||||
|
||||
// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
|
||||
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
|
||||
tcpconn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
// not a TCP connection. exit early
|
||||
return nil
|
||||
}
|
||||
rawConn, err := tcpconn.SyscallConn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting raw connection: %v", err)
|
||||
}
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting option on socket: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
|
||||
func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
|
||||
tcpconn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
|
||||
return
|
||||
}
|
||||
rawConn, err := tcpconn.SyscallConn()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error getting raw connection: %v", err)
|
||||
return
|
||||
}
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
|
||||
})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error getting option on socket: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
73
vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
generated
vendored
Normal file
73
vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
|
||||
func log() {
|
||||
once.Do(func() {
|
||||
grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
|
||||
})
|
||||
}
|
||||
|
||||
// GetCPUTime returns the how much CPU time has passed since the start of this process.
|
||||
// It always returns 0 under non-linux or appengine environment.
|
||||
func GetCPUTime() int64 {
|
||||
log()
|
||||
return 0
|
||||
}
|
||||
|
||||
// Rusage is an empty struct under non-linux or appengine environment.
|
||||
type Rusage struct{}
|
||||
|
||||
// GetRusage is a no-op function under non-linux or appengine environment.
|
||||
func GetRusage() (rusage *Rusage) {
|
||||
log()
|
||||
return nil
|
||||
}
|
||||
|
||||
// CPUTimeDiff returns the differences of user CPU time and system CPU time used
|
||||
// between two Rusage structs. It a no-op function for non-linux or appengine environment.
|
||||
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
||||
log()
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// SetTCPUserTimeout is a no-op function under non-linux or appengine environments
|
||||
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
|
||||
log()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTCPUserTimeout is a no-op function under non-linux or appengine environments
|
||||
// a negative return value indicates the operation is not supported
|
||||
func GetTCPUserTimeout(conn net.Conn) (int, error) {
|
||||
log()
|
||||
return -1, nil
|
||||
}
|
||||
141
vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
generated
vendored
Normal file
141
vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
generated
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// bdpLimit is the maximum value the flow control windows will be increased
|
||||
// to. TCP typically limits this to 4MB, but some systems go up to 16MB.
|
||||
// Since this is only a limit, it is safe to make it optimistic.
|
||||
bdpLimit = (1 << 20) * 16
|
||||
// alpha is a constant factor used to keep a moving average
|
||||
// of RTTs.
|
||||
alpha = 0.9
|
||||
// If the current bdp sample is greater than or equal to
|
||||
// our beta * our estimated bdp and the current bandwidth
|
||||
// sample is the maximum bandwidth observed so far, we
|
||||
// increase our bbp estimate by a factor of gamma.
|
||||
beta = 0.66
|
||||
// To put our bdp to be smaller than or equal to twice the real BDP,
|
||||
// we should multiply our current sample with 4/3, however to round things out
|
||||
// we use 2 as the multiplication factor.
|
||||
gamma = 2
|
||||
)
|
||||
|
||||
// Adding arbitrary data to ping so that its ack can be identified.
|
||||
// Easter-egg: what does the ping message say?
|
||||
var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
|
||||
|
||||
type bdpEstimator struct {
|
||||
// sentAt is the time when the ping was sent.
|
||||
sentAt time.Time
|
||||
|
||||
mu sync.Mutex
|
||||
// bdp is the current bdp estimate.
|
||||
bdp uint32
|
||||
// sample is the number of bytes received in one measurement cycle.
|
||||
sample uint32
|
||||
// bwMax is the maximum bandwidth noted so far (bytes/sec).
|
||||
bwMax float64
|
||||
// bool to keep track of the beginning of a new measurement cycle.
|
||||
isSent bool
|
||||
// Callback to update the window sizes.
|
||||
updateFlowControl func(n uint32)
|
||||
// sampleCount is the number of samples taken so far.
|
||||
sampleCount uint64
|
||||
// round trip time (seconds)
|
||||
rtt float64
|
||||
}
|
||||
|
||||
// timesnap registers the time bdp ping was sent out so that
|
||||
// network rtt can be calculated when its ack is received.
|
||||
// It is called (by controller) when the bdpPing is
|
||||
// being written on the wire.
|
||||
func (b *bdpEstimator) timesnap(d [8]byte) {
|
||||
if bdpPing.data != d {
|
||||
return
|
||||
}
|
||||
b.sentAt = time.Now()
|
||||
}
|
||||
|
||||
// add adds bytes to the current sample for calculating bdp.
|
||||
// It returns true only if a ping must be sent. This can be used
|
||||
// by the caller (handleData) to make decision about batching
|
||||
// a window update with it.
|
||||
func (b *bdpEstimator) add(n uint32) bool {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.bdp == bdpLimit {
|
||||
return false
|
||||
}
|
||||
if !b.isSent {
|
||||
b.isSent = true
|
||||
b.sample = n
|
||||
b.sentAt = time.Time{}
|
||||
b.sampleCount++
|
||||
return true
|
||||
}
|
||||
b.sample += n
|
||||
return false
|
||||
}
|
||||
|
||||
// calculate is called when an ack for a bdp ping is received.
|
||||
// Here we calculate the current bdp and bandwidth sample and
|
||||
// decide if the flow control windows should go up.
|
||||
func (b *bdpEstimator) calculate(d [8]byte) {
|
||||
// Check if the ping acked for was the bdp ping.
|
||||
if bdpPing.data != d {
|
||||
return
|
||||
}
|
||||
b.mu.Lock()
|
||||
rttSample := time.Since(b.sentAt).Seconds()
|
||||
if b.sampleCount < 10 {
|
||||
// Bootstrap rtt with an average of first 10 rtt samples.
|
||||
b.rtt += (rttSample - b.rtt) / float64(b.sampleCount)
|
||||
} else {
|
||||
// Heed to the recent past more.
|
||||
b.rtt += (rttSample - b.rtt) * float64(alpha)
|
||||
}
|
||||
b.isSent = false
|
||||
// The number of bytes accumulated so far in the sample is smaller
|
||||
// than or equal to 1.5 times the real BDP on a saturated connection.
|
||||
bwCurrent := float64(b.sample) / (b.rtt * float64(1.5))
|
||||
if bwCurrent > b.bwMax {
|
||||
b.bwMax = bwCurrent
|
||||
}
|
||||
// If the current sample (which is smaller than or equal to the 1.5 times the real BDP) is
|
||||
// greater than or equal to 2/3rd our perceived bdp AND this is the maximum bandwidth seen so far, we
|
||||
// should update our perception of the network BDP.
|
||||
if float64(b.sample) >= beta*float64(b.bdp) && bwCurrent == b.bwMax && b.bdp != bdpLimit {
|
||||
sampleFloat := float64(b.sample)
|
||||
b.bdp = uint32(gamma * sampleFloat)
|
||||
if b.bdp > bdpLimit {
|
||||
b.bdp = bdpLimit
|
||||
}
|
||||
bdp := b.bdp
|
||||
b.mu.Unlock()
|
||||
b.updateFlowControl(bdp)
|
||||
return
|
||||
}
|
||||
b.mu.Unlock()
|
||||
}
|
||||
930
vendor/google.golang.org/grpc/internal/transport/controlbuf.go
generated
vendored
Normal file
930
vendor/google.golang.org/grpc/internal/transport/controlbuf.go
generated
vendored
Normal file
|
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
|
||||
e.SetMaxDynamicTableSizeLimit(v)
|
||||
}
|
||||
|
||||
type itemNode struct {
|
||||
it interface{}
|
||||
next *itemNode
|
||||
}
|
||||
|
||||
type itemList struct {
|
||||
head *itemNode
|
||||
tail *itemNode
|
||||
}
|
||||
|
||||
func (il *itemList) enqueue(i interface{}) {
|
||||
n := &itemNode{it: i}
|
||||
if il.tail == nil {
|
||||
il.head, il.tail = n, n
|
||||
return
|
||||
}
|
||||
il.tail.next = n
|
||||
il.tail = n
|
||||
}
|
||||
|
||||
// peek returns the first item in the list without removing it from the
|
||||
// list.
|
||||
func (il *itemList) peek() interface{} {
|
||||
return il.head.it
|
||||
}
|
||||
|
||||
func (il *itemList) dequeue() interface{} {
|
||||
if il.head == nil {
|
||||
return nil
|
||||
}
|
||||
i := il.head.it
|
||||
il.head = il.head.next
|
||||
if il.head == nil {
|
||||
il.tail = nil
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (il *itemList) dequeueAll() *itemNode {
|
||||
h := il.head
|
||||
il.head, il.tail = nil, nil
|
||||
return h
|
||||
}
|
||||
|
||||
func (il *itemList) isEmpty() bool {
|
||||
return il.head == nil
|
||||
}
|
||||
|
||||
// The following defines various control items which could flow through
|
||||
// the control buffer of transport. They represent different aspects of
|
||||
// control tasks, e.g., flow control, settings, streaming resetting, etc.
|
||||
|
||||
// maxQueuedTransportResponseFrames is the most queued "transport response"
|
||||
// frames we will buffer before preventing new reads from occurring on the
|
||||
// transport. These are control frames sent in response to client requests,
|
||||
// such as RST_STREAM due to bad headers or settings acks.
|
||||
const maxQueuedTransportResponseFrames = 50
|
||||
|
||||
type cbItem interface {
|
||||
isTransportResponseFrame() bool
|
||||
}
|
||||
|
||||
// registerStream is used to register an incoming stream with loopy writer.
|
||||
type registerStream struct {
|
||||
streamID uint32
|
||||
wq *writeQuota
|
||||
}
|
||||
|
||||
func (*registerStream) isTransportResponseFrame() bool { return false }
|
||||
|
||||
// headerFrame is also used to register stream on the client-side.
|
||||
type headerFrame struct {
|
||||
streamID uint32
|
||||
hf []hpack.HeaderField
|
||||
endStream bool // Valid on server side.
|
||||
initStream func(uint32) (bool, error) // Used only on the client side.
|
||||
onWrite func()
|
||||
wq *writeQuota // write quota for the stream created.
|
||||
cleanup *cleanupStream // Valid on the server side.
|
||||
onOrphaned func(error) // Valid on client-side
|
||||
}
|
||||
|
||||
func (h *headerFrame) isTransportResponseFrame() bool {
|
||||
return h.cleanup != nil && h.cleanup.rst // Results in a RST_STREAM
|
||||
}
|
||||
|
||||
type cleanupStream struct {
|
||||
streamID uint32
|
||||
rst bool
|
||||
rstCode http2.ErrCode
|
||||
onWrite func()
|
||||
}
|
||||
|
||||
func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM
|
||||
|
||||
type dataFrame struct {
|
||||
streamID uint32
|
||||
endStream bool
|
||||
h []byte
|
||||
d []byte
|
||||
// onEachWrite is called every time
|
||||
// a part of d is written out.
|
||||
onEachWrite func()
|
||||
}
|
||||
|
||||
func (*dataFrame) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type incomingWindowUpdate struct {
|
||||
streamID uint32
|
||||
increment uint32
|
||||
}
|
||||
|
||||
func (*incomingWindowUpdate) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type outgoingWindowUpdate struct {
|
||||
streamID uint32
|
||||
increment uint32
|
||||
}
|
||||
|
||||
func (*outgoingWindowUpdate) isTransportResponseFrame() bool {
|
||||
return false // window updates are throttled by thresholds
|
||||
}
|
||||
|
||||
type incomingSettings struct {
|
||||
ss []http2.Setting
|
||||
}
|
||||
|
||||
func (*incomingSettings) isTransportResponseFrame() bool { return true } // Results in a settings ACK
|
||||
|
||||
type outgoingSettings struct {
|
||||
ss []http2.Setting
|
||||
}
|
||||
|
||||
func (*outgoingSettings) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type incomingGoAway struct {
|
||||
}
|
||||
|
||||
func (*incomingGoAway) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type goAway struct {
|
||||
code http2.ErrCode
|
||||
debugData []byte
|
||||
headsUp bool
|
||||
closeConn bool
|
||||
}
|
||||
|
||||
func (*goAway) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type ping struct {
|
||||
ack bool
|
||||
data [8]byte
|
||||
}
|
||||
|
||||
func (*ping) isTransportResponseFrame() bool { return true }
|
||||
|
||||
type outFlowControlSizeRequest struct {
|
||||
resp chan uint32
|
||||
}
|
||||
|
||||
func (*outFlowControlSizeRequest) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type outStreamState int
|
||||
|
||||
const (
|
||||
active outStreamState = iota
|
||||
empty
|
||||
waitingOnStreamQuota
|
||||
)
|
||||
|
||||
type outStream struct {
|
||||
id uint32
|
||||
state outStreamState
|
||||
itl *itemList
|
||||
bytesOutStanding int
|
||||
wq *writeQuota
|
||||
|
||||
next *outStream
|
||||
prev *outStream
|
||||
}
|
||||
|
||||
func (s *outStream) deleteSelf() {
|
||||
if s.prev != nil {
|
||||
s.prev.next = s.next
|
||||
}
|
||||
if s.next != nil {
|
||||
s.next.prev = s.prev
|
||||
}
|
||||
s.next, s.prev = nil, nil
|
||||
}
|
||||
|
||||
type outStreamList struct {
|
||||
// Following are sentinel objects that mark the
|
||||
// beginning and end of the list. They do not
|
||||
// contain any item lists. All valid objects are
|
||||
// inserted in between them.
|
||||
// This is needed so that an outStream object can
|
||||
// deleteSelf() in O(1) time without knowing which
|
||||
// list it belongs to.
|
||||
head *outStream
|
||||
tail *outStream
|
||||
}
|
||||
|
||||
func newOutStreamList() *outStreamList {
|
||||
head, tail := new(outStream), new(outStream)
|
||||
head.next = tail
|
||||
tail.prev = head
|
||||
return &outStreamList{
|
||||
head: head,
|
||||
tail: tail,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *outStreamList) enqueue(s *outStream) {
|
||||
e := l.tail.prev
|
||||
e.next = s
|
||||
s.prev = e
|
||||
s.next = l.tail
|
||||
l.tail.prev = s
|
||||
}
|
||||
|
||||
// remove from the beginning of the list.
|
||||
func (l *outStreamList) dequeue() *outStream {
|
||||
b := l.head.next
|
||||
if b == l.tail {
|
||||
return nil
|
||||
}
|
||||
b.deleteSelf()
|
||||
return b
|
||||
}
|
||||
|
||||
// controlBuffer is a way to pass information to loopy.
|
||||
// Information is passed as specific struct types called control frames.
|
||||
// A control frame not only represents data, messages or headers to be sent out
|
||||
// but can also be used to instruct loopy to update its internal state.
|
||||
// It shouldn't be confused with an HTTP2 frame, although some of the control frames
|
||||
// like dataFrame and headerFrame do go out on wire as HTTP2 frames.
|
||||
type controlBuffer struct {
|
||||
ch chan struct{}
|
||||
done <-chan struct{}
|
||||
mu sync.Mutex
|
||||
consumerWaiting bool
|
||||
list *itemList
|
||||
err error
|
||||
|
||||
// transportResponseFrames counts the number of queued items that represent
|
||||
// the response of an action initiated by the peer. trfChan is created
|
||||
// when transportResponseFrames >= maxQueuedTransportResponseFrames and is
|
||||
// closed and nilled when transportResponseFrames drops below the
|
||||
// threshold. Both fields are protected by mu.
|
||||
transportResponseFrames int
|
||||
trfChan atomic.Value // *chan struct{}
|
||||
}
|
||||
|
||||
func newControlBuffer(done <-chan struct{}) *controlBuffer {
|
||||
return &controlBuffer{
|
||||
ch: make(chan struct{}, 1),
|
||||
list: &itemList{},
|
||||
done: done,
|
||||
}
|
||||
}
|
||||
|
||||
// throttle blocks if there are too many incomingSettings/cleanupStreams in the
|
||||
// controlbuf.
|
||||
func (c *controlBuffer) throttle() {
|
||||
ch, _ := c.trfChan.Load().(*chan struct{})
|
||||
if ch != nil {
|
||||
select {
|
||||
case <-*ch:
|
||||
case <-c.done:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controlBuffer) put(it cbItem) error {
|
||||
_, err := c.executeAndPut(nil, it)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it cbItem) (bool, error) {
|
||||
var wakeUp bool
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return false, c.err
|
||||
}
|
||||
if f != nil {
|
||||
if !f(it) { // f wasn't successful
|
||||
c.mu.Unlock()
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
if c.consumerWaiting {
|
||||
wakeUp = true
|
||||
c.consumerWaiting = false
|
||||
}
|
||||
c.list.enqueue(it)
|
||||
if it.isTransportResponseFrame() {
|
||||
c.transportResponseFrames++
|
||||
if c.transportResponseFrames == maxQueuedTransportResponseFrames {
|
||||
// We are adding the frame that puts us over the threshold; create
|
||||
// a throttling channel.
|
||||
ch := make(chan struct{})
|
||||
c.trfChan.Store(&ch)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
if wakeUp {
|
||||
select {
|
||||
case c.ch <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Note argument f should never be nil.
|
||||
func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bool, error) {
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return false, c.err
|
||||
}
|
||||
if !f(it) { // f wasn't successful
|
||||
c.mu.Unlock()
|
||||
return false, nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *controlBuffer) get(block bool) (interface{}, error) {
|
||||
for {
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return nil, c.err
|
||||
}
|
||||
if !c.list.isEmpty() {
|
||||
h := c.list.dequeue().(cbItem)
|
||||
if h.isTransportResponseFrame() {
|
||||
if c.transportResponseFrames == maxQueuedTransportResponseFrames {
|
||||
// We are removing the frame that put us over the
|
||||
// threshold; close and clear the throttling channel.
|
||||
ch := c.trfChan.Load().(*chan struct{})
|
||||
close(*ch)
|
||||
c.trfChan.Store((*chan struct{})(nil))
|
||||
}
|
||||
c.transportResponseFrames--
|
||||
}
|
||||
c.mu.Unlock()
|
||||
return h, nil
|
||||
}
|
||||
if !block {
|
||||
c.mu.Unlock()
|
||||
return nil, nil
|
||||
}
|
||||
c.consumerWaiting = true
|
||||
c.mu.Unlock()
|
||||
select {
|
||||
case <-c.ch:
|
||||
case <-c.done:
|
||||
c.finish()
|
||||
return nil, ErrConnClosing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controlBuffer) finish() {
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
c.err = ErrConnClosing
|
||||
// There may be headers for streams in the control buffer.
|
||||
// These streams need to be cleaned out since the transport
|
||||
// is still not aware of these yet.
|
||||
for head := c.list.dequeueAll(); head != nil; head = head.next {
|
||||
hdr, ok := head.it.(*headerFrame)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if hdr.onOrphaned != nil { // It will be nil on the server-side.
|
||||
hdr.onOrphaned(ErrConnClosing)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
type side int
|
||||
|
||||
const (
|
||||
clientSide side = iota
|
||||
serverSide
|
||||
)
|
||||
|
||||
// Loopy receives frames from the control buffer.
|
||||
// Each frame is handled individually; most of the work done by loopy goes
|
||||
// into handling data frames. Loopy maintains a queue of active streams, and each
|
||||
// stream maintains a queue of data frames; as loopy receives data frames
|
||||
// it gets added to the queue of the relevant stream.
|
||||
// Loopy goes over this list of active streams by processing one node every iteration,
|
||||
// thereby closely resemebling to a round-robin scheduling over all streams. While
|
||||
// processing a stream, loopy writes out data bytes from this stream capped by the min
|
||||
// of http2MaxFrameLen, connection-level flow control and stream-level flow control.
|
||||
type loopyWriter struct {
|
||||
side side
|
||||
cbuf *controlBuffer
|
||||
sendQuota uint32
|
||||
oiws uint32 // outbound initial window size.
|
||||
// estdStreams is map of all established streams that are not cleaned-up yet.
|
||||
// On client-side, this is all streams whose headers were sent out.
|
||||
// On server-side, this is all streams whose headers were received.
|
||||
estdStreams map[uint32]*outStream // Established streams.
|
||||
// activeStreams is a linked-list of all streams that have data to send and some
|
||||
// stream-level flow control quota.
|
||||
// Each of these streams internally have a list of data items(and perhaps trailers
|
||||
// on the server-side) to be sent out.
|
||||
activeStreams *outStreamList
|
||||
framer *framer
|
||||
hBuf *bytes.Buffer // The buffer for HPACK encoding.
|
||||
hEnc *hpack.Encoder // HPACK encoder.
|
||||
bdpEst *bdpEstimator
|
||||
draining bool
|
||||
|
||||
// Side-specific handlers
|
||||
ssGoAwayHandler func(*goAway) (bool, error)
|
||||
}
|
||||
|
||||
func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator) *loopyWriter {
|
||||
var buf bytes.Buffer
|
||||
l := &loopyWriter{
|
||||
side: s,
|
||||
cbuf: cbuf,
|
||||
sendQuota: defaultWindowSize,
|
||||
oiws: defaultWindowSize,
|
||||
estdStreams: make(map[uint32]*outStream),
|
||||
activeStreams: newOutStreamList(),
|
||||
framer: fr,
|
||||
hBuf: &buf,
|
||||
hEnc: hpack.NewEncoder(&buf),
|
||||
bdpEst: bdpEst,
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
const minBatchSize = 1000
|
||||
|
||||
// run should be run in a separate goroutine.
|
||||
// It reads control frames from controlBuf and processes them by:
|
||||
// 1. Updating loopy's internal state, or/and
|
||||
// 2. Writing out HTTP2 frames on the wire.
|
||||
//
|
||||
// Loopy keeps all active streams with data to send in a linked-list.
|
||||
// All streams in the activeStreams linked-list must have both:
|
||||
// 1. Data to send, and
|
||||
// 2. Stream level flow control quota available.
|
||||
//
|
||||
// In each iteration of run loop, other than processing the incoming control
|
||||
// frame, loopy calls processData, which processes one node from the activeStreams linked-list.
|
||||
// This results in writing of HTTP2 frames into an underlying write buffer.
|
||||
// When there's no more control frames to read from controlBuf, loopy flushes the write buffer.
|
||||
// As an optimization, to increase the batch size for each flush, loopy yields the processor, once
|
||||
// if the batch size is too low to give stream goroutines a chance to fill it up.
|
||||
func (l *loopyWriter) run() (err error) {
|
||||
defer func() {
|
||||
if err == ErrConnClosing {
|
||||
// Don't log ErrConnClosing as error since it happens
|
||||
// 1. When the connection is closed by some other known issue.
|
||||
// 2. User closed the connection.
|
||||
// 3. A graceful close of connection.
|
||||
infof("transport: loopyWriter.run returning. %v", err)
|
||||
err = nil
|
||||
}
|
||||
}()
|
||||
for {
|
||||
it, err := l.cbuf.get(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = l.handle(it); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = l.processData(); err != nil {
|
||||
return err
|
||||
}
|
||||
gosched := true
|
||||
hasdata:
|
||||
for {
|
||||
it, err := l.cbuf.get(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if it != nil {
|
||||
if err = l.handle(it); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = l.processData(); err != nil {
|
||||
return err
|
||||
}
|
||||
continue hasdata
|
||||
}
|
||||
isEmpty, err := l.processData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isEmpty {
|
||||
continue hasdata
|
||||
}
|
||||
if gosched {
|
||||
gosched = false
|
||||
if l.framer.writer.offset < minBatchSize {
|
||||
runtime.Gosched()
|
||||
continue hasdata
|
||||
}
|
||||
}
|
||||
l.framer.writer.Flush()
|
||||
break hasdata
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *loopyWriter) outgoingWindowUpdateHandler(w *outgoingWindowUpdate) error {
|
||||
return l.framer.fr.WriteWindowUpdate(w.streamID, w.increment)
|
||||
}
|
||||
|
||||
func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error {
|
||||
// Otherwise update the quota.
|
||||
if w.streamID == 0 {
|
||||
l.sendQuota += w.increment
|
||||
return nil
|
||||
}
|
||||
// Find the stream and update it.
|
||||
if str, ok := l.estdStreams[w.streamID]; ok {
|
||||
str.bytesOutStanding -= int(w.increment)
|
||||
if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota > 0 && str.state == waitingOnStreamQuota {
|
||||
str.state = active
|
||||
l.activeStreams.enqueue(str)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
|
||||
return l.framer.fr.WriteSettings(s.ss...)
|
||||
}
|
||||
|
||||
func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
|
||||
if err := l.applySettings(s.ss); err != nil {
|
||||
return err
|
||||
}
|
||||
return l.framer.fr.WriteSettingsAck()
|
||||
}
|
||||
|
||||
func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
|
||||
str := &outStream{
|
||||
id: h.streamID,
|
||||
state: empty,
|
||||
itl: &itemList{},
|
||||
wq: h.wq,
|
||||
}
|
||||
l.estdStreams[h.streamID] = str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) headerHandler(h *headerFrame) error {
|
||||
if l.side == serverSide {
|
||||
str, ok := l.estdStreams[h.streamID]
|
||||
if !ok {
|
||||
warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
|
||||
return nil
|
||||
}
|
||||
// Case 1.A: Server is responding back with headers.
|
||||
if !h.endStream {
|
||||
return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
|
||||
}
|
||||
// else: Case 1.B: Server wants to close stream.
|
||||
|
||||
if str.state != empty { // either active or waiting on stream quota.
|
||||
// add it str's list of items.
|
||||
str.itl.enqueue(h)
|
||||
return nil
|
||||
}
|
||||
if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
return l.cleanupStreamHandler(h.cleanup)
|
||||
}
|
||||
// Case 2: Client wants to originate stream.
|
||||
str := &outStream{
|
||||
id: h.streamID,
|
||||
state: empty,
|
||||
itl: &itemList{},
|
||||
wq: h.wq,
|
||||
}
|
||||
str.itl.enqueue(h)
|
||||
return l.originateStream(str)
|
||||
}
|
||||
|
||||
func (l *loopyWriter) originateStream(str *outStream) error {
|
||||
hdr := str.itl.dequeue().(*headerFrame)
|
||||
sendPing, err := hdr.initStream(str.id)
|
||||
if err != nil {
|
||||
if err == ErrConnClosing {
|
||||
return err
|
||||
}
|
||||
// Other errors(errStreamDrain) need not close transport.
|
||||
return nil
|
||||
}
|
||||
if err = l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
l.estdStreams[str.id] = str
|
||||
if sendPing {
|
||||
return l.pingHandler(&ping{data: [8]byte{}})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error {
|
||||
if onWrite != nil {
|
||||
onWrite()
|
||||
}
|
||||
l.hBuf.Reset()
|
||||
for _, f := range hf {
|
||||
if err := l.hEnc.WriteField(f); err != nil {
|
||||
warningf("transport: loopyWriter.writeHeader encountered error while encoding headers:", err)
|
||||
}
|
||||
}
|
||||
var (
|
||||
err error
|
||||
endHeaders, first bool
|
||||
)
|
||||
first = true
|
||||
for !endHeaders {
|
||||
size := l.hBuf.Len()
|
||||
if size > http2MaxFrameLen {
|
||||
size = http2MaxFrameLen
|
||||
} else {
|
||||
endHeaders = true
|
||||
}
|
||||
if first {
|
||||
first = false
|
||||
err = l.framer.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: streamID,
|
||||
BlockFragment: l.hBuf.Next(size),
|
||||
EndStream: endStream,
|
||||
EndHeaders: endHeaders,
|
||||
})
|
||||
} else {
|
||||
err = l.framer.fr.WriteContinuation(
|
||||
streamID,
|
||||
endHeaders,
|
||||
l.hBuf.Next(size),
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) preprocessData(df *dataFrame) error {
|
||||
str, ok := l.estdStreams[df.streamID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
// If we got data for a stream it means that
|
||||
// stream was originated and the headers were sent out.
|
||||
str.itl.enqueue(df)
|
||||
if str.state == empty {
|
||||
str.state = active
|
||||
l.activeStreams.enqueue(str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) pingHandler(p *ping) error {
|
||||
if !p.ack {
|
||||
l.bdpEst.timesnap(p.data)
|
||||
}
|
||||
return l.framer.fr.WritePing(p.ack, p.data)
|
||||
|
||||
}
|
||||
|
||||
func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) error {
|
||||
o.resp <- l.sendQuota
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
|
||||
c.onWrite()
|
||||
if str, ok := l.estdStreams[c.streamID]; ok {
|
||||
// On the server side it could be a trailers-only response or
|
||||
// a RST_STREAM before stream initialization thus the stream might
|
||||
// not be established yet.
|
||||
delete(l.estdStreams, c.streamID)
|
||||
str.deleteSelf()
|
||||
}
|
||||
if c.rst { // If RST_STREAM needs to be sent.
|
||||
if err := l.framer.fr.WriteRSTStream(c.streamID, c.rstCode); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if l.side == clientSide && l.draining && len(l.estdStreams) == 0 {
|
||||
return ErrConnClosing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
|
||||
if l.side == clientSide {
|
||||
l.draining = true
|
||||
if len(l.estdStreams) == 0 {
|
||||
return ErrConnClosing
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) goAwayHandler(g *goAway) error {
|
||||
// Handling of outgoing GoAway is very specific to side.
|
||||
if l.ssGoAwayHandler != nil {
|
||||
draining, err := l.ssGoAwayHandler(g)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.draining = draining
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) handle(i interface{}) error {
|
||||
switch i := i.(type) {
|
||||
case *incomingWindowUpdate:
|
||||
return l.incomingWindowUpdateHandler(i)
|
||||
case *outgoingWindowUpdate:
|
||||
return l.outgoingWindowUpdateHandler(i)
|
||||
case *incomingSettings:
|
||||
return l.incomingSettingsHandler(i)
|
||||
case *outgoingSettings:
|
||||
return l.outgoingSettingsHandler(i)
|
||||
case *headerFrame:
|
||||
return l.headerHandler(i)
|
||||
case *registerStream:
|
||||
return l.registerStreamHandler(i)
|
||||
case *cleanupStream:
|
||||
return l.cleanupStreamHandler(i)
|
||||
case *incomingGoAway:
|
||||
return l.incomingGoAwayHandler(i)
|
||||
case *dataFrame:
|
||||
return l.preprocessData(i)
|
||||
case *ping:
|
||||
return l.pingHandler(i)
|
||||
case *goAway:
|
||||
return l.goAwayHandler(i)
|
||||
case *outFlowControlSizeRequest:
|
||||
return l.outFlowControlSizeRequestHandler(i)
|
||||
default:
|
||||
return fmt.Errorf("transport: unknown control message type %T", i)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *loopyWriter) applySettings(ss []http2.Setting) error {
|
||||
for _, s := range ss {
|
||||
switch s.ID {
|
||||
case http2.SettingInitialWindowSize:
|
||||
o := l.oiws
|
||||
l.oiws = s.Val
|
||||
if o < l.oiws {
|
||||
// If the new limit is greater make all depleted streams active.
|
||||
for _, stream := range l.estdStreams {
|
||||
if stream.state == waitingOnStreamQuota {
|
||||
stream.state = active
|
||||
l.activeStreams.enqueue(stream)
|
||||
}
|
||||
}
|
||||
}
|
||||
case http2.SettingHeaderTableSize:
|
||||
updateHeaderTblSize(l.hEnc, s.Val)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processData removes the first stream from active streams, writes out at most 16KB
|
||||
// of its data and then puts it at the end of activeStreams if there's still more data
|
||||
// to be sent and stream has some stream-level flow control.
|
||||
func (l *loopyWriter) processData() (bool, error) {
|
||||
if l.sendQuota == 0 {
|
||||
return true, nil
|
||||
}
|
||||
str := l.activeStreams.dequeue() // Remove the first stream.
|
||||
if str == nil {
|
||||
return true, nil
|
||||
}
|
||||
dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
|
||||
// A data item is represented by a dataFrame, since it later translates into
|
||||
// multiple HTTP2 data frames.
|
||||
// Every dataFrame has two buffers; h that keeps grpc-message header and d that is acutal data.
|
||||
// As an optimization to keep wire traffic low, data from d is copied to h to make as big as the
|
||||
// maximum possilbe HTTP2 frame size.
|
||||
|
||||
if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame
|
||||
// Client sends out empty data frame with endStream = true
|
||||
if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
|
||||
return false, err
|
||||
}
|
||||
str.itl.dequeue() // remove the empty data item from stream
|
||||
if str.itl.isEmpty() {
|
||||
str.state = empty
|
||||
} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
|
||||
if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
l.activeStreams.enqueue(str)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
var (
|
||||
idx int
|
||||
buf []byte
|
||||
)
|
||||
if len(dataItem.h) != 0 { // data header has not been written out yet.
|
||||
buf = dataItem.h
|
||||
} else {
|
||||
idx = 1
|
||||
buf = dataItem.d
|
||||
}
|
||||
size := http2MaxFrameLen
|
||||
if len(buf) < size {
|
||||
size = len(buf)
|
||||
}
|
||||
if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control.
|
||||
str.state = waitingOnStreamQuota
|
||||
return false, nil
|
||||
} else if strQuota < size {
|
||||
size = strQuota
|
||||
}
|
||||
|
||||
if l.sendQuota < uint32(size) { // connection-level flow control.
|
||||
size = int(l.sendQuota)
|
||||
}
|
||||
// Now that outgoing flow controls are checked we can replenish str's write quota
|
||||
str.wq.replenish(size)
|
||||
var endStream bool
|
||||
// If this is the last data message on this stream and all of it can be written in this iteration.
|
||||
if dataItem.endStream && size == len(buf) {
|
||||
// buf contains either data or it contains header but data is empty.
|
||||
if idx == 1 || len(dataItem.d) == 0 {
|
||||
endStream = true
|
||||
}
|
||||
}
|
||||
if dataItem.onEachWrite != nil {
|
||||
dataItem.onEachWrite()
|
||||
}
|
||||
if err := l.framer.fr.WriteData(dataItem.streamID, endStream, buf[:size]); err != nil {
|
||||
return false, err
|
||||
}
|
||||
buf = buf[size:]
|
||||
str.bytesOutStanding += size
|
||||
l.sendQuota -= uint32(size)
|
||||
if idx == 0 {
|
||||
dataItem.h = buf
|
||||
} else {
|
||||
dataItem.d = buf
|
||||
}
|
||||
|
||||
if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // All the data from that message was written out.
|
||||
str.itl.dequeue()
|
||||
}
|
||||
if str.itl.isEmpty() {
|
||||
str.state = empty
|
||||
} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // The next item is trailers.
|
||||
if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
|
||||
return false, err
|
||||
}
|
||||
} else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota.
|
||||
str.state = waitingOnStreamQuota
|
||||
} else { // Otherwise add it back to the list of active streams.
|
||||
l.activeStreams.enqueue(str)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
49
vendor/google.golang.org/grpc/internal/transport/defaults.go
generated
vendored
Normal file
49
vendor/google.golang.org/grpc/internal/transport/defaults.go
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// The default value of flow control window size in HTTP2 spec.
|
||||
defaultWindowSize = 65535
|
||||
// The initial window size for flow control.
|
||||
initialWindowSize = defaultWindowSize // for an RPC
|
||||
infinity = time.Duration(math.MaxInt64)
|
||||
defaultClientKeepaliveTime = infinity
|
||||
defaultClientKeepaliveTimeout = 20 * time.Second
|
||||
defaultMaxStreamsClient = 100
|
||||
defaultMaxConnectionIdle = infinity
|
||||
defaultMaxConnectionAge = infinity
|
||||
defaultMaxConnectionAgeGrace = infinity
|
||||
defaultServerKeepaliveTime = 2 * time.Hour
|
||||
defaultServerKeepaliveTimeout = 20 * time.Second
|
||||
defaultKeepalivePolicyMinTime = 5 * time.Minute
|
||||
// max window limit set by HTTP2 Specs.
|
||||
maxWindowSize = math.MaxInt32
|
||||
// defaultWriteQuota is the default value for number of data
|
||||
// bytes that each stream can schedule before some of it being
|
||||
// flushed out.
|
||||
defaultWriteQuota = 64 * 1024
|
||||
defaultClientMaxHeaderListSize = uint32(16 << 20)
|
||||
defaultServerMaxHeaderListSize = uint32(16 << 20)
|
||||
)
|
||||
217
vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
generated
vendored
Normal file
217
vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
generated
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// writeQuota is a soft limit on the amount of data a stream can
|
||||
// schedule before some of it is written out.
|
||||
type writeQuota struct {
|
||||
quota int32
|
||||
// get waits on read from when quota goes less than or equal to zero.
|
||||
// replenish writes on it when quota goes positive again.
|
||||
ch chan struct{}
|
||||
// done is triggered in error case.
|
||||
done <-chan struct{}
|
||||
// replenish is called by loopyWriter to give quota back to.
|
||||
// It is implemented as a field so that it can be updated
|
||||
// by tests.
|
||||
replenish func(n int)
|
||||
}
|
||||
|
||||
func newWriteQuota(sz int32, done <-chan struct{}) *writeQuota {
|
||||
w := &writeQuota{
|
||||
quota: sz,
|
||||
ch: make(chan struct{}, 1),
|
||||
done: done,
|
||||
}
|
||||
w.replenish = w.realReplenish
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *writeQuota) get(sz int32) error {
|
||||
for {
|
||||
if atomic.LoadInt32(&w.quota) > 0 {
|
||||
atomic.AddInt32(&w.quota, -sz)
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-w.ch:
|
||||
continue
|
||||
case <-w.done:
|
||||
return errStreamDone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writeQuota) realReplenish(n int) {
|
||||
sz := int32(n)
|
||||
a := atomic.AddInt32(&w.quota, sz)
|
||||
b := a - sz
|
||||
if b <= 0 && a > 0 {
|
||||
select {
|
||||
case w.ch <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type trInFlow struct {
|
||||
limit uint32
|
||||
unacked uint32
|
||||
effectiveWindowSize uint32
|
||||
}
|
||||
|
||||
func (f *trInFlow) newLimit(n uint32) uint32 {
|
||||
d := n - f.limit
|
||||
f.limit = n
|
||||
f.updateEffectiveWindowSize()
|
||||
return d
|
||||
}
|
||||
|
||||
func (f *trInFlow) onData(n uint32) uint32 {
|
||||
f.unacked += n
|
||||
if f.unacked >= f.limit/4 {
|
||||
w := f.unacked
|
||||
f.unacked = 0
|
||||
f.updateEffectiveWindowSize()
|
||||
return w
|
||||
}
|
||||
f.updateEffectiveWindowSize()
|
||||
return 0
|
||||
}
|
||||
|
||||
func (f *trInFlow) reset() uint32 {
|
||||
w := f.unacked
|
||||
f.unacked = 0
|
||||
f.updateEffectiveWindowSize()
|
||||
return w
|
||||
}
|
||||
|
||||
func (f *trInFlow) updateEffectiveWindowSize() {
|
||||
atomic.StoreUint32(&f.effectiveWindowSize, f.limit-f.unacked)
|
||||
}
|
||||
|
||||
func (f *trInFlow) getSize() uint32 {
|
||||
return atomic.LoadUint32(&f.effectiveWindowSize)
|
||||
}
|
||||
|
||||
// TODO(mmukhi): Simplify this code.
|
||||
// inFlow deals with inbound flow control
|
||||
type inFlow struct {
|
||||
mu sync.Mutex
|
||||
// The inbound flow control limit for pending data.
|
||||
limit uint32
|
||||
// pendingData is the overall data which have been received but not been
|
||||
// consumed by applications.
|
||||
pendingData uint32
|
||||
// The amount of data the application has consumed but grpc has not sent
|
||||
// window update for them. Used to reduce window update frequency.
|
||||
pendingUpdate uint32
|
||||
// delta is the extra window update given by receiver when an application
|
||||
// is reading data bigger in size than the inFlow limit.
|
||||
delta uint32
|
||||
}
|
||||
|
||||
// newLimit updates the inflow window to a new value n.
|
||||
// It assumes that n is always greater than the old limit.
|
||||
func (f *inFlow) newLimit(n uint32) uint32 {
|
||||
f.mu.Lock()
|
||||
d := n - f.limit
|
||||
f.limit = n
|
||||
f.mu.Unlock()
|
||||
return d
|
||||
}
|
||||
|
||||
func (f *inFlow) maybeAdjust(n uint32) uint32 {
|
||||
if n > uint32(math.MaxInt32) {
|
||||
n = uint32(math.MaxInt32)
|
||||
}
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
// estSenderQuota is the receiver's view of the maximum number of bytes the sender
|
||||
// can send without a window update.
|
||||
estSenderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate))
|
||||
// estUntransmittedData is the maximum number of bytes the sends might not have put
|
||||
// on the wire yet. A value of 0 or less means that we have already received all or
|
||||
// more bytes than the application is requesting to read.
|
||||
estUntransmittedData := int32(n - f.pendingData) // Casting into int32 since it could be negative.
|
||||
// This implies that unless we send a window update, the sender won't be able to send all the bytes
|
||||
// for this message. Therefore we must send an update over the limit since there's an active read
|
||||
// request from the application.
|
||||
if estUntransmittedData > estSenderQuota {
|
||||
// Sender's window shouldn't go more than 2^31 - 1 as specified in the HTTP spec.
|
||||
if f.limit+n > maxWindowSize {
|
||||
f.delta = maxWindowSize - f.limit
|
||||
} else {
|
||||
// Send a window update for the whole message and not just the difference between
|
||||
// estUntransmittedData and estSenderQuota. This will be helpful in case the message
|
||||
// is padded; We will fallback on the current available window(at least a 1/4th of the limit).
|
||||
f.delta = n
|
||||
}
|
||||
return f.delta
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// onData is invoked when some data frame is received. It updates pendingData.
|
||||
func (f *inFlow) onData(n uint32) error {
|
||||
f.mu.Lock()
|
||||
f.pendingData += n
|
||||
if f.pendingData+f.pendingUpdate > f.limit+f.delta {
|
||||
limit := f.limit
|
||||
rcvd := f.pendingData + f.pendingUpdate
|
||||
f.mu.Unlock()
|
||||
return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", rcvd, limit)
|
||||
}
|
||||
f.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// onRead is invoked when the application reads the data. It returns the window size
|
||||
// to be sent to the peer.
|
||||
func (f *inFlow) onRead(n uint32) uint32 {
|
||||
f.mu.Lock()
|
||||
if f.pendingData == 0 {
|
||||
f.mu.Unlock()
|
||||
return 0
|
||||
}
|
||||
f.pendingData -= n
|
||||
if n > f.delta {
|
||||
n -= f.delta
|
||||
f.delta = 0
|
||||
} else {
|
||||
f.delta -= n
|
||||
n = 0
|
||||
}
|
||||
f.pendingUpdate += n
|
||||
if f.pendingUpdate >= f.limit/4 {
|
||||
wu := f.pendingUpdate
|
||||
f.pendingUpdate = 0
|
||||
f.mu.Unlock()
|
||||
return wu
|
||||
}
|
||||
f.mu.Unlock()
|
||||
return 0
|
||||
}
|
||||
431
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
Normal file
431
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file is the implementation of a gRPC server using HTTP/2 which
|
||||
// uses the standard Go http2 Server implementation (via the
|
||||
// http.Handler interface), rather than speaking low-level HTTP/2
|
||||
// frames itself. It is the implementation of *grpc.Server.ServeHTTP.
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/http2"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// NewServerHandlerTransport returns a ServerTransport handling gRPC
|
||||
// from inside an http.Handler. It requires that the http Server
|
||||
// supports HTTP/2.
|
||||
func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler) (ServerTransport, error) {
|
||||
if r.ProtoMajor != 2 {
|
||||
return nil, errors.New("gRPC requires HTTP/2")
|
||||
}
|
||||
if r.Method != "POST" {
|
||||
return nil, errors.New("invalid gRPC request method")
|
||||
}
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
// TODO: do we assume contentType is lowercase? we did before
|
||||
contentSubtype, validContentType := contentSubtype(contentType)
|
||||
if !validContentType {
|
||||
return nil, errors.New("invalid gRPC request content-type")
|
||||
}
|
||||
if _, ok := w.(http.Flusher); !ok {
|
||||
return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
|
||||
}
|
||||
|
||||
st := &serverHandlerTransport{
|
||||
rw: w,
|
||||
req: r,
|
||||
closedCh: make(chan struct{}),
|
||||
writes: make(chan func()),
|
||||
contentType: contentType,
|
||||
contentSubtype: contentSubtype,
|
||||
stats: stats,
|
||||
}
|
||||
|
||||
if v := r.Header.Get("grpc-timeout"); v != "" {
|
||||
to, err := decodeTimeout(v)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
|
||||
}
|
||||
st.timeoutSet = true
|
||||
st.timeout = to
|
||||
}
|
||||
|
||||
metakv := []string{"content-type", contentType}
|
||||
if r.Host != "" {
|
||||
metakv = append(metakv, ":authority", r.Host)
|
||||
}
|
||||
for k, vv := range r.Header {
|
||||
k = strings.ToLower(k)
|
||||
if isReservedHeader(k) && !isWhitelistedHeader(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
v, err := decodeMetadataHeader(k, v)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err)
|
||||
}
|
||||
metakv = append(metakv, k, v)
|
||||
}
|
||||
}
|
||||
st.headerMD = metadata.Pairs(metakv...)
|
||||
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// serverHandlerTransport is an implementation of ServerTransport
|
||||
// which replies to exactly one gRPC request (exactly one HTTP request),
|
||||
// using the net/http.Handler interface. This http.Handler is guaranteed
|
||||
// at this point to be speaking over HTTP/2, so it's able to speak valid
|
||||
// gRPC.
|
||||
type serverHandlerTransport struct {
|
||||
rw http.ResponseWriter
|
||||
req *http.Request
|
||||
timeoutSet bool
|
||||
timeout time.Duration
|
||||
didCommonHeaders bool
|
||||
|
||||
headerMD metadata.MD
|
||||
|
||||
closeOnce sync.Once
|
||||
closedCh chan struct{} // closed on Close
|
||||
|
||||
// writes is a channel of code to run serialized in the
|
||||
// ServeHTTP (HandleStreams) goroutine. The channel is closed
|
||||
// when WriteStatus is called.
|
||||
writes chan func()
|
||||
|
||||
// block concurrent WriteStatus calls
|
||||
// e.g. grpc/(*serverStream).SendMsg/RecvMsg
|
||||
writeStatusMu sync.Mutex
|
||||
|
||||
// we just mirror the request content-type
|
||||
contentType string
|
||||
// we store both contentType and contentSubtype so we don't keep recreating them
|
||||
// TODO make sure this is consistent across handler_server and http2_server
|
||||
contentSubtype string
|
||||
|
||||
stats stats.Handler
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) Close() error {
|
||||
ht.closeOnce.Do(ht.closeCloseChanOnce)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) }
|
||||
|
||||
func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
|
||||
|
||||
// strAddr is a net.Addr backed by either a TCP "ip:port" string, or
|
||||
// the empty string if unknown.
|
||||
type strAddr string
|
||||
|
||||
func (a strAddr) Network() string {
|
||||
if a != "" {
|
||||
// Per the documentation on net/http.Request.RemoteAddr, if this is
|
||||
// set, it's set to the IP:port of the peer (hence, TCP):
|
||||
// https://golang.org/pkg/net/http/#Request
|
||||
//
|
||||
// If we want to support Unix sockets later, we can
|
||||
// add our own grpc-specific convention within the
|
||||
// grpc codebase to set RemoteAddr to a different
|
||||
// format, or probably better: we can attach it to the
|
||||
// context and use that from serverHandlerTransport.RemoteAddr.
|
||||
return "tcp"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a strAddr) String() string { return string(a) }
|
||||
|
||||
// do runs fn in the ServeHTTP goroutine.
|
||||
func (ht *serverHandlerTransport) do(fn func()) error {
|
||||
select {
|
||||
case <-ht.closedCh:
|
||||
return ErrConnClosing
|
||||
case ht.writes <- fn:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error {
|
||||
ht.writeStatusMu.Lock()
|
||||
defer ht.writeStatusMu.Unlock()
|
||||
|
||||
err := ht.do(func() {
|
||||
ht.writeCommonHeaders(s)
|
||||
|
||||
// And flush, in case no header or body has been sent yet.
|
||||
// This forces a separation of headers and trailers if this is the
|
||||
// first call (for example, in end2end tests's TestNoService).
|
||||
ht.rw.(http.Flusher).Flush()
|
||||
|
||||
h := ht.rw.Header()
|
||||
h.Set("Grpc-Status", fmt.Sprintf("%d", st.Code()))
|
||||
if m := st.Message(); m != "" {
|
||||
h.Set("Grpc-Message", encodeGrpcMessage(m))
|
||||
}
|
||||
|
||||
if p := st.Proto(); p != nil && len(p.Details) > 0 {
|
||||
stBytes, err := proto.Marshal(p)
|
||||
if err != nil {
|
||||
// TODO: return error instead, when callers are able to handle it.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
|
||||
}
|
||||
|
||||
if md := s.Trailer(); len(md) > 0 {
|
||||
for k, vv := range md {
|
||||
// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
|
||||
if isReservedHeader(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
// http2 ResponseWriter mechanism to send undeclared Trailers after
|
||||
// the headers have possibly been written.
|
||||
h.Add(http2.TrailerPrefix+k, encodeMetadataHeader(k, v))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if err == nil { // transport has not been closed
|
||||
if ht.stats != nil {
|
||||
ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
|
||||
}
|
||||
}
|
||||
ht.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// writeCommonHeaders sets common headers on the first write
|
||||
// call (Write, WriteHeader, or WriteStatus).
|
||||
func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
|
||||
if ht.didCommonHeaders {
|
||||
return
|
||||
}
|
||||
ht.didCommonHeaders = true
|
||||
|
||||
h := ht.rw.Header()
|
||||
h["Date"] = nil // suppress Date to make tests happy; TODO: restore
|
||||
h.Set("Content-Type", ht.contentType)
|
||||
|
||||
// Predeclare trailers we'll set later in WriteStatus (after the body).
|
||||
// This is a SHOULD in the HTTP RFC, and the way you add (known)
|
||||
// Trailers per the net/http.ResponseWriter contract.
|
||||
// See https://golang.org/pkg/net/http/#ResponseWriter
|
||||
// and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
|
||||
h.Add("Trailer", "Grpc-Status")
|
||||
h.Add("Trailer", "Grpc-Message")
|
||||
h.Add("Trailer", "Grpc-Status-Details-Bin")
|
||||
|
||||
if s.sendCompress != "" {
|
||||
h.Set("Grpc-Encoding", s.sendCompress)
|
||||
}
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
|
||||
return ht.do(func() {
|
||||
ht.writeCommonHeaders(s)
|
||||
ht.rw.Write(hdr)
|
||||
ht.rw.Write(data)
|
||||
ht.rw.(http.Flusher).Flush()
|
||||
})
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
|
||||
err := ht.do(func() {
|
||||
ht.writeCommonHeaders(s)
|
||||
h := ht.rw.Header()
|
||||
for k, vv := range md {
|
||||
// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
|
||||
if isReservedHeader(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
v = encodeMetadataHeader(k, v)
|
||||
h.Add(k, v)
|
||||
}
|
||||
}
|
||||
ht.rw.WriteHeader(200)
|
||||
ht.rw.(http.Flusher).Flush()
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
if ht.stats != nil {
|
||||
ht.stats.HandleRPC(s.Context(), &stats.OutHeader{})
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
|
||||
// With this transport type there will be exactly 1 stream: this HTTP request.
|
||||
|
||||
ctx := ht.req.Context()
|
||||
var cancel context.CancelFunc
|
||||
if ht.timeoutSet {
|
||||
ctx, cancel = context.WithTimeout(ctx, ht.timeout)
|
||||
} else {
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
// requestOver is closed when the status has been written via WriteStatus.
|
||||
requestOver := make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-requestOver:
|
||||
case <-ht.closedCh:
|
||||
case <-ht.req.Context().Done():
|
||||
}
|
||||
cancel()
|
||||
ht.Close()
|
||||
}()
|
||||
|
||||
req := ht.req
|
||||
|
||||
s := &Stream{
|
||||
id: 0, // irrelevant
|
||||
requestRead: func(int) {},
|
||||
cancel: cancel,
|
||||
buf: newRecvBuffer(),
|
||||
st: ht,
|
||||
method: req.URL.Path,
|
||||
recvCompress: req.Header.Get("grpc-encoding"),
|
||||
contentSubtype: ht.contentSubtype,
|
||||
}
|
||||
pr := &peer.Peer{
|
||||
Addr: ht.RemoteAddr(),
|
||||
}
|
||||
if req.TLS != nil {
|
||||
pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
|
||||
}
|
||||
ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
|
||||
s.ctx = peer.NewContext(ctx, pr)
|
||||
if ht.stats != nil {
|
||||
s.ctx = ht.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
|
||||
inHeader := &stats.InHeader{
|
||||
FullMethod: s.method,
|
||||
RemoteAddr: ht.RemoteAddr(),
|
||||
Compression: s.recvCompress,
|
||||
}
|
||||
ht.stats.HandleRPC(s.ctx, inHeader)
|
||||
}
|
||||
s.trReader = &transportReader{
|
||||
reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf, freeBuffer: func(*bytes.Buffer) {}},
|
||||
windowHandler: func(int) {},
|
||||
}
|
||||
|
||||
// readerDone is closed when the Body.Read-ing goroutine exits.
|
||||
readerDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(readerDone)
|
||||
|
||||
// TODO: minimize garbage, optimize recvBuffer code/ownership
|
||||
const readSize = 8196
|
||||
for buf := make([]byte, readSize); ; {
|
||||
n, err := req.Body.Read(buf)
|
||||
if n > 0 {
|
||||
s.buf.put(recvMsg{buffer: bytes.NewBuffer(buf[:n:n])})
|
||||
buf = buf[n:]
|
||||
}
|
||||
if err != nil {
|
||||
s.buf.put(recvMsg{err: mapRecvMsgError(err)})
|
||||
return
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
buf = make([]byte, readSize)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// startStream is provided by the *grpc.Server's serveStreams.
|
||||
// It starts a goroutine serving s and exits immediately.
|
||||
// The goroutine that is started is the one that then calls
|
||||
// into ht, calling WriteHeader, Write, WriteStatus, Close, etc.
|
||||
startStream(s)
|
||||
|
||||
ht.runStream()
|
||||
close(requestOver)
|
||||
|
||||
// Wait for reading goroutine to finish.
|
||||
req.Body.Close()
|
||||
<-readerDone
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) runStream() {
|
||||
for {
|
||||
select {
|
||||
case fn := <-ht.writes:
|
||||
fn()
|
||||
case <-ht.closedCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) IncrMsgSent() {}
|
||||
|
||||
func (ht *serverHandlerTransport) IncrMsgRecv() {}
|
||||
|
||||
func (ht *serverHandlerTransport) Drain() {
|
||||
panic("Drain() is not implemented")
|
||||
}
|
||||
|
||||
// mapRecvMsgError returns the non-nil err into the appropriate
|
||||
// error value as expected by callers of *grpc.parser.recvMsg.
|
||||
// In particular, in can only be:
|
||||
// * io.EOF
|
||||
// * io.ErrUnexpectedEOF
|
||||
// * of type transport.ConnectionError
|
||||
// * an error from the status package
|
||||
func mapRecvMsgError(err error) error {
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
return err
|
||||
}
|
||||
if se, ok := err.(http2.StreamError); ok {
|
||||
if code, ok := http2ErrConvTab[se.Code]; ok {
|
||||
return status.Error(code, se.Error())
|
||||
}
|
||||
}
|
||||
if strings.Contains(err.Error(), "body closed by handler") {
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
}
|
||||
return connectionErrorf(true, err, err.Error())
|
||||
}
|
||||
1411
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
Normal file
1411
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1220
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
Normal file
1220
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
676
vendor/google.golang.org/grpc/internal/transport/http_util.go
generated
vendored
Normal file
676
vendor/google.golang.org/grpc/internal/transport/http_util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
// http2MaxFrameLen specifies the max length of a HTTP2 frame.
|
||||
http2MaxFrameLen = 16384 // 16KB frame
|
||||
// http://http2.github.io/http2-spec/#SettingValues
|
||||
http2InitHeaderTableSize = 4096
|
||||
// baseContentType is the base content-type for gRPC. This is a valid
|
||||
// content-type on it's own, but can also include a content-subtype such as
|
||||
// "proto" as a suffix after "+" or ";". See
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
|
||||
// for more details.
|
||||
baseContentType = "application/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
clientPreface = []byte(http2.ClientPreface)
|
||||
http2ErrConvTab = map[http2.ErrCode]codes.Code{
|
||||
http2.ErrCodeNo: codes.Internal,
|
||||
http2.ErrCodeProtocol: codes.Internal,
|
||||
http2.ErrCodeInternal: codes.Internal,
|
||||
http2.ErrCodeFlowControl: codes.ResourceExhausted,
|
||||
http2.ErrCodeSettingsTimeout: codes.Internal,
|
||||
http2.ErrCodeStreamClosed: codes.Internal,
|
||||
http2.ErrCodeFrameSize: codes.Internal,
|
||||
http2.ErrCodeRefusedStream: codes.Unavailable,
|
||||
http2.ErrCodeCancel: codes.Canceled,
|
||||
http2.ErrCodeCompression: codes.Internal,
|
||||
http2.ErrCodeConnect: codes.Internal,
|
||||
http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
|
||||
http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
|
||||
http2.ErrCodeHTTP11Required: codes.Internal,
|
||||
}
|
||||
statusCodeConvTab = map[codes.Code]http2.ErrCode{
|
||||
codes.Internal: http2.ErrCodeInternal,
|
||||
codes.Canceled: http2.ErrCodeCancel,
|
||||
codes.Unavailable: http2.ErrCodeRefusedStream,
|
||||
codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
|
||||
codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
|
||||
}
|
||||
// HTTPStatusConvTab is the HTTP status code to gRPC error code conversion table.
|
||||
HTTPStatusConvTab = map[int]codes.Code{
|
||||
// 400 Bad Request - INTERNAL.
|
||||
http.StatusBadRequest: codes.Internal,
|
||||
// 401 Unauthorized - UNAUTHENTICATED.
|
||||
http.StatusUnauthorized: codes.Unauthenticated,
|
||||
// 403 Forbidden - PERMISSION_DENIED.
|
||||
http.StatusForbidden: codes.PermissionDenied,
|
||||
// 404 Not Found - UNIMPLEMENTED.
|
||||
http.StatusNotFound: codes.Unimplemented,
|
||||
// 429 Too Many Requests - UNAVAILABLE.
|
||||
http.StatusTooManyRequests: codes.Unavailable,
|
||||
// 502 Bad Gateway - UNAVAILABLE.
|
||||
http.StatusBadGateway: codes.Unavailable,
|
||||
// 503 Service Unavailable - UNAVAILABLE.
|
||||
http.StatusServiceUnavailable: codes.Unavailable,
|
||||
// 504 Gateway timeout - UNAVAILABLE.
|
||||
http.StatusGatewayTimeout: codes.Unavailable,
|
||||
}
|
||||
)
|
||||
|
||||
type parsedHeaderData struct {
|
||||
encoding string
|
||||
// statusGen caches the stream status received from the trailer the server
|
||||
// sent. Client side only. Do not access directly. After all trailers are
|
||||
// parsed, use the status method to retrieve the status.
|
||||
statusGen *status.Status
|
||||
// rawStatusCode and rawStatusMsg are set from the raw trailer fields and are not
|
||||
// intended for direct access outside of parsing.
|
||||
rawStatusCode *int
|
||||
rawStatusMsg string
|
||||
httpStatus *int
|
||||
// Server side only fields.
|
||||
timeoutSet bool
|
||||
timeout time.Duration
|
||||
method string
|
||||
// key-value metadata map from the peer.
|
||||
mdata map[string][]string
|
||||
statsTags []byte
|
||||
statsTrace []byte
|
||||
contentSubtype string
|
||||
|
||||
// isGRPC field indicates whether the peer is speaking gRPC (otherwise HTTP).
|
||||
//
|
||||
// We are in gRPC mode (peer speaking gRPC) if:
|
||||
// * We are client side and have already received a HEADER frame that indicates gRPC peer.
|
||||
// * The header contains valid a content-type, i.e. a string starts with "application/grpc"
|
||||
// And we should handle error specific to gRPC.
|
||||
//
|
||||
// Otherwise (i.e. a content-type string starts without "application/grpc", or does not exist), we
|
||||
// are in HTTP fallback mode, and should handle error specific to HTTP.
|
||||
isGRPC bool
|
||||
grpcErr error
|
||||
httpErr error
|
||||
contentTypeErr string
|
||||
}
|
||||
|
||||
// decodeState configures decoding criteria and records the decoded data.
|
||||
type decodeState struct {
|
||||
// whether decoding on server side or not
|
||||
serverSide bool
|
||||
|
||||
// Records the states during HPACK decoding. It will be filled with info parsed from HTTP HEADERS
|
||||
// frame once decodeHeader function has been invoked and returned.
|
||||
data parsedHeaderData
|
||||
}
|
||||
|
||||
// isReservedHeader checks whether hdr belongs to HTTP2 headers
|
||||
// reserved by gRPC protocol. Any other headers are classified as the
|
||||
// user-specified metadata.
|
||||
func isReservedHeader(hdr string) bool {
|
||||
if hdr != "" && hdr[0] == ':' {
|
||||
return true
|
||||
}
|
||||
switch hdr {
|
||||
case "content-type",
|
||||
"user-agent",
|
||||
"grpc-message-type",
|
||||
"grpc-encoding",
|
||||
"grpc-message",
|
||||
"grpc-status",
|
||||
"grpc-timeout",
|
||||
"grpc-status-details-bin",
|
||||
// Intentionally exclude grpc-previous-rpc-attempts and
|
||||
// grpc-retry-pushback-ms, which are "reserved", but their API
|
||||
// intentionally works via metadata.
|
||||
"te":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// isWhitelistedHeader checks whether hdr should be propagated into metadata
|
||||
// visible to users, even though it is classified as "reserved", above.
|
||||
func isWhitelistedHeader(hdr string) bool {
|
||||
switch hdr {
|
||||
case ":authority", "user-agent":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// contentSubtype returns the content-subtype for the given content-type. The
|
||||
// given content-type must be a valid content-type that starts with
|
||||
// "application/grpc". A content-subtype will follow "application/grpc" after a
|
||||
// "+" or ";". See
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||
// more details.
|
||||
//
|
||||
// If contentType is not a valid content-type for gRPC, the boolean
|
||||
// will be false, otherwise true. If content-type == "application/grpc",
|
||||
// "application/grpc+", or "application/grpc;", the boolean will be true,
|
||||
// but no content-subtype will be returned.
|
||||
//
|
||||
// contentType is assumed to be lowercase already.
|
||||
func contentSubtype(contentType string) (string, bool) {
|
||||
if contentType == baseContentType {
|
||||
return "", true
|
||||
}
|
||||
if !strings.HasPrefix(contentType, baseContentType) {
|
||||
return "", false
|
||||
}
|
||||
// guaranteed since != baseContentType and has baseContentType prefix
|
||||
switch contentType[len(baseContentType)] {
|
||||
case '+', ';':
|
||||
// this will return true for "application/grpc+" or "application/grpc;"
|
||||
// which the previous validContentType function tested to be valid, so we
|
||||
// just say that no content-subtype is specified in this case
|
||||
return contentType[len(baseContentType)+1:], true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
// contentSubtype is assumed to be lowercase
|
||||
func contentType(contentSubtype string) string {
|
||||
if contentSubtype == "" {
|
||||
return baseContentType
|
||||
}
|
||||
return baseContentType + "+" + contentSubtype
|
||||
}
|
||||
|
||||
func (d *decodeState) status() *status.Status {
|
||||
if d.data.statusGen == nil {
|
||||
// No status-details were provided; generate status using code/msg.
|
||||
d.data.statusGen = status.New(codes.Code(int32(*(d.data.rawStatusCode))), d.data.rawStatusMsg)
|
||||
}
|
||||
return d.data.statusGen
|
||||
}
|
||||
|
||||
const binHdrSuffix = "-bin"
|
||||
|
||||
func encodeBinHeader(v []byte) string {
|
||||
return base64.RawStdEncoding.EncodeToString(v)
|
||||
}
|
||||
|
||||
func decodeBinHeader(v string) ([]byte, error) {
|
||||
if len(v)%4 == 0 {
|
||||
// Input was padded, or padding was not necessary.
|
||||
return base64.StdEncoding.DecodeString(v)
|
||||
}
|
||||
return base64.RawStdEncoding.DecodeString(v)
|
||||
}
|
||||
|
||||
func encodeMetadataHeader(k, v string) string {
|
||||
if strings.HasSuffix(k, binHdrSuffix) {
|
||||
return encodeBinHeader(([]byte)(v))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func decodeMetadataHeader(k, v string) (string, error) {
|
||||
if strings.HasSuffix(k, binHdrSuffix) {
|
||||
b, err := decodeBinHeader(v)
|
||||
return string(b), err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error {
|
||||
// frame.Truncated is set to true when framer detects that the current header
|
||||
// list size hits MaxHeaderListSize limit.
|
||||
if frame.Truncated {
|
||||
return status.Error(codes.Internal, "peer header list size exceeded limit")
|
||||
}
|
||||
|
||||
for _, hf := range frame.Fields {
|
||||
d.processHeaderField(hf)
|
||||
}
|
||||
|
||||
if d.data.isGRPC {
|
||||
if d.data.grpcErr != nil {
|
||||
return d.data.grpcErr
|
||||
}
|
||||
if d.serverSide {
|
||||
return nil
|
||||
}
|
||||
if d.data.rawStatusCode == nil && d.data.statusGen == nil {
|
||||
// gRPC status doesn't exist.
|
||||
// Set rawStatusCode to be unknown and return nil error.
|
||||
// So that, if the stream has ended this Unknown status
|
||||
// will be propagated to the user.
|
||||
// Otherwise, it will be ignored. In which case, status from
|
||||
// a later trailer, that has StreamEnded flag set, is propagated.
|
||||
code := int(codes.Unknown)
|
||||
d.data.rawStatusCode = &code
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HTTP fallback mode
|
||||
if d.data.httpErr != nil {
|
||||
return d.data.httpErr
|
||||
}
|
||||
|
||||
var (
|
||||
code = codes.Internal // when header does not include HTTP status, return INTERNAL
|
||||
ok bool
|
||||
)
|
||||
|
||||
if d.data.httpStatus != nil {
|
||||
code, ok = HTTPStatusConvTab[*(d.data.httpStatus)]
|
||||
if !ok {
|
||||
code = codes.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
return status.Error(code, d.constructHTTPErrMsg())
|
||||
}
|
||||
|
||||
// constructErrMsg constructs error message to be returned in HTTP fallback mode.
|
||||
// Format: HTTP status code and its corresponding message + content-type error message.
|
||||
func (d *decodeState) constructHTTPErrMsg() string {
|
||||
var errMsgs []string
|
||||
|
||||
if d.data.httpStatus == nil {
|
||||
errMsgs = append(errMsgs, "malformed header: missing HTTP status")
|
||||
} else {
|
||||
errMsgs = append(errMsgs, fmt.Sprintf("%s: HTTP status code %d", http.StatusText(*(d.data.httpStatus)), *d.data.httpStatus))
|
||||
}
|
||||
|
||||
if d.data.contentTypeErr == "" {
|
||||
errMsgs = append(errMsgs, "transport: missing content-type field")
|
||||
} else {
|
||||
errMsgs = append(errMsgs, d.data.contentTypeErr)
|
||||
}
|
||||
|
||||
return strings.Join(errMsgs, "; ")
|
||||
}
|
||||
|
||||
func (d *decodeState) addMetadata(k, v string) {
|
||||
if d.data.mdata == nil {
|
||||
d.data.mdata = make(map[string][]string)
|
||||
}
|
||||
d.data.mdata[k] = append(d.data.mdata[k], v)
|
||||
}
|
||||
|
||||
func (d *decodeState) processHeaderField(f hpack.HeaderField) {
|
||||
switch f.Name {
|
||||
case "content-type":
|
||||
contentSubtype, validContentType := contentSubtype(f.Value)
|
||||
if !validContentType {
|
||||
d.data.contentTypeErr = fmt.Sprintf("transport: received the unexpected content-type %q", f.Value)
|
||||
return
|
||||
}
|
||||
d.data.contentSubtype = contentSubtype
|
||||
// TODO: do we want to propagate the whole content-type in the metadata,
|
||||
// or come up with a way to just propagate the content-subtype if it was set?
|
||||
// ie {"content-type": "application/grpc+proto"} or {"content-subtype": "proto"}
|
||||
// in the metadata?
|
||||
d.addMetadata(f.Name, f.Value)
|
||||
d.data.isGRPC = true
|
||||
case "grpc-encoding":
|
||||
d.data.encoding = f.Value
|
||||
case "grpc-status":
|
||||
code, err := strconv.Atoi(f.Value)
|
||||
if err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status: %v", err)
|
||||
return
|
||||
}
|
||||
d.data.rawStatusCode = &code
|
||||
case "grpc-message":
|
||||
d.data.rawStatusMsg = decodeGrpcMessage(f.Value)
|
||||
case "grpc-status-details-bin":
|
||||
v, err := decodeBinHeader(f.Value)
|
||||
if err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
|
||||
return
|
||||
}
|
||||
s := &spb.Status{}
|
||||
if err := proto.Unmarshal(v, s); err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
|
||||
return
|
||||
}
|
||||
d.data.statusGen = status.FromProto(s)
|
||||
case "grpc-timeout":
|
||||
d.data.timeoutSet = true
|
||||
var err error
|
||||
if d.data.timeout, err = decodeTimeout(f.Value); err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed time-out: %v", err)
|
||||
}
|
||||
case ":path":
|
||||
d.data.method = f.Value
|
||||
case ":status":
|
||||
code, err := strconv.Atoi(f.Value)
|
||||
if err != nil {
|
||||
d.data.httpErr = status.Errorf(codes.Internal, "transport: malformed http-status: %v", err)
|
||||
return
|
||||
}
|
||||
d.data.httpStatus = &code
|
||||
case "grpc-tags-bin":
|
||||
v, err := decodeBinHeader(f.Value)
|
||||
if err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-tags-bin: %v", err)
|
||||
return
|
||||
}
|
||||
d.data.statsTags = v
|
||||
d.addMetadata(f.Name, string(v))
|
||||
case "grpc-trace-bin":
|
||||
v, err := decodeBinHeader(f.Value)
|
||||
if err != nil {
|
||||
d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-trace-bin: %v", err)
|
||||
return
|
||||
}
|
||||
d.data.statsTrace = v
|
||||
d.addMetadata(f.Name, string(v))
|
||||
default:
|
||||
if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
|
||||
break
|
||||
}
|
||||
v, err := decodeMetadataHeader(f.Name, f.Value)
|
||||
if err != nil {
|
||||
errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
|
||||
return
|
||||
}
|
||||
d.addMetadata(f.Name, v)
|
||||
}
|
||||
}
|
||||
|
||||
type timeoutUnit uint8
|
||||
|
||||
const (
|
||||
hour timeoutUnit = 'H'
|
||||
minute timeoutUnit = 'M'
|
||||
second timeoutUnit = 'S'
|
||||
millisecond timeoutUnit = 'm'
|
||||
microsecond timeoutUnit = 'u'
|
||||
nanosecond timeoutUnit = 'n'
|
||||
)
|
||||
|
||||
func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
|
||||
switch u {
|
||||
case hour:
|
||||
return time.Hour, true
|
||||
case minute:
|
||||
return time.Minute, true
|
||||
case second:
|
||||
return time.Second, true
|
||||
case millisecond:
|
||||
return time.Millisecond, true
|
||||
case microsecond:
|
||||
return time.Microsecond, true
|
||||
case nanosecond:
|
||||
return time.Nanosecond, true
|
||||
default:
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const maxTimeoutValue int64 = 100000000 - 1
|
||||
|
||||
// div does integer division and round-up the result. Note that this is
|
||||
// equivalent to (d+r-1)/r but has less chance to overflow.
|
||||
func div(d, r time.Duration) int64 {
|
||||
if m := d % r; m > 0 {
|
||||
return int64(d/r + 1)
|
||||
}
|
||||
return int64(d / r)
|
||||
}
|
||||
|
||||
// TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it.
|
||||
func encodeTimeout(t time.Duration) string {
|
||||
if t <= 0 {
|
||||
return "0n"
|
||||
}
|
||||
if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
|
||||
return strconv.FormatInt(d, 10) + "n"
|
||||
}
|
||||
if d := div(t, time.Microsecond); d <= maxTimeoutValue {
|
||||
return strconv.FormatInt(d, 10) + "u"
|
||||
}
|
||||
if d := div(t, time.Millisecond); d <= maxTimeoutValue {
|
||||
return strconv.FormatInt(d, 10) + "m"
|
||||
}
|
||||
if d := div(t, time.Second); d <= maxTimeoutValue {
|
||||
return strconv.FormatInt(d, 10) + "S"
|
||||
}
|
||||
if d := div(t, time.Minute); d <= maxTimeoutValue {
|
||||
return strconv.FormatInt(d, 10) + "M"
|
||||
}
|
||||
// Note that maxTimeoutValue * time.Hour > MaxInt64.
|
||||
return strconv.FormatInt(div(t, time.Hour), 10) + "H"
|
||||
}
|
||||
|
||||
func decodeTimeout(s string) (time.Duration, error) {
|
||||
size := len(s)
|
||||
if size < 2 {
|
||||
return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
|
||||
}
|
||||
if size > 9 {
|
||||
// Spec allows for 8 digits plus the unit.
|
||||
return 0, fmt.Errorf("transport: timeout string is too long: %q", s)
|
||||
}
|
||||
unit := timeoutUnit(s[size-1])
|
||||
d, ok := timeoutUnitToDuration(unit)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
|
||||
}
|
||||
t, err := strconv.ParseInt(s[:size-1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
const maxHours = math.MaxInt64 / int64(time.Hour)
|
||||
if d == time.Hour && t > maxHours {
|
||||
// This timeout would overflow math.MaxInt64; clamp it.
|
||||
return time.Duration(math.MaxInt64), nil
|
||||
}
|
||||
return d * time.Duration(t), nil
|
||||
}
|
||||
|
||||
const (
|
||||
spaceByte = ' '
|
||||
tildeByte = '~'
|
||||
percentByte = '%'
|
||||
)
|
||||
|
||||
// encodeGrpcMessage is used to encode status code in header field
|
||||
// "grpc-message". It does percent encoding and also replaces invalid utf-8
|
||||
// characters with Unicode replacement character.
|
||||
//
|
||||
// It checks to see if each individual byte in msg is an allowable byte, and
|
||||
// then either percent encoding or passing it through. When percent encoding,
|
||||
// the byte is converted into hexadecimal notation with a '%' prepended.
|
||||
func encodeGrpcMessage(msg string) string {
|
||||
if msg == "" {
|
||||
return ""
|
||||
}
|
||||
lenMsg := len(msg)
|
||||
for i := 0; i < lenMsg; i++ {
|
||||
c := msg[i]
|
||||
if !(c >= spaceByte && c <= tildeByte && c != percentByte) {
|
||||
return encodeGrpcMessageUnchecked(msg)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func encodeGrpcMessageUnchecked(msg string) string {
|
||||
var buf bytes.Buffer
|
||||
for len(msg) > 0 {
|
||||
r, size := utf8.DecodeRuneInString(msg)
|
||||
for _, b := range []byte(string(r)) {
|
||||
if size > 1 {
|
||||
// If size > 1, r is not ascii. Always do percent encoding.
|
||||
buf.WriteString(fmt.Sprintf("%%%02X", b))
|
||||
continue
|
||||
}
|
||||
|
||||
// The for loop is necessary even if size == 1. r could be
|
||||
// utf8.RuneError.
|
||||
//
|
||||
// fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD".
|
||||
if b >= spaceByte && b <= tildeByte && b != percentByte {
|
||||
buf.WriteByte(b)
|
||||
} else {
|
||||
buf.WriteString(fmt.Sprintf("%%%02X", b))
|
||||
}
|
||||
}
|
||||
msg = msg[size:]
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
|
||||
func decodeGrpcMessage(msg string) string {
|
||||
if msg == "" {
|
||||
return ""
|
||||
}
|
||||
lenMsg := len(msg)
|
||||
for i := 0; i < lenMsg; i++ {
|
||||
if msg[i] == percentByte && i+2 < lenMsg {
|
||||
return decodeGrpcMessageUnchecked(msg)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func decodeGrpcMessageUnchecked(msg string) string {
|
||||
var buf bytes.Buffer
|
||||
lenMsg := len(msg)
|
||||
for i := 0; i < lenMsg; i++ {
|
||||
c := msg[i]
|
||||
if c == percentByte && i+2 < lenMsg {
|
||||
parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
|
||||
if err != nil {
|
||||
buf.WriteByte(c)
|
||||
} else {
|
||||
buf.WriteByte(byte(parsed))
|
||||
i += 2
|
||||
}
|
||||
} else {
|
||||
buf.WriteByte(c)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type bufWriter struct {
|
||||
buf []byte
|
||||
offset int
|
||||
batchSize int
|
||||
conn net.Conn
|
||||
err error
|
||||
|
||||
onFlush func()
|
||||
}
|
||||
|
||||
func newBufWriter(conn net.Conn, batchSize int) *bufWriter {
|
||||
return &bufWriter{
|
||||
buf: make([]byte, batchSize*2),
|
||||
batchSize: batchSize,
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *bufWriter) Write(b []byte) (n int, err error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
if w.batchSize == 0 { // Buffer has been disabled.
|
||||
return w.conn.Write(b)
|
||||
}
|
||||
for len(b) > 0 {
|
||||
nn := copy(w.buf[w.offset:], b)
|
||||
b = b[nn:]
|
||||
w.offset += nn
|
||||
n += nn
|
||||
if w.offset >= w.batchSize {
|
||||
err = w.Flush()
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *bufWriter) Flush() error {
|
||||
if w.err != nil {
|
||||
return w.err
|
||||
}
|
||||
if w.offset == 0 {
|
||||
return nil
|
||||
}
|
||||
if w.onFlush != nil {
|
||||
w.onFlush()
|
||||
}
|
||||
_, w.err = w.conn.Write(w.buf[:w.offset])
|
||||
w.offset = 0
|
||||
return w.err
|
||||
}
|
||||
|
||||
type framer struct {
|
||||
writer *bufWriter
|
||||
fr *http2.Framer
|
||||
}
|
||||
|
||||
func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderListSize uint32) *framer {
|
||||
if writeBufferSize < 0 {
|
||||
writeBufferSize = 0
|
||||
}
|
||||
var r io.Reader = conn
|
||||
if readBufferSize > 0 {
|
||||
r = bufio.NewReaderSize(r, readBufferSize)
|
||||
}
|
||||
w := newBufWriter(conn, writeBufferSize)
|
||||
f := &framer{
|
||||
writer: w,
|
||||
fr: http2.NewFramer(w, r),
|
||||
}
|
||||
// Opt-in to Frame reuse API on framer to reduce garbage.
|
||||
// Frames aren't safe to read from after a subsequent call to ReadFrame.
|
||||
f.fr.SetReuseFrames()
|
||||
f.fr.MaxHeaderListSize = maxHeaderListSize
|
||||
f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
|
||||
return f
|
||||
}
|
||||
44
vendor/google.golang.org/grpc/internal/transport/log.go
generated
vendored
Normal file
44
vendor/google.golang.org/grpc/internal/transport/log.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file contains wrappers for grpclog functions.
|
||||
// The transport package only logs to verbose level 2 by default.
|
||||
|
||||
package transport
|
||||
|
||||
import "google.golang.org/grpc/grpclog"
|
||||
|
||||
const logLevel = 2
|
||||
|
||||
func infof(format string, args ...interface{}) {
|
||||
if grpclog.V(logLevel) {
|
||||
grpclog.Infof(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func warningf(format string, args ...interface{}) {
|
||||
if grpclog.V(logLevel) {
|
||||
grpclog.Warningf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func errorf(format string, args ...interface{}) {
|
||||
if grpclog.V(logLevel) {
|
||||
grpclog.Errorf(format, args...)
|
||||
}
|
||||
}
|
||||
816
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
Normal file
816
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package transport defines and implements message oriented communication
|
||||
// channel to complete various transactions (e.g., an RPC). It is meant for
|
||||
// grpc-internal usage and is not intended to be imported directly by users.
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/grpc/tap"
|
||||
)
|
||||
|
||||
type bufferPool struct {
|
||||
pool sync.Pool
|
||||
}
|
||||
|
||||
func newBufferPool() *bufferPool {
|
||||
return &bufferPool{
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *bufferPool) get() *bytes.Buffer {
|
||||
return p.pool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
func (p *bufferPool) put(b *bytes.Buffer) {
|
||||
p.pool.Put(b)
|
||||
}
|
||||
|
||||
// recvMsg represents the received msg from the transport. All transport
|
||||
// protocol specific info has been removed.
|
||||
type recvMsg struct {
|
||||
buffer *bytes.Buffer
|
||||
// nil: received some data
|
||||
// io.EOF: stream is completed. data is nil.
|
||||
// other non-nil error: transport failure. data is nil.
|
||||
err error
|
||||
}
|
||||
|
||||
// recvBuffer is an unbounded channel of recvMsg structs.
|
||||
// Note recvBuffer differs from controlBuffer only in that recvBuffer
|
||||
// holds a channel of only recvMsg structs instead of objects implementing "item" interface.
|
||||
// recvBuffer is written to much more often than
|
||||
// controlBuffer and using strict recvMsg structs helps avoid allocation in "recvBuffer.put"
|
||||
type recvBuffer struct {
|
||||
c chan recvMsg
|
||||
mu sync.Mutex
|
||||
backlog []recvMsg
|
||||
err error
|
||||
}
|
||||
|
||||
func newRecvBuffer() *recvBuffer {
|
||||
b := &recvBuffer{
|
||||
c: make(chan recvMsg, 1),
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *recvBuffer) put(r recvMsg) {
|
||||
b.mu.Lock()
|
||||
if b.err != nil {
|
||||
b.mu.Unlock()
|
||||
// An error had occurred earlier, don't accept more
|
||||
// data or errors.
|
||||
return
|
||||
}
|
||||
b.err = r.err
|
||||
if len(b.backlog) == 0 {
|
||||
select {
|
||||
case b.c <- r:
|
||||
b.mu.Unlock()
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.backlog = append(b.backlog, r)
|
||||
b.mu.Unlock()
|
||||
}
|
||||
|
||||
func (b *recvBuffer) load() {
|
||||
b.mu.Lock()
|
||||
if len(b.backlog) > 0 {
|
||||
select {
|
||||
case b.c <- b.backlog[0]:
|
||||
b.backlog[0] = recvMsg{}
|
||||
b.backlog = b.backlog[1:]
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.mu.Unlock()
|
||||
}
|
||||
|
||||
// get returns the channel that receives a recvMsg in the buffer.
|
||||
//
|
||||
// Upon receipt of a recvMsg, the caller should call load to send another
|
||||
// recvMsg onto the channel if there is any.
|
||||
func (b *recvBuffer) get() <-chan recvMsg {
|
||||
return b.c
|
||||
}
|
||||
|
||||
// recvBufferReader implements io.Reader interface to read the data from
|
||||
// recvBuffer.
|
||||
type recvBufferReader struct {
|
||||
closeStream func(error) // Closes the client transport stream with the given error and nil trailer metadata.
|
||||
ctx context.Context
|
||||
ctxDone <-chan struct{} // cache of ctx.Done() (for performance).
|
||||
recv *recvBuffer
|
||||
last *bytes.Buffer // Stores the remaining data in the previous calls.
|
||||
err error
|
||||
freeBuffer func(*bytes.Buffer)
|
||||
}
|
||||
|
||||
// Read reads the next len(p) bytes from last. If last is drained, it tries to
|
||||
// read additional data from recv. It blocks if there no additional data available
|
||||
// in recv. If Read returns any non-nil error, it will continue to return that error.
|
||||
func (r *recvBufferReader) Read(p []byte) (n int, err error) {
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
}
|
||||
if r.last != nil {
|
||||
// Read remaining data left in last call.
|
||||
copied, _ := r.last.Read(p)
|
||||
if r.last.Len() == 0 {
|
||||
r.freeBuffer(r.last)
|
||||
r.last = nil
|
||||
}
|
||||
return copied, nil
|
||||
}
|
||||
if r.closeStream != nil {
|
||||
n, r.err = r.readClient(p)
|
||||
} else {
|
||||
n, r.err = r.read(p)
|
||||
}
|
||||
return n, r.err
|
||||
}
|
||||
|
||||
func (r *recvBufferReader) read(p []byte) (n int, err error) {
|
||||
select {
|
||||
case <-r.ctxDone:
|
||||
return 0, ContextErr(r.ctx.Err())
|
||||
case m := <-r.recv.get():
|
||||
return r.readAdditional(m, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *recvBufferReader) readClient(p []byte) (n int, err error) {
|
||||
// If the context is canceled, then closes the stream with nil metadata.
|
||||
// closeStream writes its error parameter to r.recv as a recvMsg.
|
||||
// r.readAdditional acts on that message and returns the necessary error.
|
||||
select {
|
||||
case <-r.ctxDone:
|
||||
// Note that this adds the ctx error to the end of recv buffer, and
|
||||
// reads from the head. This will delay the error until recv buffer is
|
||||
// empty, thus will delay ctx cancellation in Recv().
|
||||
//
|
||||
// It's done this way to fix a race between ctx cancel and trailer. The
|
||||
// race was, stream.Recv() may return ctx error if ctxDone wins the
|
||||
// race, but stream.Trailer() may return a non-nil md because the stream
|
||||
// was not marked as done when trailer is received. This closeStream
|
||||
// call will mark stream as done, thus fix the race.
|
||||
//
|
||||
// TODO: delaying ctx error seems like a unnecessary side effect. What
|
||||
// we really want is to mark the stream as done, and return ctx error
|
||||
// faster.
|
||||
r.closeStream(ContextErr(r.ctx.Err()))
|
||||
m := <-r.recv.get()
|
||||
return r.readAdditional(m, p)
|
||||
case m := <-r.recv.get():
|
||||
return r.readAdditional(m, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *recvBufferReader) readAdditional(m recvMsg, p []byte) (n int, err error) {
|
||||
r.recv.load()
|
||||
if m.err != nil {
|
||||
return 0, m.err
|
||||
}
|
||||
copied, _ := m.buffer.Read(p)
|
||||
if m.buffer.Len() == 0 {
|
||||
r.freeBuffer(m.buffer)
|
||||
r.last = nil
|
||||
} else {
|
||||
r.last = m.buffer
|
||||
}
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
type streamState uint32
|
||||
|
||||
const (
|
||||
streamActive streamState = iota
|
||||
streamWriteDone // EndStream sent
|
||||
streamReadDone // EndStream received
|
||||
streamDone // the entire stream is finished.
|
||||
)
|
||||
|
||||
// Stream represents an RPC in the transport layer.
|
||||
type Stream struct {
|
||||
id uint32
|
||||
st ServerTransport // nil for client side Stream
|
||||
ctx context.Context // the associated context of the stream
|
||||
cancel context.CancelFunc // always nil for client side Stream
|
||||
done chan struct{} // closed at the end of stream to unblock writers. On the client side.
|
||||
ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
|
||||
method string // the associated RPC method of the stream
|
||||
recvCompress string
|
||||
sendCompress string
|
||||
buf *recvBuffer
|
||||
trReader io.Reader
|
||||
fc *inFlow
|
||||
wq *writeQuota
|
||||
|
||||
// Callback to state application's intentions to read data. This
|
||||
// is used to adjust flow control, if needed.
|
||||
requestRead func(int)
|
||||
|
||||
headerChan chan struct{} // closed to indicate the end of header metadata.
|
||||
headerChanClosed uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
|
||||
|
||||
// hdrMu protects header and trailer metadata on the server-side.
|
||||
hdrMu sync.Mutex
|
||||
// On client side, header keeps the received header metadata.
|
||||
//
|
||||
// On server side, header keeps the header set by SetHeader(). The complete
|
||||
// header will merged into this after t.WriteHeader() is called.
|
||||
header metadata.MD
|
||||
trailer metadata.MD // the key-value map of trailer metadata.
|
||||
|
||||
noHeaders bool // set if the client never received headers (set only after the stream is done).
|
||||
|
||||
// On the server-side, headerSent is atomically set to 1 when the headers are sent out.
|
||||
headerSent uint32
|
||||
|
||||
state streamState
|
||||
|
||||
// On client-side it is the status error received from the server.
|
||||
// On server-side it is unused.
|
||||
status *status.Status
|
||||
|
||||
bytesReceived uint32 // indicates whether any bytes have been received on this stream
|
||||
unprocessed uint32 // set if the server sends a refused stream or GOAWAY including this stream
|
||||
|
||||
// contentSubtype is the content-subtype for requests.
|
||||
// this must be lowercase or the behavior is undefined.
|
||||
contentSubtype string
|
||||
}
|
||||
|
||||
// isHeaderSent is only valid on the server-side.
|
||||
func (s *Stream) isHeaderSent() bool {
|
||||
return atomic.LoadUint32(&s.headerSent) == 1
|
||||
}
|
||||
|
||||
// updateHeaderSent updates headerSent and returns true
|
||||
// if it was alreay set. It is valid only on server-side.
|
||||
func (s *Stream) updateHeaderSent() bool {
|
||||
return atomic.SwapUint32(&s.headerSent, 1) == 1
|
||||
}
|
||||
|
||||
func (s *Stream) swapState(st streamState) streamState {
|
||||
return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
|
||||
}
|
||||
|
||||
func (s *Stream) compareAndSwapState(oldState, newState streamState) bool {
|
||||
return atomic.CompareAndSwapUint32((*uint32)(&s.state), uint32(oldState), uint32(newState))
|
||||
}
|
||||
|
||||
func (s *Stream) getState() streamState {
|
||||
return streamState(atomic.LoadUint32((*uint32)(&s.state)))
|
||||
}
|
||||
|
||||
func (s *Stream) waitOnHeader() error {
|
||||
if s.headerChan == nil {
|
||||
// On the server headerChan is always nil since a stream originates
|
||||
// only after having received headers.
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
// We prefer success over failure when reading messages because we delay
|
||||
// context error in stream.Read(). To keep behavior consistent, we also
|
||||
// prefer success here.
|
||||
select {
|
||||
case <-s.headerChan:
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
return ContextErr(s.ctx.Err())
|
||||
case <-s.headerChan:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// RecvCompress returns the compression algorithm applied to the inbound
|
||||
// message. It is empty string if there is no compression applied.
|
||||
func (s *Stream) RecvCompress() string {
|
||||
if err := s.waitOnHeader(); err != nil {
|
||||
return ""
|
||||
}
|
||||
return s.recvCompress
|
||||
}
|
||||
|
||||
// SetSendCompress sets the compression algorithm to the stream.
|
||||
func (s *Stream) SetSendCompress(str string) {
|
||||
s.sendCompress = str
|
||||
}
|
||||
|
||||
// Done returns a channel which is closed when it receives the final status
|
||||
// from the server.
|
||||
func (s *Stream) Done() <-chan struct{} {
|
||||
return s.done
|
||||
}
|
||||
|
||||
// Header returns the header metadata of the stream.
|
||||
//
|
||||
// On client side, it acquires the key-value pairs of header metadata once it is
|
||||
// available. It blocks until i) the metadata is ready or ii) there is no header
|
||||
// metadata or iii) the stream is canceled/expired.
|
||||
//
|
||||
// On server side, it returns the out header after t.WriteHeader is called.
|
||||
func (s *Stream) Header() (metadata.MD, error) {
|
||||
if s.headerChan == nil && s.header != nil {
|
||||
// On server side, return the header in stream. It will be the out
|
||||
// header after t.WriteHeader is called.
|
||||
return s.header.Copy(), nil
|
||||
}
|
||||
err := s.waitOnHeader()
|
||||
// Even if the stream is closed, header is returned if available.
|
||||
select {
|
||||
case <-s.headerChan:
|
||||
if s.header == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return s.header.Copy(), nil
|
||||
default:
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TrailersOnly blocks until a header or trailers-only frame is received and
|
||||
// then returns true if the stream was trailers-only. If the stream ends
|
||||
// before headers are received, returns true, nil. If a context error happens
|
||||
// first, returns it as a status error. Client-side only.
|
||||
func (s *Stream) TrailersOnly() (bool, error) {
|
||||
err := s.waitOnHeader()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return s.noHeaders, nil
|
||||
}
|
||||
|
||||
// Trailer returns the cached trailer metedata. Note that if it is not called
|
||||
// after the entire stream is done, it could return an empty MD. Client
|
||||
// side only.
|
||||
// It can be safely read only after stream has ended that is either read
|
||||
// or write have returned io.EOF.
|
||||
func (s *Stream) Trailer() metadata.MD {
|
||||
c := s.trailer.Copy()
|
||||
return c
|
||||
}
|
||||
|
||||
// ContentSubtype returns the content-subtype for a request. For example, a
|
||||
// content-subtype of "proto" will result in a content-type of
|
||||
// "application/grpc+proto". This will always be lowercase. See
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||
// more details.
|
||||
func (s *Stream) ContentSubtype() string {
|
||||
return s.contentSubtype
|
||||
}
|
||||
|
||||
// Context returns the context of the stream.
|
||||
func (s *Stream) Context() context.Context {
|
||||
return s.ctx
|
||||
}
|
||||
|
||||
// Method returns the method for the stream.
|
||||
func (s *Stream) Method() string {
|
||||
return s.method
|
||||
}
|
||||
|
||||
// Status returns the status received from the server.
|
||||
// Status can be read safely only after the stream has ended,
|
||||
// that is, after Done() is closed.
|
||||
func (s *Stream) Status() *status.Status {
|
||||
return s.status
|
||||
}
|
||||
|
||||
// SetHeader sets the header metadata. This can be called multiple times.
|
||||
// Server side only.
|
||||
// This should not be called in parallel to other data writes.
|
||||
func (s *Stream) SetHeader(md metadata.MD) error {
|
||||
if md.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
if s.isHeaderSent() || s.getState() == streamDone {
|
||||
return ErrIllegalHeaderWrite
|
||||
}
|
||||
s.hdrMu.Lock()
|
||||
s.header = metadata.Join(s.header, md)
|
||||
s.hdrMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendHeader sends the given header metadata. The given metadata is
|
||||
// combined with any metadata set by previous calls to SetHeader and
|
||||
// then written to the transport stream.
|
||||
func (s *Stream) SendHeader(md metadata.MD) error {
|
||||
return s.st.WriteHeader(s, md)
|
||||
}
|
||||
|
||||
// SetTrailer sets the trailer metadata which will be sent with the RPC status
|
||||
// by the server. This can be called multiple times. Server side only.
|
||||
// This should not be called parallel to other data writes.
|
||||
func (s *Stream) SetTrailer(md metadata.MD) error {
|
||||
if md.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
if s.getState() == streamDone {
|
||||
return ErrIllegalHeaderWrite
|
||||
}
|
||||
s.hdrMu.Lock()
|
||||
s.trailer = metadata.Join(s.trailer, md)
|
||||
s.hdrMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Stream) write(m recvMsg) {
|
||||
s.buf.put(m)
|
||||
}
|
||||
|
||||
// Read reads all p bytes from the wire for this stream.
|
||||
func (s *Stream) Read(p []byte) (n int, err error) {
|
||||
// Don't request a read if there was an error earlier
|
||||
if er := s.trReader.(*transportReader).er; er != nil {
|
||||
return 0, er
|
||||
}
|
||||
s.requestRead(len(p))
|
||||
return io.ReadFull(s.trReader, p)
|
||||
}
|
||||
|
||||
// tranportReader reads all the data available for this Stream from the transport and
|
||||
// passes them into the decoder, which converts them into a gRPC message stream.
|
||||
// The error is io.EOF when the stream is done or another non-nil error if
|
||||
// the stream broke.
|
||||
type transportReader struct {
|
||||
reader io.Reader
|
||||
// The handler to control the window update procedure for both this
|
||||
// particular stream and the associated transport.
|
||||
windowHandler func(int)
|
||||
er error
|
||||
}
|
||||
|
||||
func (t *transportReader) Read(p []byte) (n int, err error) {
|
||||
n, err = t.reader.Read(p)
|
||||
if err != nil {
|
||||
t.er = err
|
||||
return
|
||||
}
|
||||
t.windowHandler(n)
|
||||
return
|
||||
}
|
||||
|
||||
// BytesReceived indicates whether any bytes have been received on this stream.
|
||||
func (s *Stream) BytesReceived() bool {
|
||||
return atomic.LoadUint32(&s.bytesReceived) == 1
|
||||
}
|
||||
|
||||
// Unprocessed indicates whether the server did not process this stream --
|
||||
// i.e. it sent a refused stream or GOAWAY including this stream ID.
|
||||
func (s *Stream) Unprocessed() bool {
|
||||
return atomic.LoadUint32(&s.unprocessed) == 1
|
||||
}
|
||||
|
||||
// GoString is implemented by Stream so context.String() won't
|
||||
// race when printing %#v.
|
||||
func (s *Stream) GoString() string {
|
||||
return fmt.Sprintf("<stream: %p, %v>", s, s.method)
|
||||
}
|
||||
|
||||
// state of transport
|
||||
type transportState int
|
||||
|
||||
const (
|
||||
reachable transportState = iota
|
||||
closing
|
||||
draining
|
||||
)
|
||||
|
||||
// ServerConfig consists of all the configurations to establish a server transport.
|
||||
type ServerConfig struct {
|
||||
MaxStreams uint32
|
||||
AuthInfo credentials.AuthInfo
|
||||
InTapHandle tap.ServerInHandle
|
||||
StatsHandler stats.Handler
|
||||
KeepaliveParams keepalive.ServerParameters
|
||||
KeepalivePolicy keepalive.EnforcementPolicy
|
||||
InitialWindowSize int32
|
||||
InitialConnWindowSize int32
|
||||
WriteBufferSize int
|
||||
ReadBufferSize int
|
||||
ChannelzParentID int64
|
||||
MaxHeaderListSize *uint32
|
||||
}
|
||||
|
||||
// NewServerTransport creates a ServerTransport with conn or non-nil error
|
||||
// if it fails.
|
||||
func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (ServerTransport, error) {
|
||||
return newHTTP2Server(conn, config)
|
||||
}
|
||||
|
||||
// ConnectOptions covers all relevant options for communicating with the server.
|
||||
type ConnectOptions struct {
|
||||
// UserAgent is the application user agent.
|
||||
UserAgent string
|
||||
// Dialer specifies how to dial a network address.
|
||||
Dialer func(context.Context, string) (net.Conn, error)
|
||||
// FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
|
||||
FailOnNonTempDialError bool
|
||||
// PerRPCCredentials stores the PerRPCCredentials required to issue RPCs.
|
||||
PerRPCCredentials []credentials.PerRPCCredentials
|
||||
// TransportCredentials stores the Authenticator required to setup a client
|
||||
// connection. Only one of TransportCredentials and CredsBundle is non-nil.
|
||||
TransportCredentials credentials.TransportCredentials
|
||||
// CredsBundle is the credentials bundle to be used. Only one of
|
||||
// TransportCredentials and CredsBundle is non-nil.
|
||||
CredsBundle credentials.Bundle
|
||||
// KeepaliveParams stores the keepalive parameters.
|
||||
KeepaliveParams keepalive.ClientParameters
|
||||
// StatsHandler stores the handler for stats.
|
||||
StatsHandler stats.Handler
|
||||
// InitialWindowSize sets the initial window size for a stream.
|
||||
InitialWindowSize int32
|
||||
// InitialConnWindowSize sets the initial window size for a connection.
|
||||
InitialConnWindowSize int32
|
||||
// WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
|
||||
WriteBufferSize int
|
||||
// ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
|
||||
ReadBufferSize int
|
||||
// ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
|
||||
ChannelzParentID int64
|
||||
// MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
|
||||
MaxHeaderListSize *uint32
|
||||
}
|
||||
|
||||
// TargetInfo contains the information of the target such as network address and metadata.
|
||||
type TargetInfo struct {
|
||||
Addr string
|
||||
Metadata interface{}
|
||||
Authority string
|
||||
}
|
||||
|
||||
// NewClientTransport establishes the transport with the required ConnectOptions
|
||||
// and returns it to the caller.
|
||||
func NewClientTransport(connectCtx, ctx context.Context, target TargetInfo, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
|
||||
return newHTTP2Client(connectCtx, ctx, target, opts, onPrefaceReceipt, onGoAway, onClose)
|
||||
}
|
||||
|
||||
// Options provides additional hints and information for message
|
||||
// transmission.
|
||||
type Options struct {
|
||||
// Last indicates whether this write is the last piece for
|
||||
// this stream.
|
||||
Last bool
|
||||
}
|
||||
|
||||
// CallHdr carries the information of a particular RPC.
|
||||
type CallHdr struct {
|
||||
// Host specifies the peer's host.
|
||||
Host string
|
||||
|
||||
// Method specifies the operation to perform.
|
||||
Method string
|
||||
|
||||
// SendCompress specifies the compression algorithm applied on
|
||||
// outbound message.
|
||||
SendCompress string
|
||||
|
||||
// Creds specifies credentials.PerRPCCredentials for a call.
|
||||
Creds credentials.PerRPCCredentials
|
||||
|
||||
// ContentSubtype specifies the content-subtype for a request. For example, a
|
||||
// content-subtype of "proto" will result in a content-type of
|
||||
// "application/grpc+proto". The value of ContentSubtype must be all
|
||||
// lowercase, otherwise the behavior is undefined. See
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
|
||||
// for more details.
|
||||
ContentSubtype string
|
||||
|
||||
PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
|
||||
}
|
||||
|
||||
// ClientTransport is the common interface for all gRPC client-side transport
|
||||
// implementations.
|
||||
type ClientTransport interface {
|
||||
// Close tears down this transport. Once it returns, the transport
|
||||
// should not be accessed any more. The caller must make sure this
|
||||
// is called only once.
|
||||
Close() error
|
||||
|
||||
// GracefulClose starts to tear down the transport: the transport will stop
|
||||
// accepting new RPCs and NewStream will return error. Once all streams are
|
||||
// finished, the transport will close.
|
||||
//
|
||||
// It does not block.
|
||||
GracefulClose()
|
||||
|
||||
// Write sends the data for the given stream. A nil stream indicates
|
||||
// the write is to be performed on the transport as a whole.
|
||||
Write(s *Stream, hdr []byte, data []byte, opts *Options) error
|
||||
|
||||
// NewStream creates a Stream for an RPC.
|
||||
NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error)
|
||||
|
||||
// CloseStream clears the footprint of a stream when the stream is
|
||||
// not needed any more. The err indicates the error incurred when
|
||||
// CloseStream is called. Must be called when a stream is finished
|
||||
// unless the associated transport is closing.
|
||||
CloseStream(stream *Stream, err error)
|
||||
|
||||
// Error returns a channel that is closed when some I/O error
|
||||
// happens. Typically the caller should have a goroutine to monitor
|
||||
// this in order to take action (e.g., close the current transport
|
||||
// and create a new one) in error case. It should not return nil
|
||||
// once the transport is initiated.
|
||||
Error() <-chan struct{}
|
||||
|
||||
// GoAway returns a channel that is closed when ClientTransport
|
||||
// receives the draining signal from the server (e.g., GOAWAY frame in
|
||||
// HTTP/2).
|
||||
GoAway() <-chan struct{}
|
||||
|
||||
// GetGoAwayReason returns the reason why GoAway frame was received.
|
||||
GetGoAwayReason() GoAwayReason
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
RemoteAddr() net.Addr
|
||||
|
||||
// IncrMsgSent increments the number of message sent through this transport.
|
||||
IncrMsgSent()
|
||||
|
||||
// IncrMsgRecv increments the number of message received through this transport.
|
||||
IncrMsgRecv()
|
||||
}
|
||||
|
||||
// ServerTransport is the common interface for all gRPC server-side transport
|
||||
// implementations.
|
||||
//
|
||||
// Methods may be called concurrently from multiple goroutines, but
|
||||
// Write methods for a given Stream will be called serially.
|
||||
type ServerTransport interface {
|
||||
// HandleStreams receives incoming streams using the given handler.
|
||||
HandleStreams(func(*Stream), func(context.Context, string) context.Context)
|
||||
|
||||
// WriteHeader sends the header metadata for the given stream.
|
||||
// WriteHeader may not be called on all streams.
|
||||
WriteHeader(s *Stream, md metadata.MD) error
|
||||
|
||||
// Write sends the data for the given stream.
|
||||
// Write may not be called on all streams.
|
||||
Write(s *Stream, hdr []byte, data []byte, opts *Options) error
|
||||
|
||||
// WriteStatus sends the status of a stream to the client. WriteStatus is
|
||||
// the final call made on a stream and always occurs.
|
||||
WriteStatus(s *Stream, st *status.Status) error
|
||||
|
||||
// Close tears down the transport. Once it is called, the transport
|
||||
// should not be accessed any more. All the pending streams and their
|
||||
// handlers will be terminated asynchronously.
|
||||
Close() error
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
RemoteAddr() net.Addr
|
||||
|
||||
// Drain notifies the client this ServerTransport stops accepting new RPCs.
|
||||
Drain()
|
||||
|
||||
// IncrMsgSent increments the number of message sent through this transport.
|
||||
IncrMsgSent()
|
||||
|
||||
// IncrMsgRecv increments the number of message received through this transport.
|
||||
IncrMsgRecv()
|
||||
}
|
||||
|
||||
// connectionErrorf creates an ConnectionError with the specified error description.
|
||||
func connectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError {
|
||||
return ConnectionError{
|
||||
Desc: fmt.Sprintf(format, a...),
|
||||
temp: temp,
|
||||
err: e,
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectionError is an error that results in the termination of the
|
||||
// entire connection and the retry of all the active streams.
|
||||
type ConnectionError struct {
|
||||
Desc string
|
||||
temp bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (e ConnectionError) Error() string {
|
||||
return fmt.Sprintf("connection error: desc = %q", e.Desc)
|
||||
}
|
||||
|
||||
// Temporary indicates if this connection error is temporary or fatal.
|
||||
func (e ConnectionError) Temporary() bool {
|
||||
return e.temp
|
||||
}
|
||||
|
||||
// Origin returns the original error of this connection error.
|
||||
func (e ConnectionError) Origin() error {
|
||||
// Never return nil error here.
|
||||
// If the original error is nil, return itself.
|
||||
if e.err == nil {
|
||||
return e
|
||||
}
|
||||
return e.err
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrConnClosing indicates that the transport is closing.
|
||||
ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
|
||||
// errStreamDrain indicates that the stream is rejected because the
|
||||
// connection is draining. This could be caused by goaway or balancer
|
||||
// removing the address.
|
||||
errStreamDrain = status.Error(codes.Unavailable, "the connection is draining")
|
||||
// errStreamDone is returned from write at the client side to indiacte application
|
||||
// layer of an error.
|
||||
errStreamDone = errors.New("the stream is done")
|
||||
// StatusGoAway indicates that the server sent a GOAWAY that included this
|
||||
// stream's ID in unprocessed RPCs.
|
||||
statusGoAway = status.New(codes.Unavailable, "the stream is rejected because server is draining the connection")
|
||||
)
|
||||
|
||||
// GoAwayReason contains the reason for the GoAway frame received.
|
||||
type GoAwayReason uint8
|
||||
|
||||
const (
|
||||
// GoAwayInvalid indicates that no GoAway frame is received.
|
||||
GoAwayInvalid GoAwayReason = 0
|
||||
// GoAwayNoReason is the default value when GoAway frame is received.
|
||||
GoAwayNoReason GoAwayReason = 1
|
||||
// GoAwayTooManyPings indicates that a GoAway frame with
|
||||
// ErrCodeEnhanceYourCalm was received and that the debug data said
|
||||
// "too_many_pings".
|
||||
GoAwayTooManyPings GoAwayReason = 2
|
||||
)
|
||||
|
||||
// channelzData is used to store channelz related data for http2Client and http2Server.
|
||||
// These fields cannot be embedded in the original structs (e.g. http2Client), since to do atomic
|
||||
// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
|
||||
// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
|
||||
type channelzData struct {
|
||||
kpCount int64
|
||||
// The number of streams that have started, including already finished ones.
|
||||
streamsStarted int64
|
||||
// Client side: The number of streams that have ended successfully by receiving
|
||||
// EoS bit set frame from server.
|
||||
// Server side: The number of streams that have ended successfully by sending
|
||||
// frame with EoS bit set.
|
||||
streamsSucceeded int64
|
||||
streamsFailed int64
|
||||
// lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
|
||||
// instead of time.Time since it's more costly to atomically update time.Time variable than int64
|
||||
// variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
|
||||
lastStreamCreatedTime int64
|
||||
msgSent int64
|
||||
msgRecv int64
|
||||
lastMsgSentTime int64
|
||||
lastMsgRecvTime int64
|
||||
}
|
||||
|
||||
// ContextErr converts the error from context package into a status error.
|
||||
func ContextErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded:
|
||||
return status.Error(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
}
|
||||
return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
|
||||
}
|
||||
85
vendor/google.golang.org/grpc/keepalive/keepalive.go
generated
vendored
Normal file
85
vendor/google.golang.org/grpc/keepalive/keepalive.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package keepalive defines configurable parameters for point-to-point
|
||||
// healthcheck.
|
||||
package keepalive
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ClientParameters is used to set keepalive parameters on the client-side.
|
||||
// These configure how the client will actively probe to notice when a
|
||||
// connection is broken and send pings so intermediaries will be aware of the
|
||||
// liveness of the connection. Make sure these parameters are set in
|
||||
// coordination with the keepalive policy on the server, as incompatible
|
||||
// settings can result in closing of connection.
|
||||
type ClientParameters struct {
|
||||
// After a duration of this time if the client doesn't see any activity it
|
||||
// pings the server to see if the transport is still alive.
|
||||
// If set below 10s, a minimum value of 10s will be used instead.
|
||||
Time time.Duration // The current default value is infinity.
|
||||
// After having pinged for keepalive check, the client waits for a duration
|
||||
// of Timeout and if no activity is seen even after that the connection is
|
||||
// closed.
|
||||
Timeout time.Duration // The current default value is 20 seconds.
|
||||
// If true, client sends keepalive pings even with no active RPCs. If false,
|
||||
// when there are no active RPCs, Time and Timeout will be ignored and no
|
||||
// keepalive pings will be sent.
|
||||
PermitWithoutStream bool // false by default.
|
||||
}
|
||||
|
||||
// ServerParameters is used to set keepalive and max-age parameters on the
|
||||
// server-side.
|
||||
type ServerParameters struct {
|
||||
// MaxConnectionIdle is a duration for the amount of time after which an
|
||||
// idle connection would be closed by sending a GoAway. Idleness duration is
|
||||
// defined since the most recent time the number of outstanding RPCs became
|
||||
// zero or the connection establishment.
|
||||
MaxConnectionIdle time.Duration // The current default value is infinity.
|
||||
// MaxConnectionAge is a duration for the maximum amount of time a
|
||||
// connection may exist before it will be closed by sending a GoAway. A
|
||||
// random jitter of +/-10% will be added to MaxConnectionAge to spread out
|
||||
// connection storms.
|
||||
MaxConnectionAge time.Duration // The current default value is infinity.
|
||||
// MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
|
||||
// which the connection will be forcibly closed.
|
||||
MaxConnectionAgeGrace time.Duration // The current default value is infinity.
|
||||
// After a duration of this time if the server doesn't see any activity it
|
||||
// pings the client to see if the transport is still alive.
|
||||
// If set below 1s, a minimum value of 1s will be used instead.
|
||||
Time time.Duration // The current default value is 2 hours.
|
||||
// After having pinged for keepalive check, the server waits for a duration
|
||||
// of Timeout and if no activity is seen even after that the connection is
|
||||
// closed.
|
||||
Timeout time.Duration // The current default value is 20 seconds.
|
||||
}
|
||||
|
||||
// EnforcementPolicy is used to set keepalive enforcement policy on the
|
||||
// server-side. Server will close connection with a client that violates this
|
||||
// policy.
|
||||
type EnforcementPolicy struct {
|
||||
// MinTime is the minimum amount of time a client should wait before sending
|
||||
// a keepalive ping.
|
||||
MinTime time.Duration // The current default value is 5 minutes.
|
||||
// If true, server allows keepalive pings even when there are no active
|
||||
// streams(RPCs). If false, and client sends ping when there are no active
|
||||
// streams, server will send GOAWAY and close the connection.
|
||||
PermitWithoutStream bool // false by default.
|
||||
}
|
||||
209
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
Normal file
209
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package metadata define the structure of the metadata supported by gRPC library.
|
||||
// Please refer to https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
|
||||
// for more information about custom-metadata.
|
||||
package metadata // import "google.golang.org/grpc/metadata"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DecodeKeyValue returns k, v, nil.
|
||||
//
|
||||
// Deprecated: use k and v directly instead.
|
||||
func DecodeKeyValue(k, v string) (string, string, error) {
|
||||
return k, v, nil
|
||||
}
|
||||
|
||||
// MD is a mapping from metadata keys to values. Users should use the following
|
||||
// two convenience functions New and Pairs to generate MD.
|
||||
type MD map[string][]string
|
||||
|
||||
// New creates an MD from a given key-value map.
|
||||
//
|
||||
// Only the following ASCII characters are allowed in keys:
|
||||
// - digits: 0-9
|
||||
// - uppercase letters: A-Z (normalized to lower)
|
||||
// - lowercase letters: a-z
|
||||
// - special characters: -_.
|
||||
// Uppercase letters are automatically converted to lowercase.
|
||||
//
|
||||
// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
|
||||
// result in errors if set in metadata.
|
||||
func New(m map[string]string) MD {
|
||||
md := MD{}
|
||||
for k, val := range m {
|
||||
key := strings.ToLower(k)
|
||||
md[key] = append(md[key], val)
|
||||
}
|
||||
return md
|
||||
}
|
||||
|
||||
// Pairs returns an MD formed by the mapping of key, value ...
|
||||
// Pairs panics if len(kv) is odd.
|
||||
//
|
||||
// Only the following ASCII characters are allowed in keys:
|
||||
// - digits: 0-9
|
||||
// - uppercase letters: A-Z (normalized to lower)
|
||||
// - lowercase letters: a-z
|
||||
// - special characters: -_.
|
||||
// Uppercase letters are automatically converted to lowercase.
|
||||
//
|
||||
// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
|
||||
// result in errors if set in metadata.
|
||||
func Pairs(kv ...string) MD {
|
||||
if len(kv)%2 == 1 {
|
||||
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
|
||||
}
|
||||
md := MD{}
|
||||
var key string
|
||||
for i, s := range kv {
|
||||
if i%2 == 0 {
|
||||
key = strings.ToLower(s)
|
||||
continue
|
||||
}
|
||||
md[key] = append(md[key], s)
|
||||
}
|
||||
return md
|
||||
}
|
||||
|
||||
// Len returns the number of items in md.
|
||||
func (md MD) Len() int {
|
||||
return len(md)
|
||||
}
|
||||
|
||||
// Copy returns a copy of md.
|
||||
func (md MD) Copy() MD {
|
||||
return Join(md)
|
||||
}
|
||||
|
||||
// Get obtains the values for a given key.
|
||||
func (md MD) Get(k string) []string {
|
||||
k = strings.ToLower(k)
|
||||
return md[k]
|
||||
}
|
||||
|
||||
// Set sets the value of a given key with a slice of values.
|
||||
func (md MD) Set(k string, vals ...string) {
|
||||
if len(vals) == 0 {
|
||||
return
|
||||
}
|
||||
k = strings.ToLower(k)
|
||||
md[k] = vals
|
||||
}
|
||||
|
||||
// Append adds the values to key k, not overwriting what was already stored at that key.
|
||||
func (md MD) Append(k string, vals ...string) {
|
||||
if len(vals) == 0 {
|
||||
return
|
||||
}
|
||||
k = strings.ToLower(k)
|
||||
md[k] = append(md[k], vals...)
|
||||
}
|
||||
|
||||
// Join joins any number of mds into a single MD.
|
||||
// The order of values for each key is determined by the order in which
|
||||
// the mds containing those values are presented to Join.
|
||||
func Join(mds ...MD) MD {
|
||||
out := MD{}
|
||||
for _, md := range mds {
|
||||
for k, v := range md {
|
||||
out[k] = append(out[k], v...)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type mdIncomingKey struct{}
|
||||
type mdOutgoingKey struct{}
|
||||
|
||||
// NewIncomingContext creates a new context with incoming md attached.
|
||||
func NewIncomingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdIncomingKey{}, md)
|
||||
}
|
||||
|
||||
// NewOutgoingContext creates a new context with outgoing md attached. If used
|
||||
// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
|
||||
// overwrite any previously-appended metadata.
|
||||
func NewOutgoingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
|
||||
}
|
||||
|
||||
// AppendToOutgoingContext returns a new context with the provided kv merged
|
||||
// with any existing metadata in the context. Please refer to the
|
||||
// documentation of Pairs for a description of kv.
|
||||
func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
|
||||
if len(kv)%2 == 1 {
|
||||
panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
|
||||
}
|
||||
md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
|
||||
added := make([][]string, len(md.added)+1)
|
||||
copy(added, md.added)
|
||||
added[len(added)-1] = make([]string, len(kv))
|
||||
copy(added[len(added)-1], kv)
|
||||
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
|
||||
}
|
||||
|
||||
// FromIncomingContext returns the incoming metadata in ctx if it exists. The
|
||||
// returned MD should not be modified. Writing to it may cause races.
|
||||
// Modification should be made to copies of the returned MD.
|
||||
func FromIncomingContext(ctx context.Context) (md MD, ok bool) {
|
||||
md, ok = ctx.Value(mdIncomingKey{}).(MD)
|
||||
return
|
||||
}
|
||||
|
||||
// FromOutgoingContextRaw returns the un-merged, intermediary contents
|
||||
// of rawMD. Remember to perform strings.ToLower on the keys. The returned
|
||||
// MD should not be modified. Writing to it may cause races. Modification
|
||||
// should be made to copies of the returned MD.
|
||||
//
|
||||
// This is intended for gRPC-internal use ONLY.
|
||||
func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
|
||||
raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
return raw.md, raw.added, true
|
||||
}
|
||||
|
||||
// FromOutgoingContext returns the outgoing metadata in ctx if it exists. The
|
||||
// returned MD should not be modified. Writing to it may cause races.
|
||||
// Modification should be made to copies of the returned MD.
|
||||
func FromOutgoingContext(ctx context.Context) (MD, bool) {
|
||||
raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
mds := make([]MD, 0, len(raw.added)+1)
|
||||
mds = append(mds, raw.md)
|
||||
for _, vv := range raw.added {
|
||||
mds = append(mds, Pairs(vv...))
|
||||
}
|
||||
return Join(mds...), ok
|
||||
}
|
||||
|
||||
type rawMD struct {
|
||||
md MD
|
||||
added [][]string
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue