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.
gbt_next(nil, _Input) ->
emqx_trie_search:ceiling();
'$end_of_table';
gbt_next({P, _V, _Smaller, Bigger}, K) when K >= P ->
gbt_next(Bigger, K);
gbt_next({P, _V, Smaller, _Bigger}, K) ->
NextKey = gbt_next(Smaller, K),
min(P, NextKey).
case gbt_next(Smaller, K) of
'$end_of_table' ->
P;
NextKey ->
NextKey
end.
make_nextf(Name) ->
{_SizeWeDontCare, TheTree} = gbt(Name),

View File

@ -35,9 +35,7 @@
%% Usable mostly for testing purposes.
-spec new() -> ets:table().
new() ->
T = ets:new(?MODULE, [public, ordered_set, {read_concurrency, true}]),
ets:insert(T, {emqx_trie_search:ceiling(), []}),
T.
ets:new(?MODULE, [public, ordered_set, {read_concurrency, true}]).
%% @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

View File

@ -98,14 +98,14 @@
-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_type([key/1, word/0, nextf/0, opts/0]).
-type word() :: binary() | '+' | '#'.
-type base_key() :: {binary() | [word()], {}}.
-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].
%% Holds the constant values of each search.
@ -134,19 +134,10 @@
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.
-spec make_key(emqx_types:topic(), ID) -> key(ID).
make_key(Topic, ID) when is_binary(Topic) ->
Words = words(Topic),
Key =
case lists:any(fun erlang:is_atom/1, Words) of
true ->
%% it's a wildcard
@ -156,9 +147,7 @@ make_key(Topic, ID) when is_binary(Topic) ->
%% because they can be found with direct lookups.
%% it is also more compact in memory.
{Topic, {ID}}
end,
Key > ceiling() andalso throw({invalid_topic, Topic}),
Key.
end.
%% @doc Extract record ID from the match.
-spec get_id(key(ID)) -> ID.
@ -236,12 +225,14 @@ search(Topic, NextF, Opts) ->
%% The recursive entrypoint of the trie-search algorithm.
%% Always start from the initial prefix and words.
search_new(#ctx{prefix0 = Prefix, words0 = Words0} = C, NewBase, Acc0) ->
#acc{target = {Filter, _}} = Acc = move_up(C, Acc0, NewBase),
case Prefix of
[] ->
case move_up(C, Acc0, NewBase) of
#acc{target = '$end_of_table'} = Acc ->
Acc;
#acc{target = {Filter, _}} = Acc when Prefix =:= [] ->
%% This is not a '$' topic, start from '+'
search_plus(C, Words0, Filter, [], Acc);
[DollarWord] ->
#acc{target = {Filter, _}} = Acc ->
[DollarWord] = Prefix,
%% Start from the '$' word
search_up(C, DollarWord, Words0, Filter, [], Acc)
end.