refactor(topic_index): no forced ceiling entry in index table

This commit is contained in:
Zaiming (Stone) Shi 2023-08-23 10:12:46 +02:00
parent f4c8c6be55
commit a1e6635614
3 changed files with 26 additions and 33 deletions

View File

@ -104,12 +104,16 @@ gbt_update(Name, Tree) ->
true. true.
gbt_next(nil, _Input) -> gbt_next(nil, _Input) ->
emqx_trie_search:ceiling(); '$end_of_table';
gbt_next({P, _V, _Smaller, Bigger}, K) when K >= P -> gbt_next({P, _V, _Smaller, Bigger}, K) when K >= P ->
gbt_next(Bigger, K); gbt_next(Bigger, K);
gbt_next({P, _V, Smaller, _Bigger}, K) -> gbt_next({P, _V, Smaller, _Bigger}, K) ->
NextKey = gbt_next(Smaller, K), case gbt_next(Smaller, K) of
min(P, NextKey). '$end_of_table' ->
P;
NextKey ->
NextKey
end.
make_nextf(Name) -> make_nextf(Name) ->
{_SizeWeDontCare, TheTree} = gbt(Name), {_SizeWeDontCare, TheTree} = gbt(Name),

View File

@ -35,9 +35,7 @@
%% Usable mostly for testing purposes. %% Usable mostly for testing purposes.
-spec new() -> ets:table(). -spec new() -> ets:table().
new() -> new() ->
T = ets:new(?MODULE, [public, ordered_set, {read_concurrency, true}]), ets:new(?MODULE, [public, ordered_set, {read_concurrency, true}]).
ets:insert(T, {emqx_trie_search:ceiling(), []}),
T.
%% @doc Insert a new entry into the index that associates given topic filter to given %% @doc Insert a new entry into the index that associates given topic filter to given
%% record ID, and attaches arbitrary record to the entry. This allows users to choose %% record ID, and attaches arbitrary record to the entry. This allows users to choose

View File

@ -98,14 +98,14 @@
-module(emqx_trie_search). -module(emqx_trie_search).
-export([ceiling/0, make_key/2]). -export([make_key/2]).
-export([match/2, matches/3, get_id/1, get_topic/1]). -export([match/2, matches/3, get_id/1, get_topic/1]).
-export_type([key/1, word/0, nextf/0, opts/0]). -export_type([key/1, word/0, nextf/0, opts/0]).
-type word() :: binary() | '+' | '#'. -type word() :: binary() | '+' | '#'.
-type base_key() :: {binary() | [word()], {}}. -type base_key() :: {binary() | [word()], {}}.
-type key(ID) :: {binary() | [word()], {ID}}. -type key(ID) :: {binary() | [word()], {ID}}.
-type nextf() :: fun((key(_) | base_key()) -> key(_)). -type nextf() :: fun((key(_) | base_key()) -> '$end_of_table' | key(_)).
-type opts() :: [unique | return_first]. -type opts() :: [unique | return_first].
%% Holds the constant values of each search. %% Holds the constant values of each search.
@ -134,19 +134,10 @@
matches = [] matches = []
}). }).
%% All valid utf8 bytes are less than 255.
-define(CEILING_TOPIC, <<255>>).
-define(CEILING, {?CEILING_TOPIC, {1}}).
%% @doc Return a key which is greater than all other valid keys.
ceiling() ->
?CEILING.
%% @doc Make a search-key for the given topic. %% @doc Make a search-key for the given topic.
-spec make_key(emqx_types:topic(), ID) -> key(ID). -spec make_key(emqx_types:topic(), ID) -> key(ID).
make_key(Topic, ID) when is_binary(Topic) -> make_key(Topic, ID) when is_binary(Topic) ->
Words = words(Topic), Words = words(Topic),
Key =
case lists:any(fun erlang:is_atom/1, Words) of case lists:any(fun erlang:is_atom/1, Words) of
true -> true ->
%% it's a wildcard %% it's a wildcard
@ -156,9 +147,7 @@ make_key(Topic, ID) when is_binary(Topic) ->
%% because they can be found with direct lookups. %% because they can be found with direct lookups.
%% it is also more compact in memory. %% it is also more compact in memory.
{Topic, {ID}} {Topic, {ID}}
end, end.
Key > ceiling() andalso throw({invalid_topic, Topic}),
Key.
%% @doc Extract record ID from the match. %% @doc Extract record ID from the match.
-spec get_id(key(ID)) -> ID. -spec get_id(key(ID)) -> ID.
@ -236,12 +225,14 @@ search(Topic, NextF, Opts) ->
%% The recursive entrypoint of the trie-search algorithm. %% The recursive entrypoint of the trie-search algorithm.
%% Always start from the initial prefix and words. %% Always start from the initial prefix and words.
search_new(#ctx{prefix0 = Prefix, words0 = Words0} = C, NewBase, Acc0) -> search_new(#ctx{prefix0 = Prefix, words0 = Words0} = C, NewBase, Acc0) ->
#acc{target = {Filter, _}} = Acc = move_up(C, Acc0, NewBase), case move_up(C, Acc0, NewBase) of
case Prefix of #acc{target = '$end_of_table'} = Acc ->
[] -> Acc;
#acc{target = {Filter, _}} = Acc when Prefix =:= [] ->
%% This is not a '$' topic, start from '+' %% This is not a '$' topic, start from '+'
search_plus(C, Words0, Filter, [], Acc); search_plus(C, Words0, Filter, [], Acc);
[DollarWord] -> #acc{target = {Filter, _}} = Acc ->
[DollarWord] = Prefix,
%% Start from the '$' word %% Start from the '$' word
search_up(C, DollarWord, Words0, Filter, [], Acc) search_up(C, DollarWord, Words0, Filter, [], Acc)
end. end.