simple-sendfile 0.2.21 → 0.2.22
raw patch · 3 files changed
+75/−15 lines, 3 filesdep ~unix
Dependency ranges changed: unix
Files
- Network/Sendfile/Linux.hsc +26/−14
- System/Linux/Sendfile.hs +47/−0
- simple-sendfile.cabal +2/−1
Network/Sendfile/Linux.hsc view
@@ -2,7 +2,9 @@ module Network.Sendfile.Linux ( sendfile+ , sendfile' , sendfileFd+ , sendfileFd' , sendfileWithHeader , sendfileFdWithHeader ) where@@ -24,6 +26,7 @@ import Network.Socket import System.Posix.Files import System.Posix.IO+import qualified System.Posix.IO.ByteString as B import System.Posix.Types #include <sys/sendfile.h>@@ -65,6 +68,13 @@ setup = openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True} teardown = closeFd +sendfile' :: Fd -> ByteString -> FileRange -> IO () -> IO ()+sendfile' dst path range hook = bracket setup teardown $ \src ->+ sendfileFd' dst src range hook+ where+ setup = B.openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}+ teardown = closeFd+ -- | -- Simple binding for sendfile() of Linux. -- Used system calls:@@ -80,22 +90,24 @@ -- Chucking is inevitable if the socket is non-blocking (this is the -- default) and the file is large. The action is called after a chunk -- is sent and bofore waiting the socket to be ready for writing.- sendfileFd :: Socket -> Fd -> FileRange -> IO () -> IO ()-sendfileFd sock fd range hook =+sendfileFd sock fd range hook = sendfileFd' dst fd range hook+ where+ dst = Fd $ fdSocket sock++sendfileFd' :: Fd -> Fd -> FileRange -> IO () -> IO ()+sendfileFd' dst src range hook = alloca $ \offp -> case range of EntireFile -> do poke offp 0 -- System call is very slow. Use PartOfFile instead.- len <- fileSize <$> getFdStatus fd+ len <- fileSize <$> getFdStatus src let len' = fromIntegral len- sendfileloop dst fd offp len' hook+ sendfileloop dst src offp len' hook PartOfFile off len -> do poke offp (fromIntegral off) let len' = fromIntegral len- sendfileloop dst fd offp len' hook- where- dst = Fd $ fdSocket sock+ sendfileloop dst src offp len' hook sendfileloop :: Fd -> Fd -> Ptr COff -> CSize -> IO () -> IO () sendfileloop dst src offp len hook = do@@ -121,12 +133,12 @@ -- Dst Src in order. take care foreign import ccall unsafe "sendfile"- c_sendfile32 :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)+ c_sendfile32 :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize foreign import ccall unsafe "sendfile64"- c_sendfile64 :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)+ c_sendfile64 :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize -c_sendfile :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)+c_sendfile :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize c_sendfile | isLargeOffset = c_sendfile64 | otherwise = c_sendfile32@@ -191,16 +203,16 @@ siz = fromIntegral len sendloop s buf siz where- MkSocket s _ _ _ _ = sock+ s = Fd $ fdSocket sock PS fptr off len = bs -sendloop :: CInt -> Ptr CChar -> CSize -> IO ()+sendloop :: Fd -> Ptr CChar -> CSize -> IO () sendloop s buf len = do bytes <- c_send s buf len (#const MSG_MORE) if bytes == -1 then do errno <- getErrno if errno == eAGAIN then do- threadWaitWrite (Fd s)+ threadWaitWrite s sendloop s buf len else throwErrno "Network.SendFile.Linux.sendloop"@@ -212,4 +224,4 @@ sendloop s ptr left foreign import ccall unsafe "send"- c_send :: CInt -> Ptr CChar -> CSize -> CInt -> IO (#type ssize_t)+ c_send :: Fd -> Ptr CChar -> CSize -> CInt -> IO CSsize
+ System/Linux/Sendfile.hs view
@@ -0,0 +1,47 @@+module System.Linux.Sendfile (+ sendfile+ , sendfileFd+ ) where++import Data.ByteString (ByteString)+import Network.Sendfile.Linux (sendfile', sendfileFd')+import Network.Sendfile.Types (FileRange)+import System.Posix.Types (Fd)++-- |+-- Simple binding for sendfile() of Linux.+-- Used system calls:+--+-- - EntireFile -- open(), stat(), sendfile(), and close()+--+-- - PartOfFile -- open(), sendfile(), and close()+--+-- If the size of the file is unknown when sending the entire file,+-- specifying PartOfFile is much faster.+--+-- The fourth action argument is called when a file is sent as chunks.+-- Chucking is inevitable if the socket is non-blocking (this is the+-- default) and the file is large. The action is called after a chunk+-- is sent and bofore waiting the socket to be ready for writing.++sendfile :: Fd -> ByteString -> FileRange -> IO () -> IO ()+sendfile = sendfile'++-- |+-- Simple binding for sendfile() of Linux.+-- Used system calls:+--+-- - EntireFile -- stat() and sendfile()+--+-- - PartOfFile -- sendfile()+--+-- If the size of the file is unknown when sending the entire file,+-- specifying PartOfFile is much faster.+--+-- The fourth action argument is called when a file is sent as chunks.+-- Chucking is inevitable if the socket is non-blocking (this is the+-- default) and the file is large. The action is called after a chunk+-- is sent and bofore waiting the socket to be ready for writing.++sendfileFd :: Fd -> Fd -> FileRange -> IO () -> IO ()+sendfileFd = sendfileFd'
simple-sendfile.cabal view
@@ -1,5 +1,5 @@ Name: simple-sendfile-Version: 0.2.21+Version: 0.2.22 Author: Kazu Yamamoto <kazu@iij.ad.jp> Maintainer: Kazu Yamamoto <kazu@iij.ad.jp> License: BSD3@@ -39,6 +39,7 @@ else if os(linux) CPP-Options: -DOS_Linux+ Exposed-Modules: System.Linux.Sendfile Other-Modules: Network.Sendfile.Linux Build-Depends: unix else