Current section
Files
Jump to
Current section
Files
src/shards_owner.erl
%%%-------------------------------------------------------------------
%%% @doc
%%% ETS owner.
%%% @end
%%%-------------------------------------------------------------------
-module(shards_owner).
-behaviour(gen_server).
%% API
-export([
start_link/2,
apply_ets_fun/3,
stop/1
]).
%% gen_server callbacks
-export([
init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3
]).
%%%===================================================================
%%% API
%%%===================================================================
-spec start_link(atom(), atom()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Name, Options) ->
gen_server:start_link({local, Name}, ?MODULE, {Name, Options}, []).
-spec apply_ets_fun(atom(), atom(), [term()]) -> term().
apply_ets_fun(Name, Fun, Args) ->
gen_server:call(Name, {Fun, Args}).
-spec stop(atom()) -> ok.
stop(ShardName) ->
true = exit(whereis(ShardName), normal),
ok.
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
%% @hidden
init({Name, Options}) ->
_ = process_flag(trap_exit, true),
NewOpts =
case lists:keyfind(restore, 1, Options) of
{restore, _, _} = Val -> Val;
false -> Options
end,
init(Name, NewOpts).
%% @private
init(Name, {restore, ShardTabs, Options}) ->
{Name, Filename} = lists:keyfind(Name, 1, ShardTabs),
case ets:file2tab(Filename, Options) of
{ok, _} -> {ok, #{name => Name, opts => []}};
Error -> {stop, {restore_error, Error}}
end;
init(Name, Options) ->
NewOpts = validate_options(Options),
Name = ets:new(Name, NewOpts),
{ok, #{name => Name, opts => NewOpts}}.
%% @private
validate_options(Options) ->
Options1 =
case lists:member(named_table, Options) of
true -> Options;
_ -> [named_table | Options]
end,
case lists:member(public, Options1) of
true -> Options1;
_ -> [public | Options1]
end.
%% @hidden
handle_call({Fun, Args}, _From, #{name := Name} = State) ->
Response = apply(ets, Fun, [Name | Args]),
{reply, Response, State};
handle_call(_Request, _From, State) ->
{reply, ok, State}.
%% @hidden
handle_cast(_Request, State) ->
{noreply, State}.
%% @hidden
handle_info(_Info, State) ->
{noreply, State}.
%% @hidden
terminate(_Reason, _State) ->
ok.
%% @hidden
code_change(_OldVsn, State, _Extra) ->
{ok, State}.