refactor(topic): move triples/1 func into emqx_trie module
This commit is contained in:
parent
1700a7a98a
commit
9a8859a44c
|
@ -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"}}}
|
||||||
|
|
|
@ -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('') -> <<>>;
|
||||||
|
|
|
@ -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}) ->
|
||||||
|
|
|
@ -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">>)),
|
||||||
|
|
|
@ -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).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue