Add local:otp_name/1 and local:which_processes/{1,2}
diff --git a/doc/local.md b/doc/local.md
index ba8f4fa..7d3eaf8 100644
--- a/doc/local.md
+++ b/doc/local.md
@@ -42,6 +42,30 @@
+### <a name="type-otp_name">otp_name()</a> ###
+
+
+
+<pre><code>
+otp_name() = {local, Name::atom()} | {global, Name::term()} | {via, module(), Name::term()}
+</code></pre>
+
+
+
+
+
+### <a name="type-otp_ref">otp_ref()</a> ###
+
+
+
+<pre><code>
+otp_ref() = (Name::atom()) | {Name::atom(), node()} | {global, Name::term()} | {via, module(), Name::term()} | pid()
+</code></pre>
+
+
+
+
+
### <a name="type-process_name">process_name()</a> ###
@@ -56,7 +80,7 @@
## Function Index ##
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#name_server_child_spec-1">name_server_child_spec/1</a></td><td>Equivalent to <a href="#name_server_child_spec-3"><tt>name_server_child_spec(Name, Name, 5000)</tt></a>.</td></tr><tr><td valign="top"><a href="#name_server_child_spec-3">name_server_child_spec/3</a></td><td>Returns the child spec for a local name server that is used in embedded mode.</td></tr><tr><td valign="top"><a href="#register_name-2">register_name/2</a></td><td>Locally assocates the name <code>Name</code> with a pid <code>Pid</code>.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends the message <code>Msg</code> to the pid locally registered as <code>Name</code></td></tr><tr><td valign="top"><a href="#start_name_server-1">start_name_server/1</a></td><td>Starts a name server process.</td></tr><tr><td valign="top"><a href="#stop_name_server-1">stop_name_server/1</a></td><td>Stops the name server <code>ServerName</code></td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Removes the locally registered name <code>Name</code></td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Returns the pid with the locally registered name <code>Name</code></td></tr><tr><td valign="top"><a href="#which_name_servers-0">which_name_servers/0</a></td><td>Returns a list of running name server.</td></tr></table>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#name_server_child_spec-1">name_server_child_spec/1</a></td><td>Equivalent to <a href="#name_server_child_spec-3"><tt>name_server_child_spec(Name, Name, 5000)</tt></a>.</td></tr><tr><td valign="top"><a href="#name_server_child_spec-3">name_server_child_spec/3</a></td><td>Returns the child spec for a local name server that is used in embedded mode.</td></tr><tr><td valign="top"><a href="#otp_name-1">otp_name/1</a></td><td>Returns OTP compatible name.</td></tr><tr><td valign="top"><a href="#register_name-2">register_name/2</a></td><td>Locally assocates the name <code>Name</code> with a pid <code>Pid</code>.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends the message <code>Msg</code> to the pid locally registered as <code>Name</code></td></tr><tr><td valign="top"><a href="#start_name_server-1">start_name_server/1</a></td><td>Starts a name server process.</td></tr><tr><td valign="top"><a href="#stop_name_server-1">stop_name_server/1</a></td><td>Stops the name server <code>ServerName</code></td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Removes the locally registered name <code>Name</code></td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Returns the pid with the locally registered name <code>Name</code></td></tr><tr><td valign="top"><a href="#which_name_servers-0">which_name_servers/0</a></td><td>Returns a list of running name server.</td></tr><tr><td valign="top"><a href="#which_processes-1">which_processes/1</a></td><td>Returns a list of registered process.</td></tr><tr><td valign="top"><a href="#which_processes-2">which_processes/2</a></td><td>Returns a list of registered process that has a name which matches the pattern <code>Pattern</code></td></tr></table>
<a name="functions"></a>
@@ -91,7 +115,20 @@
Returns the child spec for a local name server that is used in embedded mode.
-To embed a local name server in your application, you can add the child spec `ChildSpec` to your supervision tree.
+To embed a local name server in your application, you can simply add `ChildSpec` to your supervision tree.
+<a name="otp_name-1"></a>
+
+### otp_name/1 ###
+
+
+<pre><code>
+otp_name(Name::<a href="#type-name">name()</a>) -> <a href="#type-otp_name">otp_name()</a>
+</code></pre>
+
+<br></br>
+
+
+Returns OTP compatible name
<a name="register_name-2"></a>
### register_name/2 ###
@@ -220,3 +257,29 @@
Returns a list of running name server
+<a name="which_processes-1"></a>
+
+### which_processes/1 ###
+
+
+<pre><code>
+which_processes(NameServer::<a href="#type-name_server_name">name_server_name()</a>) -> [{<a href="#type-process_name">process_name()</a>, pid()}]
+</code></pre>
+
+<br></br>
+
+
+Returns a list of registered process
+<a name="which_processes-2"></a>
+
+### which_processes/2 ###
+
+
+<pre><code>
+which_processes(NameServer::<a href="#type-name_server_name">name_server_name()</a>, Pattern::<a href="ets.md#type-match_pattern">ets:match_pattern()</a>) -> [{<a href="#type-process_name">process_name()</a>, pid()}]
+</code></pre>
+
+<br></br>
+
+
+Returns a list of registered process that has a name which matches the pattern `Pattern`
diff --git a/rebar.config.script b/rebar.config.script
new file mode 100644
index 0000000..fa7d969
--- /dev/null
+++ b/rebar.config.script
@@ -0,0 +1,8 @@
+%% vim: set ft=erlang : -*- erlang -*-
+
+case erlang:system_info(version) < "6" of
+ false -> CONFIG;
+ true ->
+ ErlOpts = proplists:get_value(erl_opts, CONFIG, []) ++ [{d, 'LOCAL_BEFORE_OTP17'}],
+ proplists:delete(erl_opts, CONFIG) ++ [{erl_opts, ErlOpts}]
+end.
diff --git a/src/local.erl b/src/local.erl
index 5eb128e..9ec5975 100644
--- a/src/local.erl
+++ b/src/local.erl
@@ -14,12 +14,17 @@
-export([unregister_name/1]).
-export([whereis_name/1]).
-export([send/2]).
+-export([which_processes/1, which_processes/2]).
-export([name_server_child_spec/1, name_server_child_spec/3]).
+-export([otp_name/1]).
+
-export_type([name/0]).
-export_type([name_server_name/0]).
-export_type([process_name/0]).
+-export_type([otp_name/0]).
+-export_type([otp_ref/0]).
%%----------------------------------------------------------------------------------------------------------------------
%% Macros & Types
@@ -28,6 +33,16 @@
-type name_server_name() :: atom().
-type process_name() :: term().
+-type otp_name() :: {local, Name :: atom()}
+ | {global, Name :: term()}
+ | {via, module(), Name :: term()}.
+
+-type otp_ref() :: (Name :: atom())
+ | {Name :: atom(), node()}
+ | {global, Name :: term()}
+ | {via, module(), Name :: term()}
+ | pid().
+
%%----------------------------------------------------------------------------------------------------------------------
%% Exported Functions
%%----------------------------------------------------------------------------------------------------------------------
@@ -97,6 +112,16 @@
Pid -> _ = Pid ! Msg, Pid
end.
+%% @doc Returns a list of registered process
+-spec which_processes(name_server_name()) -> [{process_name(), pid()}].
+which_processes(NameServer) ->
+ local_name_server:which_processes(NameServer).
+
+%% @doc Returns a list of registered process that has a name which matches the pattern `Pattern'
+-spec which_processes(name_server_name(), ets:match_pattern()) -> [{process_name(), pid()}].
+which_processes(NameServer, ProcNamePattern) ->
+ local_name_server:which_processes(NameServer, ProcNamePattern).
+
%% @equiv name_server_child_spec(Name, Name, 5000)
-spec name_server_child_spec(name_server_name()) -> supervisor:child_spec().
name_server_child_spec(Name) ->
@@ -114,3 +139,13 @@
{ChildId, {local_name_server, start_link, [ServerName]}, permanent, Shutdown, worker, [local_name_server]};
name_server_child_spec(ChildId, ServerName, Shutdown) ->
error(badarg, [ChildId, ServerName, Shutdown]).
+
+%% @doc Returns OTP compatible name
+-spec otp_name(name()) -> otp_name().
+-ifdef('LOCAL_BEFORE_OTP17').
+otp_name(Name) ->
+ list_to_tuple([via, local, Name]).
+-else.
+otp_name(Name) ->
+ {via, local, Name}.
+-endif.
diff --git a/src/local_name_server.erl b/src/local_name_server.erl
index a9b5391..da0ac6b 100644
--- a/src/local_name_server.erl
+++ b/src/local_name_server.erl
@@ -13,6 +13,7 @@
-export([register_name/3]).
-export([unregister_name/2]).
-export([whereis_name/2]).
+-export([which_processes/1, which_processes/2]).
%%----------------------------------------------------------------------------------------------------------------------
%% 'gen_server' Callback API
@@ -57,6 +58,24 @@
_:_ -> undefined
end.
+%% @see local:which_processes/1
+-spec which_processes(local:name_server_name()) -> [{local:process_name(), pid()}].
+which_processes(Server) ->
+ try
+ ets:tab2list(Server)
+ catch
+ _:_ -> []
+ end.
+
+%% @see local:which_processes/2
+-spec which_processes(local:name_server_name(), ets:match_pattern()) -> [{local:process_name(), pid()}].
+which_processes(Server, ProcNamePattern) ->
+ try
+ ets:match_object(Server, {ProcNamePattern, '_'})
+ catch
+ _:_ -> []
+ end.
+
%%----------------------------------------------------------------------------------------------------------------------
%% 'gen_server' Callback Functions
%%----------------------------------------------------------------------------------------------------------------------
diff --git a/test/local_tests.erl b/test/local_tests.erl
index 042890b..dad6fdf 100644
--- a/test/local_tests.erl
+++ b/test/local_tests.erl
@@ -195,6 +195,31 @@
end}
]}.
+which_processes_test_() ->
+ {foreach,
+ fun () -> ok = local:start_name_server(?NS) end,
+ fun (_) -> ok = local:stop_name_server(?NS) end,
+ [
+ {"get a list of registered process",
+ fun () ->
+ ?assertEqual([], local:which_processes(?NS)),
+
+ yes = local:register_name(?NAME(hoge), self()),
+ ?assertEqual([{hoge, self()}], local:which_processes(?NS)),
+
+ ok = local:unregister_name(?NAME(hoge)),
+ ?assertEqual([], local:which_processes(?NS))
+ end},
+ {"get a filtered list of registered process",
+ fun () ->
+ yes = local:register_name(?NAME(hoge), self()),
+
+ ?assertEqual([], local:which_processes(?NS, fuga)),
+ ?assertEqual([{hoge, self()}], local:which_processes(?NS, hoge)),
+ ?assertEqual([{hoge, self()}], local:which_processes(?NS, '_'))
+ end}
+ ]}.
+
%%----------------------------------------------------------------------------------------------------------------------
%% Internal Functions
%%----------------------------------------------------------------------------------------------------------------------