浏览代码

feat: reserved 1-1024 topic id for predefined topics

JianBo He 2 年之前
父节点
当前提交
9c4a576fb3

+ 2 - 0
apps/emqx_gateway_mqttsn/include/emqx_mqttsn.hrl

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

+ 21 - 20
apps/emqx_gateway_mqttsn/src/emqx_mqttsn_registry.erl

@@ -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()
+}.
+
 %%-----------------------------------------------------------------------------
+%% APIs
 
--spec persist_predefined_topics(list()) -> ok.
+-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)
             },

+ 2 - 1
apps/emqx_gateway_mqttsn/src/emqx_mqttsn_schema.erl

@@ -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)
             })},

+ 1 - 1
apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE.erl

@@ -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">>).

+ 4 - 3
apps/emqx_gateway_mqttsn/test/emqx_sn_registry_SUITE.erl

@@ -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(),