github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/Godeps/_workspace/src/google.golang.org/grpc/rpc_util.go (about)

     1  /*
     2   *
     3   * Copyright 2014, Google Inc.
     4   * All rights reserved.
     5   *
     6   * Redistribution and use in source and binary forms, with or without
     7   * modification, are permitted provided that the following conditions are
     8   * met:
     9   *
    10   *     * Redistributions of source code must retain the above copyright
    11   * notice, this list of conditions and the following disclaimer.
    12   *     * Redistributions in binary form must reproduce the above
    13   * copyright notice, this list of conditions and the following disclaimer
    14   * in the documentation and/or other materials provided with the
    15   * distribution.
    16   *     * Neither the name of Google Inc. nor the names of its
    17   * contributors may be used to endorse or promote products derived from
    18   * this software without specific prior written permission.
    19   *
    20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31   *
    32   */
    33  
    34  package grpc
    35  
    36  import (
    37  	"encoding/binary"
    38  	"fmt"
    39  	"io"
    40  	"math"
    41  	"math/rand"
    42  	"os"
    43  	"time"
    44  
    45  	"github.com/golang/protobuf/proto"
    46  	"golang.org/x/net/context"
    47  	"google.golang.org/grpc/codes"
    48  	"google.golang.org/grpc/metadata"
    49  	"google.golang.org/grpc/transport"
    50  )
    51  
    52  // Codec defines the interface gRPC uses to encode and decode messages.
    53  type Codec interface {
    54  	// Marshal returns the wire format of v.
    55  	Marshal(v interface{}) ([]byte, error)
    56  	// Unmarshal parses the wire format into v.
    57  	Unmarshal(data []byte, v interface{}) error
    58  	// String returns the name of the Codec implementation. The returned
    59  	// string will be used as part of content type in transmission.
    60  	String() string
    61  }
    62  
    63  // protoCodec is a Codec implemetation with protobuf. It is the default codec for gRPC.
    64  type protoCodec struct{}
    65  
    66  func (protoCodec) Marshal(v interface{}) ([]byte, error) {
    67  	return proto.Marshal(v.(proto.Message))
    68  }
    69  
    70  func (protoCodec) Unmarshal(data []byte, v interface{}) error {
    71  	return proto.Unmarshal(data, v.(proto.Message))
    72  }
    73  
    74  func (protoCodec) String() string {
    75  	return "proto"
    76  }
    77  
    78  // callInfo contains all related configuration and information about an RPC.
    79  type callInfo struct {
    80  	failFast  bool
    81  	headerMD  metadata.MD
    82  	trailerMD metadata.MD
    83  	traceInfo traceInfo // in trace.go
    84  }
    85  
    86  // CallOption configures a Call before it starts or extracts information from
    87  // a Call after it completes.
    88  type CallOption interface {
    89  	// before is called before the call is sent to any server.  If before
    90  	// returns a non-nil error, the RPC fails with that error.
    91  	before(*callInfo) error
    92  
    93  	// after is called after the call has completed.  after cannot return an
    94  	// error, so any failures should be reported via output parameters.
    95  	after(*callInfo)
    96  }
    97  
    98  type beforeCall func(c *callInfo) error
    99  
   100  func (o beforeCall) before(c *callInfo) error { return o(c) }
   101  func (o beforeCall) after(c *callInfo)        {}
   102  
   103  type afterCall func(c *callInfo)
   104  
   105  func (o afterCall) before(c *callInfo) error { return nil }
   106  func (o afterCall) after(c *callInfo)        { o(c) }
   107  
   108  // Header returns a CallOptions that retrieves the header metadata
   109  // for a unary RPC.
   110  func Header(md *metadata.MD) CallOption {
   111  	return afterCall(func(c *callInfo) {
   112  		*md = c.headerMD
   113  	})
   114  }
   115  
   116  // Trailer returns a CallOptions that retrieves the trailer metadata
   117  // for a unary RPC.
   118  func Trailer(md *metadata.MD) CallOption {
   119  	return afterCall(func(c *callInfo) {
   120  		*md = c.trailerMD
   121  	})
   122  }
   123  
   124  // The format of the payload: compressed or not?
   125  type payloadFormat uint8
   126  
   127  const (
   128  	compressionNone payloadFormat = iota // no compression
   129  	compressionFlate
   130  	// More formats
   131  )
   132  
   133  // parser reads complelete gRPC messages from the underlying reader.
   134  type parser struct {
   135  	s io.Reader
   136  }
   137  
   138  // recvMsg is to read a complete gRPC message from the stream. It is blocking if
   139  // the message has not been complete yet. It returns the message and its type,
   140  // EOF is returned with nil msg and 0 pf if the entire stream is done. Other
   141  // non-nil error is returned if something is wrong on reading.
   142  func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) {
   143  	// The header of a gRPC message. Find more detail
   144  	// at http://www.grpc.io/docs/guides/wire.html.
   145  	var buf [5]byte
   146  
   147  	if _, err := io.ReadFull(p.s, buf[:]); err != nil {
   148  		return 0, nil, err
   149  	}
   150  
   151  	pf = payloadFormat(buf[0])
   152  	length := binary.BigEndian.Uint32(buf[1:])
   153  
   154  	if length == 0 {
   155  		return pf, nil, nil
   156  	}
   157  	msg = make([]byte, int(length))
   158  	if _, err := io.ReadFull(p.s, msg); err != nil {
   159  		if err == io.EOF {
   160  			err = io.ErrUnexpectedEOF
   161  		}
   162  		return 0, nil, err
   163  	}
   164  	return pf, msg, nil
   165  }
   166  
   167  // encode serializes msg and prepends the message header. If msg is nil, it
   168  // generates the message header of 0 message length.
   169  func encode(c Codec, msg interface{}, pf payloadFormat) ([]byte, error) {
   170  	var b []byte
   171  	var length uint
   172  	if msg != nil {
   173  		var err error
   174  		// TODO(zhaoq): optimize to reduce memory alloc and copying.
   175  		b, err = c.Marshal(msg)
   176  		if err != nil {
   177  			return nil, err
   178  		}
   179  		length = uint(len(b))
   180  	}
   181  	if length > math.MaxUint32 {
   182  		return nil, Errorf(codes.InvalidArgument, "grpc: message too large (%d bytes)", length)
   183  	}
   184  
   185  	const (
   186  		payloadLen = 1
   187  		sizeLen    = 4
   188  	)
   189  
   190  	var buf = make([]byte, payloadLen+sizeLen+len(b))
   191  
   192  	// Write payload format
   193  	buf[0] = byte(pf)
   194  	// Write length of b into buf
   195  	binary.BigEndian.PutUint32(buf[1:], uint32(length))
   196  	// Copy encoded msg to buf
   197  	copy(buf[5:], b)
   198  
   199  	return buf, nil
   200  }
   201  
   202  func recv(p *parser, c Codec, m interface{}) error {
   203  	pf, d, err := p.recvMsg()
   204  	if err != nil {
   205  		return err
   206  	}
   207  	switch pf {
   208  	case compressionNone:
   209  		if err := c.Unmarshal(d, m); err != nil {
   210  			if rErr, ok := err.(rpcError); ok {
   211  				return rErr
   212  			} else {
   213  				return Errorf(codes.Internal, "grpc: %v", err)
   214  			}
   215  		}
   216  	default:
   217  		return Errorf(codes.Internal, "gprc: compression is not supported yet.")
   218  	}
   219  	return nil
   220  }
   221  
   222  // rpcError defines the status from an RPC.
   223  type rpcError struct {
   224  	code codes.Code
   225  	desc string
   226  }
   227  
   228  func (e rpcError) Error() string {
   229  	return fmt.Sprintf("rpc error: code = %d desc = %q", e.code, e.desc)
   230  }
   231  
   232  // Code returns the error code for err if it was produced by the rpc system.
   233  // Otherwise, it returns codes.Unknown.
   234  func Code(err error) codes.Code {
   235  	if err == nil {
   236  		return codes.OK
   237  	}
   238  	if e, ok := err.(rpcError); ok {
   239  		return e.code
   240  	}
   241  	return codes.Unknown
   242  }
   243  
   244  // ErrorDesc returns the error description of err if it was produced by the rpc system.
   245  // Otherwise, it returns err.Error() or empty string when err is nil.
   246  func ErrorDesc(err error) string {
   247  	if err == nil {
   248  		return ""
   249  	}
   250  	if e, ok := err.(rpcError); ok {
   251  		return e.desc
   252  	}
   253  	return err.Error()
   254  }
   255  
   256  // Errorf returns an error containing an error code and a description;
   257  // Errorf returns nil if c is OK.
   258  func Errorf(c codes.Code, format string, a ...interface{}) error {
   259  	if c == codes.OK {
   260  		return nil
   261  	}
   262  	return rpcError{
   263  		code: c,
   264  		desc: fmt.Sprintf(format, a...),
   265  	}
   266  }
   267  
   268  // toRPCErr converts an error into a rpcError.
   269  func toRPCErr(err error) error {
   270  	switch e := err.(type) {
   271  	case rpcError:
   272  		return err
   273  	case transport.StreamError:
   274  		return rpcError{
   275  			code: e.Code,
   276  			desc: e.Desc,
   277  		}
   278  	case transport.ConnectionError:
   279  		return rpcError{
   280  			code: codes.Internal,
   281  			desc: e.Desc,
   282  		}
   283  	}
   284  	return Errorf(codes.Unknown, "%v", err)
   285  }
   286  
   287  // convertCode converts a standard Go error into its canonical code. Note that
   288  // this is only used to translate the error returned by the server applications.
   289  func convertCode(err error) codes.Code {
   290  	switch err {
   291  	case nil:
   292  		return codes.OK
   293  	case io.EOF:
   294  		return codes.OutOfRange
   295  	case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
   296  		return codes.FailedPrecondition
   297  	case os.ErrInvalid:
   298  		return codes.InvalidArgument
   299  	case context.Canceled:
   300  		return codes.Canceled
   301  	case context.DeadlineExceeded:
   302  		return codes.DeadlineExceeded
   303  	}
   304  	switch {
   305  	case os.IsExist(err):
   306  		return codes.AlreadyExists
   307  	case os.IsNotExist(err):
   308  		return codes.NotFound
   309  	case os.IsPermission(err):
   310  		return codes.PermissionDenied
   311  	}
   312  	return codes.Unknown
   313  }
   314  
   315  const (
   316  	// how long to wait after the first failure before retrying
   317  	baseDelay = 1.0 * time.Second
   318  	// upper bound of backoff delay
   319  	maxDelay = 120 * time.Second
   320  	// backoff increases by this factor on each retry
   321  	backoffFactor = 1.6
   322  	// backoff is randomized downwards by this factor
   323  	backoffJitter = 0.2
   324  )
   325  
   326  func backoff(retries int) (t time.Duration) {
   327  	if retries == 0 {
   328  		return baseDelay
   329  	}
   330  	backoff, max := float64(baseDelay), float64(maxDelay)
   331  	for backoff < max && retries > 0 {
   332  		backoff *= backoffFactor
   333  		retries--
   334  	}
   335  	if backoff > max {
   336  		backoff = max
   337  	}
   338  	// Randomize backoff delays so that if a cluster of requests start at
   339  	// the same time, they won't operate in lockstep.
   340  	backoff *= 1 + backoffJitter*(rand.Float64()*2-1)
   341  	if backoff < 0 {
   342  		return 0
   343  	}
   344  	return time.Duration(backoff)
   345  }