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 }