Permalink
Browse files

rebar.config.script and dynamic deps handling

  • Loading branch information...
1 parent 26b48ae commit 44a3ad7d34d41cc91258597556584833e8a6a38b @uwiger uwiger committed Jan 11, 2013
Showing with 167 additions and 51 deletions.
  1. +13 −13 README.md
  2. +9 −2 doc/gproc_dist.md
  3. +17 −5 doc/gproc_ps.md
  4. +33 −0 priv/check_edown.script
  5. +18 −0 priv/remove_deps.script
  6. +1 −0 rebar.config.script
  7. +76 −31 src/gproc_dist.erl
View
@@ -62,8 +62,8 @@ 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/master/doc/gproc.md#get_env-4), [`gproc:get_set_env/4`](http://github.com/esl/gproc/blob/master/doc/gproc.md#get_set_env-4) and
-[`gproc:set_env/5`](http://github.com/esl/gproc/blob/master/doc/gproc.md#set_env-5) for details.
+See [`gproc:get_env/4`](http://github.com/esl/gproc/blob/0.2.14/doc/gproc.md#get_env-4), [`gproc:get_set_env/4`](http://github.com/esl/gproc/blob/0.2.14/doc/gproc.md#get_set_env-4) and
+[`gproc:set_env/5`](http://github.com/esl/gproc/blob/0.2.14/doc/gproc.md#set_env-5) for details.
##Testing##
@@ -82,21 +82,21 @@ global gproc.
By default, `./rebar doc` generates Github-flavored Markdown files.
If you want to change this, remove the `edoc_opts` line from `rebar.config`.Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
-Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/doc/erlang07-wiger.pdf)).
+Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/0.2.14/doc/erlang07-wiger.pdf)).
##Modules##
<table width="100%" border="0" summary="list of modules">
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc.md" class="module">gproc</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_app.md" class="module">gproc_app</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_bcast.md" class="module">gproc_bcast</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_dist.md" class="module">gproc_dist</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_init.md" class="module">gproc_init</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_lib.md" class="module">gproc_lib</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_monitor.md" class="module">gproc_monitor</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_ps.md" class="module">gproc_ps</a></td></tr>
-<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc.md" class="module">gproc</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_app.md" class="module">gproc_app</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_bcast.md" class="module">gproc_bcast</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_dist.md" class="module">gproc_dist</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_init.md" class="module">gproc_init</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_lib.md" class="module">gproc_lib</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_monitor.md" class="module">gproc_monitor</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_ps.md" class="module">gproc_ps</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/0.2.14/doc/gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
View
@@ -23,7 +23,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a
##Function Index##
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-4">code_change/4</a></td><td></td></tr><tr><td valign="top"><a href="#elected-2">elected/2</a></td><td></td></tr><tr><td valign="top"><a href="#elected-3">elected/3</a></td><td></td></tr><tr><td valign="top"><a href="#from_leader-3">from_leader/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_leader-0">get_leader/0</a></td><td>Returns the node of the current gproc leader.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_DOWN-3">handle_DOWN/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-4">handle_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-3">handle_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_call-4">handle_leader_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_cast-3">handle_leader_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_call-1">leader_call/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_cast-1">leader_cast/1</a></td><td></td></tr><tr><td valign="top"><a href="#mreg-2">mreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#munreg-2">munreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td></td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-4">code_change/4</a></td><td></td></tr><tr><td valign="top"><a href="#elected-2">elected/2</a></td><td></td></tr><tr><td valign="top"><a href="#elected-3">elected/3</a></td><td></td></tr><tr><td valign="top"><a href="#from_leader-3">from_leader/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_leader-0">get_leader/0</a></td><td>Returns the node of the current gproc leader.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_DOWN-3">handle_DOWN/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-4">handle_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-3">handle_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-3">handle_info/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_call-4">handle_leader_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_cast-3">handle_leader_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_call-1">leader_call/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_cast-1">leader_cast/1</a></td><td></td></tr><tr><td valign="top"><a href="#mreg-2">mreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#munreg-2">munreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td></td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>
Class = n - unique name
| p - non-unique property
| c - counter
@@ -107,6 +107,13 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
`handle_info(X1, S) -> any()`
+<a name="handle_info-3"></a>
+
+###handle_info/3##
+
+
+`handle_info(Msg, S, E) -> any()`
+
<a name="handle_leader_call-4"></a>
###handle_leader_call/4##
@@ -222,7 +229,7 @@ Scope = l | g (global or local)<a name="reg_or_locate-3"></a>
###surrendered/3##
-`surrendered(S, X2, E) -> any()`
+`surrendered(State, X2, E) -> any()`
<a name="sync-0"></a>
View
@@ -280,11 +280,17 @@ Subscribe to events of type `Event`
-Any messages published with `gproc_ps:publish(Scope, Event, Msg)` will be delivered to
-the current process, along with all other subscribers.
+Any messages published with `gproc_ps:publish(Scope, Event, Msg)` will be
+delivered to the current process, along with all other subscribers.
-This function creates a property, `{p,Scope,{gproc_ps_event,Event}}`, which can be
-searched and displayed for debugging purposes.<a name="subscribe_cond-3"></a>
+
+
+This function creates a property, `{p,Scope,{gproc_ps_event,Event}}`, which
+can be searched and displayed for debugging purposes.
+
+Note that, as with [`gproc:reg/1`](gproc.md#reg-1), this function will raise an
+exception if you try to subscribe to the same event twice from the same
+process.<a name="subscribe_cond-3"></a>
###subscribe_cond/3##
@@ -322,8 +328,14 @@ like [`publish/3`](#publish-3) does, except that `publish/3` strictly speaking
ignores the Value part of the property completely, whereas `publish_cond/3`
expects it to be either undefined or a valid match spec).
+
+
This means that `Cond=undefined` and `Cond=[{'_',[],[true]}]` are
-equivalent.<a name="tell_singles-3"></a>
+equivalent.
+
+Note that, as with [`gproc:reg/1`](gproc.md#reg-1), this function will raise an
+exception if you try to subscribe to the same event twice from the same
+process.<a name="tell_singles-3"></a>
###tell_singles/3##
View
@@ -0,0 +1,33 @@
+%% -*- erlang -*-
+%%
+%% This helper script checks if doc is being built, otherwise removes edoc dep.
+%% To build docs, call `rebar get-deps doc`
+%% Assumes that the rebar config is bound to CONFIG
+
+[_|Args] = init:get_plain_arguments(). % rebar 'commands' and options
+case lists:member("doc", Args) of
+ false ->
+ {ok,C1} = file:script(filename:join(filename:dirname(SCRIPT),
+ "remove_deps.script"),
+ [{'CONFIG', CONFIG}, {'DEPS', [edown]}]),
+ C1;
+ true ->
+ case code:lib_dir(edown) of
+ {error, bad_name} ->
+ io:fwrite("cannot find edown~n", []),
+ D = {edown, ".*",
+ {git, "git://github.com/esl/edown.git", "HEAD"}},
+ Deps = case lists:keyfind(deps, 1, CONFIG) of
+ false -> [D];
+ {_, Ds} ->
+ case lists:keymember(edown, 1, Ds) of
+ true -> Ds;
+ false -> [D|Ds]
+ end
+ end,
+ lists:keystore(deps, 1, CONFIG, {deps, Deps});
+ _ ->
+ io:fwrite("edown in path~n", []),
+ CONFIG
+ end
+end.
View
@@ -0,0 +1,18 @@
+%% -*- erlang -*-
+%%
+%% Assumes the following bound variables:
+%% CONFIG - a rebar.config options list
+%% DEPS :: [atom()] - a list of deps to remove
+case lists:keyfind(deps, 1, CONFIG) of
+ {_, Deps0} ->
+ Deps1 = lists:filter(
+ fun(D) when is_atom(D) ->
+ not lists:member(D, DEPS);
+ (D) when is_tuple(D) ->
+ not lists:member(element(1,D), DEPS)
+ end, Deps0),
+ lists:keyreplace(deps, 1, CONFIG, {deps, Deps1});
+ false ->
+ CONFIG
+end.
+
View
View
@@ -44,7 +44,7 @@
-export([init/1,
handle_cast/3,
handle_call/4,
- handle_info/2,
+ handle_info/2, handle_info/3,
handle_leader_call/4,
handle_leader_cast/3,
handle_DOWN/3,
@@ -208,11 +208,15 @@ handle_call(_, _, S, _) ->
{reply, badarg, S}.
handle_info({'DOWN', _MRef, process, Pid, _}, S) ->
+ ets:delete(?TAB, {{Pid, g}}),
leader_cast({pid_is_DOWN, Pid}),
{ok, S};
handle_info(_, S) ->
{ok, S}.
+handle_info(Msg, S, _E) ->
+ handle_info(Msg, S).
+
elected(S, _E) ->
{ok, {globals,globs()}, S#state{is_leader = true}}.
@@ -233,8 +237,14 @@ elected(S, _E, _Node) ->
end.
globs() ->
- ets:select(?TAB, [{{{{'_',g,'_'},'_'},'_','_'},[],['$_']}]).
+ Gs = ets:select(?TAB, [{{{{'_',g,'_'},'_'},'_','_'},[],['$_']}]),
+ _ = [gproc_lib:ensure_monitor(Pid, g) || {_, Pid, _} <- Gs],
+ Gs.
+surrendered(#state{is_leader = true} = S, {globals, Globs}, _E) ->
+ %% Leader conflict!
+ surrendered_1(Globs),
+ {ok, S#state{is_leader = false}};
surrendered(S, {globals, Globs}, _E) ->
%% globals from this node should be more correct in our table than
%% in the leader's
@@ -276,22 +286,23 @@ handle_leader_call(sync, From, #state{sync_requests = SReqs} = S, E) ->
gen_leader:broadcast({from_leader, {sync, From}}, Alive, E),
{noreply, S#state{sync_requests = [{From, Alive}|SReqs]}}
end;
-handle_leader_call({reg, {C,g,Name} = K, Value, Pid}, _From, S, _E) ->
+handle_leader_call({reg, {_C,g,_Name} = K, Value, Pid}, _From, S, _E) ->
case gproc_lib:insert_reg(K, Value, Pid, g) of
false ->
{reply, badarg, S};
true ->
_ = gproc_lib:ensure_monitor(Pid,g),
- Vals =
- if C == a ->
- ets:lookup(?TAB, {K,a});
- C == c ->
- [{{K,Pid},Pid,Value} | ets:lookup(?TAB,{{a,g,Name},a})];
- C == n ->
- [{{K,n},Pid,Value}];
- true ->
- [{{K,Pid},Pid,Value}]
- end,
+ Vals = mk_broadcast_insert_vals([{K, Pid, Value}]),
+ %% Vals =
+ %% if C == a ->
+ %% ets:lookup(?TAB, {K,a});
+ %% C == c ->
+ %% [{{K,Pid},Pid,Value} | ets:lookup(?TAB,{{a,g,Name},a})];
+ %% C == n ->
+ %% [{{K,n},Pid,Value}];
+ %% true ->
+ %% [{{K,Pid},Pid,Value}]
+ %% end,
{reply, true, [{insert, Vals}], S}
end;
handle_leader_call({reg_or_locate, {n,g,_} = K, Value, Pid}, _From, S, _E) ->
@@ -500,8 +511,8 @@ handle_leader_cast({add_globals, Missing}, S, _E) ->
%% This is an audit message: a peer (non-leader) had info about granted
%% global resources that we didn't know of when we became leader.
%% This could happen due to a race condition when the old leader died.
- ets:insert(?TAB, Missing),
- {ok, [{insert, Missing}], S};
+ Update = insert_globals(Missing),
+ {ok, [{insert, Update}], S};
handle_leader_cast({remove_globals, Globals}, S, _E) ->
delete_globals(Globals, []),
{ok, S};
@@ -533,6 +544,22 @@ handle_leader_cast({pid_is_DOWN, Pid}, S, _E) ->
{ok, Broadcast, S}
end.
+mk_broadcast_insert_vals(Objs) ->
+ lists:flatmap(
+ fun({{C, g, Name} = K, Pid, Value}) ->
+ if C == a ->
+ ets:lookup(?TAB, {K,a}) ++ ets:lookup(?TAB, {Pid,K});
+ C == c ->
+ [{{K,Pid},Pid,Value} | ets:lookup(?TAB,{{a,g,Name},a})]
+ ++ ets:lookup(?TAB, {Pid,K});
+ C == n ->
+ [{{K,n},Pid,Value}| ets:lookup(?TAB, {Pid,K})];
+ true ->
+ [{{K,Pid},Pid,Value} | ets:lookup(?TAB, {Pid,K})]
+ end
+ end, Objs).
+
+
process_globals(Globals) ->
Modified =
lists:foldl(
@@ -579,20 +606,36 @@ from_leader(Ops, S, _E) ->
fun({delete, Globals, Event}) ->
delete_globals(Globals, Event);
({insert, Globals}) ->
- ets:insert(?TAB, Globals),
- lists:foreach(
- fun({{{_,g,_}=Key,_}, P, _}) ->
- ets:insert_new(?TAB, {{P,Key}, []}),
- gproc_lib:ensure_monitor(P,g);
- ({{P,_K}, _Opts} = Obj) when is_pid(P) ->
- ets:insert(?TAB, Obj),
- gproc_lib:ensure_monitor(P,g);
- (_) ->
- skip
- end, Globals)
+ _ = insert_globals(Globals)
end, Ops),
{ok, S}.
+insert_globals(Globals) ->
+ ets:insert(?TAB, Globals),
+ lists:foldl(
+ fun({{{T,_,_} = Key,Pid}, Pid, _}, A) ->
+ A1 = case T of
+ c ->
+ Incr = ets:lookup_element(?TAB, {Key,Pid}, 3),
+ update_aggr_counter(Key, -Incr) ++ A;
+ _ ->
+ A
+ end,
+ ets:insert_new(?TAB, {{Pid,Key}, []}),
+ gproc_lib:ensure_monitor(Pid,g),
+ A1;
+ ({{{_,_,_}, n}, Pid, _}, A) ->
+ gproc_lib:ensure_monitor(Pid,g),
+ A;
+ ({{P,_K}, Opts} = Obj, A) when is_pid(P), is_list(Opts),Opts =/= [] ->
+ ets:insert(?TAB, Obj),
+ gproc_lib:ensure_monitor(P,g),
+ [Obj] ++ A;
+ (_Other, A) ->
+ A
+ end, Globals, Globals).
+
+
delete_globals(Globals, Event) ->
lists:foreach(
fun({{_,g,_},T} = K) when is_atom(T) ->
@@ -629,10 +672,11 @@ init(Opts) ->
surrendered_1(Globs) ->
My_local_globs =
- ets:select(?TAB, [{{{{'_',g,'_'},'_'},'$1', '_'},
+ ets:select(?TAB, [{{{{'_',g,'_'},'_'},'$1', '$2'},
[{'==', {node,'$1'}, node()}],
- ['$_']}]),
- %% remove all remote globals - we don't have monitors on them.
+ [{{ {element,1,{element,1,'$_'}}, '$1', '$2' }}]}]),
+ _ = [gproc_lib:ensure_monitor(Pid, g) || {_, Pid, _} <- My_local_globs],
+ %% remove all remote globals.
ets:select_delete(?TAB, [{{{{'_',g,'_'},'_'}, '$1', '_'},
[{'=/=', {node,'$1'}, node()}],
[true]}]),
@@ -642,7 +686,8 @@ surrendered_1(Globs) ->
lists:foldl(
fun({{Key,_}=K, Pid, V}, Acc) when node(Pid) =/= node() ->
ets:insert(?TAB, {K, Pid, V}),
- ets:insert_new(?TAB, {{Pid,Key}, r}),
+ _ = gproc_lib:ensure_monitor(Pid, g),
+ ets:insert_new(?TAB, {{Pid,Key}, []}),
Acc;
({{Pid,_}=K, Opts}, Acc) when node(Pid) =/= node() ->
ets:insert(?TAB, {K, Opts}),
@@ -658,7 +703,7 @@ surrendered_1(Globs) ->
ok;
[_|_] = Missing ->
%% This is very unlikely, I think
- leader_cast({add_globals, Missing})
+ leader_cast({add_globals, mk_broadcast_insert_vals(Missing)})
end,
case [{K,P} || {K,P,_} <- Ldr_local_globs,
is_pid(P) andalso

0 comments on commit 44a3ad7

Please sign in to comment.