From 539e5b8246d8a57e4b87860a576be20bb41ac097 Mon Sep 17 00:00:00 2001 From: rampage Date: Mon, 29 Nov 2010 19:44:08 -0500 Subject: [PATCH 01/10] Fixed call reference deletion --- src/gen_leader.erl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index 185f117..3d965b2 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -1014,10 +1014,11 @@ handle_msg({'$leader_call', From, Request} = Msg, Server, Role, handle_msg({Ref, {leader,reply,Reply}} = Msg, Server, Role, #election{buffered = Buffered} = E) -> {value, {_,From}} = lists:keysearch(Ref,1,Buffered), - NewServer = reply(From, {leader,reply,Reply}, Server, Role, - E#election{buffered = - lists:keydelete(Ref,1,Buffered)}), - loop(NewServer, Role, E, Msg); + El = E#election{buffered = lists:keydelete(Ref,1,Buffered)}, + + NewServer = reply(From, {leader,reply,Reply}, Server, Role, El), + + loop(NewServer, Role, El, Msg); handle_msg({'$gen_call', From, get_candidates} = Msg, Server, Role, E) -> NewServer = reply(From, {ok, candidates(E)}, Server, Role, E), loop(NewServer, Role, E, Msg); From de57ba7eb5a88c4a3d9f12829cc85300f8f77eaf Mon Sep 17 00:00:00 2001 From: Juan Jose Comellas Date: Mon, 27 Dec 2010 19:20:36 -0300 Subject: [PATCH 02/10] Reorder type specifications to avoid compile-time warning. --- src/gen_leader.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index 185f117..ba19afa 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -92,6 +92,11 @@ ]). +%% Notification control of candidate membership changes. `all' +%% means that returns from the handle_DOWN/3 and elected/3 leader's events +%% will be broadcast to all candidates. +-type bcast_type() :: 'all' | 'sender'. + -type option() :: {'workers', Workers::[node()]} | {'vardir', Dir::string()} | {'bcast_type', Type::bcast_type()} @@ -99,11 +104,6 @@ -type options() :: [option()]. -%% Notification control of candidate membership changes. `all' -%% means that returns from the handle_DOWN/3 and elected/3 leader's events -%% will be broadcast to all candidates. --type bcast_type() :: 'all' | 'sender'. - -type status() :: 'elec1' | 'elec2' | 'wait' | 'joining' | 'worker' | 'waiting_worker' | 'norm'. From 115d30b00adbd7a48067de2bf2eac9f6ccb197f8 Mon Sep 17 00:00:00 2001 From: Garret Smith Date: Fri, 28 Jan 2011 12:11:47 -0800 Subject: [PATCH 03/10] fix creating more than 1 monitor process for a server --- src/gen_leader.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index ba19afa..2c52217 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -446,9 +446,7 @@ init_it(Starter,Parent,Name,Mod,{CandidateNodes,OptArgs,Arg},Options) -> hasBecomeLeader(NewE,Server,{init}); false -> %% more than one candidate worker, continue as normal - safe_loop(#server{parent = Parent,mod = Mod, - state = State,debug = Debug}, - candidate, NewE,{init}) + safe_loop(Server, candidate, NewE,{init}) end; {{ok, State}, true, true} -> Server = #server{parent = Parent,mod = Mod, From ace9428801d67e5d3a3175742ffdb45af91972cf Mon Sep 17 00:00:00 2001 From: Garret Smith Date: Fri, 28 Jan 2011 12:12:25 -0800 Subject: [PATCH 04/10] fix to return the ref as indicated instead of node name --- src/gen_leader.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index 2c52217..d64115a 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -1442,7 +1442,7 @@ mon_handle_req({monitor, P}, From, Refs) -> Pid when is_pid(Pid) -> node(Pid) end, case lists:keyfind(Node, 2, Refs) of - {_, Ref} -> + {Ref, _} -> mon_reply(From, {Ref,Node}), Refs; false -> From baad18d4bf7c3ab8d5d72eedcbeb33229572a88e Mon Sep 17 00:00:00 2001 From: Garret Smith Date: Fri, 28 Jan 2011 12:13:04 -0800 Subject: [PATCH 05/10] do not remember multiple monitors for the same node --- src/gen_leader.erl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index d64115a..b81d4c6 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -1403,11 +1403,23 @@ mon_nodes(E,Nodes,Server) -> mon_node(El, Pid, Server) end,E1,Nodes -- [node()]). -%% Star monitoring one Process -mon_node(E,Proc,Server) -> - {Ref,Node} = do_monitor(Proc, Server), - E#election{monitored = [{Ref,Node} | E#election.monitored]}. +%% Start monitoring one Process +mon_node(E,{_RegName, NodeName} = Proc,Server) -> + case lists:keymember(NodeName, 2, E#election.monitored) of + true -> E; + false -> + {Ref,Node} = do_monitor(Proc, Server), + E#election{monitored = [{Ref,Node} | E#election.monitored]} + end; +mon_node(E,Proc,Server) when is_pid(Proc) -> + case lists:keymember(node(Proc), 2, E#election.monitored) of + true -> E; + false -> + {Ref,Node} = do_monitor(Proc, Server), + E#election{monitored = [{Ref,Node} | E#election.monitored]} + end + . spawn_monitor_proc() -> Parent = self(), From e8e4b6399ef7865f85881a0b955945d6de585cc5 Mon Sep 17 00:00:00 2001 From: Geoff Cant Date: Mon, 9 May 2011 15:43:37 -0700 Subject: [PATCH 06/10] Add an opaque type gen_leader:election() -> #election{}. --- src/gen_leader.erl | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/gen_leader.erl b/src/gen_leader.erl index ba19afa..34aa4cb 100644 --- a/src/gen_leader.erl +++ b/src/gen_leader.erl @@ -156,6 +156,10 @@ bcast_type :: bcast_type() }). +-opaque election() :: #election{}. + +-export_type([election/0]). + -record(server, { parent, mod, @@ -242,27 +246,27 @@ start_link(Name, CandidateNodes, OptArgs, Mod, Arg, Options) %% Query functions to be used from the callback module %% @doc Returns list of alive nodes. --spec alive(#election{}) -> [node()]. +-spec alive(election()) -> [node()]. alive(E) -> candidates(E) -- down(E). %% @doc Returns list of down nodes. --spec down(#election{}) -> [node()]. +-spec down(election()) -> [node()]. down(#election{down = Down}) -> Down. %% @doc Returns the current leader node. --spec leader_node(#election{}) -> node() | 'none'. +-spec leader_node(election()) -> node() | 'none'. leader_node(#election{leadernode=Leader}) -> Leader. %% @doc Returns a list of known candidates. --spec candidates(#election{}) -> [node()]. +-spec candidates(election()) -> [node()]. candidates(#election{candidate_nodes = Cands}) -> Cands. %% @doc Returns a list of known workers. --spec workers(#election{}) -> [node()]. +-spec workers(election()) -> [node()]. workers(#election{worker_nodes = Workers}) -> Workers. @@ -344,23 +348,23 @@ leader_call(Name, Request, Timeout) -> %% @equiv gen_server:cast/2 --spec cast(Name::name()|pid(), Request::term()) -> 'ok'. +-spec cast(Name::server_ref(), Request::term()) -> 'ok'. cast(Name, Request) -> catch do_cast('$gen_cast', Name, Request), ok. %% @doc Similar to gen_server:cast/2 but will be forwarded to %% the leader via the local gen_leader instance. --spec leader_cast(Name::name()|pid(), Request::term()) -> 'ok'. +-spec leader_cast(Name::server_ref(), Request::term()) -> 'ok'. leader_cast(Name, Request) -> catch do_cast('$leader_cast', Name, Request), ok. -do_cast(Tag, Name, Request) when is_atom(Name) -> - Name ! {Tag, Request}; -do_cast(Tag, Pid, Request) when is_pid(Pid) -> - Pid ! {Tag, Request}. +do_cast(Tag, {global, Name}, Request) -> + global:send(Name, {Tag, Request}); +do_cast(Tag, ServerRef, Request) -> + ServerRef ! {Tag, Request}. %% @equiv gen_server:reply/2 From e1e92b3b348b807239e7a444cf9f31ba0f764f06 Mon Sep 17 00:00:00 2001 From: Geoff Cant Date: Mon, 9 May 2011 15:44:05 -0700 Subject: [PATCH 07/10] Adds a list of type specs for gen_leader callback functions. --- include/gen_leader_specs.hrl | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 include/gen_leader_specs.hrl diff --git a/include/gen_leader_specs.hrl b/include/gen_leader_specs.hrl new file mode 100644 index 0000000..9297a40 --- /dev/null +++ b/include/gen_leader_specs.hrl @@ -0,0 +1,64 @@ + +-spec init (Args::term()) -> + {ok, State::term()} | + ignore | + {stop, Reason}. + +-spec elected(State, gen_leader:election(), node()) -> + {ok, Sync::term(), State} | + {reply, Sync::term(), State}. + +-spec surrendered(State, Sync, gen_leader:election()) -> + {ok, State}. + +-spec handle_leader_call(Request::term(), + From::{pid(), reference()}, + State, + gen_leader:election()) -> + {reply, Reply::term(), State} | + {reply, Reply::term(), Broadcast::term(), State} | + {noreply, State} | + {stop, Reason::term(), Reply::term(), State}. + +-spec handle_leader_cast(Msg::term(), + State, + gen_leader:election()) -> + {ok, Broadcast::term(), State} | + {noreply, State} | + {stop, Reason::term(), State}. + +-spec from_leader(Msg::term(), + State) -> + {noreply, State} | + {ok, State} | + {stop, Reason::term(), State}. + +-spec handle_call(Request::term(), + From::{pid(), reference()}, + State, + gen_leader:election()) -> + {reply, Reply::term(), State} | + {noreply, State} | + {stop, Reason::term(), State} | + {stop, Reason::term(), Reply::term(), State}. + +-spec handle_cast(Msg::term(), + State, + gen_leader:election()) -> + {noreply, State} | + {stop, Reason::term(), State}. + +-spec handle_DOWN(node(), State, gen_leader:election()) -> + {ok, State} | + {ok, Sync::term(), State}. + +-spec handle_info(Msg::term(), State) -> + {noreply, State} | + {stop, Reason::term(), State} | + {ok, State}. + +-spec terminate(Reason::term(), State) -> any(). + +-spec code_change(OldVsn::term(), State, gen_leader:election(), Extra::term()) -> + {ok, State} | + {ok, State, gen_leader:election()}}. From 1a05e57ff3bb9f81eb5a2f79a33da8245ce4c12d Mon Sep 17 00:00:00 2001 From: Geoff Cant Date: Tue, 10 May 2011 15:13:53 -0700 Subject: [PATCH 08/10] Fix gen_leader callback type specs. --- include/gen_leader_specs.hrl | 67 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/include/gen_leader_specs.hrl b/include/gen_leader_specs.hrl index 9297a40..9235208 100644 --- a/include/gen_leader_specs.hrl +++ b/include/gen_leader_specs.hrl @@ -1,64 +1,65 @@ -spec init (Args::term()) -> - {ok, State::term()} | - ignore | - {stop, Reason}. + {'ok', State::term()} | + 'ignore' | + {'stop', Reason::term()}. --spec elected(State, gen_leader:election(), node()) -> - {ok, Sync::term(), State} | - {reply, Sync::term(), State}. +-spec elected(State, gen_leader:election(), node() | 'undefined') -> + {'ok', Sync::term(), State} | + {'reply', Sync::term(), State}. --spec surrendered(State, Sync, gen_leader:election()) -> - {ok, State}. +-spec surrendered(State, Sync::term(), gen_leader:election()) -> + {'ok', State}. -spec handle_leader_call(Request::term(), From::{pid(), reference()}, State, gen_leader:election()) -> - {reply, Reply::term(), State} | - {reply, Reply::term(), Broadcast::term(), State} | - {noreply, State} | - {stop, Reason::term(), Reply::term(), State}. + {'reply', Reply::term(), State} | + {'reply', Reply::term(), Broadcast::term(), State} | + {'noreply', State} | + {'stop', Reason::term(), Reply::term(), State}. -spec handle_leader_cast(Msg::term(), State, gen_leader:election()) -> - {ok, Broadcast::term(), State} | - {noreply, State} | - {stop, Reason::term(), State}. + {'ok', Broadcast::term(), State} | + {'noreply', State} | + {'stop', Reason::term(), State}. -spec from_leader(Msg::term(), - State) -> - {noreply, State} | - {ok, State} | - {stop, Reason::term(), State}. + State, + gen_leader:election()) -> + {'noreply', State} | + {'ok', State} | + {'stop', Reason::term(), State}. -spec handle_call(Request::term(), From::{pid(), reference()}, State, gen_leader:election()) -> - {reply, Reply::term(), State} | - {noreply, State} | - {stop, Reason::term(), State} | - {stop, Reason::term(), Reply::term(), State}. + {'reply', Reply::term(), State} | + {'noreply', State} | + {'stop', Reason::term(), State} | + {'stop', Reason::term(), Reply::term(), State}. -spec handle_cast(Msg::term(), State, gen_leader:election()) -> - {noreply, State} | - {stop, Reason::term(), State}. + {'noreply', State} | + {'stop', Reason::term(), State}. -spec handle_DOWN(node(), State, gen_leader:election()) -> - {ok, State} | - {ok, Sync::term(), State}. + {'ok', State} | + {'ok', Sync::term(), State}. -spec handle_info(Msg::term(), State) -> - {noreply, State} | - {stop, Reason::term(), State} | - {ok, State}. + {'noreply', State} | + {'stop', Reason::term(), State} | + {'ok', State}. --spec terminate(Reason::term(), State) -> any(). +-spec terminate(Reason::term(), State::term()) -> any(). -spec code_change(OldVsn::term(), State, gen_leader:election(), Extra::term()) -> - {ok, State} | - {ok, State, gen_leader:election()}}. + {'ok', State} | + {'ok', State, gen_leader:election()}. From c2a90791dece3757cb9a6de6f1d3884c36863bde Mon Sep 17 00:00:00 2001 From: Geoff Cant Date: Mon, 16 May 2011 13:47:19 -0700 Subject: [PATCH 09/10] Adding a documentation note about return values for elected/3. --- include/gen_leader_specs.hrl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/gen_leader_specs.hrl b/include/gen_leader_specs.hrl index 9235208..e152bb6 100644 --- a/include/gen_leader_specs.hrl +++ b/include/gen_leader_specs.hrl @@ -4,6 +4,11 @@ 'ignore' | {'stop', Reason::term()}. +%% elected(_,_,node()) - captured a single candidate +%% reply notifies only the new candidate of the +%% sync state, ok notifies all candidates +%% elected(_,_,undefined) - won a general election +%% ok broadcasts sync to all candidates -spec elected(State, gen_leader:election(), node() | 'undefined') -> {'ok', Sync::term(), State} | {'reply', Sync::term(), State}. From 0382b0e78906a122cb90132394c3a32288f286b8 Mon Sep 17 00:00:00 2001 From: Geoff Cant Date: Mon, 23 May 2011 13:47:09 -0700 Subject: [PATCH 10/10] Ignore emacs swap files. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7729023..f502836 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ profile # Vim *.swp *.swo + +# Emacs +*~