Skip to content

Commit

Permalink
mod_register: Migrate from one treap in ets to all in ets
Browse files Browse the repository at this point in the history
The old logic stores a single data structure in the ets table, a "treap", which
is then cleaned and scan, but we can do the same using a table of type
'ordered_set' and cleaning records in a similar fashion. Same logic, simpler
code, and potentially even more performant.
  • Loading branch information
NelsonVides committed Oct 12, 2023
1 parent 763f20f commit b66fc65
Showing 1 changed file with 17 additions and 28 deletions.
45 changes: 17 additions & 28 deletions src/mod_register.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@
start(HostType, #{iqdisc := IQDisc}) ->
[gen_iq_handler:add_iq_handler_for_domain(HostType, ?NS_REGISTER, Component, Fn, #{}, IQDisc) ||
{Component, Fn} <- iq_handlers()],
ejabberd_sup:create_ets_table(?TABLE, [named_table, public, {read_concurrency, true}]).
Concurrency = case IQDisc of
one_queue -> [];
_ -> [{read_concurrency, true}]
end,
ejabberd_sup:create_ets_table(?TABLE, [named_table, public | Concurrency]).

-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
Expand All @@ -61,7 +65,8 @@ stop(HostType) ->
ok.

iq_handlers() ->
[{ejabberd_local, fun ?MODULE:process_iq/5}, {ejabberd_sm, fun ?MODULE:process_iq/5}].
[{ejabberd_local, fun ?MODULE:process_iq/5},
{ejabberd_sm, fun ?MODULE:process_iq/5}].

-spec hooks(mongooseim:host_type()) -> gen_hook:hook_list().
hooks(HostType) ->
Expand Down Expand Up @@ -433,40 +438,24 @@ check_timeout(Source) ->
Timeout = mongoose_config:get_opt(registration_timeout),
case is_integer(Timeout) of
true ->
Priority = -(erlang:system_time(second)),
CleanPriority = Priority + Timeout,
check_and_store_ip_entry(Source, Priority, CleanPriority);
TS = erlang:system_time(second),
clean_ets(TS - Timeout),
check_and_store_ip_entry(Source, TS);
false ->
true
end.

check_and_store_ip_entry(Source, Priority, CleanPriority) ->
Treap = case ets:lookup(?TABLE, treap) of
[] -> treap:empty();
[{treap, T}] -> T
end,
Treap1 = clean_treap(Treap, CleanPriority),
case treap:lookup(Source, Treap1) of
error ->
Treap2 = treap:insert(Source, Priority, [], Treap1),
ets:insert(?TABLE, {treap, Treap2}),
check_and_store_ip_entry(Source, Timestamp) ->
case ets:member(?TABLE, Source) of
false ->
ets:insert(?TABLE, {Source, Timestamp}),
true;
{ok, _, _} ->
ets:insert(?TABLE, {treap, Treap1}),
true ->
false
end.

clean_treap(Treap, CleanPriority) ->
case treap:is_empty(Treap) of
true ->
Treap;
false ->
{_Key, Priority, _Value} = treap:get_root(Treap),
case Priority > CleanPriority of
true -> clean_treap(treap:delete_root(Treap), CleanPriority);
false -> Treap
end
end.
clean_ets(CleanPriority) ->
ets:select_delete(?TABLE, [{ {'_', '$1'}, [{'<', '$1', CleanPriority}], [true]}]).

ip_to_string(Source) when is_tuple(Source) -> inet_parse:ntoa(Source);
ip_to_string(undefined) -> "undefined";
Expand Down

0 comments on commit b66fc65

Please sign in to comment.