@@ -24,14 +24,15 @@ import Data.Map (Map)
2424import qualified Data.Map as Map
2525 ( empty
2626 , toList
27+ , fromList
2728 , partitionWithKey
2829 , elems
2930 , filterWithKey
3031 )
3132import Data.Set (Set )
3233import qualified Data.Set as Set (empty , insert , delete , member )
3334import Data.Foldable (forM_ )
34- import Data.Maybe (isJust , isNothing )
35+ import Data.Maybe (isJust , isNothing , catMaybes )
3536import Data.Typeable (Typeable )
3637import Control.Category ((>>>) )
3738import Control.Applicative ((<$>) )
@@ -438,8 +439,8 @@ data NCState = NCState
438439 _links :: ! (Map Identifier (Set ProcessId ))
439440 -- Mapping from remote processes to monitoring local processes
440441 , _monitors :: ! (Map Identifier (Set (ProcessId , MonitorRef )))
441- -- Process registry
442- , _registry :: ! (Map String ProcessId )
442+ -- Process registry: names and where they live, mapped to the PIDs
443+ , _registry :: ! (Map ( String , NodeId ) ProcessId )
443444 }
444445
445446newtype NC a = NC { unNC :: StateT NCState (ReaderT LocalNode IO ) a }
@@ -486,8 +487,8 @@ nodeController = do
486487 ncEffectDied ident reason
487488 NCMsg (ProcessIdentifier from) (Spawn proc ref) ->
488489 ncEffectSpawn from proc ref
489- NCMsg (ProcessIdentifier from) (Register label pid) ->
490- ncEffectRegister from label pid
490+ NCMsg (ProcessIdentifier from) (Register label pid force ) ->
491+ ncEffectRegister from label pid force
491492 NCMsg (ProcessIdentifier from) (WhereIs label) ->
492493 ncEffectWhereIs from label
493494 NCMsg from (NamedSend label msg') ->
@@ -555,6 +556,8 @@ ncEffectDied ident reason = do
555556 (affectedLinks, unaffectedLinks) <- gets (splitNotif ident . (^. links))
556557 (affectedMons, unaffectedMons) <- gets (splitNotif ident . (^. monitors))
557558
559+ -- _registry :: !(Map (String,NodeId) ProcessId)
560+
558561 let localOnly = case ident of NodeIdentifier _ -> True ; _ -> False
559562
560563 forM_ (Map. toList affectedLinks) $ \ (them, uss) ->
@@ -565,10 +568,27 @@ ncEffectDied ident reason = do
565568 forM_ (Map. toList affectedMons) $ \ (them, refs) ->
566569 forM_ refs $ \ (us, ref) ->
567570 when (localOnly <= isLocal node (ProcessIdentifier us)) $
568- notifyDied us them reason (Just ref)
571+ notifyDied us them reason (Just ref)
569572
570573 modify' $ (links ^= unaffectedLinks) . (monitors ^= unaffectedMons)
571574
575+ remaining <- fmap Map. toList (gets (^. registry)) >>= mapM ( \ whl@ ((_,nid),pid) ->
576+ case ident `impliesDeathOf` ProcessIdentifier pid ||
577+ ident `impliesDeathOf` NodeIdentifier nid of
578+ True ->
579+ do when (not $ isLocal node (NodeIdentifier nid)) $
580+ liftIO $ sendBinary node
581+ (NodeIdentifier $ localNodeId node)
582+ (NodeIdentifier $ nid)
583+ WithImplicitReconnect
584+ NCMsg
585+ { ctrlMsgSender = NodeIdentifier (localNodeId node)
586+ , ctrlMsgSignal = Died ident reason
587+ }
588+ return Nothing
589+ False -> return $ Just whl)
590+ modify' $ registry ^= Map. fromList (catMaybes remaining)
591+
572592-- [Unified: Table 13]
573593ncEffectSpawn :: ProcessId -> Closure (Process () ) -> SpawnRef -> NC ()
574594ncEffectSpawn pid cProc ref = do
@@ -589,18 +609,33 @@ ncEffectSpawn pid cProc ref = do
589609-- Unified semantics does not explicitly describe how to implement 'register',
590610-- but mentions it's "very similar to nsend" (Table 14)
591611-- We send a response indicated if the operation is invalid
592- ncEffectRegister :: ProcessId -> String -> Maybe ProcessId -> NC ()
593- ncEffectRegister from label mPid = do
612+ ncEffectRegister :: ProcessId -> String -> Maybe ProcessId -> Bool -> NC ()
613+ ncEffectRegister from label mPid reregistration = do
594614 node <- ask
595- currentVal <- gets (^. registryFor label)
596- let isOk =
615+ currentVal <- gets (^. registryFor ( label, localNodeId node) )
616+ isOk <-
597617 case mPid of
598618 Nothing -> -- unregister request
599- isJust currentVal
600- Just _ -> -- register request
601- isNothing currentVal
602- when (isOk) $
603- modify' $ registryFor label ^= mPid
619+ return $ isJust currentVal
620+ Just thepid -> -- register request
621+ do isvalidlocal <- isValidLocalIdentifier (ProcessIdentifier thepid)
622+ return $ (isNothing currentVal /= reregistration) &&
623+ (not (isLocal node (ProcessIdentifier thepid) ) || isvalidlocal )
624+ if isLocal node (ProcessIdentifier from)
625+ then when (isOk) $
626+ do modify' $ registryFor (label, localNodeId node) ^= mPid
627+ let namedPid =
628+ head $ catMaybes [mPid, currentVal]
629+ when (not $ isLocal node (ProcessIdentifier namedPid)) $
630+ liftIO $ sendBinary node
631+ (ProcessIdentifier from)
632+ (NodeIdentifier (processNodeId namedPid))
633+ WithImplicitReconnect
634+ NCMsg
635+ { ctrlMsgSender = ProcessIdentifier from
636+ , ctrlMsgSignal = Register label mPid reregistration
637+ }
638+ else modify' $ registryFor (label,processNodeId from) ^= mPid
604639 liftIO $ sendMessage node
605640 (NodeIdentifier (localNodeId node))
606641 (ProcessIdentifier from)
@@ -611,7 +646,7 @@ ncEffectRegister from label mPid = do
611646ncEffectWhereIs :: ProcessId -> String -> NC ()
612647ncEffectWhereIs from label = do
613648 node <- ask
614- mPid <- gets (^. registryFor label)
649+ mPid <- gets (^. registryFor ( label, localNodeId node) )
615650 liftIO $ sendMessage node
616651 (NodeIdentifier (localNodeId node))
617652 (ProcessIdentifier from)
@@ -621,9 +656,9 @@ ncEffectWhereIs from label = do
621656-- [Unified: Table 14]
622657ncEffectNamedSend :: Identifier -> String -> Message -> NC ()
623658ncEffectNamedSend from label msg = do
624- mPid <- gets (^. registryFor label)
659+ node <- ask
660+ mPid <- gets (^. registryFor (label, localNodeId node))
625661 -- If mPid is Nothing, we just ignore the named send (as per Table 14)
626- node <- ask
627662 forM_ mPid $ \ pid ->
628663 liftIO $ sendPayload node
629664 from
@@ -673,7 +708,7 @@ destNid (Unlink ident) = Just $ nodeOf ident
673708destNid (Monitor ref) = Just $ nodeOf (monitorRefIdent ref)
674709destNid (Unmonitor ref) = Just $ nodeOf (monitorRefIdent ref)
675710destNid (Spawn _ _) = Nothing
676- destNid (Register _ _) = Nothing
711+ destNid (Register _ _ _) = Nothing
677712destNid (WhereIs _) = Nothing
678713destNid (NamedSend _ _) = Nothing
679714-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
@@ -745,7 +780,7 @@ links = accessor _links (\ls st -> st { _links = ls })
745780monitors :: Accessor NCState (Map Identifier (Set (ProcessId , MonitorRef )))
746781monitors = accessor _monitors (\ ms st -> st { _monitors = ms })
747782
748- registry :: Accessor NCState (Map String ProcessId )
783+ registry :: Accessor NCState (Map ( String , NodeId ) ProcessId )
749784registry = accessor _registry (\ ry st -> st { _registry = ry })
750785
751786linksFor :: Identifier -> Accessor NCState (Set ProcessId )
@@ -754,7 +789,7 @@ linksFor ident = links >>> DAC.mapDefault Set.empty ident
754789monitorsFor :: Identifier -> Accessor NCState (Set (ProcessId , MonitorRef ))
755790monitorsFor ident = monitors >>> DAC. mapDefault Set. empty ident
756791
757- registryFor :: String -> Accessor NCState (Maybe ProcessId )
792+ registryFor :: ( String , NodeId ) -> Accessor NCState (Maybe ProcessId )
758793registryFor ident = registry >>> DAC. mapMaybe ident
759794
760795-- | @splitNotif ident@ splits a notifications map into those
0 commit comments