Browse Source

doc additions, inherit by name, init_arg

Ulf Wiger 14 years ago
parent
commit
af14ad2230
6 changed files with 177 additions and 16 deletions
  1. 46 2
      README.md
  2. 46 2
      doc/README.md
  3. 15 5
      doc/gproc.md
  4. 24 2
      doc/overview.edoc
  5. 24 4
      src/gproc.erl
  6. 22 1
      test/gproc_tests.erl

+ 46 - 2
README.md

@@ -12,7 +12,7 @@ Extended process dictionary
 
 
 
-<h3><a name="Introduction">Introduction</a></h3>
+<h2>Introduction</h2>
 
 
 
@@ -43,6 +43,26 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
+<h3>Use case: System inspection</h3>
+
+
+
+
+
+Gproc was designed to work as a central index for "process metadata", i.e.
+properties that describe the role and characteristics of each process. Having
+a single registry that is flexible enough to hold important types of property
+makes it easier to (a) find processes of a certain type, and (b) query and 
+browse key data in a running system.
+
+
+
+<h3>Use case: Pub/Sub patterns</h3>
+
+
+
+
+
 An interesting application of gproc is building publish/subscribe patterns.
 Example:
 
@@ -58,6 +78,30 @@ notify(EventType, Msg) ->
 
 
 
