@@ -4,12 +4,13 @@ module Network.Transport.Pipes
4 ( mkTransport
4 ( mkTransport
7−import Control.Monad (when)
7+import Control.Monad (when, unless)
8import Control.Concurrent.MVar
8import Control.Concurrent.MVar
9import Control.Concurrent (threadDelay, forkOS)
9import Control.Concurrent (threadDelay, forkOS)
10import Data.IntMap (IntMap)
10import Data.IntMap (IntMap)
11-- import Data.ByteString.Char8 (ByteString)
11-- import Data.ByteString.Char8 (ByteString)
12import Data.Word
12import Data.Word
13import qualified Data.IntMap as IntMap
14import qualified Data.IntMap as IntMap
14import qualified Data.ByteString.Char8 as BS
15import qualified Data.ByteString.Char8 as BS
15-- import qualified Data.ByteString.Lazy.Char8 as BS
16-- import qualified Data.ByteString.Lazy.Char8 as BS
@@ -69,8 +70,16 @@ mkTransport = do
70 mkSourceEnd :: String -> IO SourceEnd
71 mkSourceEnd :: String -> IO SourceEnd
71 mkSourceEnd filename = do
72 mkSourceEnd filename = do
72-- fd <- openFile filename AppendMode
74-- fd <- openFile filename AppendMode
75+-- _ <- openFile filename WriteMode
73-- mv <- onOSThread$ openFile filename WriteMode
76-- mv <- onOSThread$ openFile filename WriteMode
77+ mv <- onOSThread$ PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
79+ -- [2012.02.19] Still getting indefinite MVar block errors even
80+ -- using IORefs here:
81+-- fdref <- newIORef Nothing
75 -- Write to the named pipe. If the message is less than
84 -- Write to the named pipe. If the message is less than
76 -- PIPE_BUF (4KB on linux) then this should be atomic, otherwise
85 -- PIPE_BUF (4KB on linux) then this should be atomic, otherwise
@@ -85,20 +94,43 @@ mkTransport = do
85 error "Message larger than blocksize written atomically to a named pipe. Unimplemented."
94 error "Message larger than blocksize written atomically to a named pipe. Unimplemented."
86 -- Otherwise it's just a simple write:
95 -- Otherwise it's just a simple write:
87 -- We append the length as a header. TODO - REMOVE EXTRA COPY HERE:
96 -- We append the length as a header. TODO - REMOVE EXTRA COPY HERE:
89−-- fd <- readMVar mv
98+# ifdef KEEP_CLOSED
90− dbgprint1$ " (sending... got file descriptor) "
91-- fd <- openFile filename AppendMode
99-- fd <- openFile filename AppendMode
92 fd <- openFile filename WriteMode
100 fd <- openFile filename WriteMode
102+ -- OPTION 1: Lazy opening:
103+ -- r <- readIORef fdref
106+ -- dbgprint1$ " (No FD for sending yet... opening) "
107+ -- fd <- openFile filename AppendMode
108+ -- writeIORef fdref (Just fd)
110+ -- Just fd -> return fd
112+ -- OPTION 2: Speculative file opening, plus this synchronnization:
114+ dbgprint1$ " (sending... got file descriptor) "
94-- TODO: Consider nonblocking opening of file to make things simpler.
117-- TODO: Consider nonblocking opening of file to make things simpler.
96 let finalmsg = BS.concat (encode msgsize : bss)
119 let finalmsg = BS.concat (encode msgsize : bss)
97 dbgprint1$ " Final send msg: " ++ show finalmsg
120 dbgprint1$ " Final send msg: " ++ show finalmsg
121+ ----------------------------------------
98− BS.hPut fd finalmsg
122+ -- BS.hPut fd finalmsg -- The actual send!
123+ cnt <- PIO.fdWrite fd (BS.unpack finalmsg) -- inefficient!
124+ unless (fromIntegral cnt == BS.length finalmsg) $
125+ error$ "Failed to write message in one go, length: "++ show (BS.length finalmsg)
126+ ----------------------------------------
99 hClose fd -- TEMP -- opening and closing on each send!
128 hClose fd -- TEMP -- opening and closing on each send!
102-- mkTargetEnd :: Fd -> MVar () -> TargetEnd
134-- mkTargetEnd :: Fd -> MVar () -> TargetEnd
103 mkTargetEnd filename lock = TargetEnd
135 mkTargetEnd filename lock = TargetEnd
104 { receive = do
136 { receive = do
@@ -108,7 +140,8 @@ mkTransport = do
108 takeMVar lock
140 takeMVar lock
109#ifdef UNIXIO
141#ifdef UNIXIO
110-- fd <- PIO.openFd filename PIO.ReadOnly Nothing PIO.defaultFileFlags
142-- fd <- PIO.openFd filename PIO.ReadOnly Nothing PIO.defaultFileFlags
111− fd <- PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
143+ mv <- onOSThread$ PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
112 let oneread n = do (s,cnt) <- PIO.fdRead fd (fromIntegral n)
145 let oneread n = do (s,cnt) <- PIO.fdRead fd (fromIntegral n)
113 return (BS.pack s, fromIntegral cnt)
146 return (BS.pack s, fromIntegral cnt)
@@ -117,7 +150,7 @@ mkTransport = do
117 return (bs, BS.length bs)
150 return (bs, BS.length bs)
119 dbgprint2$ " Attempt read header..."
152 dbgprint2$ " Attempt read header..."
121 let spinread :: Int -> IO BS.ByteString
154 let spinread :: Int -> IO BS.ByteString
122 spinread desired = do
155 spinread desired = do
123-- hPutStr stderr "."
156-- hPutStr stderr "."
@@ -140,10 +173,13 @@ mkTransport = do
140 return [payload]
173 return [payload]
143−-- dbgprint2 = hPutStrLn stdout
177+dbgprint2 = hPutStrLn stdout
144−-- dbgprint1 = hPutStrLn stderr
178+dbgprint1 = hPutStrLn stderr
145dbgprint1 _ = return ()
180dbgprint1 _ = return ()
146dbgprint2 _ = return ()
181dbgprint2 _ = return ()
149-- Execute an action on its own OS thread. Return an MVar to synchronize on.
185-- Execute an action on its own OS thread. Return an MVar to synchronize on.
@@ -152,3 +188,4 @@ onOSThread action = do
152 mv <- newEmptyMVar
188 mv <- newEmptyMVar
153 forkOS (action >>= putMVar mv )
189 forkOS (action >>= putMVar mv )
154 return mv
190 return mv
191+-- [2012.02.19] This didn't seem to help.