| @@ -192,6 +192,11 @@ where I: Io, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn try_keep_alive(&mut self) { | ||||||
|  |         self.state.try_keep_alive(); | ||||||
|  |         self.maybe_unpark(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     fn can_write_head(&self) -> bool { |     fn can_write_head(&self) -> bool { | ||||||
|         match self.state.writing { |         match self.state.writing { | ||||||
|             Writing::Init => true, |             Writing::Init => true, | ||||||
| @@ -209,6 +214,13 @@ where I: Io, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn has_queued_body(&self) -> bool { | ||||||
|  |         match self.state.writing { | ||||||
|  |             Writing::Body(_, Some(_)) => true, | ||||||
|  |             _ => false, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     fn write_head(&mut self, mut head: http::MessageHead<T::Outgoing>, body: bool) -> StartSend<http::MessageHead<T::Outgoing>,io::Error> { |     fn write_head(&mut self, mut head: http::MessageHead<T::Outgoing>, body: bool) -> StartSend<http::MessageHead<T::Outgoing>,io::Error> { | ||||||
|         debug_assert!(self.can_write_head()); |         debug_assert!(self.can_write_head()); | ||||||
|         if !body { |         if !body { | ||||||
| @@ -239,6 +251,10 @@ where I: Io, | |||||||
|     fn write_body(&mut self, chunk: Option<B>) -> StartSend<Option<B>, io::Error> { |     fn write_body(&mut self, chunk: Option<B>) -> StartSend<Option<B>, io::Error> { | ||||||
|         debug_assert!(self.can_write_body()); |         debug_assert!(self.can_write_body()); | ||||||
|  |  | ||||||
|  |         if self.has_queued_body() { | ||||||
|  |             try!(self.flush()); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         let state = match self.state.writing { |         let state = match self.state.writing { | ||||||
|             Writing::Body(ref mut encoder, ref mut queued) => { |             Writing::Body(ref mut encoder, ref mut queued) => { | ||||||
|                 if queued.is_some() { |                 if queued.is_some() { | ||||||
| @@ -319,12 +335,16 @@ where I: Io, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn flush(&mut self) -> Poll<(), io::Error> { |     fn flush(&mut self) -> Poll<(), io::Error> { | ||||||
|         let ret = try!(self.write_queued()); |         loop { | ||||||
|         try_nb!(self.io.flush()); |             let queue_finished = try!(self.write_queued()).is_ready(); | ||||||
|         self.state.try_keep_alive(); |             try_nb!(self.io.flush()); | ||||||
|  |             if queue_finished { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         self.try_keep_alive(); | ||||||
|         trace!("flushed {:?}", self.state); |         trace!("flushed {:?}", self.state); | ||||||
|         self.maybe_unpark(); |         Ok(Async::Ready(())) | ||||||
|         Ok(ret) |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -652,6 +672,15 @@ mod tests { | |||||||
|  |  | ||||||
|     use std::str::FromStr; |     use std::str::FromStr; | ||||||
|  |  | ||||||
|  |     impl<T> Writing<T> { | ||||||
|  |         fn is_queued(&self) -> bool { | ||||||
|  |             match *self { | ||||||
|  |                 Writing::Body(_, Some(_)) => true, | ||||||
|  |                 _ => false, | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_conn_init_read() { |     fn test_conn_init_read() { | ||||||
|         let good_message = b"GET / HTTP/1.1\r\n\r\n".to_vec(); |         let good_message = b"GET / HTTP/1.1\r\n\r\n".to_vec(); | ||||||
| @@ -709,17 +738,10 @@ mod tests { | |||||||
|             conn.state.writing = Writing::Body(Encoder::length((max * 2) as u64), None); |             conn.state.writing = Writing::Body(Encoder::length((max * 2) as u64), None); | ||||||
|  |  | ||||||
|             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'a'; 1024 * 4].into()) }).unwrap().is_ready()); |             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'a'; 1024 * 4].into()) }).unwrap().is_ready()); | ||||||
|             match conn.state.writing { |             assert!(!conn.state.writing.is_queued()); | ||||||
|                 Writing::Body(_, None) => {}, |  | ||||||
|                 _ => panic!("writing did not queue chunk: {:?}", conn.state.writing), |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'b'; max].into()) }).unwrap().is_ready()); |             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'b'; max].into()) }).unwrap().is_ready()); | ||||||
|  |             assert!(conn.state.writing.is_queued()); | ||||||
|             match conn.state.writing { |  | ||||||
|                 Writing::Body(_, Some(_)) => {}, |  | ||||||
|                 _ => panic!("writing did not queue chunk: {:?}", conn.state.writing), |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'b'; 1024 * 4].into()) }).unwrap().is_not_ready()); |             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'b'; 1024 * 4].into()) }).unwrap().is_not_ready()); | ||||||
|  |  | ||||||
| @@ -728,7 +750,6 @@ mod tests { | |||||||
|             conn.io.io_mut().block_in(1024 * 3); |             conn.io.io_mut().block_in(1024 * 3); | ||||||
|             assert!(conn.poll_complete().unwrap().is_not_ready()); |             assert!(conn.poll_complete().unwrap().is_not_ready()); | ||||||
|             conn.io.io_mut().block_in(max * 2); |             conn.io.io_mut().block_in(max * 2); | ||||||
|             assert!(conn.poll_complete().unwrap().is_not_ready()); |  | ||||||
|             assert!(conn.poll_complete().unwrap().is_ready()); |             assert!(conn.poll_complete().unwrap().is_ready()); | ||||||
|  |  | ||||||
|             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'c'; 1024 * 4].into()) }).unwrap().is_ready()); |             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'c'; 1024 * 4].into()) }).unwrap().is_ready()); | ||||||
| @@ -749,6 +770,22 @@ mod tests { | |||||||
|         }).wait(); |         }).wait(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_conn_body_flush() { | ||||||
|  |         let _: Result<(), ()> = ::futures::lazy(|| { | ||||||
|  |             let io = AsyncIo::new_buf(vec![], 1024 * 1024 * 5); | ||||||
|  |             let mut conn = Conn::<_, http::Chunk, ServerTransaction>::new(io, Default::default()); | ||||||
|  |             conn.state.writing = Writing::Body(Encoder::length(1024 * 1024), None); | ||||||
|  |             assert!(conn.start_send(Frame::Body { chunk: Some(vec![b'a'; 1024 * 1024].into()) }).unwrap().is_ready()); | ||||||
|  |             println!("{:#?}", conn); | ||||||
|  |             assert!(conn.state.writing.is_queued()); | ||||||
|  |             assert!(conn.poll_complete().unwrap().is_ready()); | ||||||
|  |             assert!(!conn.state.writing.is_queued()); | ||||||
|  |  | ||||||
|  |             Ok(()) | ||||||
|  |         }).wait(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_conn_parking() { |     fn test_conn_parking() { | ||||||
|         use std::sync::Arc; |         use std::sync::Arc; | ||||||
|   | |||||||
| @@ -269,7 +269,7 @@ impl WriteBuf { | |||||||
|         let mut vec = &mut self.0.bytes; |         let mut vec = &mut self.0.bytes; | ||||||
|         let cap = vec.capacity(); |         let cap = vec.capacity(); | ||||||
|         if cap == 0 { |         if cap == 0 { | ||||||
|             let init = cmp::max(INIT_BUFFER_SIZE, needed); |             let init = cmp::min(MAX_BUFFER_SIZE, cmp::max(INIT_BUFFER_SIZE, needed)); | ||||||
|             trace!("WriteBuf reserving initial {}", init); |             trace!("WriteBuf reserving initial {}", init); | ||||||
|             vec.reserve(init); |             vec.reserve(init); | ||||||
|         } else if cap < MAX_BUFFER_SIZE { |         } else if cap < MAX_BUFFER_SIZE { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user