Use FlowControl::available to size data frames (#29)
				
					
				
			This commit is contained in:
		| @@ -1,7 +1,8 @@ | |||||||
| use frame::{util, Frame, Head, Error, StreamId, Kind}; | use frame::{util, Frame, Head, Error, StreamId, Kind}; | ||||||
| use bytes::{BufMut, Bytes, Buf}; | use bytes::{BufMut, Bytes, Buf}; | ||||||
|  |  | ||||||
| #[derive(Debug)] | use std::fmt; | ||||||
|  |  | ||||||
| pub struct Data<T = Bytes> { | pub struct Data<T = Bytes> { | ||||||
|     stream_id: StreamId, |     stream_id: StreamId, | ||||||
|     data: T, |     data: T, | ||||||
| @@ -9,7 +10,7 @@ pub struct Data<T = Bytes> { | |||||||
|     pad_len: Option<u8>, |     pad_len: Option<u8>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | #[derive(Copy, Clone, Eq, PartialEq)] | ||||||
| pub struct DataFlag(u8); | pub struct DataFlag(u8); | ||||||
|  |  | ||||||
| const END_STREAM: u8 = 0x1; | const END_STREAM: u8 = 0x1; | ||||||
| @@ -112,6 +113,16 @@ impl<T> From<Data<T>> for Frame<T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl<T> fmt::Debug for Data<T> { | ||||||
|  |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||||||
|  |         fmt.debug_struct("Data") | ||||||
|  |             .field("stream_id", &self.stream_id) | ||||||
|  |             .field("flags", &self.flags) | ||||||
|  |             .field("pad_len", &self.pad_len) | ||||||
|  |             .finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| // ===== impl DataFlag ===== | // ===== impl DataFlag ===== | ||||||
|  |  | ||||||
| impl DataFlag { | impl DataFlag { | ||||||
| @@ -156,3 +167,19 @@ impl From<DataFlag> for u8 { | |||||||
|         src.0 |         src.0 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl fmt::Debug for DataFlag { | ||||||
|  |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||||||
|  |         let mut f = fmt.debug_struct("DataFlag"); | ||||||
|  |  | ||||||
|  |         if self.is_end_stream() { | ||||||
|  |             f.field("end_stream", &true); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if self.is_padded() { | ||||||
|  |             f.field("padded", &true); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         f.finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -117,7 +117,7 @@ impl<T> fmt::Debug for Frame<T> { | |||||||
|         use self::Frame::*; |         use self::Frame::*; | ||||||
|  |  | ||||||
|         match *self { |         match *self { | ||||||
|             Data(..) => write!(fmt, "Frame::Data(..)"), |             Data(ref frame) => write!(fmt, "Frame::Data({:?})", frame), | ||||||
|             Headers(ref frame) => write!(fmt, "Frame::Headers({:?})", frame), |             Headers(ref frame) => write!(fmt, "Frame::Headers({:?})", frame), | ||||||
|             Priority(ref frame) => write!(fmt, "Frame::Priority({:?})", frame), |             Priority(ref frame) => write!(fmt, "Frame::Priority({:?})", frame), | ||||||
|             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame), |             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame), | ||||||
|   | |||||||
| @@ -93,6 +93,8 @@ impl FlowControl { | |||||||
|             return Err(FlowControlError.into()); |             return Err(FlowControlError.into()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         trace!("inc_window; sz={}; old={}; new={}", sz, self.window_size, val); | ||||||
|  |  | ||||||
|         self.window_size = val; |         self.window_size = val; | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -96,6 +96,9 @@ impl<B> Prioritize<B> | |||||||
|         // Update the buffered data counter |         // Update the buffered data counter | ||||||
|         stream.buffered_send_data += sz; |         stream.buffered_send_data += sz; | ||||||
|  |  | ||||||
|  |         trace!("send_data; sz={}; buffered={}; requested={}", | ||||||
|  |                sz, stream.buffered_send_data, stream.requested_send_capacity); | ||||||
|  |  | ||||||
|         // Implicitly request more send capacity if not enough has been |         // Implicitly request more send capacity if not enough has been | ||||||
|         // requested yet. |         // requested yet. | ||||||
|         if stream.requested_send_capacity < stream.buffered_send_data { |         if stream.requested_send_capacity < stream.buffered_send_data { | ||||||
| @@ -109,7 +112,11 @@ impl<B> Prioritize<B> | |||||||
|             try!(stream.state.send_close()); |             try!(stream.state.send_close()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if stream.send_flow.available() > stream.buffered_send_data { |         trace!("send_data (2); available={}; buffered={}", | ||||||
|  |                stream.send_flow.available(), | ||||||
|  |                stream.buffered_send_data); | ||||||
|  |  | ||||||
|  |         if stream.send_flow.available() >= stream.buffered_send_data { | ||||||
|             // The stream currently has capacity to send the data frame, so |             // The stream currently has capacity to send the data frame, so | ||||||
|             // queue it up and notify the connection task. |             // queue it up and notify the connection task. | ||||||
|             self.queue_frame(frame.into(), stream, task); |             self.queue_frame(frame.into(), stream, task); | ||||||
| @@ -118,6 +125,8 @@ impl<B> Prioritize<B> | |||||||
|             // don't notify the conneciton task. Once additional capacity |             // don't notify the conneciton task. Once additional capacity | ||||||
|             // becomes available, the frame will be flushed. |             // becomes available, the frame will be flushed. | ||||||
|             stream.pending_send.push_back(&mut self.buffer, frame.into()); |             stream.pending_send.push_back(&mut self.buffer, frame.into()); | ||||||
|  |  | ||||||
|  |             debug_assert!(stream.is_pending_send_capacity); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
| @@ -172,6 +181,7 @@ impl<B> Prioritize<B> | |||||||
|     { |     { | ||||||
|         // Update the connection's window |         // Update the connection's window | ||||||
|         self.flow.inc_window(inc)?; |         self.flow.inc_window(inc)?; | ||||||
|  |         self.flow.assign_capacity(inc)?; | ||||||
|  |  | ||||||
|         // Assign newly acquired capacity to streams pending capacity. |         // Assign newly acquired capacity to streams pending capacity. | ||||||
|         while self.flow.available() > 0 { |         while self.flow.available() > 0 { | ||||||
| @@ -232,6 +242,12 @@ impl<B> Prioritize<B> | |||||||
|             self.flow.claim_capacity(assign); |             self.flow.claim_capacity(assign); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         trace!("try_assign_capacity; available={}; requested={}; buffered={}; has_unavailable={:?}", | ||||||
|  |                stream.send_flow.available(), | ||||||
|  |                stream.requested_send_capacity, | ||||||
|  |                stream.buffered_send_data, | ||||||
|  |                stream.send_flow.has_unavailable()); | ||||||
|  |  | ||||||
|         if stream.send_flow.available() < stream.requested_send_capacity { |         if stream.send_flow.available() < stream.requested_send_capacity { | ||||||
|             if stream.send_flow.has_unavailable() { |             if stream.send_flow.has_unavailable() { | ||||||
|                 // The stream requires additional capacity and the stream's |                 // The stream requires additional capacity and the stream's | ||||||
| @@ -246,6 +262,7 @@ impl<B> Prioritize<B> | |||||||
|  |  | ||||||
|         // If data is buffered, then schedule the stream for execution |         // If data is buffered, then schedule the stream for execution | ||||||
|         if stream.buffered_send_data > 0 { |         if stream.buffered_send_data > 0 { | ||||||
|  |             debug_assert!(stream.send_flow.available() > 0); | ||||||
|             self.pending_send.push(stream); |             self.pending_send.push(stream); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -317,7 +334,7 @@ impl<B> Prioritize<B> | |||||||
|  |  | ||||||
|         // First check if there are any data chunks to take back |         // First check if there are any data chunks to take back | ||||||
|         if let Some(frame) = dst.take_last_data_frame() { |         if let Some(frame) = dst.take_last_data_frame() { | ||||||
|             trace!("  -> reclaimed; frame={:?}", frame); |             trace!("  -> reclaimed; frame={:?}; sz={}", frame, frame.payload().remaining()); | ||||||
|  |  | ||||||
|             let mut eos = false; |             let mut eos = false; | ||||||
|             let key = frame.payload().stream; |             let key = frame.payload().stream; | ||||||
| @@ -351,11 +368,11 @@ impl<B> Prioritize<B> | |||||||
|         stream.pending_send.push_front(&mut self.buffer, frame); |         stream.pending_send.push_front(&mut self.buffer, frame); | ||||||
|  |  | ||||||
|         // If needed, schedule the sender |         // If needed, schedule the sender | ||||||
|         self.pending_send.push(stream); |         if stream.send_flow.available() > 0 { | ||||||
|  |             self.pending_send.push(stream); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // =========== OLD JUNK =========== |  | ||||||
|  |  | ||||||
|     fn pop_frame(&mut self, store: &mut Store<B>, max_len: usize) |     fn pop_frame(&mut self, store: &mut Store<B>, max_len: usize) | ||||||
|         -> Option<Frame<Prioritized<B>>> |         -> Option<Frame<Prioritized<B>>> | ||||||
|     { |     { | ||||||
| @@ -365,16 +382,33 @@ impl<B> Prioritize<B> | |||||||
|                 Some(mut stream) => { |                 Some(mut stream) => { | ||||||
|                     let frame = match stream.pending_send.pop_front(&mut self.buffer).unwrap() { |                     let frame = match stream.pending_send.pop_front(&mut self.buffer).unwrap() { | ||||||
|                         Frame::Data(mut frame) => { |                         Frame::Data(mut frame) => { | ||||||
|                             trace!(" --> data frame"); |  | ||||||
|  |  | ||||||
|                             // Get the amount of capacity remaining for stream's |                             // Get the amount of capacity remaining for stream's | ||||||
|                             // window. |                             // window. | ||||||
|                             // |                             // | ||||||
|                             // TODO: Is this the right thing to check? |                             // TODO: Is this the right thing to check? | ||||||
|                             let stream_capacity = stream.send_flow.window_size(); |                             let stream_capacity = stream.send_flow.available(); | ||||||
|  |                             let sz = frame.payload().remaining(); | ||||||
|  |  | ||||||
|  |                             trace!(" --> data frame; stream={:?}; sz={}; eos={:?}; window={}; available={}; requested={}", | ||||||
|  |                                    frame.stream_id(), | ||||||
|  |                                    sz, | ||||||
|  |                                    frame.is_end_stream(), | ||||||
|  |                                    stream_capacity, | ||||||
|  |                                    stream.send_flow.available(), | ||||||
|  |                                    stream.requested_send_capacity); | ||||||
|  |  | ||||||
|  |                             // Zero length data frames always have capacity to | ||||||
|  |                             // be sent. | ||||||
|  |                             if sz > 0 && stream_capacity == 0 { | ||||||
|  |                                 trace!(" --> stream capacity is 0; requested={}", | ||||||
|  |                                        stream.requested_send_capacity); | ||||||
|  |  | ||||||
|  |                                 // Ensure that the stream is waiting for | ||||||
|  |                                 // connection level capacity | ||||||
|  |                                 // | ||||||
|  |                                 // TODO: uncomment | ||||||
|  |                                 // debug_assert!(stream.is_pending_send_capacity); | ||||||
|  |  | ||||||
|                             if stream_capacity == 0 { |  | ||||||
|                                 trace!(" --> stream capacity is 0, return"); |  | ||||||
|                                 // The stream has no more capacity, this can |                                 // The stream has no more capacity, this can | ||||||
|                                 // happen if the remote reduced the stream |                                 // happen if the remote reduced the stream | ||||||
|                                 // window. In this case, we need to buffer the |                                 // window. In this case, we need to buffer the | ||||||
| @@ -384,9 +418,7 @@ impl<B> Prioritize<B> | |||||||
|                             } |                             } | ||||||
|  |  | ||||||
|                             // Only send up to the max frame length |                             // Only send up to the max frame length | ||||||
|                             let len = cmp::min( |                             let len = cmp::min(sz, max_len); | ||||||
|                                 frame.payload().remaining(), |  | ||||||
|                                 max_len); |  | ||||||
|  |  | ||||||
|                             // Only send up to the stream's window capacity |                             // 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); | ||||||
| @@ -428,6 +460,10 @@ impl<B> Prioritize<B> | |||||||
|                     }; |                     }; | ||||||
|  |  | ||||||
|                     if !stream.pending_send.is_empty() { |                     if !stream.pending_send.is_empty() { | ||||||
|  |                         // TODO: Only requeue the sender IF it is ready to send | ||||||
|  |                         // the next frame. i.e. don't requeue it if the next | ||||||
|  |                         // frame is a data frame and the stream does not have | ||||||
|  |                         // any more capacity. | ||||||
|                         self.pending_send.push(&mut stream); |                         self.pending_send.push(&mut stream); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user