feat: reserved 1-1024 topic id for predefined topics
This commit is contained in:
parent
ac6693c8cc
commit
9c4a576fb3
|
@ -14,6 +14,8 @@
|
|||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-define(SN_MAX_PREDEF_TOPIC_ID, 1024).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT-SN Types
|
||||
%%--------------------------------------------------------------------
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
})},
|
||||
|
|
|
@ -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">>).
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in New Issue