Packages
ra
1.1.6
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_directory.erl
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(ra_directory).
-export([
init/1,
deinit/0,
register_name/3,
register_name/4,
register_name/5,
unregister_name/1,
where_is/1,
where_is_parent/1,
name_of/1,
cluster_name_of/1,
pid_of/1,
uid_of/1,
send/2,
overview/0,
list_registered/0
]).
-export_type([
]).
-include("ra.hrl").
-define(REVERSE_TBL, ra_directory_reverse).
% registry for a ra servers's locally unique name
-spec init(file:filename()) -> ok.
init(Dir) ->
_ = ets:new(?MODULE, [named_table,
public,
{read_concurrency, true},
{write_concurrency, true}
]),
ok = ra_lib:make_dir(Dir),
Dets = filename:join(Dir, "names.dets"),
{ok, ?REVERSE_TBL} = dets:open_file(?REVERSE_TBL,
[{file, Dets},
{auto_save, 500},
{access, read_write}]),
ok.
-spec deinit() -> ok.
deinit() ->
_ = ets:delete(?MODULE),
_ = dets:close(?REVERSE_TBL),
ok.
-spec register_name(ra_uid(), pid(), maybe(pid()), atom(),
ra_cluster_name()) -> yes | no.
register_name(UId, Pid, ParentPid, ServerName, ClusterName) ->
true = ets:insert(?MODULE, {UId, Pid, ParentPid, ServerName,
ClusterName}),
ok = dets:insert(?REVERSE_TBL, {ServerName, UId}),
yes.
-spec register_name(ra_uid(), pid(), maybe(pid()), atom()) -> yes | no.
register_name(UId, Pid, ParentPid, ServerName) ->
register_name(UId, Pid, ParentPid, ServerName, undefined).
-spec register_name(ra_uid(), pid(), atom()) -> yes | no.
register_name(UId, Pid, ServerName) ->
register_name(UId, Pid, undefined, ServerName).
-spec unregister_name(ra_uid()) -> ra_uid().
unregister_name(UId) ->
case ets:take(?MODULE, UId) of
[{_, _, _, ServerName, _}] ->
_ = ets:take(?MODULE, UId),
ok = dets:delete(?REVERSE_TBL, ServerName),
UId;
[] ->
UId
end.
-spec where_is(ra_uid() | atom()) -> pid() | undefined.
where_is(ServerName) when is_atom(ServerName) ->
case dets:lookup(?REVERSE_TBL, ServerName) of
[] -> undefined;
[{_, UId}] ->
where_is(UId)
end;
where_is(UId) when is_binary(UId) ->
case ets:lookup(?MODULE, UId) of
[{_, Pid, _, _, _}] -> Pid;
[] -> undefined
end.
-spec where_is_parent(ra_uid() | atom()) -> pid() | undefined.
where_is_parent(ServerName) when is_atom(ServerName) ->
case dets:lookup(?REVERSE_TBL, ServerName) of
[] -> undefined;
[{_, UId}] ->
where_is_parent(UId)
end;
where_is_parent(UId) when is_binary(UId) ->
case ets:lookup(?MODULE, UId) of
[{_, _, Pid, _, _}] -> Pid;
[] -> undefined
end.
-spec name_of(ra_uid()) -> maybe(atom()).
name_of(UId) ->
case ets:lookup(?MODULE, UId) of
[{_, _, _, ServerName, _}] -> ServerName;
[] -> undefined
end.
-spec cluster_name_of(ra_uid()) -> maybe(ra_cluster_name()).
cluster_name_of(UId) ->
case ets:lookup(?MODULE, UId) of
[{_, _, _, _, ClusterName}] -> ClusterName;
[] -> undefined
end.
-spec pid_of(ra_uid()) -> maybe(pid()).
pid_of(UId) ->
case ets:lookup(?MODULE, UId) of
[{_, Pid, _, _, _}] -> Pid;
[] -> undefined
end.
uid_of(ServerName) when is_atom(ServerName) ->
case dets:lookup(?REVERSE_TBL, ServerName) of
[] -> undefined;
[{_, UId}] ->
UId
end.
-spec send(ra_uid() | atom(), term()) -> pid().
send(UIdOrName, Msg) ->
case where_is(UIdOrName) of
undefined ->
exit({badarg, {UIdOrName, Msg}});
Pid ->
_ = erlang:send(Pid, Msg),
Pid
end.
overview() ->
Dir = ets:tab2list(?MODULE),
States = maps:from_list(ets:tab2list(ra_state)),
Snaps = maps:from_list(ets:tab2list(ra_log_snapshot_state)),
lists:foldl(fun ({UId, Pid, Parent, ServerName, ClusterName}, Acc) ->
Acc#{ServerName =>
#{uid => UId,
pid => Pid,
parent => Parent,
state => maps:get(ServerName, States, undefined),
cluster_name => ClusterName,
snapshot_state => maps:get(UId, Snaps,
undefined)}}
end, #{}, Dir).
-spec list_registered() -> [{atom(), ra_uid()}].
list_registered() ->
dets:select(?REVERSE_TBL, [{'_', [], ['$_']}]).