@@ -24,6 +24,7 @@ import Data.Map (Map)
2424import qualified Data.Map as Map
2525 ( empty
2626 , toList
27+ , fromList
2728 , partitionWithKey
2829 , elems
2930 , filterWithKey
@@ -31,7 +32,7 @@ import qualified Data.Map as Map
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