packages feed

splice 0.6.0.2 → 0.6.1

raw patch · 5 files changed

+452/−443 lines, 5 filesdep ~basedep ~network

Dependency ranges changed: base, network

Files

LICENSE view
@@ -1,31 +1,31 @@-Copyright (c) 2012, Cetin Sert--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are-met:--    * Redistributions of source code must retain the above copyright-      notice, this list of conditions and the following disclaimer.--    * Redistributions in binary form must reproduce the above-      copyright notice, this list of conditions and the following-      disclaimer in the documentation and/or other materials provided-      with the distribution.--    * The names of contributors may not be used to endorse or promote-      products derived from this software without specific prior-      written permission. --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+Copyright (c) 2012, Cetin Sert
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of contributors may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
splice.cabal view
@@ -1,65 +1,65 @@-name:          splice-version:       0.6.0.2-stability:     stable on all operating systems-synopsis:      Cross-platform Socket to Socket Data Splicing-description:   A library that implements most efficient socket to socket-               data transfer loops for proxy servers on all operating systems.-               .-               On GNU/Linux, it uses the zero-copy @splice()@ system-               call (<http://kerneltrap.org/node/6505>) and exports it as-               @c_splice@ in @System.IO.Splice.Linux@.-               .-               On other operating systems, it uses a portable Haskell-               implementation.-               .-               [Legal]-               This work is undertaken by Corsis Research for the development of-               PortFusion \]-\[ayabusa (はやぶさ) (Hayabusa) -               (<https://fusion.corsis.eu>) – German-Japanese joint research-               project for building the simplest and most concise-               high-performance distributed reverse / forward proxy application-               possible on commodity hardware and operating systems.-copyright:     Copyright © 2012 Cetin Sert-license:       BSD3-license-file:  LICENSE-author:        Cetin Sert <fusion@corsis.eu>-maintainer:    Cetin Sert <fusion@corsis.eu>-homepage:      http://corsis.github.com/splice/-bug-reports:   http://github.com/corsis/splice/issues-category:      System, Network-build-type:    Simple-cabal-version: >=1.6---source-repository head-    type:      git-    location:  git://github.com/corsis/splice.git---flag portable-    description: force portable 'splice' implementation on GNU\/Linux-    default    : False---flag llvm-    description: compile via LLVM-    default    : False---library-    hs-source-dirs:      src-    exposed-modules:     Network.Socket.Splice-    other-modules:       Network.Socket.Splice.Internal-    build-depends:       base    >= 4 && <= 6,-                         network >= 2 && <= 4--    if os(linux) && !flag(portable)-      exposed-modules:   System.IO.Splice.Linux-      build-depends:     unix    >= 2 && <= 4-      cpp-options:       -DLINUX_SPLICE---    ghc-options:         -Wall -O2 -O3--    if flag(llvm)-      ghc-options:       -fllvm -optlo-O3 -msse4.2+name:          splice
+version:       0.6.1
+stability:     stable on all operating systems
+synopsis:      Cross-platform Socket to Socket Data Splicing
+description:   A library that implements most efficient socket to socket
+               data transfer loops for proxy servers on all operating systems.
+               .
+               On GNU/Linux, it exports the zero-copy system call @c_splice()@
+               (<http://kerneltrap.org/node/6505>) in @System.IO.Splice.Linux@.
+               .
+               On other operating systems, it only exports a portable Haskell
+               implementation.
+               .
+               A unified sockets API for all operating systems is available in
+               @Network.Socket.Splice@.
+               .
+               [Version Scheme]
+               Major-@/R/@-ewrite . New-@/F/@-unctionality . @/I/@-mprovementAndBugFixes . @/P/@-ackagingOnly
+               .
+               * @PackagingOnly@ changes are made for quality assurance reasons.
+               
+copyright:     Copyright © 2012 Cetin Sert
+license:       BSD3
+license-file:  LICENSE
+author:        Cetin Sert <fusion@corsis.eu>, Corsis Research
+maintainer:    Cetin Sert <fusion@corsis.eu>, Corsis Research
+homepage:      http://corsis.github.com/splice/
+bug-reports:   http://github.com/corsis/splice/issues
+category:      System, Network
+build-type:    Simple
+cabal-version: >= 1.6
+
+
+source-repository head
+    type:      git
+    location:  git://github.com/corsis/splice.git
+
+
+flag portable
+    description: force portable 'splice' implementation on GNU\/Linux
+    default    : True
+
+
+flag llvm
+    description: compile via LLVM
+    default    : False
+
+
+library
+    hs-source-dirs:      src
+    exposed-modules:     Network.Socket.Splice
+    other-modules:       Network.Socket.Splice.Internal
+    build-depends:       base    >= 4 && <= 5,
+                         network -any
+
+    if os(linux) && !flag(portable)
+      exposed-modules:   System.IO.Splice.Linux
+      build-depends:     unix    >= 2 && <= 4
+      cpp-options:       -DLINUX_SPLICE
+
+      
+    ghc-options:         -Wall -O2
+
+    if flag(llvm)
+      ghc-options:       -fllvm -optlo-O3
src/Network/Socket/Splice.hs view
@@ -1,29 +1,29 @@-{- |-  This library implements most efficient socket to socket data transfer loops-  for proxy servers on each operating system.-               -  On GNU\/Linux, it uses and exposes the zero-copy @splice()@ system call:-  <http://kerneltrap.org/node/6505>.--  On all other operating systems, it currently falls back to a portable Haskell-  implementation – which allocates a single memory buffer in user address space,-  then enters an inner loop that uses 'System.IO.hGetBufSome' and-  'System.IO.hPutBuf'. This avoids lots of tiny allocations as would otherwise-  be caused by 'Network.Socket.ByteString.recv' and-  'Network.Socket.ByteString.sendAll' from the @bytestring@ package.--}---  --- Module      : Network.Socket.Splice--- Copyright   : (c) Cetin Sert 2012--- License     : BSD3--- Maintainer  : fusion@corsis.eu--- Stability   : stable--- Portability : works on all operating systems--module Network.Socket.Splice (--  module Network.Socket.Splice.Internal--  ) where--import Network.Socket.Splice.Internal+{- |
+  This library implements most efficient socket to socket data transfer loops
+  for proxy servers on each operating system.
+               
+  On GNU\/Linux, it uses and exposes the zero-copy @splice()@ system call:
+  <http://kerneltrap.org/node/6505>.
+
+  On all other operating systems, it currently falls back to a portable Haskell
+  implementation – which allocates a single memory buffer in user address space,
+  then enters an inner loop that uses 'System.IO.hGetBufSome' and
+  'System.IO.hPutBuf'. This avoids lots of tiny allocations as would otherwise
+  be caused by 'Network.Socket.ByteString.recv' and
+  'Network.Socket.ByteString.sendAll' from the @bytestring@ package.
+-}
+--  
+-- Module      : Network.Socket.Splice
+-- Copyright   : (c) Cetin Sert 2012
+-- License     : BSD3
+-- Maintainer  : fusion@corsis.eu
+-- Stability   : stable
+-- Portability : works on all operating systems
+
+module Network.Socket.Splice (
+
+  module Network.Socket.Splice.Internal
+
+  ) where
+
+import Network.Socket.Splice.Internal
src/Network/Socket/Splice/Internal.hsc view
@@ -1,243 +1,251 @@--- | Implementation.------ Module      : Network.Socket.Splice.Internal--- Copyright   : (c) Cetin Sert 2012--- License     : BSD3--- Maintainer  : fusion@corsis.eu--- Stability   : stable--- Portability : works on all operating systems---#ifdef LINUX_SPLICE-#include <fcntl.h>-#endif-{-# LANGUAGE CPP #-}-{-# LANGUAGE ForeignFunctionInterface #-}---module Network.Socket.Splice.Internal (--  -- * Cross-platform API for Socket to Socket Data Transfer Loops--  {- | 'splice' is the cross-platform API for continous, uni-directional-       data transfer between two network sockets.--       'splice' and its implementation primitives 'hSplice' and 'fdSplice' are-       /infinite/ loops that are intended to be used with-       'Control.Concurrent.forkIO' and exception handlers. 'splice' is a-       terminal operation; it cannot be interleaved by other IO operations on-       its sockets or handles.--       [Initiate bi-directional continuous data transfer between two sockets:]-    -       > void . forkIO . tryWith handler $ splice 1024 (sourceSocket, _) (targetSocket, _)-       > void . forkIO . tryWith handler $ splice 1024 (targetSocket, _) (sourceSocket, _)--       where @handler@ is an IO operation that would do the necessary clean up –-       such as ensuring the sockets are closed and any resources that may be-       associated with the sockets are properly disposed of.--       [Notes]--         * 'System.IO.Splice.Linux.c_splice', the Linux-only system call, is not-           a terminal infinite loop and can be safely interleaved by other IO-           operations on sockets or socket handles.-  -}--    splice-  , ChunkSize-  , zeroCopy--  -- * Combinators for Exception Handling-  , tryWith-  , try_--  -- * Implementation Primitives-  {- | Infinite loops used in the cross-platform implementation of 'splice'.-  -}--  , hSplice-#ifdef LINUX_SPLICE-  , fdSplice-#endif--  ) where---import Data.Word-import Foreign.Ptr--import System.IO-import Network.Socket-import Control.Monad-import Control.Exception-import Foreign.Marshal.Alloc--#ifdef LINUX_SPLICE-import Data.Int-import Data.Bits-import System.Posix.IO-import Unsafe.Coerce-import Foreign.C.Error-import System.Posix.Types-import System.Posix.Internals-import qualified System.IO.Splice.Linux as L-#else-import Data.Maybe-#endif---------------------------------------------------------------------------------------- | Indicates whether 'splice' uses zero-copy system calls or the portable user ---   space Haskell implementation.-zeroCopy :: Bool -- ^ @True@ if 'splice' uses zero-copy system calls;-                 --   otherwise, false.-zeroCopy =-#ifdef LINUX_SPLICE-  True-#else-  False-#endif----- | The numeric type to recommend chunk sizes for moving data between sockets---   used by both zero-copy and portable implementations of 'splice'.-type ChunkSize =-#ifdef LINUX_SPLICE-  L.ChunkSize-#else-  Int-#endif---throwRecv0 :: a+-- | Implementation.
+--
+-- Module      : Network.Socket.Splice.Internal
+-- Copyright   : (c) Cetin Sert 2012
+-- License     : BSD3
+-- Maintainer  : fusion@corsis.eu
+-- Stability   : stable
+-- Portability : works on all operating systems
+
+
+#ifdef LINUX_SPLICE
+#include <fcntl.h>
+#endif
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+
+
+module Network.Socket.Splice.Internal (
+
+  -- * Cross-platform API for Socket to Socket Data Transfer Loops
+
+  {- | 'splice' is the cross-platform API for continous, uni-directional
+       data transfer between two network sockets.
+
+       'splice' and its implementation primitives 'hSplice' and 'fdSplice' are
+       /infinite/ loops that are intended to be used with
+       'Control.Concurrent.forkIO' and exception handlers. 'splice' is a
+       terminal operation; it cannot be interleaved by other IO operations on
+       its sockets or handles.
+
+       [Initiate bi-directional continuous data transfer between two sockets:]
+    
+       > void . forkIO . tryWith handler $! splice void 1024 (sourceSocket, _) (targetSocket, _)
+       > void . forkIO . tryWith handler $! splice void 1024 (targetSocket, _) (sourceSocket, _)
+
+       where @handler@ is an IO operation that would do the necessary clean up –
+       such as ensuring the sockets are closed and any resources that may be
+       associated with the sockets are properly disposed of.
+
+       [Notes]
+
+         * 'System.IO.Splice.Linux.c_splice', the Linux-only system call, is not
+           a terminal infinite loop and can be safely interleaved by other IO
+           operations on sockets or socket handles.
+  -}
+
+    splice
+  , ChunkSize
+  , zeroCopy
+
+  -- * Combinators for Exception Handling
+  , tryWith
+  , try_
+
+  -- * Implementation Primitives
+  {- | Infinite loops used in the cross-platform implementation of 'splice'. -}
+
+  , hSplice
+#ifdef LINUX_SPLICE
+  , fdSplice
+#endif
+
+  ) where
+
+
+import Data.Word
+import Foreign.Ptr
+
+import System.IO
+import Network.Socket
+import Control.Monad
+import Control.Exception
+import Foreign.Marshal.Alloc
+
+#ifdef LINUX_SPLICE
+import Data.Int
+import Data.Bits
+import System.Posix.IO
+import Unsafe.Coerce
+import Foreign.C.Error
+import System.Posix.Types
+import System.Posix.Internals
+import qualified System.IO.Splice.Linux as L
+#else
+import Data.Maybe
+#endif
+
+
+----------------------------------------------------------------------------------------------------
+
+
+-- | Indicates whether 'splice' uses zero-copy system calls or the portable user
+--   space Haskell implementation.
+zeroCopy :: Bool -- ^ @True@ if 'splice' uses zero-copy system calls; otherwise, false.
+zeroCopy =
+#ifdef LINUX_SPLICE
+  True
+#else
+  False
+#endif
+
+
+-- | The numeric type to recommend chunk sizes for moving data between sockets
+--   used by both zero-copy and portable implementations of 'splice'.
+type ChunkSize =
+#ifdef LINUX_SPLICE
+  L.ChunkSize
+#else
+  Int
+#endif
+
+
+----------------------------------------------------------------------------------------------SPLICE
+
+
+-- | Pipes data from one socket to another in an /infinite loop/.
+--
+--   'splice' currently has two implementations:
+--
+--   [on GNU\/Linux using 'fdSplice' ≅]
+--
+--   > splice len (sIn, _       ) (sOut, _        ) = ... fdSplice ...
+--
+--   [on all other operating systems using 'hSplice' ≅]
+--
+--   > splice len (_  , Just hIn) (_   , Just hOut) = ... hSplice  ...
+--
+--   [Notes]
+--
+--     * 'fdSplice' and 'fdSplice' implementation of 'splice' are only available
+--        on GNU\/Linux.
+--
+--     * 'hSplice' is always available and the 'hSplice' implementation of
+--       'splice' can be forced on GNU\/Linux by defining the @portable@ flag at
+--       compile time.
+--
+--     * 'hSplice' implementation requires handles in 'NoBuffering' mode.
+--
+--     * 'splice' is a terminal loop on two sockets and once entered its sockets
+--        and handles cannot be interleaved by other IO operations.
+--
+splice
+  :: ChunkSize               -- ^ maximal chunk size.
+  -> (Socket, Maybe Handle)  -- ^ source socket and possibly its opened handle.
+  -> (Socket, Maybe Handle)  -- ^ target socket and possibly its opened handle.
+  -> IO ()                   -- ^ infinite loop.
+#ifdef LINUX_SPLICE
+splice len (sIn, _  ) (sOut, _   ) = do
+#else
+splice len (_  , hIn) (_   , hOut) = do
+#endif
+#ifdef LINUX_SPLICE
+  let s = Fd $! fdSocket sIn
+  let t = Fd $! fdSocket sOut
+  fdSplice len s t
+#else
+  let s = fromJust hIn
+  let t = fromJust hOut
+  hSplice (fromIntegral len) s t
+#endif
+
+
+--------------------------------------------------------------------------------------------FDSPLICE
+
+
+#ifdef LINUX_SPLICE
+
+{- | GNU\/Linux @splice()@ system call loop.
+
+       1. creates a pipe in kernel address space
+
+       2. uses it until the loop terminates by exception
+
+       3. closes the pipe and returns
+-}
+fdSplice :: ChunkSize -> Fd -> Fd -> IO ()
+fdSplice len s@(Fd fdIn) t@(Fd fdOut) = do
+
+  (r,w) <- createPipe
+  let n = nullPtr  
+  let u = unsafeCoerce :: (#type ssize_t) -> (#type size_t)
+  let check = throwErrnoIfMinus1 "Network.Socket.Splice.splice"
+  let flags = L.sPLICE_F_MOVE .|. L.sPLICE_F_MORE
+  let setNonBlockingMode v = do setNonBlockingFD fdIn  v
+                                setNonBlockingFD fdOut v
+  setNonBlockingMode False
+
+  finally
+    (forever $! do 
+       bytes   <- check $! L.c_splice s n w n    len    flags
+       if bytes > 0
+         then              L.c_splice r n t n (u bytes) flags
+         else              throwRecv0)
+    (do closeFd r
+        closeFd w
+        try_ $! setNonBlockingMode True)
+
+#endif
+
+
+---------------------------------------------------------------------------------------------HSPLICE
+
+
+{- | The portable Haskell loop.
+
+       1. allocates a /single/ memory buffer in user address space
+
+       2. uses it until the loop terminates by exception
+
+       3. frees the buffer and returns
+
+   [Notes]
+
+     * the socket handles are required to be in 'NoBuffering' mode.
+-} 
+hSplice :: Int -> Handle -> Handle -> IO ()
+hSplice len s t = do
+
+  a <- mallocBytes len :: IO (Ptr Word8)
+
+  finally
+    (forever $! do
+       bytes   <- hGetBufSome s a len
+       if bytes > 0
+         then     hPutBuf     t a bytes
+         else     throwRecv0)
+    (free a)
+
+
+------------------------------------------------------------------------------------------EXCEPTIONS
+
+
+-- | Similar to 'Control.Exception.Base.try' but used when an obvious exception
+--   is expected and can be handled easily. Unlike 'finally' exceptions are
+--   /NOT/ rethrown once handled.
+tryWith
+  :: (SomeException -> IO a) -- ^ exception handler.
+  -> IO a                    -- ^ action to run which can throw /any/ exception.
+  -> IO a                    -- ^ new action where all exceptions are handled by the single handler.
+tryWith h a = try a >>= \r -> case r of Left x -> h x; Right y -> return y
+
+
+-- | Similar to 'Control.Exception.Base.try' but used when an obvious exception
+--   is expected which can be safely ignored.
+try_
+  :: IO ()                   -- ^ action to run which can throw /any/ exception.
+  -> IO ()                   -- ^ new action where exceptions are silenced.
+try_ a = (try a :: IO (Either SomeException ())) >> return ()
+
+
+throwRecv0 :: a
 throwRecv0 = error "Network.Socket.Splice.splice ended"---- | Pipes data from one socket to another in an /infinite loop/.------   'splice' currently has two implementations:------   [on GNU\/Linux using 'fdSplice' ≅]------   > splice len (sIn, _       ) (sOut, _        ) = ... fdSplice ...------   [on all other operating systems using 'hSplice' ≅]------   > splice len (_  , Just hIn) (_   , Just hOut) = ... hSplice  ...------   [Notes]------     * 'fdSplice' and 'fdSplice' implementation of 'splice' are only available---        on GNU\/Linux.------     * 'hSplice' is always available and the 'hSplice' implementation of---       'splice' can be forced on GNU\/Linux by defining the @portable@ flag at---       compile time.------     * 'hSplice' implementation requires handles in 'NoBuffering' mode.------     * 'splice' is a terminal loop on two sockets and once entered its sockets---        and handles cannot be interleaved by other IO operations.----splice-  :: ChunkSize               -- ^ chunk size.-  -> (Socket, Maybe Handle)  -- ^ source socket and possibly its opened handle.-  -> (Socket, Maybe Handle)  -- ^ target socket and possibly its opened handle.-  -> IO ()                   -- ^ infinite loop.-#ifdef LINUX_SPLICE-splice len (sIn, _  ) (sOut, _   ) = do-#else-splice len (_  , hIn) (_   , hOut) = do-#endif-#ifdef LINUX_SPLICE-  let s = Fd $ fdSocket sIn-  let t = Fd $ fdSocket sOut-  fdSplice len s t-#else-  let s = fromJust hIn-  let t = fromJust hOut-  hSplice (fromIntegral len) s t-#endif----#ifdef LINUX_SPLICE--{- | GNU\/Linux @splice()@ system call loop.--       1. creates a pipe in kernel address space--       2. uses it until the loop terminates by exception--       3. closes the pipe and returns--}-fdSplice :: ChunkSize -> Fd -> Fd -> IO ()-fdSplice len s@(Fd fdIn) t@(Fd fdOut) = do--  (r,w) <- createPipe-  let n = nullPtr  -  let u = unsafeCoerce :: (#type ssize_t) -> (#type size_t)-  let check = throwErrnoIfMinus1 "Network.Socket.Splice.splice"-  let flags = L.sPLICE_F_MOVE .|. L.sPLICE_F_MORE-  let setNonBlockingMode v = do setNonBlockingFD fdIn  v-                                setNonBlockingFD fdOut v-  setNonBlockingMode False--  finally-    (forever $ do -       bytes <- check $ L.c_splice s n w n    len    flags-       if bytes > 0-         then           L.c_splice r n t n (u bytes) flags-         else           throwRecv0)-    (do closeFd r-        closeFd w-        try_ $ setNonBlockingMode True)--#endif----{- | The portable Haskell loop.--       1. allocates a /single/ memory buffer in user address space--       2. uses it until the loop terminates by exception--       3. frees the buffer and returns--   [Notes]--     * the socket handles are required to be in 'NoBuffering' mode.--} -hSplice :: Int -> Handle -> Handle -> IO ()-hSplice len s t = do--  a  <- mallocBytes len :: IO (Ptr Word8)--  finally-    (forever $ do-       bytes <-   hGetBufSome s a len-       if bytes > 0-         then     hPutBuf     t a bytes-         else     throwRecv0)-    (free a)----- | Similar to 'Control.Exception.Base.try' but used when an obvious exception---   is expected and can be handled easily. Unlike 'finally' exceptions are---   /NOT/ rethrown once handled.-tryWith-  :: (SomeException -> IO a) -- ^ exception handler.-  -> IO a -- ^ action to run which can throw /any/ exception.-  -> IO a -- ^ new action where all exceptions are handled by the single handler.-tryWith h a = try a >>= \r -> case r of Left x -> h x; Right y -> return y----- | Similar to 'Control.Exception.Base.try' but used when an obvious exception---   is expected which can be safely ignored.-try_-  :: IO () -- ^ action to run which can throw /any/ exception.-  -> IO () -- ^ new action where exceptions are silenced.-try_ a = (try a :: IO (Either SomeException ())) >> return ()
src/System/IO/Splice/Linux.hsc view
@@ -1,77 +1,78 @@-{- | Exposes the GNU\/Linux system call @splice()@: <http://kerneltrap.org/node/6505>.--     /This module is only available (compiled & exposed) on GNU/\//Linux./--}---  --- Module      : System.IO.Splice.Linux--- Copyright   : (c) Cetin Sert 2012--- License     : BSD3--- Maintainer  : fusion@corsis.eu--- Stability   : stable--- Portability : GNU\/Linux-only--#include <fcntl.h>-{-# LANGUAGE CPP #-}-{-# LANGUAGE ForeignFunctionInterface #-}--module System.IO.Splice.Linux (--    c_splice-  , ChunkSize-  , sPLICE_F_MOVE-  , sPLICE_F_MORE-  , sPLICE_F_NONBLOCK--  ) where---import Data.Int-import Data.Word-import Foreign.Ptr-import Foreign.C.Types-import System.Posix.Types----- | The numeric type used by 'c_splice' for chunk size recommendations when---   moving data.-type ChunkSize = (#type size_t)---- | Moves data between two file descriptors without copying between kernel---   address space and user address space. It transfers up to @len@ bytes of---   data from the file descriptor @fd_in@ to the file descriptor @fd_out@,---   where one of the descriptors must refer to a pipe.------   'c_splice' is /NOT/ a loop and needs to be called repeatedly.------   For an example, see 'Network.Socket.Splice.Internal.splice'.-foreign import ccall "splice"-  c_splice-  :: Fd                  -- ^ @fd_in@.-  -> Ptr (#type loff_t)  -- ^ @off_in@.-  -> Fd                  -- ^ @fd_out@.-  -> Ptr (#type loff_t)  -- ^ @off_out@.-  -> ChunkSize           -- ^ @len@.-  -> Word                -- ^ @flags@.-  -> IO (#type ssize_t)  -- ^ number of bytes moved if successful; otherwise -1.----- | Attempt to move pages instead of copying. This is only a hint to the---   kernel: pages may stil be copied (/in kernel address space/) if the kernel---   cannot move the pages from the pipe, or if the pipe buffers don't refer to---   full pages.-sPLICE_F_MOVE :: Word-sPLICE_F_MOVE = (#const "SPLICE_F_MOVE")----- | More data will be coming in a subsequent 'c_splice'. This is a helpful hint---   when @fd_out@ refers to a socket.-sPLICE_F_MORE :: Word-sPLICE_F_MORE = (#const "SPLICE_F_MORE")----- | Do not block on I\/O. This makes the 'c_splice' pipe operations---   nonblocking, but 'c_splice' may nevertheless block because the file---   descriptors that are 'c_splice'd to\/from may block (unless they have the---   @O_NONBLOCK@ flag set).-sPLICE_F_NONBLOCK :: Word+{- | Exposes the GNU\/Linux system call @splice()@: <http://kerneltrap.org/node/6505>.
+
+     /This module is only available (compiled & exposed) on GNU/\//Linux./
+-}
+--  
+-- Module      : System.IO.Splice.Linux
+-- Copyright   : (c) Cetin Sert 2012
+-- License     : BSD3
+-- Maintainer  : fusion@corsis.eu
+-- Stability   : stable
+-- Portability : GNU\/Linux-only
+
+
+#include <fcntl.h>
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+
+
+module System.IO.Splice.Linux (
+
+    c_splice
+  , ChunkSize
+  , sPLICE_F_MOVE
+  , sPLICE_F_MORE
+  , sPLICE_F_NONBLOCK
+
+  ) where
+
+
+import Data.Int
+import Data.Word
+import Foreign.Ptr
+import Foreign.C.Types
+import System.Posix.Types
+
+
+-- | The numeric type used by 'c_splice' for chunk size recommendations when
+--   moving data.
+type ChunkSize = (#type size_t)
+
+-- | Moves data between two file descriptors without copying between kernel
+--   address space and user address space. It transfers up to @len@ bytes of
+--   data from the file descriptor @fd_in@ to the file descriptor @fd_out@,
+--   where one of the descriptors must refer to a pipe.
+--
+--   'c_splice' is /NOT/ a loop and needs to be called repeatedly.
+--
+--   For an example, see 'Network.Socket.Splice.Internal.splice'.
+foreign import ccall "splice"
+  c_splice
+  :: Fd                  -- ^ @fd_in@.
+  -> Ptr (#type loff_t)  -- ^ @off_in@.
+  -> Fd                  -- ^ @fd_out@.
+  -> Ptr (#type loff_t)  -- ^ @off_out@.
+  -> ChunkSize           -- ^ @len@.
+  -> Word                -- ^ @flags@.
+  -> IO (#type ssize_t)  -- ^ number of bytes moved if successful; otherwise -1.
+
+
+-- | Attempt to move pages instead of copying. This is only a hint to the
+--   kernel: pages may stil be copied (/in kernel address space/) if the kernel
+--   cannot move the pages from the pipe, or if the pipe buffers don't refer to
+--   full pages.
+sPLICE_F_MOVE :: Word
+sPLICE_F_MOVE = (#const "SPLICE_F_MOVE")
+
+
+-- | More data will be coming in a subsequent 'c_splice'. This is a helpful hint
+--   when @fd_out@ refers to a socket.
+sPLICE_F_MORE :: Word
+sPLICE_F_MORE = (#const "SPLICE_F_MORE")
+
+
+-- | Do not block on I\/O. This makes the 'c_splice' pipe operations
+--   nonblocking, but 'c_splice' may nevertheless block because the file
+--   descriptors that are 'c_splice'd to\/from may block (unless they have the
+--   @O_NONBLOCK@ flag set).
+sPLICE_F_NONBLOCK :: Word
 sPLICE_F_NONBLOCK = (#const "SPLICE_F_NONBLOCK")