refactor(mgmt_api): use `select_table` congruously.

This commit is contained in:
JimMoen 2021-10-08 15:29:02 +08:00
parent b65c9908a1
commit ea7aa5bc41
4 changed files with 30 additions and 80 deletions

View File

@ -201,9 +201,9 @@ query(Tab, {Qs, []}, Continuation, Limit) ->
query(Tab, {Qs, Fuzzy}, Continuation, Limit) ->
Ms = qs2ms(Qs),
MatchFun = match_fun(Ms, Fuzzy),
emqx_mgmt_api:traverse_table(Tab, MatchFun, Continuation, Limit,
fun format_channel_info/1).
FuzzyFilterFun = fuzzy_filter_fun(Fuzzy),
emqx_mgmt_api:select_table(Tab, {Ms, FuzzyFilterFun}, Continuation, Limit,
fun format_channel_info/1).
qs2ms(Qs) ->
{MtchHead, Conds} = qs2ms(Qs, 2, {#{}, []}),
@ -247,32 +247,26 @@ ms(created_at, X) ->
#{session => #{created_at => X}}.
%%--------------------------------------------------------------------
%% Match funcs
%% Fuzzy filter funcs
match_fun(Ms, Fuzzy) ->
MsC = ets:match_spec_compile(Ms),
fuzzy_filter_fun(Fuzzy) ->
REFuzzy = lists:map(fun({K, like, S}) ->
{ok, RE} = re:compile(S),
{K, like, RE}
end, Fuzzy),
fun(Rows) ->
case ets:match_spec_run(Rows, MsC) of
[] -> [];
Ls ->
lists:filter(fun(E) ->
run_fuzzy_match(E, REFuzzy)
end, Ls)
end
fun(MsRaws) when is_list(MsRaws) ->
lists:filter( fun(E) -> run_fuzzy_filter(E, REFuzzy) end
, MsRaws)
end.
run_fuzzy_match(_, []) ->
run_fuzzy_filter(_, []) ->
true;
run_fuzzy_match(E = {_, #{clientinfo := ClientInfo}, _}, [{Key, _, RE}|Fuzzy]) ->
run_fuzzy_filter(E = {_, #{clientinfo := ClientInfo}, _}, [{Key, _, RE}|Fuzzy]) ->
Val = case maps:get(Key, ClientInfo, "") of
undefined -> "";
V -> V
end,
re:run(Val, RE, [{capture, none}]) == match andalso run_fuzzy_match(E, Fuzzy).
re:run(Val, RE, [{capture, none}]) == match andalso run_fuzzy_filter(E, Fuzzy).
%%--------------------------------------------------------------------
%% format funcs

View File

@ -27,7 +27,6 @@
%% first_next query APIs
-export([ node_query/5
, cluster_query/4
, traverse_table/5
, select_table/5
]).
@ -197,40 +196,6 @@ rpc_call(Node, M, F, A, T) ->
%% Table Select
%%--------------------------------------------------------------------
traverse_table(Tab, MatchFun, Start, Limit, FmtFun) ->
ets:safe_fixtable(Tab, true),
{NStart, Rows} = traverse_n_by_one(Tab, ets:first(Tab), MatchFun, Start, Limit, []),
ets:safe_fixtable(Tab, false),
{NStart, lists:map(FmtFun, Rows)}.
%% @private
traverse_n_by_one(_, '$end_of_table', _, Start, _, Acc) ->
{Start, lists:flatten(lists:reverse(Acc))};
traverse_n_by_one(_, _, _, Start, _Limit=0, Acc) ->
{Start, lists:flatten(lists:reverse(Acc))};
traverse_n_by_one(Tab, K, MatchFun, Start, Limit, Acc) ->
GetRows = fun _GetRows('$end_of_table', _, Ks) ->
{'$end_of_table', Ks};
_GetRows(Kn, 1, Ks) ->
{ets:next(Tab, Kn), [ets:lookup(Tab, Kn) | Ks]};
_GetRows(Kn, N, Ks) ->
_GetRows(ets:next(Tab, Kn), N-1, [ets:lookup(Tab, Kn) | Ks])
end,
{K2, Rows} = GetRows(K, 100, []),
case MatchFun(lists:flatten(lists:reverse(Rows))) of
[] ->
traverse_n_by_one(Tab, K2, MatchFun, Start, Limit, Acc);
Ls ->
case Start - length(Ls) of
N when N > 0 -> %% Skip
traverse_n_by_one(Tab, K2, MatchFun, N, Limit, Acc);
_ ->
Got = lists:sublist(Ls, Start+1, Limit),
NLimit = Limit - length(Got),
traverse_n_by_one(Tab, K2, MatchFun, 0, NLimit, [Got|Acc])
end
end.
select_table(Tab, {Ms, FuzzyFilterFun}, ?FRESH_SELECT, Limit, FmtFun)
when is_function(FuzzyFilterFun) andalso Limit > 0 ->
case ets:select(Tab, Ms, Limit) of

View File

@ -562,9 +562,9 @@ query(Tab, {Qs, []}, Continuation, Limit) ->
query(Tab, {Qs, Fuzzy}, Continuation, Limit) ->
Ms = qs2ms(Qs),
MatchFun = match_fun(Ms, Fuzzy),
emqx_mgmt_api:traverse_table(Tab, MatchFun, Continuation, Limit,
fun format_channel_info/1).
FuzzyFilterFun = fuzzy_filter_fun(Fuzzy),
emqx_mgmt_api:select_table(Tab, {Ms, FuzzyFilterFun}, Continuation, Limit,
fun format_channel_info/1).
%%--------------------------------------------------------------------
%% QueryString to Match Spec
@ -616,30 +616,24 @@ ms(created_at, X) ->
%%--------------------------------------------------------------------
%% Match funcs
match_fun(Ms, Fuzzy) ->
MsC = ets:match_spec_compile(Ms),
fuzzy_filter_fun(Fuzzy) ->
REFuzzy = lists:map(fun({K, like, S}) ->
{ok, RE} = re:compile(S),
{K, like, RE}
end, Fuzzy),
fun(Rows) ->
case ets:match_spec_run(Rows, MsC) of
[] -> [];
Ls ->
lists:filter(fun(E) ->
run_fuzzy_match(E, REFuzzy)
end, Ls)
end
fun(MsRaws) when is_list(MsRaws) ->
lists:filter( fun(E) -> run_fuzzy_filter(E, REFuzzy) end
, MsRaws)
end.
run_fuzzy_match(_, []) ->
run_fuzzy_filter(_, []) ->
true;
run_fuzzy_match(E = {_, #{clientinfo := ClientInfo}, _}, [{Key, _, RE}|Fuzzy]) ->
run_fuzzy_filter(E = {_, #{clientinfo := ClientInfo}, _}, [{Key, _, RE}|Fuzzy]) ->
Val = case maps:get(Key, ClientInfo, "") of
undefined -> "";
V -> V
end,
re:run(Val, RE, [{capture, none}]) == match andalso run_fuzzy_match(E, Fuzzy).
re:run(Val, RE, [{capture, none}]) == match andalso run_fuzzy_filter(E, Fuzzy).
%%--------------------------------------------------------------------
%% format funcs

View File

@ -154,22 +154,19 @@ query(Tab, {Qs, []}, Continuation, Limit) ->
query(Tab, {Qs, Fuzzy}, Continuation, Limit) ->
Ms = qs2ms(Qs),
MatchFun = match_fun(Ms, Fuzzy),
emqx_mgmt_api:traverse_table(Tab, MatchFun, Continuation, Limit, fun format/1).
FuzzyFilterFun = fuzzy_filter_fun(Fuzzy),
emqx_mgmt_api:select_table(Tab, {Ms, FuzzyFilterFun}, Continuation, Limit, fun format/1).
match_fun(Ms, Fuzzy) ->
MsC = ets:match_spec_compile(Ms),
fun(Rows) ->
case ets:match_spec_run(Rows, MsC) of
[] -> [];
Ls -> lists:filter(fun(E) -> run_fuzzy_match(E, Fuzzy) end, Ls)
end
fuzzy_filter_fun(Fuzzy) ->
fun(MsRaws) when is_list(MsRaws) ->
lists:filter( fun(E) -> run_fuzzy_filter(E, Fuzzy) end
, MsRaws)
end.
run_fuzzy_match(_, []) ->
run_fuzzy_filter(_, []) ->
true;
run_fuzzy_match(E = {{_, Topic}, _}, [{topic, match, TopicFilter}|Fuzzy]) ->
emqx_topic:match(Topic, TopicFilter) andalso run_fuzzy_match(E, Fuzzy).
run_fuzzy_filter(E = {{_, Topic}, _}, [{topic, match, TopicFilter}|Fuzzy]) ->
emqx_topic:match(Topic, TopicFilter) andalso run_fuzzy_filter(E, Fuzzy).
%%--------------------------------------------------------------------
%% Query String to Match Spec