@@ -1,19 +1,20 @@
1module Control.Distributed.Process.Internal.Messaging
1module Control.Distributed.Process.Internal.Messaging
2− ( -- * Message sending
3− ImplicitReconnect(WithImplicitReconnect, NoImplicitReconnect)
4− , sendPayload
2+ ( sendPayload
5 , sendBinary
3 , sendBinary
6 , sendMessage
4 , sendMessage
7 , disconnect
5 , disconnect
6+ , closeImplicitReconnections
10import Data.Accessor ((^.), (^=))
10import Data.Accessor ((^.), (^=))
11import Data.Binary (Binary, encode)
11import Data.Binary (Binary, encode)
12+import qualified Data.Map as Map (partitionWithKey, elems)
12import qualified Data.ByteString.Lazy as BSL (toChunks)
13import qualified Data.ByteString.Lazy as BSL (toChunks)
13import qualified Data.ByteString as BSS (ByteString)
14import qualified Data.ByteString as BSS (ByteString)
14import Control.Distributed.Process.Internal.StrictMVar (withMVar, modifyMVar_)
15import Control.Distributed.Process.Internal.StrictMVar (withMVar, modifyMVar_)
15import Control.Concurrent.Chan (writeChan)
16import Control.Concurrent.Chan (writeChan)
16−import Control.Monad (unless, when)
17+import Control.Monad (unless)
17import qualified Network.Transport as NT
18import qualified Network.Transport as NT
18 ( Connection
19 ( Connection
@@ -25,6 +26,7 @@ import qualified Network.Transport as NT
25import Control.Distributed.Process.Internal.Types
26import Control.Distributed.Process.Internal.Types
26 ( LocalNode(localState, localEndPoint, localCtrlChan)
27 ( LocalNode(localState, localEndPoint, localCtrlChan)
27 , Identifier
28 , Identifier
28 , localConnectionBetween
30 , localConnectionBetween
29 , nodeAddress
31 , nodeAddress
@@ -33,6 +35,11 @@ import Control.Distributed.Process.Internal.Types
33 , NCMsg(..)
35 , NCMsg(..)
34 , ProcessSignal(Died)
36 , ProcessSignal(Died)
35 , DiedReason(DiedDisconnect)
37 , DiedReason(DiedDisconnect)
38+ , ImplicitReconnect(WithImplicitReconnect)
40+ , ProcessId(processNodeId)
41+ , SendPortId(sendPortProcessId)
42+ , Identifier(NodeIdentifier, ProcessIdentifier, SendPortIdentifier)
37import Control.Distributed.Process.Serializable (Serializable)
44import Control.Distributed.Process.Serializable (Serializable)
@@ -40,9 +47,6 @@ import Control.Distributed.Process.Serializable (Serializable)
40-- Message sending --
47-- Message sending --
41--------------------------------------------------------------------------------
48--------------------------------------------------------------------------------
43−data ImplicitReconnect = WithImplicitReconnect | NoImplicitReconnect
46sendPayload :: LocalNode
50sendPayload :: LocalNode
47 -> Identifier
51 -> Identifier
48 -> Identifier
52 -> Identifier
@@ -50,7 +54,7 @@ sendPayload :: LocalNode
50 -> [BSS.ByteString]
54 -> [BSS.ByteString]
52sendPayload node from to implicitReconnect payload = do
56sendPayload node from to implicitReconnect payload = do
53− mConn <- connBetween node from to
57+ mConn <- connBetween node from to implicitReconnect
54 didSend <- case mConn of
58 didSend <- case mConn of
55 Just conn -> do
59 Just conn -> do
56 didSend <- NT.send conn payload
60 didSend <- NT.send conn payload
@@ -63,11 +67,6 @@ sendPayload node from to implicitReconnect payload = do
63 { ctrlMsgSender = to
67 { ctrlMsgSender = to
64 , ctrlMsgSignal = Died to DiedDisconnect
68 , ctrlMsgSignal = Died to DiedDisconnect
66− when (implicitReconnect == WithImplicitReconnect) $ do
67− disconnect node from to
69− -- (TODO: not quite sure this is the Right Thing)
70− sendPayload node from to NoImplicitReconnect payload
72sendBinary :: Binary a
71sendBinary :: Binary a
73 => LocalNode
72 => LocalNode
@@ -89,12 +88,16 @@ sendMessage :: Serializable a
89sendMessage node from to implicitReconnect =
88sendMessage node from to implicitReconnect =
90 sendPayload node from to implicitReconnect . messageToPayload . createMessage
89 sendPayload node from to implicitReconnect . messageToPayload . createMessage
92−setupConnBetween :: LocalNode -> Identifier -> Identifier -> IO (Maybe NT.Connection)
91+setupConnBetween :: LocalNode
95+ -> IO (Maybe NT.Connection)
93−setupConnBetween node from to = do
96+setupConnBetween node from to implicitReconnect = do
94− mConn <- NT.connect endPoint
97+ mConn <- NT.connect endPoint
95− (nodeAddress . nodeOf $ to)
98+ (nodeAddress . nodeOf $ to)
96− NT.ReliableOrdered
99+ NT.ReliableOrdered
97− NT.defaultConnectHints
100+ NT.defaultConnectHints
98 case mConn of
101 case mConn of
99 Right conn -> do
102 Right conn -> do
100 didSend <- NT.send conn (BSL.toChunks . encode $ to)
103 didSend <- NT.send conn (BSL.toChunks . encode $ to)
@@ -103,7 +106,7 @@ setupConnBetween node from to = do
103 return Nothing
106 return Nothing
104 Right () -> do
107 Right () -> do
105 modifyMVar_ nodeState $ return .
108 modifyMVar_ nodeState $ return .
106− (localConnectionBetween from to ^= Just conn)
109+ (localConnectionBetween from to ^= Just (conn, implicitReconnect))
107 return $ Just conn
110 return $ Just conn
108 Left _ ->
111 Left _ ->
109 return Nothing
112 return Nothing
@@ -111,12 +114,18 @@ setupConnBetween node from to = do
111 endPoint = localEndPoint node
114 endPoint = localEndPoint node
112 nodeState = localState node
115 nodeState = localState node
114−connBetween :: LocalNode -> Identifier -> Identifier -> IO (Maybe NT.Connection)
117+connBetween :: LocalNode
120+ -> ImplicitReconnect
121+ -> IO (Maybe NT.Connection)
115−connBetween node from to = do
122+connBetween node from to implicitReconnect = do
116 mConn <- withMVar nodeState $ return . (^. localConnectionBetween from to)
123 mConn <- withMVar nodeState $ return . (^. localConnectionBetween from to)
117 case mConn of
124 case mConn of
118− Just conn -> return $ Just conn
126+ return $ Just conn
119− Nothing -> setupConnBetween node from to
128+ setupConnBetween node from to implicitReconnect
121 nodeState = localState node
130 nodeState = localState node
@@ -126,6 +135,35 @@ disconnect node from to =
126 case st ^. localConnectionBetween from to of
135 case st ^. localConnectionBetween from to of
127 Nothing ->
136 Nothing ->
128 return st
137 return st
129− Just conn -> do
138+ Just (conn, _) -> do
130 NT.close conn
139 NT.close conn
131 return (localConnectionBetween from to ^= Nothing $ st)
140 return (localConnectionBetween from to ^= Nothing $ st)
142+closeImplicitReconnections :: LocalNode -> Identifier -> IO ()
143+closeImplicitReconnections node to =
144+ modifyMVar_ (localState node) $ \st -> do
145+ let shouldClose (_, to') (_, WithImplicitReconnect) = to `impliesDeathOf` to'
146+ shouldClose _ _ = False
147+ let (affected, unaffected) = Map.partitionWithKey shouldClose (st ^. localConnections)
148+ mapM_ (NT.close . fst) (Map.elems affected)
149+ return (localConnections ^= unaffected $ st)
151+-- | @a `impliesDeathOf` b@ is true if the death of @a@ (for instance, a node)
152+-- implies the death of @b@ (for instance, a process on that node)
153+impliesDeathOf :: Identifier
156+NodeIdentifier nid `impliesDeathOf` NodeIdentifier nid' =
158+NodeIdentifier nid `impliesDeathOf` ProcessIdentifier pid =
159+ processNodeId pid == nid
160+NodeIdentifier nid `impliesDeathOf` SendPortIdentifier cid =
161+ processNodeId (sendPortProcessId cid) == nid
162+ProcessIdentifier pid `impliesDeathOf` ProcessIdentifier pid' =
164+ProcessIdentifier pid `impliesDeathOf` SendPortIdentifier cid =
165+ sendPortProcessId cid == pid
166+SendPortIdentifier cid `impliesDeathOf` SendPortIdentifier cid' =
168+_ `impliesDeathOf` _ =