github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/Godeps/_workspace/src/google.golang.org/grpc/transport/control.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 transport
    35  
    36  import (
    37  	"fmt"
    38  	"sync"
    39  
    40  	"golang.org/x/net/http2"
    41  )
    42  
    43  const (
    44  	// The default value of flow control window size in HTTP2 spec.
    45  	defaultWindowSize = 65535
    46  	// The initial window size for flow control.
    47  	initialWindowSize     = defaultWindowSize      // for an RPC
    48  	initialConnWindowSize = defaultWindowSize * 16 // for a connection
    49  )
    50  
    51  // The following defines various control items which could flow through
    52  // the control buffer of transport. They represent different aspects of
    53  // control tasks, e.g., flow control, settings, streaming resetting, etc.
    54  type windowUpdate struct {
    55  	streamID  uint32
    56  	increment uint32
    57  }
    58  
    59  func (windowUpdate) isItem() bool {
    60  	return true
    61  }
    62  
    63  type settings struct {
    64  	ack bool
    65  	ss  []http2.Setting
    66  }
    67  
    68  func (settings) isItem() bool {
    69  	return true
    70  }
    71  
    72  type resetStream struct {
    73  	streamID uint32
    74  	code     http2.ErrCode
    75  }
    76  
    77  func (resetStream) isItem() bool {
    78  	return true
    79  }
    80  
    81  type flushIO struct {
    82  }
    83  
    84  func (flushIO) isItem() bool {
    85  	return true
    86  }
    87  
    88  type ping struct {
    89  	ack  bool
    90  	data [8]byte
    91  }
    92  
    93  func (ping) isItem() bool {
    94  	return true
    95  }
    96  
    97  // quotaPool is a pool which accumulates the quota and sends it to acquire()
    98  // when it is available.
    99  type quotaPool struct {
   100  	c chan int
   101  
   102  	mu    sync.Mutex
   103  	quota int
   104  }
   105  
   106  // newQuotaPool creates a quotaPool which has quota q available to consume.
   107  func newQuotaPool(q int) *quotaPool {
   108  	qb := &quotaPool{
   109  		c: make(chan int, 1),
   110  	}
   111  	if q > 0 {
   112  		qb.c <- q
   113  	} else {
   114  		qb.quota = q
   115  	}
   116  	return qb
   117  }
   118  
   119  // add adds n to the available quota and tries to send it on acquire.
   120  func (qb *quotaPool) add(n int) {
   121  	qb.mu.Lock()
   122  	defer qb.mu.Unlock()
   123  	qb.quota += n
   124  	if qb.quota <= 0 {
   125  		return
   126  	}
   127  	select {
   128  	case qb.c <- qb.quota:
   129  		qb.quota = 0
   130  	default:
   131  	}
   132  }
   133  
   134  // cancel cancels the pending quota sent on acquire, if any.
   135  func (qb *quotaPool) cancel() {
   136  	qb.mu.Lock()
   137  	defer qb.mu.Unlock()
   138  	select {
   139  	case n := <-qb.c:
   140  		qb.quota += n
   141  	default:
   142  	}
   143  }
   144  
   145  // reset cancels the pending quota sent on acquired, incremented by v and sends
   146  // it back on acquire.
   147  func (qb *quotaPool) reset(v int) {
   148  	qb.mu.Lock()
   149  	defer qb.mu.Unlock()
   150  	select {
   151  	case n := <-qb.c:
   152  		qb.quota += n
   153  	default:
   154  	}
   155  	qb.quota += v
   156  	if qb.quota <= 0 {
   157  		return
   158  	}
   159  	select {
   160  	case qb.c <- qb.quota:
   161  		qb.quota = 0
   162  	default:
   163  	}
   164  }
   165  
   166  // acquire returns the channel on which available quota amounts are sent.
   167  func (qb *quotaPool) acquire() <-chan int {
   168  	return qb.c
   169  }
   170  
   171  // inFlow deals with inbound flow control
   172  type inFlow struct {
   173  	// The inbound flow control limit for pending data.
   174  	limit uint32
   175  	// conn points to the shared connection-level inFlow that is shared
   176  	// by all streams on that conn. It is nil for the inFlow on the conn
   177  	// directly.
   178  	conn *inFlow
   179  
   180  	mu sync.Mutex
   181  	// pendingData is the overall data which have been received but not been
   182  	// consumed by applications.
   183  	pendingData uint32
   184  	// The amount of data the application has consumed but grpc has not sent
   185  	// window update for them. Used to reduce window update frequency.
   186  	pendingUpdate uint32
   187  }
   188  
   189  // onData is invoked when some data frame is received. It increments not only its
   190  // own pendingData but also that of the associated connection-level flow.
   191  func (f *inFlow) onData(n uint32) error {
   192  	if n == 0 {
   193  		return nil
   194  	}
   195  	f.mu.Lock()
   196  	defer f.mu.Unlock()
   197  	if f.pendingData+f.pendingUpdate+n > f.limit {
   198  		return fmt.Errorf("recieved %d-bytes data exceeding the limit %d bytes", f.pendingData+f.pendingUpdate+n, f.limit)
   199  	}
   200  	if f.conn != nil {
   201  		if err := f.conn.onData(n); err != nil {
   202  			return ConnectionErrorf("%v", err)
   203  		}
   204  	}
   205  	f.pendingData += n
   206  	return nil
   207  }
   208  
   209  // connOnRead updates the connection level states when the application consumes data.
   210  func (f *inFlow) connOnRead(n uint32) uint32 {
   211  	if n == 0 || f.conn != nil {
   212  		return 0
   213  	}
   214  	f.mu.Lock()
   215  	defer f.mu.Unlock()
   216  	f.pendingData -= n
   217  	f.pendingUpdate += n
   218  	if f.pendingUpdate >= f.limit/4 {
   219  		ret := f.pendingUpdate
   220  		f.pendingUpdate = 0
   221  		return ret
   222  	}
   223  	return 0
   224  }
   225  
   226  // onRead is invoked when the application reads the data. It returns the window updates
   227  // for both stream and connection level.
   228  func (f *inFlow) onRead(n uint32) (swu, cwu uint32) {
   229  	if n == 0 {
   230  		return
   231  	}
   232  	f.mu.Lock()
   233  	defer f.mu.Unlock()
   234  	if f.pendingData == 0 {
   235  		// pendingData has been adjusted by restoreConn.
   236  		return
   237  	}
   238  	f.pendingData -= n
   239  	f.pendingUpdate += n
   240  	if f.pendingUpdate >= f.limit/4 {
   241  		swu = f.pendingUpdate
   242  		f.pendingUpdate = 0
   243  	}
   244  	cwu = f.conn.connOnRead(n)
   245  	return
   246  }
   247  
   248  // restoreConn is invoked when a stream is terminated. It removes its stake in
   249  // the connection-level flow and resets its own state.
   250  func (f *inFlow) restoreConn() uint32 {
   251  	if f.conn == nil {
   252  		return 0
   253  	}
   254  	f.mu.Lock()
   255  	defer f.mu.Unlock()
   256  	n := f.pendingData
   257  	f.pendingData = 0
   258  	f.pendingUpdate = 0
   259  	return f.conn.connOnRead(n)
   260  }