View Source gen_leader behaviour (util v1.1.5)
This application implements a leader election behavior modeled after gen_server. This behavior intends to make it reasonably straightforward to implement a fully distributed server with master-slave semantics.
The gen_leader behavior supports nearly everything that gen_server does (some functions, such as multicall() and the internal timeout, have been removed), and adds a few callbacks and API functions to support leader election etc.
Also included is an example program, a global dictionary, based on the modules gen_leader and dict. The callback implementing the global dictionary is called 'test_cb', for no particularly logical reason.
New version: The internal leader election algorithm was faulty and has been replaced with a new version based on a different leader election algorithm. As a consequence of this the query functions alive and down can no longer be provided. The new algorithm also make use of an incarnation parameter, by default written to disk in the function incarnation. This implies that only one gen_leader per node is permitted, if used in a diskless environment, incarnation must be adapted.
Modifications contributed by Serge Aleynikov:
- Added configurable startup options (see leader_options() type)
- Implemented handle_DOWN/3 callback with propagation of the leader's state via broadcast to all connected candidates.
- Fixed population of the #election.down member so that down/1 query can be used in the behavior's implementation
- Rewrote implementation of the tau timer to prevent the leader looping on the timer timeout event when all candidates are connected.
Link to this section Summary
Functions
gen_server:call/2
, but with a slightly different exit reason if something goes wrong. This function calls the gen_leader
process exactly as if it were a gen_server (which, for practical purposes, it is.)gen_server:call/3
, but with a slightly different exit reason if something goes wrong. This function calls the gen_leader
process exactly as if it were a gen_server (which, for practical purposes, it is.)Equivalent to gen_server:cast / 2.
gen_server:call/2
) to the leader. The call is forwarded via the local gen_leader instance, if that one isn't actually the leader. The client will exit if the leader dies while the request is outstanding.This function uses gen:call/3
, and is subject to the same default timeout as e.g. gen_server:call/2
.
gen_server:call/3
) to the leader. The call is forwarded via the local gen_leader instance, if that one isn't actually the leader. The client will exit if the leader dies while the request is outstanding.gen_server:cast/2
but will be forwarded to the leader via the local gen_leader instance.Equivalent to gen_server:reply / 2.
See also: start_link/6.
gen_leader
.- {workers, Workers}
- {vardir, Dir}
- {bcast_type, Type}
Type
is 'all' each election event (when a new candidate becomes visible to the leader) will be broadcast to all live candidate nodes. Each candidate will get a from_leader/3 callback. When Type
is sender
, only the newly registered candidate will get the surrendered/3 callback. Default: sender
.- {heartbeat, Seconds}
Mod:init/1
OptionsSame as gen_server's OptionsThe list of candidates needs to be known from the start. Workers could potentially be added at runtime, but no functionality to do this is provided by this version.
Link to this section Types
-type bcast_type() :: all | sender.
-type caller_ref() :: {pid(), reference()}.
-type incarn() :: non_neg_integer().
-type lclock() :: non_neg_integer().
-type mon_ref() :: reference().
-type name() :: atom().
-type option() :: {workers, Workers :: [node()]} | {vardir, Dir :: string()} | {bcast_type, Type :: bcast_type()} | {heartbeat, Seconds :: integer()}.
-type options() :: [option()].
-type priority() :: integer().
-type start_ret() :: {ok, pid()} | {error, term()}.
-type status() :: elec1 | elec2 | wait | joining | worker | waiting_worker | norm.
Link to this section Functions
-spec alive(#election{}) -> [node()].
-spec behaviour_info(atom()) -> undefined | [{atom(), arity()}].
-spec call(server_ref(), term()) -> term().
gen_server:call/2
, but with a slightly different exit reason if something goes wrong. This function calls the gen_leader
process exactly as if it were a gen_server (which, for practical purposes, it is.)
-spec call(server_ref(), term(), integer()) -> term().
gen_server:call/3
, but with a slightly different exit reason if something goes wrong. This function calls the gen_leader
process exactly as if it were a gen_server (which, for practical purposes, it is.)
-spec candidates(#election{}) -> [node()].
-spec cast(Name :: name() | pid(), Request :: term()) -> ok.
Equivalent to gen_server:cast / 2.
-spec down(#election{}) -> [node()].
-spec leader_call(Name :: server_ref(), Request :: term()) -> term().
gen_server:call/2
) to the leader. The call is forwarded via the local gen_leader instance, if that one isn't actually the leader. The client will exit if the leader dies while the request is outstanding.This function uses gen:call/3
, and is subject to the same default timeout as e.g. gen_server:call/2
.
-spec leader_call(Name :: server_ref(), Request :: term(), Timeout :: integer()) -> term().
gen_server:call/3
) to the leader. The call is forwarded via the local gen_leader instance, if that one isn't actually the leader. The client will exit if the leader dies while the request is outstanding.
-spec leader_cast(Name :: name() | pid(), Request :: term()) -> ok.
gen_server:cast/2
but will be forwarded to the leader via the local gen_leader instance.
-spec leader_node(#election{}) -> node() | none.
-spec reply(From :: caller_ref(), Reply :: term()) -> term().
Equivalent to gen_server:reply / 2.
-spec start(Name :: atom(), CandidateNodes :: [node()], OptArgs :: options(), Mod :: module(), Arg :: term(), Options :: list()) -> start_ret().
See also: start_link/6.
-spec start_link(Name :: atom(), CandidateNodes :: [node()], OptArgs :: options(), Mod :: module(), Arg :: term(), Options :: list()) -> start_ret().
gen_leader
.- {workers, Workers}
- {vardir, Dir}
- {bcast_type, Type}
Type
is 'all' each election event (when a new candidate becomes visible to the leader) will be broadcast to all live candidate nodes. Each candidate will get a from_leader/3 callback. When Type
is sender
, only the newly registered candidate will get the surrendered/3 callback. Default: sender
.- {heartbeat, Seconds}
Mod:init/1
OptionsSame as gen_server's OptionsThe list of candidates needs to be known from the start. Workers could potentially be added at runtime, but no functionality to do this is provided by this version.
-spec workers(#election{}) -> [node()].