From ea7aa5bc41d2a584bb5ced928ed932515e95debb Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 8 Oct 2021 15:29:02 +0800 Subject: [PATCH] refactor(mgmt_api): use `select_table` congruously. --- .../src/emqx_gateway_api_clients.erl | 28 ++++++--------- apps/emqx_management/src/emqx_mgmt_api.erl | 35 ------------------- .../src/emqx_mgmt_api_clients.erl | 26 ++++++-------- .../src/emqx_mgmt_api_subscriptions.erl | 21 +++++------ 4 files changed, 30 insertions(+), 80 deletions(-) diff --git a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl index 8020b19fa..d084d3f9b 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl @@ -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 diff --git a/apps/emqx_management/src/emqx_mgmt_api.erl b/apps/emqx_management/src/emqx_mgmt_api.erl index a1d4cf813..f88cf0adb 100644 --- a/apps/emqx_management/src/emqx_mgmt_api.erl +++ b/apps/emqx_management/src/emqx_mgmt_api.erl @@ -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 diff --git a/apps/emqx_management/src/emqx_mgmt_api_clients.erl b/apps/emqx_management/src/emqx_mgmt_api_clients.erl index 6fa90ad83..b9b42e280 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_clients.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_clients.erl @@ -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 diff --git a/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl b/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl index 969ff9202..33e26d06f 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl @@ -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