Flow control bug fix (#70)
The requested capacity was not decreased as data is written.
This commit is contained in:
@@ -144,6 +144,12 @@ impl<B, P> Prioritize<B, P>
|
||||
|
||||
/// Request capacity to send data
|
||||
pub fn reserve_capacity(&mut self, capacity: WindowSize, stream: &mut store::Ptr<B, P>) {
|
||||
trace!("reserve_capacity; stream={:?}; requested={:?}; effective={:?}; curr={:?}",
|
||||
stream.id,
|
||||
capacity,
|
||||
capacity + stream.buffered_send_data,
|
||||
stream.requested_send_capacity);
|
||||
|
||||
// Actual capacity is `capacity` + the current amount of buffered data.
|
||||
// It it were less, then we could never send out the buffered data.
|
||||
let capacity = capacity + stream.buffered_send_data;
|
||||
@@ -242,8 +248,12 @@ impl<B, P> Prioritize<B, P>
|
||||
total_requested - stream.send_flow.available(),
|
||||
stream.send_flow.window_size());
|
||||
|
||||
trace!("try_assign_capacity; requested={}; additional={}; window={}; conn={}",
|
||||
total_requested, additional, stream.send_flow.window_size(), self.flow.available());
|
||||
trace!("try_assign_capacity; requested={}; additional={}; buffered={}; window={}; conn={}",
|
||||
total_requested,
|
||||
additional,
|
||||
stream.buffered_send_data,
|
||||
stream.send_flow.window_size(),
|
||||
self.flow.available());
|
||||
|
||||
if additional == 0 {
|
||||
// Nothing more to do
|
||||
@@ -296,7 +306,18 @@ impl<B, P> Prioritize<B, P>
|
||||
// If data is buffered, then schedule the stream for execution
|
||||
if stream.buffered_send_data > 0 {
|
||||
debug_assert!(stream.send_flow.available() > 0);
|
||||
debug_assert!(!stream.pending_send.is_empty());
|
||||
|
||||
// TODO: This assertion isn't *exactly* correct. There can still be
|
||||
// buffered send data while the stream's pending send queue is
|
||||
// empty. This can happen when a large data frame is in the process
|
||||
// of being **partially** sent. Once the window has been sent, the
|
||||
// data frame will be returned to the prioritization layer to be
|
||||
// re-scheduled.
|
||||
//
|
||||
// That said, it would be nice to figure out how to make this
|
||||
// assertion correctly.
|
||||
//
|
||||
// debug_assert!(!stream.pending_send.is_empty());
|
||||
|
||||
self.pending_send.push(stream);
|
||||
}
|
||||
@@ -464,32 +485,36 @@ impl<B, P> Prioritize<B, P>
|
||||
let len = cmp::min(sz, max_len);
|
||||
|
||||
// Only send up to the stream's window capacity
|
||||
let len = cmp::min(len, stream_capacity as usize);
|
||||
let len = cmp::min(len, stream_capacity as usize) as WindowSize;
|
||||
|
||||
// There *must* be be enough connection level
|
||||
// capacity at this point.
|
||||
debug_assert!(len <= self.flow.window_size() as usize);
|
||||
debug_assert!(len <= self.flow.window_size());
|
||||
|
||||
trace!(" --> sending data frame; len={}", len);
|
||||
|
||||
// Update the flow control
|
||||
trace!(" -- updating stream flow --");
|
||||
stream.send_flow.send_data(len as WindowSize);
|
||||
stream.send_flow.send_data(len);
|
||||
|
||||
// Decrement the stream's buffered data counter
|
||||
debug_assert!(stream.buffered_send_data >= len as u32);
|
||||
stream.buffered_send_data -= len as u32;
|
||||
debug_assert!(stream.buffered_send_data >= len);
|
||||
stream.buffered_send_data -= len;
|
||||
stream.requested_send_capacity -= len;
|
||||
|
||||
// Assign the capacity back to the connection that
|
||||
// was just consumed from the stream in the previous
|
||||
// line.
|
||||
self.flow.assign_capacity(len as WindowSize);
|
||||
self.flow.assign_capacity(len);
|
||||
|
||||
trace!(" -- updating connection flow --");
|
||||
self.flow.send_data(len as WindowSize);
|
||||
self.flow.send_data(len);
|
||||
|
||||
// Wrap the frame's data payload to ensure that the
|
||||
// correct amount of data gets written.
|
||||
|
||||
let eos = frame.is_end_stream();
|
||||
let len = len as usize;
|
||||
|
||||
if frame.payload().remaining() > len {
|
||||
frame.set_end_stream(false);
|
||||
|
||||
Reference in New Issue
Block a user