feat: reserved 1-1024 topic id for predefined topics

This commit is contained in:
JianBo He 2023-06-11 11:37:59 +08:00
parent ac6693c8cc
commit 9c4a576fb3
5 changed files with 31 additions and 26 deletions

View File

@ -14,6 +14,8 @@
%% limitations under the License.
%%--------------------------------------------------------------------
-define(SN_MAX_PREDEF_TOPIC_ID, 1024).
%%--------------------------------------------------------------------
%% MQTT-SN Types
%%--------------------------------------------------------------------

View File

@ -33,38 +33,40 @@
]).
-define(PKEY(Id), {mqttsn, predef_topics, Id}).
-define(PKEY_MAX_PREDEF_ID, {mqttsn, max_predef_topic_id}).
-type registry() :: #{
%% The next topic id to be assigned to new registration
next_topic_id := pos_integer(),
last_topic_id := pos_integer(),
%% The mapping from topic id to topic name
id_to_name := map(),
%% The mapping from topic name to topic id
name_to_id := map()
}.
%%-----------------------------------------------------------------------------
-type predef_topic() :: #{
id := 1..1024,
topic := iolist()
}.
-spec persist_predefined_topics(list()) -> ok.
%%-----------------------------------------------------------------------------
%% APIs
-spec persist_predefined_topics([predef_topic()]) -> ok.
persist_predefined_topics(PredefTopics) when is_list(PredefTopics) ->
MaxPredefId = lists:foldl(
fun(#{id := TopicId, topic := TopicName0}, AccId) ->
try
F = fun(#{id := TopicId, topic := TopicName0}) when TopicId =< 1024 ->
TopicName = iolist_to_binary(TopicName0),
persistent_term:put(?PKEY(TopicId), TopicName),
persistent_term:put(?PKEY(TopicName), TopicId),
case TopicId > AccId of
true -> TopicId;
false -> AccId
end
persistent_term:put(?PKEY(TopicName), TopicId)
end,
0,
PredefTopics
),
persistent_term:put(?PKEY_MAX_PREDEF_ID, MaxPredefId),
ok.
lists:foreach(F, PredefTopics)
catch
_:_ ->
clear_predefined_topics(PredefTopics),
error(badarg)
end.
-spec clear_predefined_topics(list()) -> ok.
-spec clear_predefined_topics([predef_topic()]) -> ok.
clear_predefined_topics(PredefTopics) ->
lists:foreach(
fun(#{id := TopicId, topic := TopicName0}) ->
@ -74,13 +76,12 @@ clear_predefined_topics(PredefTopics) ->
end,
PredefTopics
),
persistent_term:erase(?PKEY_MAX_PREDEF_ID),
ok.
-spec init() -> registry().
init() ->
#{
next_topic_id => persistent_term:get(?PKEY_MAX_PREDEF_ID, 0),
last_topic_id => ?SN_MAX_PREDEF_TOPIC_ID,
id_to_name => #{},
name_to_id => #{}
}.
@ -113,7 +114,7 @@ reg(
do_reg(
TopicName,
Registry = #{
next_topic_id := TopicId0,
last_topic_id := TopicId0,
id_to_name := IdMap,
name_to_id := NameMap
}
@ -123,7 +124,7 @@ do_reg(
{error, too_large};
NextTopicId ->
NRegistry = Registry#{
next_topic_id := NextTopicId,
last_topic_id := NextTopicId,
id_to_name := maps:put(NextTopicId, TopicName, IdMap),
name_to_id := maps:put(TopicName, NextTopicId, NameMap)
},

View File

@ -16,6 +16,7 @@
-module(emqx_mqttsn_schema).
-include("emqx_mqttsn.hrl").
-include_lib("hocon/include/hoconsc.hrl").
-include_lib("typerefl/include/types.hrl").
@ -72,7 +73,7 @@ fields(mqttsn) ->
fields(mqttsn_predefined) ->
[
{id,
sc(integer(), #{
sc(range(1, ?SN_MAX_PREDEF_TOPIC_ID), #{
required => true,
desc => ?DESC(mqttsn_predefined_id)
})},

View File

@ -47,7 +47,7 @@
-define(LOG(Format, Args), ct:log("TEST: " ++ Format, Args)).
-define(MAX_PRED_TOPIC_ID, 2).
-define(MAX_PRED_TOPIC_ID, ?SN_MAX_PREDEF_TOPIC_ID).
-define(PREDEF_TOPIC_ID1, 1).
-define(PREDEF_TOPIC_ID2, 2).
-define(PREDEF_TOPIC_NAME1, <<"/predefined/topic/name/hello">>).

View File

@ -19,10 +19,11 @@
-compile(export_all).
-compile(nowarn_export_all).
-include("emqx_mqttsn.hrl").
-include_lib("eunit/include/eunit.hrl").
-define(REGISTRY, emqx_mqttsn_registry).
-define(MAX_PREDEF_ID, 2).
-define(MAX_PREDEF_ID, ?SN_MAX_PREDEF_TOPIC_ID).
-define(PREDEF_TOPICS, [
#{id => 1, topic => <<"/predefined/topic/name/hello">>},
#{id => 2, topic => <<"/predefined/topic/name/nice">>}
@ -75,8 +76,8 @@ t_reach_maximum(_) ->
Reg0 = ?REGISTRY:init(),
Reg = register_a_lot(?MAX_PREDEF_ID + 1, 16#ffff, Reg0),
?assertEqual({error, too_large}, ?REGISTRY:reg(<<"TopicABC">>, Reg)),
?assertEqual(?MAX_PREDEF_ID + 1, ?REGISTRY:lookup_topic_id(<<"Topic3">>, Reg)),
?assertEqual(?MAX_PREDEF_ID + 2, ?REGISTRY:lookup_topic_id(<<"Topic4">>, Reg)).
?assertEqual(?MAX_PREDEF_ID + 1, ?REGISTRY:lookup_topic_id(<<"Topic1025">>, Reg)),
?assertEqual(?MAX_PREDEF_ID + 2, ?REGISTRY:lookup_topic_id(<<"Topic1026">>, Reg)).
t_deny_wildcard_topic(_) ->
Reg = ?REGISTRY:init(),