Sophie

Sophie

distrib > Fedora > 16 > i386 > by-pkgid > 6048cee8a558eec9d1d34eac70346535 > files > 52

ghc-sendfile-devel-0.7.6-1.fc16.i686.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>src/Network/Socket/SendFile/Iter.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Socket</span><span class='hs-varop'>.</span><span class='hs-conid'>SendFile</span><span class='hs-varop'>.</span><span class='hs-conid'>Iter</span> <span class='hs-keyword'>where</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span> <span class='hs-layout'>(</span><span class='hs-varid'>threadWaitWrite</span><span class='hs-layout'>)</span>
<a name="line-4"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Int</span>           <span class='hs-layout'>(</span><span class='hs-conid'>Int64</span><span class='hs-layout'>)</span>
<a name="line-5"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Posix</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span> <span class='hs-layout'>(</span><span class='hs-conid'>Fd</span><span class='hs-layout'>)</span>
<a name="line-6"></a>
<a name="line-7"></a><a name="Iter"></a><span class='hs-comment'>-- | An iteratee for sendfile</span>
<a name="line-8"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-9"></a><a name="Iter"></a><span class='hs-comment'>-- In general, a whole file is not sent by a single call to</span>
<a name="line-10"></a><a name="Iter"></a><span class='hs-comment'>-- sendfile(), but a series of calls which send successive pieces.</span>
<a name="line-11"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-12"></a><a name="Iter"></a><span class='hs-comment'>-- The high-level API in this sendfile library has calls which will</span>
<a name="line-13"></a><a name="Iter"></a><span class='hs-comment'>-- send the entire file (or an entire requested offset+length), before</span>
<a name="line-14"></a><a name="Iter"></a><span class='hs-comment'>-- returning.</span>
<a name="line-15"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-16"></a><a name="Iter"></a><span class='hs-comment'>-- However, there are instances where you want to be a bit more</span>
<a name="line-17"></a><a name="Iter"></a><span class='hs-comment'>-- involved in the sending loop. For example, if you want to tickle a</span>
<a name="line-18"></a><a name="Iter"></a><span class='hs-comment'>-- timeout after each chunk is sent or update a progress bar.</span>
<a name="line-19"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-20"></a><a name="Iter"></a><span class='hs-comment'>-- The 'Iter' type gives you that power with out requiring you to</span>
<a name="line-21"></a><a name="Iter"></a><span class='hs-comment'>-- manage all the low-level details of the sendfile loop. The</span>
<a name="line-22"></a><a name="Iter"></a><span class='hs-comment'>-- interface is simple and consistant across all platforms.</span>
<a name="line-23"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-24"></a><a name="Iter"></a><span class='hs-comment'>-- A call to sendfile() can result in three different states:</span>
<a name="line-25"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-26"></a><a name="Iter"></a><span class='hs-comment'>--  (1) the requested number of bytes for that iteration was sent</span>
<a name="line-27"></a><a name="Iter"></a><span class='hs-comment'>--  successfully, there are more bytes left to send.</span>
<a name="line-28"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-29"></a><a name="Iter"></a><span class='hs-comment'>--  (2) some (possibly 0) bytes were sent, but the file descriptor</span>
<a name="line-30"></a><a name="Iter"></a><span class='hs-comment'>--  would now block if more bytes were written. There are more bytes</span>
<a name="line-31"></a><a name="Iter"></a><span class='hs-comment'>--  left to send.</span>
<a name="line-32"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-33"></a><a name="Iter"></a><span class='hs-comment'>--  (2) All the bytes were sent, and there is nothing left to send.</span>
<a name="line-34"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-35"></a><a name="Iter"></a><span class='hs-comment'>-- We handle these three cases by using a type with three</span>
<a name="line-36"></a><a name="Iter"></a><span class='hs-comment'>-- constructors:</span>
<a name="line-37"></a><a name="Iter"></a><span class='hs-comment'>-- </span>
<a name="line-38"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-39"></a><a name="Iter"></a><span class='hs-comment'>--  data Iter</span>
<a name="line-40"></a><a name="Iter"></a><span class='hs-comment'>--      = Sent       Int64    (IO Iter)</span>
<a name="line-41"></a><a name="Iter"></a><span class='hs-comment'>--      | WouldBlock Int64 Fd (IO Iter)</span>
<a name="line-42"></a><a name="Iter"></a><span class='hs-comment'>--      | Done       Int64             </span>
<a name="line-43"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-44"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-45"></a><a name="Iter"></a><span class='hs-comment'>-- All three constructors provide an 'Int64' which represents the</span>
<a name="line-46"></a><a name="Iter"></a><span class='hs-comment'>-- number of bytes sent for that particular iteration. (Not the total</span>
<a name="line-47"></a><a name="Iter"></a><span class='hs-comment'>-- byte count).</span>
<a name="line-48"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-49"></a><a name="Iter"></a><span class='hs-comment'>-- The 'Sent' and 'WouldBlock' constructors provide 'IO' 'Iter' as their</span>
<a name="line-50"></a><a name="Iter"></a><span class='hs-comment'>-- final argument. Running this IO action will send the next block of</span>
<a name="line-51"></a><a name="Iter"></a><span class='hs-comment'>-- data.</span>
<a name="line-52"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-53"></a><a name="Iter"></a><span class='hs-comment'>-- The 'WouldBlock' constructor also provides the 'Fd' for the output</span>
<a name="line-54"></a><a name="Iter"></a><span class='hs-comment'>-- socket. You should not send anymore data until the 'Fd' would not</span>
<a name="line-55"></a><a name="Iter"></a><span class='hs-comment'>-- block. The easiest way to do that is to use 'threadWaitWrite' to</span>
<a name="line-56"></a><a name="Iter"></a><span class='hs-comment'>-- suspend the thread until the 'Fd' is available.</span>
<a name="line-57"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-58"></a><a name="Iter"></a><span class='hs-comment'>-- A very simple function to drive the Iter might look like:</span>
<a name="line-59"></a><a name="Iter"></a><span class='hs-comment'>-- </span>
<a name="line-60"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-61"></a><a name="Iter"></a><span class='hs-comment'>-- runIter :: IO Iter -&gt; IO ()</span>
<a name="line-62"></a><a name="Iter"></a><span class='hs-comment'>-- runIter iter =</span>
<a name="line-63"></a><a name="Iter"></a><span class='hs-comment'>--    do r &lt;- iter</span>
<a name="line-64"></a><a name="Iter"></a><span class='hs-comment'>--       case r of</span>
<a name="line-65"></a><a name="Iter"></a><span class='hs-comment'>--         (Done _n)      -&gt; return ()</span>
<a name="line-66"></a><a name="Iter"></a><span class='hs-comment'>--         (Sent _n cont) -&gt; runIter cont</span>
<a name="line-67"></a><a name="Iter"></a><span class='hs-comment'>--         (WouldBlock _n fd cont) -&gt; </span>
<a name="line-68"></a><a name="Iter"></a><span class='hs-comment'>--             do threadWaitWrite fd</span>
<a name="line-69"></a><a name="Iter"></a><span class='hs-comment'>--                runIter cont</span>
<a name="line-70"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-71"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-72"></a><a name="Iter"></a><span class='hs-comment'>-- You would use it as the first argument to a *IterWith function, e.g.</span>
<a name="line-73"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-74"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-75"></a><a name="Iter"></a><span class='hs-comment'>--  sendFileIterWith runIter outputSocket \"\/path\/to\/file\" 2^16 </span>
<a name="line-76"></a><a name="Iter"></a><span class='hs-comment'>-- @</span>
<a name="line-77"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-78"></a><a name="Iter"></a><span class='hs-comment'>-- The 'runIter' function provided by this module is similar, but also returns the total number of bytes sent.</span>
<a name="line-79"></a><a name="Iter"></a><span class='hs-comment'>--</span>
<a name="line-80"></a><a name="Iter"></a><span class='hs-comment'>-- NOTE: You must not use the 'Fd' or the 'IO' 'Iter' after the call</span>
<a name="line-81"></a><a name="Iter"></a><span class='hs-comment'>-- to *IterWith has returned. When the *IterWith functions return,</span>
<a name="line-82"></a><a name="Iter"></a><span class='hs-comment'>-- the file descriptors may be closed due to finalizers running.</span>
<a name="line-83"></a><a name="Iter"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Iter</span>
<a name="line-84"></a>    <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Sent</span>       <span class='hs-conid'>Int64</span>    <span class='hs-layout'>(</span><span class='hs-conid'>IO</span> <span class='hs-conid'>Iter</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ number of bytes sent this pass and a continuation to send more</span>
<a name="line-85"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>WouldBlock</span> <span class='hs-conid'>Int64</span> <span class='hs-conid'>Fd</span> <span class='hs-layout'>(</span><span class='hs-conid'>IO</span> <span class='hs-conid'>Iter</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ number of bytes sent, Fd that blocked, continuation to send more. NOTE: The Fd should not be used outside the running of the Iter as it may be freed when the Iter is done</span>
<a name="line-86"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Done</span>       <span class='hs-conid'>Int64</span>              <span class='hs-comment'>-- ^ number of bytes sent, no more to send</span>
<a name="line-87"></a>
<a name="line-88"></a><a name="runIter"></a><span class='hs-comment'>-- | A simple function to drive the *IterWith functions.</span>
<a name="line-89"></a><span class='hs-comment'>-- It returns the total number of bytes sent.</span>
<a name="line-90"></a><span class='hs-definition'>runIter</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Iter</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Int64</span>
<a name="line-91"></a><span class='hs-definition'>runIter</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runIter'</span> <span class='hs-num'>0</span>
<a name="line-92"></a>    <span class='hs-keyword'>where</span>
<a name="line-93"></a>      <span class='hs-varid'>runIter'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int64</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Iter</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Int64</span>
<a name="line-94"></a>      <span class='hs-varid'>runIter'</span> <span class='hs-varid'>acc</span> <span class='hs-varid'>iter</span> <span class='hs-keyglyph'>=</span>
<a name="line-95"></a>          <span class='hs-keyword'>do</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>iter</span>
<a name="line-96"></a>             <span class='hs-keyword'>case</span> <span class='hs-varid'>r</span> <span class='hs-keyword'>of</span>
<a name="line-97"></a>               <span class='hs-layout'>(</span><span class='hs-conid'>Sent</span> <span class='hs-varid'>n</span> <span class='hs-varid'>cont</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> 
<a name="line-98"></a>                   <span class='hs-keyword'>do</span> <span class='hs-keyword'>let</span> <span class='hs-varid'>acc'</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>acc</span> <span class='hs-varop'>+</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> 
<a name="line-99"></a><span class='hs-comment'>--                      putStrLn $ "Sent " ++ show acc'</span>
<a name="line-100"></a>                      <span class='hs-varid'>acc'</span> <span class='hs-varop'>`seq`</span> <span class='hs-varid'>runIter'</span> <span class='hs-varid'>acc'</span> <span class='hs-varid'>cont</span>
<a name="line-101"></a>               <span class='hs-layout'>(</span><span class='hs-conid'>Done</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-102"></a>                   <span class='hs-keyword'>do</span> <span class='hs-comment'>-- putStrLn $ "Done " ++ show (acc + n)</span>
<a name="line-103"></a>                      <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>acc</span> <span class='hs-varop'>+</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span>
<a name="line-104"></a>               <span class='hs-layout'>(</span><span class='hs-conid'>WouldBlock</span> <span class='hs-varid'>n</span> <span class='hs-varid'>fd</span> <span class='hs-varid'>cont</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> 
<a name="line-105"></a>                   <span class='hs-keyword'>do</span> <span class='hs-varid'>threadWaitWrite</span> <span class='hs-varid'>fd</span>
<a name="line-106"></a>                      <span class='hs-keyword'>let</span> <span class='hs-varid'>acc'</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>acc</span> <span class='hs-varop'>+</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> 
<a name="line-107"></a><span class='hs-comment'>--                      putStrLn $ "WouldBlock " ++ (show acc')</span>
<a name="line-108"></a>                      <span class='hs-varid'>acc'</span> <span class='hs-varop'>`seq`</span> <span class='hs-varid'>runIter'</span> <span class='hs-varid'>acc'</span> <span class='hs-varid'>cont</span>
</pre></body>
</html>