Packages
ra
1.0.8
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.2
3.0.1
3.0.0
3.0.0-beta.1
2.17.3
2.17.2
2.17.1
2.17.0
2.16.13
2.16.12
2.16.11
2.16.10
2.16.9
2.16.8
2.16.7
2.16.6
2.16.5
2.16.4
2.16.3
2.16.2
2.16.1
2.16.0
2.16.0-pre.12
2.16.0-pre.11
2.16.0-pre.10
2.16.0-pre.9
2.16.0-pre.8
2.16.0-pre.7
2.16.0-pre.6
2.16.0-pre.5
2.16.0-pre.4
2.16.0-pre.3
2.16.0-pre.2
2.16.0-pre.1
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.0
2.13.6
2.13.5
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.13.0-pre.1
2.12.0
2.11.0
2.11.0-pre.1
2.10.2-pre.2
2.10.2-pre.1
2.10.1
2.10.0
2.10.0-pre.3
2.10.0-pre.2
2.10.0-pre.1
2.9.10-pre.1
2.9.1
2.9.1-pre.2
2.9.1-pre.1
2.9.0
2.8.0
retired
2.7.3
2.7.2
2.7.1
2.7.0
2.7.0-pre.3
2.7.0-pre.2
2.7.0-pre.1
2.6.3
2.6.2
2.6.1
2.6.0-pre.1
2.5.1
2.5.1-pre.1
2.5.0
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
retired
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.13
2.0.12
2.0.11
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.9.6
0.9.5
0.9.4
0.9.2
0.3.3
retired
0.3.2
retired
0.3.1
retired
Raft library
Current section
Files
Jump to
Current section
Files
src/ra_server_sup_sup.erl
%% @hidden
-module(ra_server_sup_sup).
-behaviour(supervisor).
%% API functions
-export([start_server/1,
restart_server/1,
stop_server/1,
delete_server/1,
remove_all/0,
start_link/0,
% for rpcs only
prepare_start_rpc/1,
prepare_restart_rpc/1,
delete_server_rpc/1]).
%% Supervisor callbacks
-export([init/1]).
-include("ra.hrl").
-spec start_server(ra_server:ra_server_config()) ->
supervisor:startchild_ret() | {error, not_new}.
start_server(#{id := NodeId,
uid := UId} = Config) ->
%% check that the node isn't already registered
Node = ra_lib:ra_server_id_node(NodeId),
case rpc:call(Node, ?MODULE, prepare_start_rpc, [UId]) of
ok ->
supervisor:start_child({?MODULE, Node}, [Config]);
Err ->
Err
end.
-spec restart_server(ra_server_id()) -> supervisor:startchild_ret().
restart_server({RaName, Node}) ->
case rpc:call(Node, ?MODULE, prepare_restart_rpc, [RaName]) of
{ok, Config} ->
supervisor:start_child({?MODULE, Node}, [Config]);
{error, _} = Err ->
Err;
Err ->
{error, Err}
end.
prepare_start_rpc(UId) ->
case ra_directory:name_of(UId) of
undefined ->
ok;
Name ->
case whereis(Name) of
undefined ->
{error, not_new};
Pid ->
{error, {already_started, Pid}}
end
end.
prepare_restart_rpc(RaName) ->
case ra_directory:uid_of(RaName) of
undefined ->
name_not_registered;
UId ->
Dir = ra_env:server_data_dir(UId),
case ra_directory:where_is(UId) of
Pid when is_pid(Pid) ->
case is_process_alive(Pid) of
true ->
{error, {already_started, Pid}};
false ->
ra_log:read_config(Dir)
end;
_ ->
% can it be made generic without already knowing the config state?
ra_log:read_config(Dir)
end
end.
-spec stop_server(RaNodeId :: ra_server_id()) -> ok | {error, term()}.
stop_server({RaName, Node}) ->
Pid = rpc:call(Node, ra_directory,
where_is_parent, [RaName]),
case Pid of
undefined ->
ok;
_ when is_pid(Pid) ->
supervisor:terminate_child({?MODULE, Node}, Pid);
Err ->
{error, Err}
end;
stop_server(RaName) ->
% local node
case ra_directory:where_is_parent(RaName) of
undefined -> ok;
Pid ->
supervisor:terminate_child(?MODULE, Pid)
end.
-spec delete_server(NodeId :: ra_server_id()) ->
ok | {error, term()} | {badrpc, term()}.
delete_server(NodeId) ->
Node = ra_lib:ra_server_id_node(NodeId),
Name = ra_lib:ra_server_id_to_local_name(NodeId),
case stop_server(NodeId) of
ok ->
rpc:call(Node, ?MODULE, delete_server_rpc, [Name]);
{error, _} = Err -> Err
end.
delete_server_rpc(RaName) ->
?INFO("Deleting server ~w and its data directory.~n",
[RaName]),
%% TODO: better handle and report errors
UId = ra_directory:uid_of(RaName),
Pid = ra_directory:where_is(RaName),
ra_log_meta:delete(UId),
Dir = ra_env:server_data_dir(UId),
_ = supervisor:terminate_child(?MODULE, UId),
_ = delete_data_directory(Dir),
_ = ra_directory:unregister_name(UId),
%% forcefully clean up ETS tables
catch ets:delete(ra_log_metrics, UId),
catch ets:delete(ra_log_snapshot_state, UId),
catch ets:delete(ra_metrics, RaName),
catch ets:delete(ra_state, RaName),
catch ets:delete(ra_open_file_metrics, Pid),
ok.
delete_data_directory(Directory) ->
DeleteFunction = fun() ->
try ra_lib:recursive_delete(Directory) of
ok ->
% moving on
ok
catch
_:_ = Err ->
?WARN("delete_server/1 failed to delete directory ~s~n"
"Error: ~p~n", [Directory, Err]),
error
end
end,
case DeleteFunction() of
ok ->
ok;
_ ->
spawn(fun() ->
ra_lib:retry(DeleteFunction, 2)
end)
end.
remove_all() ->
_ = [begin
?INFO("terminating child ~w~n", [Pid]),
supervisor:terminate_child(?MODULE, Pid)
end
|| {_, Pid, _, _} <- supervisor:which_children(?MODULE)],
ok.
-spec start_link() ->
{ok, pid()} | ignore | {error, term()}.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
SupFlags = #{strategy => simple_one_for_one},
ChildSpec = #{id => undefined,
type => supervisor,
restart => temporary,
start => {ra_server_sup, start_link, []}},
{ok, {SupFlags, [ChildSpec]}}.