on master help sign in
Tickling sendFile responses
80e4c14Michael Snoyman
Network/Wai/Handler/Warp.hs+17−4
@@ -64,7 +64,7 @@ import Control.Exception
64 ( bracket, finally, Exception, SomeException, catch
64 ( bracket, finally, Exception, SomeException, catch
65 , fromException
65 , fromException
66 )
66 )
67−import Control.Concurrent (forkIO)
67+import Control.Concurrent (forkIO, threadWaitWrite)
68import Data.Maybe (fromMaybe)
68import Data.Maybe (fromMaybe)
69
69
70import Data.Typeable (Typeable)
70import Data.Typeable (Typeable)
@@ -80,7 +80,7 @@ import Blaze.ByteString.Builder
80 (copyByteString, Builder, toLazyByteString, toByteStringIO)
80 (copyByteString, Builder, toLazyByteString, toByteStringIO)
81import Blaze.ByteString.Builder.Char8 (fromChar, fromShow)
81import Blaze.ByteString.Builder.Char8 (fromChar, fromShow)
82import Data.Monoid (mappend, mconcat)
82import Data.Monoid (mappend, mconcat)
83−import Network.Socket.SendFile (sendFile)
83+import Network.Socket.SendFile (sendFileIterWith, Iter (..))
84
84
85import Control.Monad.IO.Class (liftIO)
85import Control.Monad.IO.Class (liftIO)
86import qualified Timeout as T
86import qualified Timeout as T
@@ -186,6 +186,9 @@ maxHeaders = 30
186maxHeaderLength = 1024
186maxHeaderLength = 1024
187bytesPerRead = 4096
187bytesPerRead = 4096
188
188
189+sendFileCount :: Integer
190+sendFileCount = 65536
191+
189data InvalidRequest =
192data InvalidRequest =
190 NotEnoughLines [String]
193 NotEnoughLines [String]
191 | BadFirstLine String
194 | BadFirstLine String
@@ -296,13 +299,23 @@ hasBody s req = s /= (Status 204 "") && requestMethod req /= "HEAD"
296
299
297sendResponse :: T.Handle
300sendResponse :: T.Handle
298 -> Request -> HttpVersion -> Socket -> Response -> IO Bool
301 -> Request -> HttpVersion -> Socket -> Response -> IO Bool
299−sendResponse _FIXMEth req hv socket (ResponseFile s hs fp) = do
302+sendResponse th req hv socket (ResponseFile s hs fp) = do
300 Sock.sendMany socket $ L.toChunks $ toLazyByteString $ headers hv s hs False
303 Sock.sendMany socket $ L.toChunks $ toLazyByteString $ headers hv s hs False
301 if hasBody s req
304 if hasBody s req
302 then do
305 then do
303− sendFile socket fp -- FIXME tickle the timeout here
306+ sendFileIterWith tickler socket fp sendFileCount
304 return $ lookup "content-length" hs /= Nothing
307 return $ lookup "content-length" hs /= Nothing
305 else return True
308 else return True
309+ where
310+ tickler iter = do
311+ r <- iter
312+ case r of
313+ Done _ -> return ()
314+ Sent _ cont -> T.tickle th >> tickler cont
315+ WouldBlock _ fd cont -> do
316+ -- FIXME do we want to tickle here?
317+ threadWaitWrite fd
318+ tickler cont
306sendResponse _FIXMEth req hv socket (ResponseBuilder s hs b)
319sendResponse _FIXMEth req hv socket (ResponseBuilder s hs b)
307 | hasBody s req = do
320 | hasBody s req = do
308 toByteStringIO (Sock.sendAll socket) b'
321 toByteStringIO (Sock.sendAll socket) b'