refactor(topic_index): no forced ceiling entry in index table
This commit is contained in:
parent
f4c8c6be55
commit
a1e6635614
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue