@@ -5,6 +5,7 @@ module Network.Transport.Pipes
7import Control.Monad (when, unless)
7import Control.Monad (when, unless)
8+import Control.Exception (evaluate)
8import Control.Concurrent.MVar
9import Control.Concurrent.MVar
9import Control.Concurrent (threadDelay, forkOS)
10import Control.Concurrent (threadDelay, forkOS)
10import Data.IntMap (IntMap)
11import Data.IntMap (IntMap)
@@ -16,8 +17,14 @@ import qualified Data.IntMap as IntMap
16import qualified Data.ByteString.Char8 as BSS
17import qualified Data.ByteString.Char8 as BSS
17import qualified Data.ByteString.Lazy.Char8 as BS
18import qualified Data.ByteString.Lazy.Char8 as BS
19−import Data.Binary (encode,decode)
20+-- For some STRANGE reason this is not working with Data.Binary [2012.02.20]:
20−-- import Data.Serialize (encode,decode)
23+import Data.Serialize (encode,decode) -- Uses strict BS
25+import Data.Binary (encode,decode) -- Uses lazy BS
21import Data.List (foldl')
28import Data.List (foldl')
22import Network.Transport
29import Network.Transport
23import System.Random (randomIO)
30import System.Random (randomIO)
@@ -27,6 +34,7 @@ import System.Posix.Files (createNamedPipe, unionFileModes, ownerReadMode, owner
27import System.Posix.Types (Fd)
34import System.Posix.Types (Fd)
29-- define DEBUG
36-- define DEBUG
37+-- define USE_UNIX_BYTESTRING
31#ifdef USE_UNIX_BYTESTRING
39#ifdef USE_UNIX_BYTESTRING
32import qualified "unix-bytestring" System.Posix.IO.ByteString as PIO
40import qualified "unix-bytestring" System.Posix.IO.ByteString as PIO
@@ -79,11 +87,19 @@ mkTransport = do
79 -- Initiate but do not block on file opening:
87 -- Initiate but do not block on file opening:
80 -- Note: Linux fifo semantics are NOT to block on open-RW, but this is not Posix standard.
88 -- Note: Linux fifo semantics are NOT to block on open-RW, but this is not Posix standard.
91+ -- All THREE of the below options were observed to work on a simple demo:
82− -- We may protect from blocking other threads by running on a separate (OS) thread:
94+ -- Here we protect from blocking other threads by running on a separate (OS) thread:
83-- mv <- onOSThread$ PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
95-- mv <- onOSThread$ PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
84-- fd <- PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
99-- fd <- PIO.openFd filename PIO.ReadWrite Nothing PIO.defaultFileFlags
85 fd <- PIO.openFd filename PIO.WriteOnly Nothing PIO.defaultFileFlags
102 fd <- PIO.openFd filename PIO.WriteOnly Nothing PIO.defaultFileFlags
87 dbgprint1$ "GOT WRITING END OPEN ... "
103 dbgprint1$ "GOT WRITING END OPEN ... "
@@ -92,7 +108,7 @@ mkTransport = do
92 -- we have to do something more sophisticated.
108 -- we have to do something more sophisticated.
93 SourceEnd
109 SourceEnd
94 { send = \bss -> do
110 { send = \bss -> do
95− dbgprint1$ "SENDING ... "++ show bss
111+ dbgprint1$ "Sending.. "++ show bss
97 -- This may happen on multiple processes/threads:
113 -- This may happen on multiple processes/threads:
98 let msgsize :: Word32 = fromIntegral$ foldl' (\n s -> n + BS.length s) 0 bss
114 let msgsize :: Word32 = fromIntegral$ foldl' (\n s -> n + BS.length s) 0 bss
@@ -100,7 +116,8 @@ mkTransport = do
100 error "Message larger than blocksize written atomically to a named pipe. Unimplemented."
116 error "Message larger than blocksize written atomically to a named pipe. Unimplemented."
101 -- Otherwise it's just a simple write:
117 -- Otherwise it's just a simple write:
102 -- We append the length as a header. TODO - REMOVE EXTRA COPY HERE:
118 -- We append the length as a header. TODO - REMOVE EXTRA COPY HERE:
103− let finalmsg = BS.concat (encode msgsize : bss)
119+-- let finalmsg = BS.concat (encode msgsize : bss)
120+ let finalmsg = BS.concat ((BS.fromChunks[encode msgsize]) : bss)
104 dbgprint1$ " Final send msg: " ++ show finalmsg
121 dbgprint1$ " Final send msg: " ++ show finalmsg
106 -- OPTION 2: Speculative file opening, plus this synchronnization:
123 -- OPTION 2: Speculative file opening, plus this synchronnization:
@@ -132,7 +149,8 @@ mkTransport = do
132 let spinread :: Int64 -> IO BS.ByteString
149 let spinread :: Int64 -> IO BS.ByteString
133 spinread desired = do
150 spinread desired = do
134#ifdef DEBUG
151#ifdef DEBUG
135−-- hPutStr stderr "."
152+ hPutStr stderr "."
153+-- dbgprint2$ " SPINREAD "++ show desired
136 BSS.hPutStr stdout (BSS.pack$ " "++show desired)
154 BSS.hPutStr stdout (BSS.pack$ " "++show desired)
138 (bytes,len) <- oneread desired
156 (bytes,len) <- oneread desired
@@ -144,8 +162,16 @@ mkTransport = do
144 show desired ++" bytes) got "++ show l ++ " bytes"
162 show desired ++" bytes) got "++ show l ++ " bytes"
146 hdr <- spinread sizeof_header
164 hdr <- spinread sizeof_header
147− dbgprint2$ " Got header "++ show hdr ++ " attempt read payload"
165+ dbgprint2$ " Got header "++ show hdr ++ ", next attempt to read payload:"
167+ let decoded = decode (BSS.concat$ BS.toChunks hdr)
168+-- dbgprint2$ " DECODING HDR, bytes "++ show (BS.length hdr) ++ ": "++show hdr
170+-- dbgprint2$ " DONE DECODING HDR"
172+ let decoded = decode hdr
148− payload <- case decode hdr of
174+ payload <- case decoded of
149 Left err -> error$ "ERROR: "++ err
175 Left err -> error$ "ERROR: "++ err
150 Right size -> spinread (fromIntegral (size::Word32))
176 Right size -> spinread (fromIntegral (size::Word32))
151 dbgprint2$ " Got payload "++ show payload
177 dbgprint2$ " Got payload "++ show payload