[erlang-questions] gen behaviors and global groups
Gleb Peregud
gleber.p@REDACTED
Thu Aug 28 14:20:58 CEST 2008
2008/8/28 Serge Aleynikov <saleyn@REDACTED>:
> 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
> erlang-questions@REDACTED
> 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