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 bytes::{BufMut, Bytes, Buf}; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| use std::fmt; | ||||
|  | ||||
| pub struct Data<T = Bytes> { | ||||
|     stream_id: StreamId, | ||||
|     data: T, | ||||
| @@ -9,7 +10,7 @@ pub struct Data<T = Bytes> { | ||||
|     pad_len: Option<u8>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[derive(Copy, Clone, Eq, PartialEq)] | ||||
| pub struct DataFlag(u8); | ||||
|  | ||||
| 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 { | ||||
| @@ -156,3 +167,19 @@ impl From<DataFlag> for u8 { | ||||
|         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::*; | ||||
|  | ||||
|         match *self { | ||||
|             Data(..) => write!(fmt, "Frame::Data(..)"), | ||||
|             Data(ref frame) => write!(fmt, "Frame::Data({:?})", frame), | ||||
|             Headers(ref frame) => write!(fmt, "Frame::Headers({:?})", frame), | ||||
|             Priority(ref frame) => write!(fmt, "Frame::Priority({:?})", frame), | ||||
|             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame), | ||||
|   | ||||
| @@ -93,6 +93,8 @@ impl FlowControl { | ||||
|             return Err(FlowControlError.into()); | ||||
|         } | ||||
|  | ||||
|         trace!("inc_window; sz={}; old={}; new={}", sz, self.window_size, val); | ||||
|  | ||||
|         self.window_size = val; | ||||
|         Ok(()) | ||||
|     } | ||||
|   | ||||
| @@ -96,6 +96,9 @@ impl<B> Prioritize<B> | ||||
|         // Update the buffered data counter | ||||
|         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 | ||||
|         // requested yet. | ||||
|         if stream.requested_send_capacity < stream.buffered_send_data { | ||||
| @@ -109,7 +112,11 @@ impl<B> Prioritize<B> | ||||
|             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 | ||||
|             // queue it up and notify the connection 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 | ||||
|             // becomes available, the frame will be flushed. | ||||
|             stream.pending_send.push_back(&mut self.buffer, frame.into()); | ||||
|  | ||||
|             debug_assert!(stream.is_pending_send_capacity); | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
| @@ -172,6 +181,7 @@ impl<B> Prioritize<B> | ||||
|     { | ||||
|         // Update the connection's window | ||||
|         self.flow.inc_window(inc)?; | ||||
|         self.flow.assign_capacity(inc)?; | ||||
|  | ||||
|         // Assign newly acquired capacity to streams pending capacity. | ||||
|         while self.flow.available() > 0 { | ||||
| @@ -232,6 +242,12 @@ impl<B> Prioritize<B> | ||||
|             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.has_unavailable() { | ||||
|                 // 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 stream.buffered_send_data > 0 { | ||||
|             debug_assert!(stream.send_flow.available() > 0); | ||||
|             self.pending_send.push(stream); | ||||
|         } | ||||
|     } | ||||
| @@ -317,7 +334,7 @@ impl<B> Prioritize<B> | ||||
|  | ||||
|         // First check if there are any data chunks to take back | ||||
|         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 key = frame.payload().stream; | ||||
| @@ -351,11 +368,11 @@ impl<B> Prioritize<B> | ||||
|         stream.pending_send.push_front(&mut self.buffer, frame); | ||||
|  | ||||
|         // 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) | ||||
|         -> Option<Frame<Prioritized<B>>> | ||||
|     { | ||||
| @@ -365,16 +382,33 @@ impl<B> Prioritize<B> | ||||
|                 Some(mut stream) => { | ||||
|                     let frame = match stream.pending_send.pop_front(&mut self.buffer).unwrap() { | ||||
|                         Frame::Data(mut frame) => { | ||||
|                             trace!(" --> data frame"); | ||||
|  | ||||
|                             // Get the amount of capacity remaining for stream's | ||||
|                             // window. | ||||
|                             // | ||||
|                             // 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 | ||||
|                                 // happen if the remote reduced the stream | ||||
|                                 // 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 | ||||
|                             let len = cmp::min( | ||||
|                                 frame.payload().remaining(), | ||||
|                                 max_len); | ||||
|                             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); | ||||
| @@ -428,6 +460,10 @@ impl<B> Prioritize<B> | ||||
|                     }; | ||||
|  | ||||
|                     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); | ||||
|                     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user