@@ -14,8 +14,8 @@ import Prelude hiding (catch)
16import System.IO (fixIO, hPutStrLn, stderr)
16import System.IO (fixIO, hPutStrLn, stderr)
17−import qualified Data.ByteString.Lazy as BSL (fromChunks)
17+import qualified Data.NotByteString.Lazy as BSL (fromChunks)
18−import Data.Binary (decode)
18+import Data.NotByteString.Lazy.Binary (decode)
19import Data.Map (Map)
19import Data.Map (Map)
20import qualified Data.Map as Map
20import qualified Data.Map as Map
@@ -25,10 +25,10 @@ import qualified Data.Map as Map
26 , partitionWithKey
26 , partitionWithKey
27 , filterWithKey
27 , filterWithKey
29−import qualified Data.List as List (delete, (\\))
30import Data.Set (Set)
30import Data.Set (Set)
31−import qualified Data.Set as Set (empty, insert, delete, member, (\\), fromList)
31+import qualified Data.Set as Set (empty, insert, delete, member, filter)
32import Data.Foldable (forM_)
32import Data.Foldable (forM_)
33import Data.Maybe (isJust)
33import Data.Maybe (isJust)
34import Data.Typeable (Typeable)
34import Data.Typeable (Typeable)
@@ -65,6 +65,8 @@ import qualified Network.Transport as NT
66 , closeEndPoint
66 , closeEndPoint
67 , ConnectionId
67 , ConnectionId
69import Data.Accessor (Accessor, accessor, (^.), (^=), (^:))
71import Data.Accessor (Accessor, accessor, (^.), (^=), (^:))
70import qualified Data.Accessor.Container as DAC (mapDefault, mapMaybe)
72import qualified Data.Accessor.Container as DAC (mapDefault, mapMaybe)
@@ -89,6 +91,7 @@ import Control.Distributed.Process.Internal.Types
89 , localPidCounter
91 , localPidCounter
90 , localPidUnique
92 , localPidUnique
91 , localProcessWithId
93 , localProcessWithId
92 , MonitorRef(..)
95 , MonitorRef(..)
93 , ProcessMonitorNotification(..)
96 , ProcessMonitorNotification(..)
94 , NodeMonitorNotification(..)
97 , NodeMonitorNotification(..)
@@ -119,6 +122,7 @@ import Control.Distributed.Process.Internal.Node
119 ( sendBinary
122 ( sendBinary
120 , sendMessage
123 , sendMessage
121 , sendPayload
124 , sendPayload
123import Control.Distributed.Process.Internal.Primitives (expect, register, finally)
127import Control.Distributed.Process.Internal.Primitives (expect, register, finally)
124import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
128import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
@@ -212,8 +216,13 @@ forkProcess node proc = modifyMVar (localState node) $ \st -> do
212 (runLocalProcess lproc proc >> return DiedNormal)
216 (runLocalProcess lproc proc >> return DiedNormal)
213 (return . DiedException . (show :: SomeException -> String))
217 (return . DiedException . (show :: SomeException -> String))
214 -- [Unified: Table 4, rules termination and exiting]
218 -- [Unified: Table 4, rules termination and exiting]
215− modifyMVar_ (localState node) $
219+ modifyMVar_ (localState node) $ \st -> do
220+ let pid' = ProcessIdentifier pid
221+ let (affected, unaffected) = Map.partitionWithKey (\(fr, _to) !_v -> impliesDeathOf pid' fr) (st ^. localConnections)
222+ mapM_ NT.close (Map.elems affected)
216− return . (localProcessWithId lpid ^= Nothing)
223+ return $ (localProcessWithId lpid ^= Nothing)
224+ . (localConnections ^= unaffected)
217 writeChan (localCtrlChan node) NCMsg
226 writeChan (localCtrlChan node) NCMsg
218 { ctrlMsgSender = ProcessIdentifier pid
227 { ctrlMsgSender = ProcessIdentifier pid
219 , ctrlMsgSignal = Died (ProcessIdentifier pid) reason
228 , ctrlMsgSignal = Died (ProcessIdentifier pid) reason
@@ -237,25 +246,25 @@ forkProcess node proc = modifyMVar (localState node) $ \st -> do
239handleIncomingMessages :: LocalNode -> IO ()
248handleIncomingMessages :: LocalNode -> IO ()
240−handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
249+handleIncomingMessages node = go Set.empty Map.empty Map.empty Set.empty
242− go :: [NT.ConnectionId] -- ^ Connections whose purpose we don't yet know
251+ go :: Set NT.ConnectionId -- ^ Connections whose purpose we don't yet know
243 -> Map NT.ConnectionId LocalProcess -- ^ Connections to local processes
252 -> Map NT.ConnectionId LocalProcess -- ^ Connections to local processes
244 -> Map NT.ConnectionId TypedChannel -- ^ Connections to typed channels
253 -> Map NT.ConnectionId TypedChannel -- ^ Connections to typed channels
245 -> Set NT.ConnectionId -- ^ Connections to our controller
254 -> Set NT.ConnectionId -- ^ Connections to our controller
246 -> IO ()
255 -> IO ()
247− go uninitConns procs chans ctrls = do
256+ go !uninitConns !procs !chans !ctrls = do
248 event <- NT.receive endpoint
257 event <- NT.receive endpoint
249 case event of
258 case event of
250 NT.ConnectionOpened cid _rel _theirAddr ->
259 NT.ConnectionOpened cid _rel _theirAddr ->
251 -- TODO: Check if _rel is ReliableOrdered, and if not, treat as
260 -- TODO: Check if _rel is ReliableOrdered, and if not, treat as
252 -- (**) below.
261 -- (**) below.
253− go (cid : uninitConns) procs chans ctrls
262+ go (Set.insert cid uninitConns) procs chans ctrls
254 NT.Received cid payload ->
263 NT.Received cid payload ->
255 case ( Map.lookup cid procs
264 case ( Map.lookup cid procs
256 , Map.lookup cid chans
265 , Map.lookup cid chans
257 , cid `Set.member` ctrls
266 , cid `Set.member` ctrls
258− , cid `elem` uninitConns
267+ , cid `Set.member` uninitConns
260 (Just proc, _, _, _) -> do
269 (Just proc, _, _, _) -> do
261 let msg = payloadToMessage payload
270 let msg = payloadToMessage payload
@@ -275,7 +284,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
275 mProc <- withMVar state $ return . (^. localProcessWithId lpid)
284 mProc <- withMVar state $ return . (^. localProcessWithId lpid)
276 case mProc of
285 case mProc of
277 Just proc ->
286 Just proc ->
278− go (List.delete cid uninitConns)
287+ go (Set.delete cid uninitConns)
279 (Map.insert cid proc procs)
288 (Map.insert cid proc procs)
@@ -287,7 +296,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
287 -- remote node as having died, and we should close
296 -- remote node as having died, and we should close
288 -- incoming connections (this requires a Transport layer
297 -- incoming connections (this requires a Transport layer
289 -- extension). (**)
298 -- extension). (**)
290− go (List.delete cid uninitConns) procs chans ctrls
299+ go (Set.delete cid uninitConns) procs chans ctrls
291 SendPortIdentifier chId -> do
300 SendPortIdentifier chId -> do
292 let lcid = sendPortLocalId chId
301 let lcid = sendPortLocalId chId
293 lpid = processLocalId (sendPortProcessId chId)
302 lpid = processLocalId (sendPortProcessId chId)
@@ -297,20 +306,20 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
297 mChannel <- withMVar (processState proc) $ return . (^. typedChannelWithId lcid)
306 mChannel <- withMVar (processState proc) $ return . (^. typedChannelWithId lcid)
298 case mChannel of
307 case mChannel of
299 Just channel ->
308 Just channel ->
300− go (List.delete cid uninitConns)
309+ go (Set.delete cid uninitConns)
302 (Map.insert cid channel chans)
311 (Map.insert cid channel chans)
304 Nothing ->
313 Nothing ->
305 -- Unknown typed channel
314 -- Unknown typed channel
306 -- TODO (**) above
315 -- TODO (**) above
307− go (List.delete cid uninitConns) procs chans ctrls
316+ go (Set.delete cid uninitConns) procs chans ctrls
308 Nothing ->
317 Nothing ->
309 -- Unknown process
318 -- Unknown process
310 -- TODO (**) above
319 -- TODO (**) above
311− go (List.delete cid uninitConns) procs chans ctrls
320+ go (Set.delete cid uninitConns) procs chans ctrls
312 NodeIdentifier _ ->
321 NodeIdentifier _ ->
313− go (List.delete cid uninitConns)
322+ go (Set.delete cid uninitConns)
316 (Set.insert cid ctrls)
325 (Set.insert cid ctrls)
@@ -319,7 +328,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
319 -- TODO (**) above
328 -- TODO (**) above
320 go uninitConns procs chans ctrls
329 go uninitConns procs chans ctrls
321 NT.ConnectionClosed cid ->
330 NT.ConnectionClosed cid ->
322− go (List.delete cid uninitConns)
331+ go (Set.delete cid uninitConns)
323 (Map.delete cid procs)
332 (Map.delete cid procs)
324 (Map.delete cid chans)
333 (Map.delete cid chans)
325 (Set.delete cid ctrls)
334 (Set.delete cid ctrls)
@@ -330,10 +339,11 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
330 { ctrlMsgSender = nid
339 { ctrlMsgSender = nid
331 , ctrlMsgSignal = Died nid DiedDisconnect
340 , ctrlMsgSignal = Died nid DiedDisconnect
342+ let notRemoved k = k `notElem` cids
333− go (uninitConns List.\\ cids)
343+ go (Set.filter notRemoved uninitConns)
334− (Map.filterWithKey (\k _ -> k `notElem` cids) procs)
344+ (Map.filterWithKey (const . notRemoved) procs)
335− (Map.filterWithKey (\k _ -> k `notElem` cids) chans)
345+ (Map.filterWithKey (const . notRemoved) chans)
336− (ctrls Set.\\ Set.fromList cids)
346+ (Set.filter notRemoved ctrls)
337 NT.ErrorEvent (NT.TransportError (NT.EventConnectionLost Nothing _) _) ->
347 NT.ErrorEvent (NT.TransportError (NT.EventConnectionLost Nothing _) _) ->
338 -- TODO: We should treat an asymetrical connection loss (incoming
348 -- TODO: We should treat an asymetrical connection loss (incoming
339 -- connection broken, but outgoing connection still potentially ok)
349 -- connection broken, but outgoing connection still potentially ok)
@@ -424,6 +434,8 @@ nodeController = do
424 ncEffectWhereIs from label
434 ncEffectWhereIs from label
425 NCMsg from (NamedSend label msg') ->
435 NCMsg from (NamedSend label msg') ->
426 ncEffectNamedSend from label msg'
436 ncEffectNamedSend from label msg'
437+ NCMsg from (Reconnect to) ->
438+ ncEffectReconnect from to
427 unexpected ->
439 unexpected ->
428 error $ "nodeController: unexpected message " ++ show unexpected
440 error $ "nodeController: unexpected message " ++ show unexpected
@@ -547,6 +559,12 @@ ncEffectNamedSend from label msg = do
547 (ProcessIdentifier pid)
559 (ProcessIdentifier pid)
548 (messageToPayload msg)
560 (messageToPayload msg)
563+ncEffectReconnect :: Identifier -> Identifier -> NC ()
564+ncEffectReconnect from to = do
566+ liftIO $ reconnect node from to
550--------------------------------------------------------------------------------
568--------------------------------------------------------------------------------
551-- Auxiliary --
569-- Auxiliary --
552--------------------------------------------------------------------------------
570--------------------------------------------------------------------------------
@@ -592,6 +610,7 @@ destNid (Spawn _ _) = Nothing
592destNid (Register _ _) = Nothing
610destNid (Register _ _) = Nothing
593destNid (WhereIs _) = Nothing
611destNid (WhereIs _) = Nothing
594destNid (NamedSend _ _) = Nothing
612destNid (NamedSend _ _) = Nothing
613+destNid (Reconnect _) = Nothing
595-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
614-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
596-- then when a local process dies the monitoring/linking machinery will take
615-- then when a local process dies the monitoring/linking machinery will take
597-- care of notifying remote nodes
616-- care of notifying remote nodes