[erlang-questions] gen behaviors and global groups

Gleb Peregud <>
Thu Aug 28 14:20:58 CEST 2008


2008/8/28 Serge Aleynikov <>:
> Since I haven't seen any follow-up on this question, I'd like to rephrase
> it.  Is there any drawback in applying the attached patch that would allow
> all gen behaviors to specify registered names in given global groups?
>
> Serge
>
> Serge Aleynikov wrote:
>>
>> Little bugfix in my previous posting below:
>>
>> Serge Aleynikov wrote:
>>>
>>> Currently when using gen_* behaviors the way to reference a
>>> locally/globally registered server is by providing a server name in the
>>> form:
>>>
>>>        ServerName = {local,Name} | {global,GlobalName}
>>>
>>> When the cluster of nodes is partitioned into global groups, there
>>> doesn't seem to be a way to instruct a server to do a global name lookup in
>>> a specific global group.  Unless I am missing something, it looks like the
>>> gen behaviors should allow this types of server names:
>>>
>>>        ServerName = {local,Name} | {global,GlobalName} |
>>>                      {{group, Group}, GlobalName}
>>>
>>> Without this third option one would have to do something like this in
>>> order to call a server registered in group G:
>>>
>>
>> my_function({{group, Group}, Name}, Args) ->
>>     case global_group:whereis_name(Group, Name) of
>>     Pid when is_pid(Pid) ->
>>         my_function(Pid, Args);
>>     undefined ->
>>        {error, noproc}
>>     end;
>> my_function(Name, Args) ->
>>     gen_server:call(Name, {my_function, Args}).
>>
>>> Shouldn't gen.erl handle this sort of name lookups automatically?
>>>
>>> Serge
>
>
> --- lib/stdlib/src/gen.erl.orig      Tue Jun 10 19:16:04 2008 UTC
> +++ lib/stdlib/src/gen.erl      Thu Aug 28 11:42:18 2008 UTC
> @@ -36,12 +36,14 @@
>  %% start(GenMod, LinkP, Name, Mod, Args, Options)
>  %% start_link(Mod, Args, Options)
>  %% start_link(Name, Mod, Args, Options) where:
> -%%    Name = {local, atom()} | {global, atom()}
> +%%    Name = {local, atom()} | {global, atom()} |
> +%%           {global_group, atom()} | {global_group, Where, atom()}
>  %%    Mod  = atom(), callback module implementing the 'real' fsm
>  %%    Args = term(), init arguments (to Mod:init/1)
>  %%    Options = [{debug, [Flag]}]
>  %%      Flag = trace | log | {logfile, File} | statistics | debug
>  %%          (debug == log && statistics)
> +%%    Where = {node, node()} | {group, atom()}
>  %% Returns: {ok, Pid} |
>  %%          {error, {already_started, Pid}} |
>  %%          {error, Reason}
> @@ -140,19 +142,21 @@
>  call({global, _Name}=Process, Label, Request, Timeout)
>   when Timeout =:= infinity;
>        is_integer(Timeout), Timeout >= 0 ->
> -    case where(Process) of
> -       Pid when is_pid(Pid) ->
> -           Node = node(Pid),
> -           try do_call(Pid, Label, Request, Timeout)
> -           catch
> -               exit:{nodedown, Node} ->
> -                   %% A nodedown not yet detected by global,
> -                   %% pretend that it was.
> -                   exit(noproc)
> -           end;
> -       undefined ->
> -           exit(noproc)
> -    end;
> +    do_global_call(Process, Label, Request, Timeout);
> +
> +%% Global group by name
> +call({global_group, _Name}=Process, Label, Request, Timeout)
> +  when Timeout =:= infinity;
> +       is_integer(Timeout), Timeout >= 0 ->
> +    do_global_call(Process, Label, Request, Timeout);
> +
> +%% Call by name registered on the specified node or in the
> +%% specified global group
> +call({global_group, _Where, _Name}=Process, Label, Request, Timeout)
> +  when Timeout =:= infinity;
> +       is_integer(Timeout), Timeout >= 0 ->
> +    do_global_call(Process, Label, Request, Timeout);
> +
>  %% Local by name in disguise
>  call({Name, Node}, Label, Request, Timeout)
>   when Node =:= node(), Timeout =:= infinity;
> @@ -169,6 +173,21 @@
>            do_call(Process, Label, Request, Timeout)
>     end.
>
> +do_global_call(Process, Label, Request, Timeout) ->
> +    case where(Process) of
> +       Pid when is_pid(Pid) ->
> +           Node = node(Pid),
> +           try do_call(Pid, Label, Request, Timeout)
> +           catch
> +               exit:{nodedown, Node} ->
> +                   %% A nodedown not yet detected by global,
> +                   %% pretend that it was.
> +                   exit(noproc)
> +           end;
> +       undefined ->
> +           exit(noproc)
> +    end.
> +
>  do_call(Process, Label, Request, Timeout) ->
>     %% We trust the arguments to be correct, i.e
>     %% Process is either a local or remote pid,
> @@ -257,11 +276,15 @@
>  %%%-----------------------------------------------------------------
>  %%%  Misc. functions.
>  %%%-----------------------------------------------------------------
> +where({local, Name})               -> whereis(Name);
>  where({global, Name})    -> global:safe_whereis_name(Name);
> -where({local, Name})  -> whereis(Name).
> +where({global_group, Name})        -> global_group:whereis_name(Name);
> +where({global_group, Where, Name}) -> global_group:whereis_name(Where,
> Name).
>
> +name({local,  Name})               -> Name;
>  name({global, Name})    -> Name;
> -name({local, Name})     -> Name.
> +name({global_group, Name})         -> Name;
> +name({global_group, _Where, Name}) -> Name.
>
>  name_register({local, Name} = LN) ->
>     try register(Name, self()) of
> @@ -271,6 +294,13 @@
>            {false, where(LN)}
>     end;
>  name_register({global, Name} = GN) ->
> +    name_register_global(GN, Name);
> +name_register({global_group, Name} = GN) ->
> +    name_register_global(GN, Name);
> +name_register({global_group, _Where, Name} = GN) ->
> +    name_register_global(GN, Name).
> +
> +name_register_global(GN, Name) ->
>     case global:register_name(Name, self()) of
>        yes -> true;
>        no -> {false, where(GN)}
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://www.erlang.org/mailman/listinfo/erlang-questions
>

Hi,

It doesn't seem to take care about gen_server:enter_loop/2,3,4. From man:

Module, Options and ServerName have the same meanings as when calling
gen_server:start[_link]/3,4. However, if ServerName is specified, the
process must have been registered accordingly before this function is
called.

and

Failure: If the calling process was not started by a proc_lib start
function, or if it is not registered according to ServerName.

BR
-- 
Gleb Peregud
http://gleber.pl/

Every minute is to be grasped.
Time waits for nobody.
-- Inscription on a Zen Gong


More information about the erlang-questions mailing list