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. %% limitations under the License.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-define(SN_MAX_PREDEF_TOPIC_ID, 1024).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% MQTT-SN Types %% MQTT-SN Types
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

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

View File

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

View File

@ -47,7 +47,7 @@
-define(LOG(Format, Args), ct:log("TEST: " ++ Format, Args)). -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_ID1, 1).
-define(PREDEF_TOPIC_ID2, 2). -define(PREDEF_TOPIC_ID2, 2).
-define(PREDEF_TOPIC_NAME1, <<"/predefined/topic/name/hello">>). -define(PREDEF_TOPIC_NAME1, <<"/predefined/topic/name/hello">>).

View File

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