Browse Source

Demonitor a local process in unregister_and_register/2,3.

Roberto Ostinelli 5 years ago
parent
commit
1e45c6f653
3 changed files with 41 additions and 23 deletions
  1. 2 2
      README.md
  2. 16 10
      src/syn_registry.erl
  3. 23 11
      test/syn_registry_SUITE.erl

+ 2 - 2
README.md

@@ -180,13 +180,13 @@ Types:
 >
 >Note that the previously registered process will not be killed and will be demonitored, so that the `on_process_exit/4` callback will _not_ be called (even if implemented) when the process dies.
 
-To retrieve the total count of registered processes running in the cluster:
+To retrieve the total count of registered names:
 
 ```erlang
 syn:registry_count() -> non_neg_integer().
 ```
 
-To retrieve the total count of registered processes running on a specific node:
+To retrieve the total count of registered names of processes running on a specific node:
 
 ```erlang
 syn:registry_count(Node) -> non_neg_integer().

+ 16 - 10
src/syn_registry.erl

@@ -223,10 +223,11 @@ handle_call({register_on_node, Name, Pid, Meta, Force}, _From, State) ->
                     %% return
                     {reply, ok, State};
 
-                {Name, _, _, _} ->
+                {Name, TablePid, _, _} ->
                     %% same name, different pid
                     case Force of
                         true ->
+                            demonitor_if_local(TablePid),
                             %% force register
                             {ok, Time} = register_on_node(Name, Pid, Meta),
                             %% multicast
@@ -277,15 +278,7 @@ handle_cast({sync_register, Name, RemotePid, RemoteMeta, RemoteTime, Force}, Sta
             add_to_local_table(Name, RemotePid, RemoteMeta, RemoteTime, undefined);
 
         {Name, TablePid, _, _} when Force =:= true ->
-            case node(TablePid) =:= node() of
-                true ->
-                    %% demonitor
-                    MonitorRef = syn_registry:find_monitor_for_pid(TablePid),
-                    catch erlang:demonitor(MonitorRef, [flush]);
-
-                _ ->
-                    ok
-            end,
+            demonitor_if_local(TablePid),
             %% overwrite
             add_to_local_table(Name, RemotePid, RemoteMeta, RemoteTime, undefined);
 
@@ -818,3 +811,16 @@ set_timer_for_anti_entropy(#state{
     IntervalMs = round(AntiEntropyIntervalMs + rand:uniform() * AntiEntropyIntervalMaxDeviationMs),
     {ok, _} = timer:send_after(IntervalMs, self(), sync_anti_entropy),
     ok.
+
+-spec demonitor_if_local(pid()) -> ok.
+demonitor_if_local(Pid) ->
+    case node(Pid) =:= node() of
+        true ->
+            %% demonitor
+            MonitorRef = syn_registry:find_monitor_for_pid(Pid),
+            catch erlang:demonitor(MonitorRef, [flush]),
+            ok;
+
+        _ ->
+            ok
+    end.

+ 23 - 11
test/syn_registry_SUITE.erl

@@ -679,22 +679,34 @@ two_nodes_unregister_and_register(Config) ->
     timer:sleep(100),
     %% start processes
     PidLocal = syn_test_suite_helper:start_process(),
+    PidLocal2 = syn_test_suite_helper:start_process(),
     PidRemote = syn_test_suite_helper:start_process(SlaveNode),
     %% register
-    TestPid = self(),
-    ok = rpc:call(SlaveNode, syn, register, [Name, PidRemote, {pid_remote, TestPid}]),
+    ok = rpc:call(SlaveNode, syn, register, [Name, PidRemote, SlaveNode]),
     timer:sleep(250),
-    {PidRemote, {pid_remote, TestPid}} = syn:whereis(Name, with_meta),
-    {PidRemote, {pid_remote, TestPid}} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
-    %% force
-    ok = syn:unregister_and_register(Name, PidLocal, {pid_local, TestPid}),
+    {PidRemote, SlaveNode} = syn:whereis(Name, with_meta),
+    {PidRemote, SlaveNode} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
+    %% un/register local over remote
+    Node = node(),
+    ok = syn:unregister_and_register(Name, PidLocal, Node),
     timer:sleep(1000),
-    {PidLocal, {pid_local, TestPid}} = syn:whereis(Name, with_meta),
-    {PidLocal, {pid_local, TestPid}} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
-    ok = rpc:call(SlaveNode, syn, unregister_and_register, [Name, PidRemote, {pid_remote, TestPid}]),
+    {PidLocal, Node} = syn:whereis(Name, with_meta),
+    {PidLocal, Node} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
+    ok = rpc:call(SlaveNode, syn, unregister_and_register, [Name, PidRemote, {SlaveNode, 2}]),
+    timer:sleep(1000),
+    {PidRemote, {SlaveNode, 2}} = syn:whereis(Name, with_meta),
+    {PidRemote, {SlaveNode, 2}} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
+    %% check that overwritten process is not monitored
+    {monitored_by, []} = erlang:process_info(PidLocal, monitored_by),
+    %% register local
+    ok = syn:unregister_and_register(Name, PidLocal, Node),
+    %% check a monitor exists
+    {monitored_by, [_MonitoringPid]} = erlang:process_info(PidLocal, monitored_by),
+    %% un/register local over local
+    ok = syn:unregister_and_register(Name, PidLocal2, {Node, 2}),
     timer:sleep(1000),
-    {PidRemote, {pid_remote, TestPid}} = syn:whereis(Name, with_meta),
-    {PidRemote, {pid_remote, TestPid}} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
+    {PidLocal2, {Node, 2}} = syn:whereis(Name, with_meta),
+    {PidLocal2, {Node, 2}} = rpc:call(SlaveNode, syn, whereis, [Name, with_meta]),
     %% check that overwritten process is not monitored
     {monitored_by, []} = erlang:process_info(PidLocal, monitored_by).