+<h3>Use case: Environment handling</h3>
+
+
+
+
+
+Gproc provides a set of functions to read environment variables, possibly from
+alternative sources, and cache them for efficient lookup. Caching also provides
+a way to see which processes rely on certain configuration values, as well as 
+which values they actually ended up using. 
+
+
+
+See [`gproc:get_env/4`](http://github.com/esl/gproc/blob/env_vars/doc/gproc.md#get_env-4), [`gproc:get_set_env/4`](http://github.com/esl/gproc/blob/env_vars/doc/gproc.md#get_set_env-4) and 
+[`gproc:set_env/5`](http://github.com/esl/gproc/blob/env_vars/doc/gproc.md#set_env-5) for details.
+
+
+
+<h2>Testing</h2>
+
+
+
+
+
 Gproc has a QuickCheck test suite, covering a fairly large part of the local 
 gproc functionality, although none of the global registry. It requires a 
 commercial EQC license, but rebar is smart enough to detect whether EQC is 
@@ -70,7 +114,7 @@ global gproc.
 
 
 
-<h3><a name="Building_Edoc">Building Edoc</a></h3>
+<h2>Building Edoc</h2>
 
 
 

+ 46 - 2
doc/README.md

@@ -12,7 +12,7 @@ Extended process dictionary
 
 
 
-<h3><a name="Introduction">Introduction</a></h3>
+<h2>Introduction</h2>
 
 
 
@@ -43,6 +43,26 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
+<h3>Use case: System inspection</h3>
+
+
+
+
+
+Gproc was designed to work as a central index for "process metadata", i.e.
+properties that describe the role and characteristics of each process. Having
+a single registry that is flexible enough to hold important types of property
+makes it easier to (a) find processes of a certain type, and (b) query and 
+browse key data in a running system.
+
+
+
+<h3>Use case: Pub/Sub patterns</h3>
+
+
+
+
+
 An interesting application of gproc is building publish/subscribe patterns.
 Example:
 
@@ -58,6 +78,30 @@ notify(EventType, Msg) ->
 
 
 
+<h3>Use case: Environment handling</h3>
+
+
+
+
+
+Gproc provides a set of functions to read environment variables, possibly from
+alternative sources, and cache them for efficient lookup. Caching also provides
+a way to see which processes rely on certain configuration values, as well as 
+which values they actually ended up using. 
+
+
+
+See [`gproc:get_env/4`](gproc.md#get_env-4), [`gproc:get_set_env/4`](gproc.md#get_set_env-4) and 
+[`gproc:set_env/5`](gproc.md#set_env-5) for details.
+
+
+
+<h2>Testing</h2>
+
+
+
+
+
 Gproc has a QuickCheck test suite, covering a fairly large part of the local 
 gproc functionality, although none of the global registry. It requires a 
 commercial EQC license, but rebar is smart enough to detect whether EQC is 
@@ -70,7 +114,7 @@ global gproc.
 
 
 
-<h3><a name="Building_Edoc">Building Edoc</a></h3>
+<h2>Building Edoc</h2>
 
 
 

+ 15 - 5
doc/gproc.md

@@ -384,6 +384,12 @@ uppercase string
 * `{os_env, ENV}` - try `os:getenv(ENV)`
 * `inherit` - inherit the cached value, if any, held by the (proc_lib) parent.
 * `{inherit, Pid}` - inherit the cached value, if any, held by `Pid`.
+* `{inherit, Name}` - inherit the cached value, if any, held by the process
+registered in `gproc` as `Name`.
+* `init_arg` - try `init:get_argument(Key)`; expects a single value, if any.
+* `{mnesia, ActivityType, Oid, Pos}` - try
+`mnesia:activity(ActivityType, fun() -> mnesia:read(Oid) end)`; retrieve the
+value in position `Pos` if object found.
 * `{default, Value}` - set a default value to return once alternatives have been
 exhausted; if not set, `undefined` will be returned.
 * `error` - raise an exception, `erlang:error(gproc_env, [App, Key, Scope])`.
@@ -391,8 +397,8 @@ exhausted; if not set, `undefined` will be returned.
 
 
 While any alternative can occur more than once, the only one that might make
-sense to repeat is `{default, Value}`. The last instance will be the one that  
-determines the return value.
+sense to repeat is `{default, Value}`.  
+The last instance will be the one that determines the return value.
 
 The `error` option can be used to assert that a value has been previously
 cached. Alternatively, it can be used to assert that a value is either cached
@@ -424,12 +430,16 @@ Equivalent to [`get_set_env(Scope, App, Key, [app_env])`](#get_set_env-4).<a nam
 
 
 
-Fetch and cache an environment value, if not already cached.
 
 
-__See also:__ [This function does the same thing as [`get_env/4`](#get_env-4), but also updates the
+Fetch and cache an environment value, if not already cached.
+
+This function does the same thing as [`get_env/4`](#get_env-4), but also updates the
 cache. Note that the cache will be updated even if the result of the lookup
-is `undefined`.](#get_env-4).<a name="get_value-1"></a>
+is `undefined`.
+
+
+__See also:__ [get_env/4](#get_env-4).<a name="get_value-1"></a>
 
 <h3>get_value/1</h3>
 

+ 24 - 2
doc/overview.edoc

@@ -3,7 +3,7 @@
 
 @doc Extended process dictionary
 
-== Introduction ==
+<h2>Introduction</h2>
 
 Gproc is a process dictionary for Erlang, which provides a number of useful features beyond what the built-in dictionary has:
 
@@ -20,6 +20,16 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 <li>Global registry, with all the above functions applied to a network of nodes</li>
 </ul>
 
+<h3>Use case: System inspection</h3>
+
+Gproc was designed to work as a central index for "process metadata", i.e.
+properties that describe the role and characteristics of each process. Having
+a single registry that is flexible enough to hold important types of property
+makes it easier to (a) find processes of a certain type, and (b) query and 
+browse key data in a running system.
+
+<h3>Use case: Pub/Sub patterns</h3>
+
 An interesting application of gproc is building publish/subscribe patterns.
 Example:
 
@@ -33,6 +43,18 @@ notify(EventType, Msg) ->
     gproc:send({p, l, Key}, {self(), Key, Msg}).
 </pre>
 
+<h3>Use case: Environment handling</h3>
+
+Gproc provides a set of functions to read environment variables, possibly from
+alternative sources, and cache them for efficient lookup. Caching also provides
+a way to see which processes rely on certain configuration values, as well as 
+which values they actually ended up using. 
+
+See {@link gproc:get_env/4}, {@link gproc:get_set_env/4} and 
+{@link gproc:set_env/5} for details.
+
+<h2>Testing</h2>
+
 Gproc has a QuickCheck test suite, covering a fairly large part of the local 
 gproc functionality, although none of the global registry. It requires a 
 commercial EQC license, but rebar is smart enough to detect whether EQC is 
@@ -41,7 +63,7 @@ available, and if it isn't, the code in gproc_eqc.erl will be "defined away".
 There is also an eunit suite, covering the basic operations for local and 
 global gproc.
 
-== Building Edoc ==
+<h2>Building Edoc</h2>
 By default, `./rebar doc` generates Github-flavored Markdown files.
 If you want to change this, remove the `edoc_opts' line from `rebar.config'.
 

+ 24 - 4
src/gproc.erl

@@ -299,13 +299,19 @@ get_env(Scope, App, Key) ->
 %% * `{os_env, ENV}' - try `os:getenv(ENV)'
 %% * `inherit' - inherit the cached value, if any, held by the (proc_lib) parent.
 %% * `{inherit, Pid}' - inherit the cached value, if any, held by `Pid'.
+%% * `{inherit, Name}' - inherit the cached value, if any, held by the process
+%%    registered in `gproc' as `Name'.
+%% * `init_arg' - try `init:get_argument(Key)'; expects a single value, if any.
+%% * `{mnesia, ActivityType, Oid, Pos}' - try 
+%%   `mnesia:activity(ActivityType, fun() -> mnesia:read(Oid) end)'; retrieve the
+%%    value in position `Pos' if object found.
 %% * `{default, Value}' - set a default value to return once alternatives have been
 %%    exhausted; if not set, `undefined' will be returned.
 %% * `error' - raise an exception, `erlang:error(gproc_env, [App, Key, Scope])'.
 %%
 %% While any alternative can occur more than once, the only one that might make 
-%% sense to repeat is `{default, Value}'. The last instance will be the one that 
-%% determines the return value.
+%% sense to repeat is `{default, Value}'. 
+%% The last instance will be the one that determines the return value.
 %%
 %% The `error' option can be used to assert that a value has been previously 
 %% cached. Alternatively, it can be used to assert that a value is either cached
@@ -324,10 +330,11 @@ get_set_env(Scope, App, Key) ->
 %% @spec get_set_env(Scope::scope(), App::atom(), Key::atom(), Strategy) -> Value
 %% @doc Fetch and cache an environment value, if not already cached.
 %%
-%% @see get_env/4.
 %% This function does the same thing as {@link get_env/4}, but also updates the 
 %% cache. Note that the cache will be updated even if the result of the lookup
 %% is `undefined'.
+%%
+%% @see get_env/4.
 %% @end
 %%
 get_set_env(Scope, App, Key, Strategy)
@@ -398,8 +405,14 @@ try_alternative(inherit, App, Key, Scope) ->
 	_ ->
 	    undefined
     end;
-try_alternative({inherit, P}, App, Key, Scope) ->
+try_alternative({inherit, P}, App, Key, Scope) when is_pid(P) ->
     lookup_env(Scope, App, Key, P);
+try_alternative({inherit, P}, App, Key, Scope) ->
+    case where(P) of
+	undefined -> undefined;
+	Pid when is_pid(Pid) ->
+	    lookup_env(Scope, App, Key, Pid)
+    end;
 try_alternative(app_env, App, Key, _Scope) ->
     case application:get_env(App, Key) of
 	undefined       -> undefined;
@@ -416,6 +429,13 @@ try_alternative({os_env, Key}, _, _, _) ->
 	""  -> undefined;
 	Val -> {ok, Val}
     end;
+try_alternative(init_arg, _, Key, _) ->
+    case init:get_argument(Key) of
+	{ok, [[Value]]} ->
+	    {ok, Value};
+	error ->
+	    undefined
+    end;
 try_alternative({mnesia,Type,Key,Pos}, _, _, _) ->
     case mnesia:activity(Type, fun() -> mnesia:read(Key) end) of
 	[] -> undefined;

+ 22 - 1
test/gproc_tests.erl

@@ -63,6 +63,8 @@ reg_test_() ->
       , ?_test(t_is_clean())
       , {spawn, ?_test(t_set_env())}
       , ?_test(t_is_clean())
+      , {spawn, ?_test(t_get_env_inherit())}
+      , ?_test(t_is_clean())
      ]}.
 
 t_simple_reg() ->
@@ -286,11 +288,19 @@ t_get_env() ->
     ?assertEqual(true, os:putenv("TTTT", "s3")),
     ?assertEqual(ok, application:set_env(gproc, aaaa, a)),
     ?assertEqual(undefined, gproc:get_env(l, gproc, ssss, [])),
+    %%
     ?assertEqual("s1", gproc:get_env(l, gproc, ssss, [app_env])),
     ?assertEqual("s2", gproc:get_env(l, gproc, ssss, [os_env])),
     ?assertEqual("s1", gproc:get_env(l, gproc, ssss, [app_env, os_env])),
     ?assertEqual("s3", gproc:get_env(l, gproc, ssss, [{os_env,"TTTT"}])),
-    ?assertEqual("s4", gproc:get_env(l, gproc, ssss, [{default,"s4"}])).
+    ?assertEqual("s4", gproc:get_env(l, gproc, ssss, [{default,"s4"}])),
+    %%
+    ?assertEqual(ok, application:start(mnesia)),
+    ?assertEqual({atomic,ok}, mnesia:create_table(t, [{ram_copies, [node()]}])),
+    ?assertEqual(ok, mnesia:dirty_write({t, foo, bar})),
+    ?assertEqual(bar, gproc:get_env(l, gproc, some_env, [{mnesia,transaction,
+							  {t, foo}, 3}])),
+    ?assertEqual("erl", gproc:get_env(l, gproc, progname, [init_arg])).
 
 t_get_set_env() ->
     ?assertEqual(ok, application:set_env(gproc, aaaa, a)),
@@ -313,6 +323,17 @@ t_set_env() ->
     ?assertEqual([{self(),"s1"}],
 		 gproc:lookup_values({p,l,{gproc_env,gproc,ssss}})).
 
+t_get_env_inherit() ->
+    P = spawn_link(fun() ->
+			   ?assertEqual(bar, gproc:set_env(l,gproc,foo,bar,[])),
+			   gproc:reg({n,l,get_env_p}),
+			   t_loop()
+		   end),
+    ?assertEqual({P,undefined}, gproc:await({n,l,get_env_p},1000)),
+    ?assertEqual(bar, gproc:get_env(l, gproc, foo, [{inherit, P}])),
+    ?assertEqual(bar, gproc:get_env(l, gproc, foo, [{inherit, {n,l,get_env_p}}])),
+    ?assertEqual(ok, t_call(P, die)).
+
 t_loop() ->
     receive
 	{From, {give_away, Key}} ->