Skip to content

Instantly share code, notes, and snippets.

@RJ
Created April 15, 2011 15:47
Show Gist options
  • Save RJ/921918 to your computer and use it in GitHub Desktop.
Save RJ/921918 to your computer and use it in GitHub Desktop.
%% Just stores an in #state{}
-module(leadertest).
-behaviour(gen_leader).
%% API
-export([start_link/1, start_link/2, get_num/0, set_num/1, info/0]).
%% gen_leader callbacks
-export([init/1,
handle_cast/3,
handle_call/4,
handle_info/2,
handle_leader_call/4,
handle_leader_cast/3,
handle_DOWN/3,
elected/3,
surrendered/3,
from_leader/3,
code_change/4,
terminate/2]).
-define(SERVER, ?MODULE).
-record(state, {num}).
%%%===================================================================
%%% API
%%%===================================================================
%%--------------------------------------------------------------------
%% @doc
%% Starts the server
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Nodes) ->
start_link(Nodes, []).
start_link(Nodes, Seed) when is_list(Nodes), is_atom(Seed) ->
start_link(Nodes, {seed_node, Seed});
start_link(Nodes, Opts) ->
gen_leader:start_link(?SERVER, Nodes, Opts, ?MODULE, [], []).
get_num() ->
gen_leader:call(?SERVER, get_num).
set_num(N) ->
gen_leader:leader_call(?SERVER, {set_num, N}).
info() ->
gen_leader:leader_call(?SERVER, info).
%%%===================================================================
%%% gen_leader callbacks
%%%===================================================================
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Initializes the server
%%
%% @spec init(Args) -> {ok, State} |
%% ignore |
%% {stop, Reason}
%% @end
%%--------------------------------------------------------------------
init([]) ->
{ok, #state{num=0}}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Called only in the leader process when it is elected. The Synch
%% term will be broadcasted to all the nodes in the cluster.
%%
%% @spec elected(State, Election, undefined) -> {ok, Synch, State}
%% @end
%%--------------------------------------------------------------------
elected(State, _Election, undefined) ->
Sync = foo1,
io:format("elected! broadcasting sync:~p~n", [Sync]),
{ok, Sync, State};
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Called only in the leader process when a new candidate joins the
%% cluster. The Synch term will be sent to Node.
%%
%% @spec elected(State, Election, Node) -> {ok, Synch, State}
%% @end
%%--------------------------------------------------------------------
elected(State, _Election, Node) ->
io:format("new candidate ~p joined cluster, sending them num~n", [Node]),
Sync = State#state.num,
{reply, Sync, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Called in all members of the cluster except the leader. Synch is a
%% term returned by the leader in the elected/3 callback.
%%
%% @spec surrendered(State, Sync, Election) -> {ok, State}
%% @end
%%--------------------------------------------------------------------
surrendered(State, Sync, _Election) ->
io:format("surrendered. leader sent this sync to us: ~p~n", [Sync]),
{ok, State#state{num=Sync}}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling call messages. Called in the leader.
%%
%% @spec handle_leader_call(Request, From, State, Election) ->
%% {reply, Reply, Broadcast, State} |
%% {reply, Reply, State} |
%% {noreply, State} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_leader_call(info, _From, State, Election) ->
Ret = [
{candidates, gen_leader:candidates(Election)},
{leader_node, gen_leader:leader_node(Election)},
{workers, gen_leader:workers(Election)}
],
{reply, Ret, State};
handle_leader_call({set_num, N}, _From, State, _Election) ->
io:format("leader call~n", []),
{reply, ok, {set_n, N}, State#state{num=N}}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling cast messages. Called in the leader.
%%
%% @spec handle_leader_cast(Request, State, Election) ->
%% {ok, Broadcast, State} |
%% {noreply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_leader_cast(_Request, State, _Election) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling messages from leader.
%%
%% @spec from_leader(Request, State, Election) ->
%% {ok, State} |
%% {noreply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
from_leader({set_n, N} = Sync, State, _Election) ->
io:format("~p Got this from the leader:~p~n", [self(), Sync]),
{ok, State#state{num=N}}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling nodes going down. Called in the leader only.
%%
%% @spec handle_DOWN(Node, State, Election) ->
%% {ok, State} |
%% {ok, Broadcast, State} |
%% @end
%%--------------------------------------------------------------------
handle_DOWN(Node, State, _Election) ->
io:format("i'm the leader, and this node just went down: ~p~n", [Node]),
{ok, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling call messages
%%
%% @spec handle_call(Request, From, State, Election) ->
%% {reply, Reply, State} |
%% {noreply, State} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_call(get_num, _From, State, _Election) ->
io:format("normal call~n", []),
Ret = State#state.num,
{reply, Ret, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling cast messages
%%
%% @spec handle_cast(Msg, State, Election) ->
%% {noreply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_cast(_Msg, State, _Election) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling all non call/cast messages
%%
%% @spec handle_info(Info, State) -> {noreply, State} |
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_info(_Info, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% This function is called by a gen_leader when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_leader terminates
%% with Reason. The return value is ignored.
%%
%% @spec terminate(Reason, State) -> void()
%% @end
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Convert process state when code is changed
%%
%% @spec code_change(OldVsn, State, Election, Extra) ->
%% {ok, NewState} |
%% {ok, NewState, NewElection}
%% @end
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Election, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment