refactor(topic): move triples/1 func into emqx_trie module

This commit is contained in:
JianBo He 2020-06-18 12:36:25 +08:00 committed by JianBo He
parent 1700a7a98a
commit 9a8859a44c
5 changed files with 33 additions and 36 deletions

View File

@ -6,7 +6,7 @@
[{gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}}, [{gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}},
{jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.4"}}}, {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.4"}}},
{cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.7.1"}}}, {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.7.1"}}},
{esockd, {git, "https://github.com/emqx/esockd", {tag, "5.6.2"}}}, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.7.0"}}},
{ekka, {git, "https://github.com/emqx/ekka", {tag, "0.7.3"}}}, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.7.3"}}},
{gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.4.1"}}}, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.4.1"}}},
{cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.0.0"}}} {cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.0.0"}}}

View File

@ -21,7 +21,6 @@
, validate/1 , validate/1
, validate/2 , validate/2
, levels/1 , levels/1
, triples/1
, tokens/1 , tokens/1
, words/1 , words/1
, wildcard/1 , wildcard/1
@ -36,14 +35,12 @@
-export_type([ group/0 -export_type([ group/0
, topic/0 , topic/0
, word/0 , word/0
, triple/0
]). ]).
-type(group() :: binary()). -type(group() :: binary()).
-type(topic() :: binary()). -type(topic() :: binary()).
-type(word() :: '' | '+' | '#' | binary()). -type(word() :: '' | '+' | '#' | binary()).
-type(words() :: list(word())). -type(words() :: list(word())).
-type(triple() :: {root | binary(), word(), binary()}).
-define(MAX_TOPIC_LEN, 4096). -define(MAX_TOPIC_LEN, 4096).
@ -129,32 +126,15 @@ validate3(<<C/utf8, _Rest/binary>>) when C == $#; C == $+; C == 0 ->
validate3(<<_/utf8, Rest/binary>>) -> validate3(<<_/utf8, Rest/binary>>) ->
validate3(Rest). validate3(Rest).
%% @doc Topic to triples.
-spec(triples(topic()) -> list(triple())).
triples(Topic) when is_binary(Topic) ->
triples(words(Topic), root, []).
triples([], _Parent, Acc) ->
lists:reverse(Acc);
triples([W|Words], Parent, Acc) ->
Node = join(Parent, W),
triples(Words, Node, [{Parent, W, Node}|Acc]).
join(root, W) ->
bin(W);
join(Parent, W) ->
<<(bin(Parent))/binary, $/, (bin(W))/binary>>.
%% @doc Prepend a topic prefix. %% @doc Prepend a topic prefix.
%% Ensured to have only one / between prefix and suffix. %% Ensured to have only one / between prefix and suffix.
prepend(root, W) -> bin(W);
prepend(undefined, W) -> bin(W); prepend(undefined, W) -> bin(W);
prepend(<<>>, W) -> bin(W); prepend(<<>>, W) -> bin(W);
prepend(Parent0, W) -> prepend(Parent0, W) ->
Parent = bin(Parent0), Parent = bin(Parent0),
case binary:last(Parent) of case binary:last(Parent) of
$/ -> <<Parent/binary, (bin(W))/binary>>; $/ -> <<Parent/binary, (bin(W))/binary>>;
_ -> join(Parent, W) _ -> <<Parent/binary, $/, (bin(W))/binary>>
end. end.
bin('') -> <<>>; bin('') -> <<>>;

View File

@ -33,6 +33,13 @@
-export([empty/0]). -export([empty/0]).
-ifdef(TEST).
-compile(export_all).
-compile(nowarn_export_all).
-endif.
-type(triple() :: {root | binary(), emqx_topic:word(), binary()}).
%% Mnesia tables %% Mnesia tables
-define(TRIE_TAB, emqx_trie). -define(TRIE_TAB, emqx_trie).
-define(TRIE_NODE_TAB, emqx_trie_node). -define(TRIE_NODE_TAB, emqx_trie_node).
@ -80,7 +87,7 @@ insert(Topic) when is_binary(Topic) ->
write_trie_node(TrieNode#trie_node{topic = Topic}); write_trie_node(TrieNode#trie_node{topic = Topic});
[] -> [] ->
%% Add trie path %% Add trie path
ok = lists:foreach(fun add_path/1, emqx_topic:triples(Topic)), ok = lists:foreach(fun add_path/1, triples(Topic)),
%% Add last node %% Add last node
write_trie_node(#trie_node{node_id = Topic, topic = Topic}) write_trie_node(#trie_node{node_id = Topic, topic = Topic})
end. end.
@ -102,7 +109,7 @@ delete(Topic) when is_binary(Topic) ->
case mnesia:wread({?TRIE_NODE_TAB, Topic}) of case mnesia:wread({?TRIE_NODE_TAB, Topic}) of
[#trie_node{edge_count = 0}] -> [#trie_node{edge_count = 0}] ->
ok = mnesia:delete({?TRIE_NODE_TAB, Topic}), ok = mnesia:delete({?TRIE_NODE_TAB, Topic}),
delete_path(lists:reverse(emqx_topic:triples(Topic))); delete_path(lists:reverse(triples(Topic)));
[TrieNode] -> [TrieNode] ->
write_trie_node(TrieNode#trie_node{topic = undefined}); write_trie_node(TrieNode#trie_node{topic = undefined});
[] -> ok [] -> ok
@ -117,6 +124,22 @@ empty() ->
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% @doc Topic to triples.
-spec(triples(emqx_topic:topic()) -> list(triple())).
triples(Topic) when is_binary(Topic) ->
triples(emqx_topic:words(Topic), root, []).
triples([], _Parent, Acc) ->
lists:reverse(Acc);
triples([W|Words], Parent, Acc) ->
Node = join(Parent, W),
triples(Words, Node, [{Parent, W, Node}|Acc]).
join(root, W) ->
emqx_topic:join([W]);
join(Parent, W) ->
emqx_topic:join([Parent, W]).
%% @private %% @private
%% @doc Add a path to the trie. %% @doc Add a path to the trie.
add_path({Node, Word, Child}) -> add_path({Node, Word, Child}) ->

View File

@ -26,7 +26,6 @@
[ wildcard/1 [ wildcard/1
, match/2 , match/2
, validate/1 , validate/1
, triples/1
, prepend/2 , prepend/2
, join/1 , join/1
, words/1 , words/1
@ -143,18 +142,7 @@ t_sigle_level_validate(_) ->
true = validate({filter, <<"sport/+/player1">>}), true = validate({filter, <<"sport/+/player1">>}),
ok = ?catch_error(topic_invalid_char, validate({filter, <<"sport+">>})). ok = ?catch_error(topic_invalid_char, validate({filter, <<"sport+">>})).
t_triples(_) ->
Triples = [{root,<<"a">>,<<"a">>},
{<<"a">>,<<"b">>,<<"a/b">>},
{<<"a/b">>,<<"c">>,<<"a/b/c">>}],
?assertEqual(Triples, triples(<<"a/b/c">>)).
t_triples_perf(_) ->
Topic = <<"/abkc/19383/192939/akakdkkdkak/xxxyyuya/akakak">>,
ok = bench('triples/1', fun emqx_topic:triples/1, [Topic]).
t_prepend(_) -> t_prepend(_) ->
?assertEqual(<<"a/b/c">>, prepend(root, <<"a/b/c">>)),
?assertEqual(<<"ab">>, prepend(undefined, <<"ab">>)), ?assertEqual(<<"ab">>, prepend(undefined, <<"ab">>)),
?assertEqual(<<"a/b">>, prepend(<<>>, <<"a/b">>)), ?assertEqual(<<"a/b">>, prepend(<<>>, <<"a/b">>)),
?assertEqual(<<"x/a/b">>, prepend("x/", <<"a/b">>)), ?assertEqual(<<"x/a/b">>, prepend("x/", <<"a/b">>)),

View File

@ -141,6 +141,12 @@ t_delete3(_) ->
end, end,
?assertEqual({atomic, {[], []}}, trans(Fun)). ?assertEqual({atomic, {[], []}}, trans(Fun)).
t_triples(_) ->
Triples = [{root,<<"a">>,<<"a">>},
{<<"a">>,<<"b">>,<<"a/b">>},
{<<"a/b">>,<<"c">>,<<"a/b/c">>}],
?assertEqual(Triples, emqx_trie:triples(<<"a/b/c">>)).
clear_tables() -> clear_tables() ->
lists:foreach(fun mnesia:clear_table/1, ?TRIE_TABS). lists:foreach(fun mnesia:clear_table/1, ?TRIE_TABS).