@@ -14,8 +14,8 @@ import Prelude hiding (catch)
1414#endif
1515
1616import System.IO (fixIO, hPutStrLn, stderr)
17−import qualified Data.ByteString.Lazy as BSL (fromChunks)
18−import Data.Binary (decode)
17+import qualified Data.NotByteString.Lazy as BSL (fromChunks)
18+import Data.NotByteString.Lazy.Binary (decode)
1919import Data.Map (Map)
2020import qualified Data.Map as Map
2121 ( empty
@@ -25,10 +25,10 @@ import qualified Data.Map as Map
2525 , toList
2626 , partitionWithKey
2727 , filterWithKey
28+ , elems
2829 )
29−import qualified Data.List as List (delete, (\\))
3030import 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)
3232import Data.Foldable (forM_)
3333import Data.Maybe (isJust)
3434import Data.Typeable (Typeable)
@@ -65,6 +65,8 @@ import qualified Network.Transport as NT
6565 , address
6666 , closeEndPoint
6767 , ConnectionId
68+ , Connection
69+ , close
6870 )
6971import Data.Accessor (Accessor, accessor, (^.), (^=), (^:))
7072import qualified Data.Accessor.Container as DAC (mapDefault, mapMaybe)
@@ -89,6 +91,7 @@ import Control.Distributed.Process.Internal.Types
8991 , localPidCounter
9092 , localPidUnique
9193 , localProcessWithId
94+ , localConnections
9295 , MonitorRef(..)
9396 , ProcessMonitorNotification(..)
9497 , NodeMonitorNotification(..)
@@ -119,6 +122,7 @@ import Control.Distributed.Process.Internal.Node
119122 ( sendBinary
120123 , sendMessage
121124 , sendPayload
125+ , reconnect
122126 )
123127import Control.Distributed.Process.Internal.Primitives (expect, register, finally)
124128import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
@@ -212,8 +216,13 @@ forkProcess node proc = modifyMVar (localState node) $ \st -> do
212216 (runLocalProcess lproc proc >> return DiedNormal)
213217 (return . DiedException . (show :: SomeException -> String))
214218 -- [Unified: Table 4, rules termination and exiting]
215− modifyMVar_ (localState node) $
216− return . (localProcessWithId lpid ^= Nothing)
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)
223+ return $ (localProcessWithId lpid ^= Nothing)
224+ . (localConnections ^= unaffected)
225+ $ st
217226 writeChan (localCtrlChan node) NCMsg
218227 { ctrlMsgSender = ProcessIdentifier pid
219228 , ctrlMsgSignal = Died (ProcessIdentifier pid) reason
@@ -237,25 +246,25 @@ forkProcess node proc = modifyMVar (localState node) $ \st -> do
237246 )
238247
239248handleIncomingMessages :: LocalNode -> IO ()
240−handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
249+handleIncomingMessages node = go Set.empty Map.empty Map.empty Set.empty
241250 where
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
243252 -> Map NT.ConnectionId LocalProcess -- ^ Connections to local processes
244253 -> Map NT.ConnectionId TypedChannel -- ^ Connections to typed channels
245254 -> Set NT.ConnectionId -- ^ Connections to our controller
246255 -> IO ()
247− go uninitConns procs chans ctrls = do
256+ go !uninitConns !procs !chans !ctrls = do
248257 event <- NT.receive endpoint
249258 case event of
250259 NT.ConnectionOpened cid _rel _theirAddr ->
251260 -- TODO: Check if _rel is ReliableOrdered, and if not, treat as
252261 -- (**) below.
253− go (cid : uninitConns) procs chans ctrls
262+ go (Set.insert cid uninitConns) procs chans ctrls
254263 NT.Received cid payload ->
255264 case ( Map.lookup cid procs
256265 , Map.lookup cid chans
257266 , cid `Set.member` ctrls
258− , cid `elem` uninitConns
267+ , cid `Set.member` uninitConns
259268 ) of
260269 (Just proc, _, _, _) -> do
261270 let msg = payloadToMessage payload
@@ -275,7 +284,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
275284 mProc <- withMVar state $ return . (^. localProcessWithId lpid)
276285 case mProc of
277286 Just proc ->
278− go (List.delete cid uninitConns)
287+ go (Set.delete cid uninitConns)
279288 (Map.insert cid proc procs)
280289 chans
281290 ctrls
@@ -287,7 +296,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
287296 -- remote node as having died, and we should close
288297 -- incoming connections (this requires a Transport layer
289298 -- extension). (**)
290− go (List.delete cid uninitConns) procs chans ctrls
299+ go (Set.delete cid uninitConns) procs chans ctrls
291300 SendPortIdentifier chId -> do
292301 let lcid = sendPortLocalId chId
293302 lpid = processLocalId (sendPortProcessId chId)
@@ -297,20 +306,20 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
297306 mChannel <- withMVar (processState proc) $ return . (^. typedChannelWithId lcid)
298307 case mChannel of
299308 Just channel ->
300− go (List.delete cid uninitConns)
309+ go (Set.delete cid uninitConns)
301310 procs
302311 (Map.insert cid channel chans)
303312 ctrls
304313 Nothing ->
305314 -- Unknown typed channel
306315 -- TODO (**) above
307− go (List.delete cid uninitConns) procs chans ctrls
316+ go (Set.delete cid uninitConns) procs chans ctrls
308317 Nothing ->
309318 -- Unknown process
310319 -- TODO (**) above
311− go (List.delete cid uninitConns) procs chans ctrls
320+ go (Set.delete cid uninitConns) procs chans ctrls
312321 NodeIdentifier _ ->
313− go (List.delete cid uninitConns)
322+ go (Set.delete cid uninitConns)
314323 procs
315324 chans
316325 (Set.insert cid ctrls)
@@ -319,7 +328,7 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
319328 -- TODO (**) above
320329 go uninitConns procs chans ctrls
321330 NT.ConnectionClosed cid ->
322− go (List.delete cid uninitConns)
331+ go (Set.delete cid uninitConns)
323332 (Map.delete cid procs)
324333 (Map.delete cid chans)
325334 (Set.delete cid ctrls)
@@ -330,10 +339,11 @@ handleIncomingMessages node = go [] Map.empty Map.empty Set.empty
330339 { ctrlMsgSender = nid
331340 , ctrlMsgSignal = Died nid DiedDisconnect
332341 }
333− go (uninitConns List.\\ cids)
334− (Map.filterWithKey (\k _ -> k `notElem` cids) procs)
335− (Map.filterWithKey (\k _ -> k `notElem` cids) chans)
336− (ctrls Set.\\ Set.fromList cids)
342+ let notRemoved k = k `notElem` cids
343+ go (Set.filter notRemoved uninitConns)
344+ (Map.filterWithKey (const . notRemoved) procs)
345+ (Map.filterWithKey (const . notRemoved) chans)
346+ (Set.filter notRemoved ctrls)
337347 NT.ErrorEvent (NT.TransportError (NT.EventConnectionLost Nothing _) _) ->
338348 -- TODO: We should treat an asymetrical connection loss (incoming
339349 -- connection broken, but outgoing connection still potentially ok)
@@ -424,6 +434,8 @@ nodeController = do
424434 ncEffectWhereIs from label
425435 NCMsg from (NamedSend label msg') ->
426436 ncEffectNamedSend from label msg'
437+ NCMsg from (Reconnect to) ->
438+ ncEffectReconnect from to
427439 unexpected ->
428440 error $ "nodeController: unexpected message " ++ show unexpected
429441
@@ -547,6 +559,12 @@ ncEffectNamedSend from label msg = do
547559 (ProcessIdentifier pid)
548560 (messageToPayload msg)
549561
562+-- Reconnecting
563+ncEffectReconnect :: Identifier -> Identifier -> NC ()
564+ncEffectReconnect from to = do
565+ node <- ask
566+ liftIO $ reconnect node from to
567+
550568--------------------------------------------------------------------------------
551569-- Auxiliary --
552570--------------------------------------------------------------------------------
@@ -592,6 +610,7 @@ destNid (Spawn _ _) = Nothing
592610destNid (Register _ _) = Nothing
593611destNid (WhereIs _) = Nothing
594612destNid (NamedSend _ _) = Nothing
613+destNid (Reconnect _) = Nothing
595614-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
596615-- then when a local process dies the monitoring/linking machinery will take
597616-- care of notifying remote nodes