@@ -24,6 +24,7 @@ import Data.Map (Map)
24import qualified Data.Map as Map
24import qualified Data.Map as Map
27 , partitionWithKey
28 , partitionWithKey
29 , filterWithKey
30 , filterWithKey
@@ -31,7 +32,7 @@ import qualified Data.Map as Map
31import Data.Set (Set)
32import Data.Set (Set)
32import qualified Data.Set as Set (empty, insert, delete, member)
33import qualified Data.Set as Set (empty, insert, delete, member)
33import Data.Foldable (forM_)
34import Data.Foldable (forM_)
34−import Data.Maybe (isJust, isNothing)
35+import Data.Maybe (isJust, isNothing, catMaybes)
35import Data.Typeable (Typeable)
36import Data.Typeable (Typeable)
36import Control.Category ((>>>))
37import Control.Category ((>>>))
37import Control.Applicative ((<$>))
38import Control.Applicative ((<$>))
@@ -438,8 +439,8 @@ data NCState = NCState
438 _links :: !(Map Identifier (Set ProcessId))
439 _links :: !(Map Identifier (Set ProcessId))
439 -- Mapping from remote processes to monitoring local processes
440 -- Mapping from remote processes to monitoring local processes
440 , _monitors :: !(Map Identifier (Set (ProcessId, MonitorRef)))
441 , _monitors :: !(Map Identifier (Set (ProcessId, MonitorRef)))
441− -- Process registry
442+ -- Process registry: names and where they live, mapped to the PIDs
442− , _registry :: !(Map String ProcessId)
443+ , _registry :: !(Map (String,NodeId) ProcessId)
445newtype NC a = NC { unNC :: StateT NCState (ReaderT LocalNode IO) a }
446newtype NC a = NC { unNC :: StateT NCState (ReaderT LocalNode IO) a }
@@ -486,8 +487,8 @@ nodeController = do
486 ncEffectDied ident reason
487 ncEffectDied ident reason
487 NCMsg (ProcessIdentifier from) (Spawn proc ref) ->
488 NCMsg (ProcessIdentifier from) (Spawn proc ref) ->
488 ncEffectSpawn from proc ref
489 ncEffectSpawn from proc ref
489− NCMsg (ProcessIdentifier from) (Register label pid) ->
490+ NCMsg (ProcessIdentifier from) (Register label pid force) ->
490− ncEffectRegister from label pid
491+ ncEffectRegister from label pid force
491 NCMsg (ProcessIdentifier from) (WhereIs label) ->
492 NCMsg (ProcessIdentifier from) (WhereIs label) ->
492 ncEffectWhereIs from label
493 ncEffectWhereIs from label
493 NCMsg from (NamedSend label msg') ->
494 NCMsg from (NamedSend label msg') ->
@@ -555,6 +556,8 @@ ncEffectDied ident reason = do
555 (affectedLinks, unaffectedLinks) <- gets (splitNotif ident . (^. links))
556 (affectedLinks, unaffectedLinks) <- gets (splitNotif ident . (^. links))
556 (affectedMons, unaffectedMons) <- gets (splitNotif ident . (^. monitors))
557 (affectedMons, unaffectedMons) <- gets (splitNotif ident . (^. monitors))
559+-- _registry :: !(Map (String,NodeId) ProcessId)
558 let localOnly = case ident of NodeIdentifier _ -> True ; _ -> False
561 let localOnly = case ident of NodeIdentifier _ -> True ; _ -> False
560 forM_ (Map.toList affectedLinks) $ \(them, uss) ->
563 forM_ (Map.toList affectedLinks) $ \(them, uss) ->
@@ -565,10 +568,27 @@ ncEffectDied ident reason = do
565 forM_ (Map.toList affectedMons) $ \(them, refs) ->
568 forM_ (Map.toList affectedMons) $ \(them, refs) ->
566 forM_ refs $ \(us, ref) ->
569 forM_ refs $ \(us, ref) ->
567 when (localOnly <= isLocal node (ProcessIdentifier us)) $
570 when (localOnly <= isLocal node (ProcessIdentifier us)) $
568− notifyDied us them reason (Just ref)
571+ notifyDied us them reason (Just ref)
570 modify' $ (links ^= unaffectedLinks) . (monitors ^= unaffectedMons)
573 modify' $ (links ^= unaffectedLinks) . (monitors ^= unaffectedMons)
575+ remaining <- fmap Map.toList (gets (^. registry)) >>= mapM ( \whl@((_,nid),pid) ->
576+ case ident `impliesDeathOf` ProcessIdentifier pid ||
577+ ident `impliesDeathOf` NodeIdentifier nid of
579+ do when (not $ isLocal node (NodeIdentifier nid)) $
580+ liftIO $ sendBinary node
581+ (NodeIdentifier $ localNodeId node)
582+ (NodeIdentifier $ nid)
583+ WithImplicitReconnect
585+ { ctrlMsgSender = NodeIdentifier (localNodeId node)
586+ , ctrlMsgSignal = Died ident reason
589+ False -> return $ Just whl)
590+ modify' $ registry ^= Map.fromList (catMaybes remaining)
572-- [Unified: Table 13]
592-- [Unified: Table 13]
573ncEffectSpawn :: ProcessId -> Closure (Process ()) -> SpawnRef -> NC ()
593ncEffectSpawn :: ProcessId -> Closure (Process ()) -> SpawnRef -> NC ()
574ncEffectSpawn pid cProc ref = do
594ncEffectSpawn pid cProc ref = do
@@ -589,18 +609,33 @@ ncEffectSpawn pid cProc ref = do
589-- Unified semantics does not explicitly describe how to implement 'register',
609-- Unified semantics does not explicitly describe how to implement 'register',
590-- but mentions it's "very similar to nsend" (Table 14)
610-- but mentions it's "very similar to nsend" (Table 14)
591-- We send a response indicated if the operation is invalid
611-- We send a response indicated if the operation is invalid
592−ncEffectRegister :: ProcessId -> String -> Maybe ProcessId -> NC ()
612+ncEffectRegister :: ProcessId -> String -> Maybe ProcessId -> Bool -> NC ()
593−ncEffectRegister from label mPid = do
613+ncEffectRegister from label mPid reregistration = do
594 node <- ask
614 node <- ask
595− currentVal <- gets (^. registryFor label)
615+ currentVal <- gets (^. registryFor (label, localNodeId node))
596− let isOk =
616+ isOk <-
597 case mPid of
617 case mPid of
598 Nothing -> -- unregister request
618 Nothing -> -- unregister request
599− isJust currentVal
619+ return $ isJust currentVal
600− Just _ -> -- register request
620+ Just thepid -> -- register request
621+ do isvalidlocal <- isValidLocalIdentifier (ProcessIdentifier thepid)
601− isNothing currentVal
622+ return $ (isNothing currentVal /= reregistration) &&
623+ (not (isLocal node (ProcessIdentifier thepid) ) || isvalidlocal )
624+ if isLocal node (ProcessIdentifier from)
602− when (isOk) $
625+ then when (isOk) $
626+ do modify' $ registryFor (label, localNodeId node) ^= mPid
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
635+ { ctrlMsgSender = ProcessIdentifier from
636+ , ctrlMsgSignal = Register label mPid reregistration
603− modify' $ registryFor label ^= mPid
638+ else modify' $ registryFor (label,processNodeId from) ^= mPid
604 liftIO $ sendMessage node
639 liftIO $ sendMessage node
605 (NodeIdentifier (localNodeId node))
640 (NodeIdentifier (localNodeId node))
606 (ProcessIdentifier from)
641 (ProcessIdentifier from)
@@ -611,7 +646,7 @@ ncEffectRegister from label mPid = do
611ncEffectWhereIs :: ProcessId -> String -> NC ()
646ncEffectWhereIs :: ProcessId -> String -> NC ()
612ncEffectWhereIs from label = do
647ncEffectWhereIs from label = do
613 node <- ask
648 node <- ask
614− mPid <- gets (^. registryFor label)
649+ mPid <- gets (^. registryFor (label, localNodeId node))
615 liftIO $ sendMessage node
650 liftIO $ sendMessage node
616 (NodeIdentifier (localNodeId node))
651 (NodeIdentifier (localNodeId node))
617 (ProcessIdentifier from)
652 (ProcessIdentifier from)
@@ -621,9 +656,9 @@ ncEffectWhereIs from label = do
621-- [Unified: Table 14]
656-- [Unified: Table 14]
622ncEffectNamedSend :: Identifier -> String -> Message -> NC ()
657ncEffectNamedSend :: Identifier -> String -> Message -> NC ()
623ncEffectNamedSend from label msg = do
658ncEffectNamedSend from label msg = do
624− mPid <- gets (^. registryFor label)
660+ mPid <- gets (^. registryFor (label, localNodeId node))
625 -- If mPid is Nothing, we just ignore the named send (as per Table 14)
661 -- If mPid is Nothing, we just ignore the named send (as per Table 14)
627 forM_ mPid $ \pid ->
662 forM_ mPid $ \pid ->
628 liftIO $ sendPayload node
663 liftIO $ sendPayload node
@@ -673,7 +708,7 @@ destNid (Unlink ident) = Just $ nodeOf ident
673destNid (Monitor ref) = Just $ nodeOf (monitorRefIdent ref)
708destNid (Monitor ref) = Just $ nodeOf (monitorRefIdent ref)
674destNid (Unmonitor ref) = Just $ nodeOf (monitorRefIdent ref)
709destNid (Unmonitor ref) = Just $ nodeOf (monitorRefIdent ref)
675destNid (Spawn _ _) = Nothing
710destNid (Spawn _ _) = Nothing
676−destNid (Register _ _) = Nothing
711+destNid (Register _ _ _)= Nothing
677destNid (WhereIs _) = Nothing
712destNid (WhereIs _) = Nothing
678destNid (NamedSend _ _) = Nothing
713destNid (NamedSend _ _) = Nothing
679-- We don't need to forward 'Died' signals; if monitoring/linking is setup,
714-- 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 })
745monitors :: Accessor NCState (Map Identifier (Set (ProcessId, MonitorRef)))
780monitors :: Accessor NCState (Map Identifier (Set (ProcessId, MonitorRef)))
746monitors = accessor _monitors (\ms st -> st { _monitors = ms })
781monitors = accessor _monitors (\ms st -> st { _monitors = ms })
748−registry :: Accessor NCState (Map String ProcessId)
783+registry :: Accessor NCState (Map (String,NodeId) ProcessId)
749registry = accessor _registry (\ry st -> st { _registry = ry })
784registry = accessor _registry (\ry st -> st { _registry = ry })
751linksFor :: Identifier -> Accessor NCState (Set ProcessId)
786linksFor :: Identifier -> Accessor NCState (Set ProcessId)
@@ -754,7 +789,7 @@ linksFor ident = links >>> DAC.mapDefault Set.empty ident
754monitorsFor :: Identifier -> Accessor NCState (Set (ProcessId, MonitorRef))
789monitorsFor :: Identifier -> Accessor NCState (Set (ProcessId, MonitorRef))
755monitorsFor ident = monitors >>> DAC.mapDefault Set.empty ident
790monitorsFor ident = monitors >>> DAC.mapDefault Set.empty ident
757−registryFor :: String -> Accessor NCState (Maybe ProcessId)
792+registryFor :: (String, NodeId) -> Accessor NCState (Maybe ProcessId)
758registryFor ident = registry >>> DAC.mapMaybe ident
793registryFor ident = registry >>> DAC.mapMaybe ident
760-- | @splitNotif ident@ splits a notifications map into those
795-- | @splitNotif ident@ splits a notifications map into those