diff --git a/src/emqx.app.src b/src/emqx.app.src index 8798b6eab..f3ccb8fa3 100644 --- a/src/emqx.app.src +++ b/src/emqx.app.src @@ -6,6 +6,6 @@ {applications,[kernel,stdlib,gproc,lager,esockd,mochiweb,lager_syslog,pbkdf2,bcrypt,clique,jsx]}, {env,[]}, {mod,{emqx_app,[]}}, - {maintainers,["Feng Lee "]}, + {maintainers,["Feng Lee "]}, {licenses,["Apache-2.0"]}, {links,[{"Github","https://github.com/emqx/emqx"}]}]}. diff --git a/src/emqx.erl b/src/emqx.erl index 7d6e89427..a539bbd42 100644 --- a/src/emqx.erl +++ b/src/emqx.erl @@ -1,42 +1,36 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx). -include("emqx.hrl"). -%% Start/Stop Application +%% Start/Stop the application -export([start/0, is_running/1, stop/0]). %% PubSub API --export([subscribe/1, subscribe/2, subscribe/3, publish/1, - unsubscribe/1, unsubscribe/2]). +-export([subscribe/1, subscribe/2, subscribe/3]). +-export([publish/1]). +-export([unsubscribe/1, unsubscribe/2]). %% PubSub management API -export([topics/0, subscriptions/1, subscribers/1, subscribed/2]). - -%% Get/Set suboptions -export([get_subopts/2, set_subopts/3]). %% Hooks API -export([hook/4, hook/3, unhook/2, run_hooks/2, run_hooks/3]). -%% Debug API --export([dump/0]). - %% Shutdown and reboot -export([shutdown/0, shutdown/1, reboot/0]). @@ -76,16 +70,16 @@ is_running(Node) -> subscribe(Topic) -> emqx_broker:subscribe(iolist_to_binary(Topic)). --spec(subscribe(topic() | iodata(), subscriber() | string()) -> ok | {error, term()}). +-spec(subscribe(topic() | string(), subscriber() | string()) -> ok | {error, term()}). subscribe(Topic, Subscriber) -> emqx_broker:subscribe(iolist_to_binary(Topic), list_to_subid(Subscriber)). --spec(subscribe(topic() | iodata(), subscriber() | string(), [suboption()]) -> ok | {error, term()}). +-spec(subscribe(topic() | string(), subscriber() | string(), [suboption()]) -> ok | {error, term()}). subscribe(Topic, Subscriber, Options) -> emqx_broker:subscribe(iolist_to_binary(Topic), list_to_subid(Subscriber), Options). %% @doc Publish Message --spec(publish(message()) -> {ok, delivery()} | ignore). +-spec(publish(message()) -> {ok, delivery()} | {error, term()}). publish(Msg) -> emqx_broker:publish(Msg). @@ -118,7 +112,7 @@ subscribers(Topic) -> -spec(subscriptions(subscriber() | string()) -> [{topic(), list(suboption())}]). subscriptions(Subscriber) -> - emqx_broker:subscriptions(Subscriber). + emqx_broker:subscriptions(list_to_subid(Subscriber)). -spec(subscribed(topic() | string(), subscriber()) -> boolean()). subscribed(Topic, Subscriber) -> @@ -170,16 +164,10 @@ shutdown() -> shutdown(normal). shutdown(Reason) -> - emqx_logger:error("EMQ shutdown for ~s", [Reason]), + emqx_logger:error("emqx shutdown for ~s", [Reason]), emqx_plugins:unload(), lists:foreach(fun application:stop/1, [emqx, ekka, mochiweb, esockd, gproc]). reboot() -> lists:foreach(fun application:start/1, [gproc, esockd, mochiweb, ekka, emqx]). -%%-------------------------------------------------------------------- -%% Debug -%%-------------------------------------------------------------------- - -dump() -> lists:append([emqx_broker:dump(), emqx_router:dump()]). - diff --git a/src/emqx_access_control.erl b/src/emqx_access_control.erl index 869ef2649..75e49fe07 100644 --- a/src/emqx_access_control.erl +++ b/src/emqx_access_control.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_access_control). diff --git a/src/emqx_access_rule.erl b/src/emqx_access_rule.erl index 7eb4f2dc8..91c601db4 100644 --- a/src/emqx_access_rule.erl +++ b/src/emqx_access_rule.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_access_rule). @@ -73,8 +71,7 @@ compile(topic, Topic) -> end. 'pattern?'(Words) -> - lists:member(<<"%u">>, Words) - orelse lists:member(<<"%c">>, Words). + lists:member(<<"%u">>, Words) orelse lists:member(<<"%c">>, Words). bin(L) when is_list(L) -> list_to_binary(L); @@ -99,7 +96,7 @@ match_who(_Client, {user, all}) -> true; match_who(_Client, {client, all}) -> true; -match_who(#client{client_id = ClientId}, {client, ClientId}) -> +match_who(#client{id = ClientId}, {client, ClientId}) -> true; match_who(#client{username = Username}, {user, Username}) -> true; @@ -137,9 +134,9 @@ feed_var(Client, Pattern) -> feed_var(Client, Pattern, []). feed_var(_Client, [], Acc) -> lists:reverse(Acc); -feed_var(Client = #client{client_id = undefined}, [<<"%c">>|Words], Acc) -> +feed_var(Client = #client{id = undefined}, [<<"%c">>|Words], Acc) -> feed_var(Client, Words, [<<"%c">>|Acc]); -feed_var(Client = #client{client_id = ClientId}, [<<"%c">>|Words], Acc) -> +feed_var(Client = #client{id = ClientId}, [<<"%c">>|Words], Acc) -> feed_var(Client, Words, [ClientId |Acc]); feed_var(Client = #client{username = undefined}, [<<"%u">>|Words], Acc) -> feed_var(Client, Words, [<<"%u">>|Acc]); diff --git a/src/emqx_acl_internal.erl b/src/emqx_acl_internal.erl index 3f2824fbc..65a3199ae 100644 --- a/src/emqx_acl_internal.erl +++ b/src/emqx_acl_internal.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_acl_internal). diff --git a/src/emqx_acl_mod.erl b/src/emqx_acl_mod.erl index 217b2ecd6..85844b042 100644 --- a/src/emqx_acl_mod.erl +++ b/src/emqx_acl_mod.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_acl_mod). diff --git a/src/emqx_alarm.erl b/src/emqx_alarm_mgr.erl similarity index 52% rename from src/emqx_alarm.erl rename to src/emqx_alarm_mgr.erl index 2b5990db4..f6901c325 100644 --- a/src/emqx_alarm.erl +++ b/src/emqx_alarm_mgr.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,29 +11,24 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- --module(emqx_alarm). +-module(emqx_alarm_mgr). -behaviour(gen_event). -include("emqx.hrl"). --define(ALARM_MGR, ?MODULE). - -%% API Function Exports --export([start_link/0, alarm_fun/0, get_alarms/0, - set_alarm/1, clear_alarm/1, - add_alarm_handler/1, add_alarm_handler/2, - delete_alarm_handler/1]). +-export([start_link/0]). +-export([alarm_fun/0, get_alarms/0, set_alarm/1, clear_alarm/1]). +-export([add_alarm_handler/1, add_alarm_handler/2, delete_alarm_handler/1]). %% gen_event callbacks --export([init/1, handle_event/2, handle_call/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, + code_change/3]). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- +-define(ALARM_MGR, ?MODULE). + +-record(state, {alarms}). start_link() -> start_with(fun(Pid) -> gen_event:add_handler(Pid, ?MODULE, []) end). @@ -75,70 +69,72 @@ add_alarm_handler(Module, Args) when is_atom(Module) -> delete_alarm_handler(Module) when is_atom(Module) -> gen_event:delete_handler(?ALARM_MGR, Module, []). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Default Alarm handler -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -init(_) -> {ok, []}. +init(_) -> {ok, #state{alarms = []}}. -handle_event({set_alarm, Alarm = #alarm{id = AlarmId, - severity = Severity, - title = Title, - summary = Summary}}, Alarms)-> - TS = os:timestamp(), - case catch emqx_json:encode([{id, AlarmId}, - {severity, Severity}, - {title, iolist_to_binary(Title)}, - {summary, iolist_to_binary(Summary)}, - {ts, emqx_time:now_secs(TS)}]) of - {'EXIT', Reason} -> - emqx_logger:error("[Alarm] Failed to encode set_alarm: ~p", [Reason]); - JSON -> - emqx_broker:publish(alarm_msg(alert, AlarmId, JSON)) +handle_event({set_alarm, Alarm = #alarm{timestamp = undefined}}, State)-> + handle_event({set_alarm, Alarm#alarm{timestamp = os:timestamp()}}, State); + +handle_event({set_alarm, Alarm = #alarm{id = AlarmId}}, State = #state{alarms = Alarms}) -> + case encode_alarm(Alarm) of + {ok, Json} -> + emqx_broker:safe_publish(alarm_msg(alert, AlarmId, Json)); + {error, Reason} -> + emqx_logger:error("[AlarmMgr] Failed to encode alarm: ~p", [Reason]) end, - {ok, [Alarm#alarm{timestamp = TS} | Alarms]}; + {ok, State#state{alarms = [Alarm|Alarms]}}; -handle_event({clear_alarm, AlarmId}, Alarms) -> - case catch emqx_json:encode([{id, AlarmId}, {ts, emqx_time:now_secs()}]) of - {'EXIT', Reason} -> - emqx_logger:error("[Alarm] Failed to encode clear_alarm: ~p", [Reason]); - JSON -> - emqx_broker:publish(alarm_msg(clear, AlarmId, JSON)) +handle_event({clear_alarm, AlarmId}, State = #state{alarms = Alarms}) -> + case emqx_json:safe_encode([{id, AlarmId}, {ts, emqx_time:now_secs()}]) of + {ok, Json} -> + emqx_broker:safe_publish(alarm_msg(clear, AlarmId, Json)); + {error, Reason} -> + emqx_logger:error("[AlarmMgr] Failed to encode clear: ~p", [Reason]) end, - {ok, lists:keydelete(AlarmId, 2, Alarms), hibernate}; + {ok, State#state{alarms = lists:keydelete(AlarmId, 2, Alarms)}, hibernate}; -handle_event(_, Alarms)-> - {ok, Alarms}. +handle_event(Event, State)-> + error_logger:error("[AlarmMgr] unexpected event: ~p", [Event]), + {ok, State}. -handle_info(_, Alarms) -> - {ok, Alarms}. +handle_info(Info, State) -> + error_logger:error("[AlarmMgr] unexpected info: ~p", [Info]), + {ok, State}. -handle_call(get_alarms, Alarms) -> - {ok, Alarms, Alarms}; +handle_call(get_alarms, State = #state{alarms = Alarms}) -> + {ok, Alarms, State}; -handle_call(_Query, Alarms) -> - {ok, {error, bad_query}, Alarms}. - -terminate(swap, Alarms) -> - {?MODULE, Alarms}; +handle_call(Req, State) -> + error_logger:error("[AlarmMgr] unexpected call: ~p", [Req]), + {ok, ignored, State}. +terminate(swap, State) -> + {?MODULE, State}; terminate(_, _) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ + +encode_alarm(#alarm{id = AlarmId, severity = Severity, title = Title, + summary = Summary, timestamp = Ts}) -> + emqx_json:safe_encode([{id, AlarmId}, {severity, Severity}, + {title, iolist_to_binary(Title)}, + {summary, iolist_to_binary(Summary)}, + {ts, emqx_time:now_secs(Ts)}]). alarm_msg(Type, AlarmId, Json) -> - Msg = emqx_message:make(alarm, topic(Type, AlarmId), iolist_to_binary(Json)), - emqx_message:set_flag(sys, Msg). + emqx_message:make(?ALARM_MGR, #{sys => true, qos => 0}, topic(Type, AlarmId), Json). topic(alert, AlarmId) -> emqx_topic:systop(<<"alarms/", AlarmId/binary, "/alert">>); - topic(clear, AlarmId) -> emqx_topic:systop(<<"alarms/", AlarmId/binary, "/clear">>). diff --git a/src/emqx_app.erl b/src/emqx_app.erl index 54926f2a7..7a5426bae 100644 --- a/src/emqx_app.erl +++ b/src/emqx_app.erl @@ -1,24 +1,21 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_app). -behaviour(application). -%% Application callbacks -export([start/2, stop/1]). -define(APP, emqx). @@ -34,7 +31,7 @@ start(_Type, _Args) -> emqx_modules:load(), emqx_plugins:init(), emqx_plugins:load(), - emqx_listeners:start(), + emqx_listeners:start_all(), start_autocluster(), register(emqx, self()), print_vsn(), diff --git a/src/emqx_auth_mod.erl b/src/emqx_auth_mod.erl index 620584488..a5c3844a9 100644 --- a/src/emqx_auth_mod.erl +++ b/src/emqx_auth_mod.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_auth_mod). diff --git a/src/emqx_banned.erl b/src/emqx_banned.erl index ff5250f27..e2f03643e 100644 --- a/src/emqx_banned.erl +++ b/src/emqx_banned.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_banned). @@ -70,9 +68,7 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). -spec(check(client()) -> boolean()). -check(#client{client_id = ClientId, - username = Username, - peername = {IPAddr, _}}) -> +check(#client{id = ClientId, username = Username, peername = {IPAddr, _}}) -> ets:member(?TAB, {client_id, ClientId}) orelse ets:member(?TAB, {username, Username}) orelse ets:member(?TAB, {ipaddr, IPAddr}). diff --git a/src/emqx_base62.erl b/src/emqx_base62.erl index 3d0d01969..929089f1b 100644 --- a/src/emqx_base62.erl +++ b/src/emqx_base62.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All Rights Reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_base62). diff --git a/src/emqx_boot.erl b/src/emqx_boot.erl deleted file mode 100644 index dadc4c4cd..000000000 --- a/src/emqx_boot.erl +++ /dev/null @@ -1,63 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%%-------------------------------------------------------------------- - --module(emqx_boot). - --export([apply_module_attributes/1, all_module_attributes/1]). - -%% only {F, Args}... -apply_module_attributes(Name) -> - [{Module, [apply(Module, F, Args) || {F, Args} <- Attrs]} || - {_App, Module, Attrs} <- all_module_attributes(Name)]. - -%% Copy from rabbit_misc.erl -all_module_attributes(Name) -> - Targets = - lists:usort( - lists:append( - [[{App, Module} || Module <- Modules] || - {App, _, _} <- ignore_lib_apps(application:loaded_applications()), - {ok, Modules} <- [application:get_key(App, modules)]])), - lists:foldl( - fun ({App, Module}, Acc) -> - case lists:append([Atts || {N, Atts} <- module_attributes(Module), - N =:= Name]) of - [] -> Acc; - Atts -> [{App, Module, Atts} | Acc] - end - end, [], Targets). - -%% Copy from rabbit_misc.erl -module_attributes(Module) -> - case catch Module:module_info(attributes) of - {'EXIT', {undef, [{Module, module_info, [attributes], []} | _]}} -> - []; - {'EXIT', Reason} -> - exit(Reason); - V -> - V - end. - -ignore_lib_apps(Apps) -> - LibApps = [kernel, stdlib, sasl, appmon, eldap, erts, - syntax_tools, ssl, crypto, mnesia, os_mon, - inets, goldrush, lager, gproc, runtime_tools, - snmp, otp_mibs, public_key, asn1, ssh, hipe, - common_test, observer, webtool, xmerl, tools, - test_server, compiler, debugger, eunit, et, - wx], - [App || App = {Name, _, _} <- Apps, not lists:member(Name, LibApps)]. - diff --git a/src/emqx_bridge.erl b/src/emqx_bridge.erl index f45e4045c..ee2aa1535 100644 --- a/src/emqx_bridge.erl +++ b/src/emqx_bridge.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,22 +11,18 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_bridge). -behaviour(gen_server). -include("emqx.hrl"). - -include("emqx_mqtt.hrl"). -%% API Function Exports -export([start_link/5]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -define(PING_DOWN_INTERVAL, 1000). @@ -49,36 +44,31 @@ -export_type([option/0]). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - %% @doc Start a bridge --spec(start_link(any(), pos_integer(), atom(), binary(), [option()]) -> - {ok, pid()} | ignore | {error, term()}). +-spec(start_link(term(), pos_integer(), atom(), binary(), [option()]) + -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id, Node, Topic, Options) -> - gen_server:start_link(?MODULE, [Pool, Id, Node, Topic, Options], []). + gen_server:start_link(?MODULE, [Pool, Id, Node, Topic, Options], [{hibernate_after, 5000}]). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([Pool, Id, Node, Topic, Options]) -> process_flag(trap_exit, true), - gproc_pool:connect_worker(Pool, {Pool, Id}), + true = gproc_pool:connect_worker(Pool, {Pool, Id}), case net_kernel:connect_node(Node) of - true -> + true -> true = erlang:monitor_node(Node, true), Share = iolist_to_binary(["$bridge:", atom_to_list(Node), ":", Topic]), - %% TODO:: local??? - emqx_broker:subscribe(Topic, self(), [local, {share, Share}, {qos, ?QOS_0}]), + emqx_broker:subscribe(Topic, self(), [{share, Share}, {qos, ?QOS_0}]), State = parse_opts(Options, #state{node = Node, subtopic = Topic}), + %%TODO: queue.... MQueue = emqx_mqueue:new(qname(Node, Topic), [{max_len, State#state.max_queue_len}], emqx_alarm:alarm_fun()), - {ok, State#state{pool = Pool, id = Id, mqueue = MQueue}, - hibernate, {backoff, 1000, 1000, 10000}}; - false -> + {ok, State#state{pool = Pool, id = Id, mqueue = MQueue}}; + false -> {stop, {cannot_connect_node, Node}} end. @@ -103,44 +93,41 @@ qname(Node, Topic) -> iolist_to_binary(["Bridge:", Node, ":", Topic]). handle_call(Req, _From, State) -> - emqx_logger:error("[Bridge] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Bridge] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[Bridge] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Bridge] unexpected cast: ~p", [Msg]), {noreply, State}. -handle_info({dispatch, _Topic, Msg}, State = #state{mqueue = MQ, status = down}) -> - {noreply, State#state{mqueue = emqx_mqueue:in(Msg, MQ)}}; +handle_info({dispatch, _Topic, Msg}, State = #state{mqueue = Q, status = down}) -> + %% TODO: how to drop??? + {noreply, State#state{mqueue = emqx_mqueue:in(Msg, Q)}}; handle_info({dispatch, _Topic, Msg}, State = #state{node = Node, status = up}) -> - emqx_rpc:cast(Node, emqx, publish, [transform(Msg, State)]), - {noreply, State, hibernate}; + ok = emqx_rpc:cast(Node, emqx_broker, publish, [transform(Msg, State)]), + {noreply, State}; handle_info({nodedown, Node}, State = #state{node = Node, ping_down_interval = Interval}) -> - emqx_logger:warning("[Bridge] Node Down: ~s", [Node]), + emqx_logger:warning("[Bridge] node down: ~s", [Node]), erlang:send_after(Interval, self(), ping_down_node), {noreply, State#state{status = down}, hibernate}; handle_info({nodeup, Node}, State = #state{node = Node}) -> %% TODO: Really fast?? case emqx:is_running(Node) of - true -> - emqx_logger:warning("[Bridge] Node up: ~s", [Node]), - {noreply, dequeue(State#state{status = up})}; - false -> - self() ! {nodedown, Node}, - {noreply, State#state{status = down}} + true -> emqx_logger:warning("[Bridge] Node up: ~s", [Node]), + {noreply, dequeue(State#state{status = up})}; + false -> self() ! {nodedown, Node}, + {noreply, State#state{status = down}} end; handle_info(ping_down_node, State = #state{node = Node, ping_down_interval = Interval}) -> Self = self(), spawn_link(fun() -> case net_kernel:connect_node(Node) of - true -> %%TODO: this is not right... fixme later - Self ! {nodeup, Node}; - false -> - erlang:send_after(Interval, Self, ping_down_node) + true -> Self ! {nodeup, Node}; + false -> erlang:send_after(Interval, Self, ping_down_node) end end), {noreply, State}; @@ -149,7 +136,7 @@ handle_info({'EXIT', _Pid, normal}, State) -> {noreply, State}; handle_info(Info, State) -> - emqx_logger:error("[Bridge] Unexpected info: ~p", [Info]), + emqx_logger:error("[Bridge] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{pool = Pool, id = Id}) -> diff --git a/src/emqx_bridge_sup.erl b/src/emqx_bridge_sup.erl index 4f389c0dc..e7ba21310 100644 --- a/src/emqx_bridge_sup.erl +++ b/src/emqx_bridge_sup.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,16 +11,14 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_bridge_sup). +-include("emqx.hrl"). + -export([start_link/3]). - -%% @doc Start bridge pool supervisor --spec(start_link(atom(), binary(), [emqx_bridge:option()]) - -> {ok, pid()} | {error, term()}). +-spec(start_link(node(), topic(), [emqx_bridge:option()]) -> {ok, pid()} | {error, term()}). start_link(Node, Topic, Options) -> MFA = {emqx_bridge, start_link, [Node, Topic, Options]}, emqx_pool_sup:start_link({bridge, Node, Topic}, random, MFA). diff --git a/src/emqx_bridge_sup_sup.erl b/src/emqx_bridge_sup_sup.erl index 14fecaecc..4b34bedd9 100644 --- a/src/emqx_bridge_sup_sup.erl +++ b/src/emqx_bridge_sup_sup.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_bridge_sup_sup). @@ -23,6 +21,7 @@ -export([start_link/0, bridges/0]). -export([start_bridge/2, start_bridge/3, stop_bridge/2]). +%% Supervisor callbacks -export([init/1]). -define(CHILD_ID(Node, Topic), {bridge_sup, Node, Topic}). @@ -30,10 +29,6 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - %% @doc List all bridges -spec(bridges() -> [{node(), topic(), pid()}]). bridges() -> @@ -50,8 +45,7 @@ start_bridge(Node, Topic) when is_atom(Node), is_binary(Topic) -> start_bridge(Node, _Topic, _Options) when Node =:= node() -> {error, bridge_to_self}; start_bridge(Node, Topic, Options) when is_atom(Node), is_binary(Topic) -> - {ok, BridgeEnv} = emqx_config:get_env(bridge), - Options1 = emqx_misc:merge_opts(BridgeEnv, Options), + Options1 = emqx_misc:merge_opts(emqx_config:get_env(bridge, []), Options), supervisor:start_child(?MODULE, bridge_spec(Node, Topic, Options1)). %% @doc Stop a bridge @@ -63,15 +57,18 @@ stop_bridge(Node, Topic) when is_atom(Node), is_binary(Topic) -> Error -> Error end. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Supervisor callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> {ok, {{one_for_one, 10, 3600}, []}}. bridge_spec(Node, Topic, Options) -> - {?CHILD_ID(Node, Topic), - {emqx_bridge_sup, start_link, [Node, Topic, Options]}, - permanent, infinity, supervisor, [emqx_bridge_sup]}. + #{id => ?CHILD_ID(Node, Topic), + start => {emqx_bridge_sup, start_link, [Node, Topic, Options]}, + restart => permanent, + shutdown => infinity, + type => supervisor, + modules => [emqx_bridge_sup]}. diff --git a/src/emqx_broker.erl b/src/emqx_broker.erl index 5a6c9d954..43cc81155 100644 --- a/src/emqx_broker.erl +++ b/src/emqx_broker.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_broker). @@ -21,18 +19,17 @@ -include("emqx.hrl"). -export([start_link/2]). - -export([subscribe/1, subscribe/2, subscribe/3, subscribe/4]). --export([publish/1, publish/2]). +-export([publish/1, publish/2, safe_publish/1]). -export([unsubscribe/1, unsubscribe/2]). -export([dispatch/2, dispatch/3]). -export([subscriptions/1, subscribers/1, subscribed/2]). -export([get_subopts/2, set_subopts/3]). -export([topics/0]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {pool, id, submon}). @@ -44,19 +41,14 @@ -define(SUBSCRIBER, emqx_subscriber). -define(SUBSCRIPTION, emqx_subscription). -%%-------------------------------------------------------------------- -%% Start a broker -%%-------------------------------------------------------------------- - --spec(start_link(atom(), pos_integer()) - -> {ok, pid()} | ignore | {error, term()}). +-spec(start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id) -> gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, ?MODULE, [Pool, Id], [{hibernate_after, 2000}]). -%%-------------------------------------------------------------------- -%% Subscriber/Unsubscribe -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ +%% Subscribe/Unsubscribe +%%------------------------------------------------------------------------------ -spec(subscribe(topic()) -> ok | {error, term()}). subscribe(Topic) when is_binary(Topic) -> @@ -85,52 +77,60 @@ unsubscribe(Topic) when is_binary(Topic) -> unsubscribe(Topic, Subscriber) when is_binary(Topic) -> unsubscribe(Topic, Subscriber, ?TIMEOUT). --spec(unsubscribe(topic(), subscriber(), timeout()) - -> ok | {error, term()}). +-spec(unsubscribe(topic(), subscriber(), timeout()) -> ok | {error, term()}). unsubscribe(Topic, Subscriber, Timeout) -> {Topic1, _} = emqx_topic:parse(Topic), UnsubReq = {unsubscribe, Topic1, with_subpid(Subscriber)}, async_call(pick(Subscriber), UnsubReq, Timeout). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Publish -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(publish(topic(), payload()) -> delivery() | stopped). publish(Topic, Payload) when is_binary(Topic), is_binary(Payload) -> publish(emqx_message:make(Topic, Payload)). --spec(publish(message()) -> delivery() | stopped). +-spec(publish(message()) -> {ok, delivery()} | {error, stopped}). publish(Msg = #message{from = From}) -> %% Hook to trace? - trace(publish, From, Msg), + _ = trace(publish, From, Msg), case emqx_hooks:run('message.publish', [], Msg) of {ok, Msg1 = #message{topic = Topic}} -> - route(aggre(emqx_router:match_routes(Topic)), delivery(Msg1)); + {ok, route(aggre(emqx_router:match_routes(Topic)), delivery(Msg1))}; {stop, Msg1} -> emqx_logger:warning("Stop publishing: ~s", [emqx_message:format(Msg1)]), - stopped + {error, stopped} end. -%%-------------------------------------------------------------------- +%% called internally +safe_publish(Msg) -> + try + publish(Msg) + catch + _:Error:Stacktrace -> + emqx_logger:error("[Broker] publish error: ~p~n~p~n~p", [Error, Msg, Stacktrace]) + end. + +%%------------------------------------------------------------------------------ %% Trace -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ trace(publish, From, _Msg) when is_atom(From) -> %% Dont' trace '$SYS' publish ignore; -trace(public, #client{client_id = ClientId, username = Username}, +trace(public, #client{id = ClientId, username = Username}, #message{topic = Topic, payload = Payload}) -> emqx_logger:info([{client, ClientId}, {topic, Topic}], - "~s/~s PUBLISH to ~s: ~p", [ClientId, Username, Topic, Payload]); + "~s/~s PUBLISH to ~s: ~p", [Username, ClientId, Topic, Payload]); trace(public, From, #message{topic = Topic, payload = Payload}) when is_binary(From); is_list(From) -> emqx_logger:info([{client, From}, {topic, Topic}], "~s PUBLISH to ~s: ~p", [From, Topic, Payload]). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Route -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ route([], Delivery = #delivery{message = Msg}) -> emqx_hooks:run('message.dropped', [undefined, Msg]), @@ -193,7 +193,7 @@ dispatch({SubId, SubPid}, Topic, Msg) when is_binary(SubId), is_pid(SubPid) -> dispatch(SubId, Topic, Msg) when is_binary(SubId) -> emqx_sm:dispatch(SubId, Topic, Msg); dispatch({share, _Group, _Sub}, _Topic, _Msg) -> - ignore. + ignored. dropped(<<"$SYS/", _/binary>>) -> ok; @@ -201,16 +201,16 @@ dropped(_Topic) -> emqx_metrics:inc('messages/dropped'). delivery(Msg) -> - #delivery{message = Msg, flows = []}. + #delivery{node = node(), message = Msg, flows = []}. subscribers(Topic) -> try ets:lookup_element(?SUBSCRIBER, Topic, 2) catch error:badarg -> [] end. subscriptions(Subscriber) -> lists:map(fun({_, {share, _Group, Topic}}) -> - subscription(Topic, Subscriber); + subscription(Topic, Subscriber); ({_, Topic}) -> - subscription(Topic, Subscriber) + subscription(Topic, Subscriber) end, ets:lookup(?SUBSCRIPTION, Subscriber)). subscription(Topic, Subscriber) -> @@ -221,9 +221,7 @@ subscribed(Topic, SubPid) when is_binary(Topic), is_pid(SubPid) -> ets:member(?SUBOPTION, {Topic, SubPid}); subscribed(Topic, SubId) when is_binary(Topic), is_binary(SubId) -> length(ets:match_object(?SUBOPTION, {{Topic, {SubId, '_'}}, '_'}, 1)) == 1; -subscribed(Topic, {SubId, SubPid}) when is_binary(Topic), - is_binary(SubId), - is_pid(SubPid) -> +subscribed(Topic, {SubId, SubPid}) when is_binary(Topic), is_binary(SubId), is_pid(SubPid) -> ets:member(?SUBOPTION, {Topic, {SubId, SubPid}}). -spec(get_subopts(topic(), subscriber()) -> [suboption()]). @@ -262,26 +260,26 @@ pick(SubPid) when is_pid(SubPid) -> pick(SubId) when is_binary(SubId) -> gproc_pool:pick_worker(broker, SubId); pick({SubId, SubPid}) when is_binary(SubId), is_pid(SubPid) -> - pick(SubId). + pick(SubPid). -spec(topics() -> [topic()]). topics() -> emqx_router:topics(). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([Pool, Id]) -> - gproc_pool:connect_worker(Pool, {Pool, Id}), + true = gproc_pool:connect_worker(Pool, {Pool, Id}), {ok, #state{pool = Pool, id = Id, submon = emqx_pmon:new()}}. handle_call(Req, _From, State) -> - emqx_logger:error("[Broker] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Broker] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({From, {subscribe, Topic, Subscriber, Options}}, State) -> case ets:lookup(?SUBOPTION, {Topic, Subscriber}) of - [] -> + [] -> Group = proplists:get_value(share, Options), true = do_subscribe(Group, Topic, Subscriber, Options), emqx_shared_sub:subscribe(Group, Topic, subpid(Subscriber)), @@ -307,11 +305,10 @@ handle_cast({From, {unsubscribe, Topic, Subscriber}}, State) -> {noreply, State}; handle_cast(Msg, State) -> - emqx_logger:error("[Broker] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Broker] unexpected cast: ~p", [Msg]), {noreply, State}. -handle_info({'DOWN', _MRef, process, SubPid, _Reason}, - State = #state{submon = SubMon}) -> +handle_info({'DOWN', _MRef, process, SubPid, _Reason}, State = #state{submon = SubMon}) -> Subscriber = case SubMon:find(SubPid) of undefined -> SubPid; SubId -> {SubId, SubPid} @@ -321,7 +318,8 @@ handle_info({'DOWN', _MRef, process, SubPid, _Reason}, ({_, Topic}) -> Topic end, ets:lookup(?SUBSCRIPTION, Subscriber)), - lists:foreach(fun(Topic) -> + lists:foreach( + fun(Topic) -> case ets:lookup(?SUBOPTION, {Topic, Subscriber}) of [{_, Options}] -> Group = proplists:get_value(share, Options), @@ -336,18 +334,18 @@ handle_info({'DOWN', _MRef, process, SubPid, _Reason}, {noreply, demonitor_subscriber(SubPid, State)}; handle_info(Info, State) -> - emqx_logger:error("[Broker] Unexpected info: ~p", [Info]), + emqx_logger:error("[Broker] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{pool = Pool, id = Id}) -> - gproc_pool:disconnect_worker(Pool, {Pool, Id}). + true = gproc_pool:disconnect_worker(Pool, {Pool, Id}). code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- -%% Internal Functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ +%% Internal functions +%%------------------------------------------------------------------------------ do_subscribe(Group, Topic, Subscriber, Options) -> ets:insert(?SUBSCRIPTION, {Subscriber, shared(Group, Topic)}), diff --git a/src/emqx_broker_helper.erl b/src/emqx_broker_helper.erl index f461c44c7..975b2bf0d 100644 --- a/src/emqx_broker_helper.erl +++ b/src/emqx_broker_helper.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_broker_helper). @@ -20,8 +18,8 @@ -export([start_link/0]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -define(HELPER, ?MODULE). @@ -31,24 +29,24 @@ start_link() -> gen_server:start_link({local, ?HELPER}, ?MODULE, [], []). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> emqx_stats:update_interval(broker_stats, stats_fun()), {ok, #state{}, hibernate}. handle_call(Req, _From, State) -> - emqx_logger:error("[BrokerHelper] Unexpected request: ~p", [Req]), + emqx_logger:error("[BrokerHelper] unexpected call: ~p", [Req]), {reply, ignore, State}. handle_cast(Msg, State) -> - emqx_logger:error("[BrokerHelper] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[BrokerHelper] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info(Info, State) -> - emqx_logger:error("[BrokerHelper] Unexpected info: ~p", [Info]), + emqx_logger:error("[BrokerHelper] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{}) -> @@ -57,9 +55,9 @@ terminate(_Reason, #state{}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ stats_fun() -> fun() -> diff --git a/src/emqx_broker_sup.erl b/src/emqx_broker_sup.erl index 034d87711..51f6e72aa 100644 --- a/src/emqx_broker_sup.erl +++ b/src/emqx_broker_sup.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_broker_sup). @@ -27,15 +25,15 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Supervisor callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> %% Create the pubsub tables - lists:foreach(fun create_tab/1, [subscription, subscriber, suboption]), + ok = lists:foreach(fun create_tab/1, [subscription, subscriber, suboption]), - %% Shared Subscription + %% Shared subscription SharedSub = {shared_sub, {emqx_shared_sub, start_link, []}, permanent, 5000, worker, [emqx_shared_sub]}, @@ -43,16 +41,16 @@ init([]) -> Helper = {broker_helper, {emqx_broker_helper, start_link, []}, permanent, 5000, worker, [emqx_broker_helper]}, - %% Broker Pool + %% Broker pool BrokerPool = emqx_pool_sup:spec(emqx_broker_pool, [broker, hash, emqx_vm:schedulers() * 2, {emqx_broker, start_link, []}]), {ok, {{one_for_all, 0, 1}, [SharedSub, Helper, BrokerPool]}}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Create tables -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ create_tab(suboption) -> %% Suboption: {Topic, Sub} -> [{qos, 1}] diff --git a/src/emqx_cli.erl b/src/emqx_cli.erl index ffbacb35e..4463f2b27 100644 --- a/src/emqx_cli.erl +++ b/src/emqx_cli.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_cli). diff --git a/src/emqx_client.erl b/src/emqx_client.erl index 277d7ecd8..87b1e2bf3 100644 --- a/src/emqx_client.erl +++ b/src/emqx_client.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_client). @@ -142,9 +140,9 @@ -define(PROPERTY(Name, Val), #state{properties = #{Name := Val}}). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% API -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(start_link() -> gen_statem:start_ret()). start_link() -> start_link([]). @@ -302,9 +300,9 @@ disconnect(Client, ReasonCode) -> disconnect(Client, ReasonCode, Properties) -> gen_statem:call(Client, {disconnect, ReasonCode, Properties}). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% For test cases -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ puback(Client, PacketId) when is_integer(PacketId) -> puback(Client, PacketId, ?RC_SUCCESS). @@ -357,9 +355,9 @@ pause(Client) -> resume(Client) -> gen_statem:call(Client, resume). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_statem callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([Options]) -> process_flag(trap_exit, true), @@ -892,9 +890,9 @@ terminate(_Reason, _State, #state{socket = Socket}) -> code_change(_Vsn, State, Data, _Extra) -> {ok, State, Data}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ ensure_keepalive_timer(State = ?PROPERTY('Server-Keep-Alive', Secs)) -> ensure_keepalive_timer(timer:seconds(Secs), State); @@ -1017,7 +1015,7 @@ msg_to_packet(#mqtt_message{qos = Qos, payload = Payload}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Socket Connect/Send sock_connect(Hosts, SockOpts, Timeout) -> @@ -1057,7 +1055,7 @@ send(Packet, State = #state{socket = Sock, proto_ver = Ver}) run_sock(State = #state{socket = Sock}) -> emqx_client_sock:setopts(Sock, [{active, once}]), State. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Receive Loop receive_loop(<<>>, State) -> @@ -1076,7 +1074,7 @@ receive_loop(Bytes, State = #state{parse_state = ParseState}) -> {stop, Error} end. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Next packet id next_packet_id(State = #state{last_packet_id = 16#ffff}) -> diff --git a/src/emqx_client_sock.erl b/src/emqx_client_sock.erl index a7bc5aa15..dc19a8d91 100644 --- a/src/emqx_client_sock.erl +++ b/src/emqx_client_sock.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_client_sock). @@ -26,8 +24,7 @@ -type(sockname() :: {inet:ip_address(), inet:port_number()}). --type(option() :: gen_tcp:connect_option() - | {ssl_opts, [ssl:ssl_option()]}). +-type(option() :: gen_tcp:connect_option() | {ssl_opts, [ssl:ssl_option()]}). -export_type([socket/0, option/0]). diff --git a/src/emqx_cm.erl b/src/emqx_cm.erl index 9e3edf0b7..0adb07603 100644 --- a/src/emqx_cm.erl +++ b/src/emqx_cm.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_cm). @@ -22,20 +20,18 @@ -export([start_link/0]). --export([lookup_client/1, register_client/1, register_client/2, - unregister_client/1]). +-export([lookup_client/1]). +-export([register_client/1, register_client/2, unregister_client/1]). -export([get_client_attrs/1, lookup_client_pid/1]). - -export([get_client_stats/1, set_client_stats/2]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {client_pmon}). -define(CM, ?MODULE). - %% ETS Tables. -define(CLIENT, emqx_client). -define(CLIENT_ATTRS, emqx_client_attrs). @@ -56,22 +52,20 @@ lookup_client(ClientId) when is_binary(ClientId) -> register_client(ClientId) when is_binary(ClientId) -> register_client({ClientId, self()}); -register_client({ClientId, ClientPid}) when is_binary(ClientId), - is_pid(ClientPid) -> +register_client({ClientId, ClientPid}) when is_binary(ClientId), is_pid(ClientPid) -> register_client({ClientId, ClientPid}, []). -spec(register_client({client_id(), pid()}, list()) -> ok). -register_client({ClientId, ClientPid}, Attrs) when is_binary(ClientId), - is_pid(ClientPid) -> - ets:insert(?CLIENT, {ClientId, ClientPid}), - ets:insert(?CLIENT_ATTRS, {{ClientId, ClientPid}, Attrs}), +register_client(CObj = {ClientId, ClientPid}, Attrs) when is_binary(ClientId), is_pid(ClientPid) -> + _ = ets:insert(?CLIENT, CObj), + _ = ets:insert(?CLIENT_ATTRS, {CObj, Attrs}), notify({registered, ClientId, ClientPid}). %% @doc Get client attrs -spec(get_client_attrs({client_id(), pid()}) -> list()). -get_client_attrs({ClientId, ClientPid}) when is_binary(ClientId), - is_pid(ClientPid) -> - try ets:lookup_element(?CLIENT_ATTRS, {ClientId, ClientPid}, 2) +get_client_attrs(CObj = {ClientId, ClientPid}) when is_binary(ClientId), is_pid(ClientPid) -> + try + ets:lookup_element(?CLIENT_ATTRS, CObj, 2) catch error:badarg -> [] end. @@ -81,11 +75,10 @@ get_client_attrs({ClientId, ClientPid}) when is_binary(ClientId), unregister_client(ClientId) when is_binary(ClientId) -> unregister_client({ClientId, self()}); -unregister_client({ClientId, ClientPid}) when is_binary(ClientId), - is_pid(ClientPid) -> - ets:delete(?CLIENT_STATS, {ClientId, ClientPid}), - ets:delete(?CLIENT_ATTRS, {ClientId, ClientPid}), - ets:delete_object(?CLIENT, {ClientId, ClientPid}), +unregister_client(CObj = {ClientId, ClientPid}) when is_binary(ClientId), is_pid(ClientPid) -> + _ = ets:delete(?CLIENT_STATS, CObj), + _ = ets:delete(?CLIENT_ATTRS, CObj), + _ = ets:delete_object(?CLIENT, CObj), notify({unregistered, ClientId, ClientPid}). %% @doc Lookup client pid @@ -98,9 +91,8 @@ lookup_client_pid(ClientId) when is_binary(ClientId) -> %% @doc Get client stats -spec(get_client_stats({client_id(), pid()}) -> list(emqx_stats:stats())). -get_client_stats({ClientId, ClientPid}) when is_binary(ClientId), - is_pid(ClientPid) -> - try ets:lookup_element(?CLIENT_STATS, {ClientId, ClientPid}, 2) +get_client_stats(CObj = {ClientId, ClientPid}) when is_binary(ClientId), is_pid(ClientPid) -> + try ets:lookup_element(?CLIENT_STATS, CObj, 2) catch error:badarg -> [] end. @@ -110,16 +102,15 @@ get_client_stats({ClientId, ClientPid}) when is_binary(ClientId), set_client_stats(ClientId, Stats) when is_binary(ClientId) -> set_client_stats({ClientId, self()}, Stats); -set_client_stats({ClientId, ClientPid}, Stats) when is_binary(ClientId), - is_pid(ClientPid) -> - ets:insert(?CLIENT_STATS, {{ClientId, ClientPid}, Stats}). +set_client_stats(CObj = {ClientId, ClientPid}, Stats) when is_binary(ClientId), is_pid(ClientPid) -> + ets:insert(?CLIENT_STATS, {CObj, Stats}). notify(Msg) -> gen_server:cast(?CM, {notify, Msg}). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([]) -> TabOpts = [public, set, {write_concurrency, true}], @@ -130,8 +121,8 @@ init([]) -> {ok, #state{client_pmon = emqx_pmon:new()}}. handle_call(Req, _From, State) -> - emqx_logger:error("[CM] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[CM] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({notify, {registered, ClientId, Pid}}, State = #state{client_pmon = PMon}) -> {noreply, State#state{client_pmon = emqx_pmon:monitor(Pid, ClientId, PMon)}}; @@ -140,7 +131,7 @@ handle_cast({notify, {unregistered, _ClientId, Pid}}, State = #state{client_pmon {noreply, State#state{client_pmon = emqx_pmon:demonitor(Pid, PMon)}}; handle_cast(Msg, State) -> - emqx_logger:error("[CM] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[CM] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({'DOWN', _MRef, process, DownPid, _Reason}, State = #state{client_pmon = PMon}) -> @@ -152,7 +143,7 @@ handle_info({'DOWN', _MRef, process, DownPid, _Reason}, State = #state{client_pm end; handle_info(Info, State) -> - emqx_logger:error("[CM] Unexpected info: ~p", [Info]), + emqx_logger:error("[CM] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, _State = #state{}) -> @@ -161,9 +152,9 @@ terminate(_Reason, _State = #state{}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Internal functions -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- update_client_stats() -> case ets:info(?CLIENT, size) of diff --git a/src/emqx_cm_sup.erl b/src/emqx_cm_sup.erl index 9b98e0c97..231822ba5 100644 --- a/src/emqx_cm_sup.erl +++ b/src/emqx_cm_sup.erl @@ -1,18 +1,17 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_cm_sup). @@ -26,7 +25,11 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - CM = {emqx_cm, {emqx_cm, start_link, []}, - permanent, 5000, worker, [emqx_cm]}, - {ok, {{one_for_all, 10, 3600}, [CM]}}. + {ok, {{one_for_all, 10, 3600}, + [#{id => manager, + start => {emqx_cm, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_cm]}]}}. diff --git a/src/emqx_config.erl b/src/emqx_config.erl index ef1d8ec9f..d1456f644 100644 --- a/src/emqx_config.erl +++ b/src/emqx_config.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- %% @doc Hot Configuration %% @@ -35,7 +33,7 @@ -define(APP, emqx). --spec(get_env(Key :: atom(), Default :: any()) -> undefined | any()). +-spec(get_env(Key :: atom(), Default :: term()) -> term()). get_env(Key, Default) -> application:get_env(?APP, Key, Default). diff --git a/src/emqx_connection.erl b/src/emqx_connection.erl index fe0518072..544646701 100644 --- a/src/emqx_connection.erl +++ b/src/emqx_connection.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_connection). @@ -41,8 +39,8 @@ -export([session/1]). %% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - code_change/3, terminate/2]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, + terminate/2]). %% Unused fields: connname, peerhost, peerport -record(state, {transport, socket, peername, conn_state, await_recv, @@ -88,7 +86,7 @@ clean_acl_cache(CPid, Topic) -> gen_server:call(CPid, {clean_acl_cache, Topic}). %%-------------------------------------------------------------------- -%% gen_server Callbacks +%% gen_server callbacks %%-------------------------------------------------------------------- init([Transport, Sock, Env]) -> diff --git a/src/emqx_ctl.erl b/src/emqx_ctl.erl index a2228564a..46d97e757 100644 --- a/src/emqx_ctl.erl +++ b/src/emqx_ctl.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_ctl). @@ -22,9 +20,8 @@ -export([register_command/2, register_command/3, unregister_command/1]). -export([run_command/2, lookup_command/1]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {seq = 0}). @@ -33,10 +30,6 @@ -define(SERVER, ?MODULE). -define(TAB, emqx_command). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). @@ -64,9 +57,8 @@ run_command(Cmd, Args) when is_atom(Cmd) -> try Mod:Fun(Args) of _ -> ok catch - _:Reason -> - emqx_logger:error("[CTL] CMD Error:~p, Stacktrace:~p", - [Reason, erlang:get_stacktrace()]), + _:Reason:Stacktrace -> + emqx_logger:error("[CTL] CMD Error:~p, Stacktrace:~p", [Reason, Stacktrace]), {error, Reason} end; [] -> @@ -83,19 +75,19 @@ lookup_command(Cmd) when is_atom(Cmd) -> usage() -> io:format("Usage: ~s~n", [?MODULE]), [begin io:format("~80..-s~n", [""]), Mod:Cmd(usage) end - || {_, {Mod, Cmd}, _} <- ets:tab2list(?TAB)]. + || {_, {Mod, Cmd}, _} <- ets:tab2list(?TAB)]. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> _ = emqx_tables:new(?TAB, [ordered_set, protected]), {ok, #state{seq = 0}}. handle_call(Req, _From, State) -> - emqx_logger:error("Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({register_command, Cmd, MF, Opts}, State = #state{seq = Seq}) -> case ets:match(?TAB, {{'$1', Cmd}, '_', '_'}) of @@ -111,11 +103,11 @@ handle_cast({unregister_command, Cmd}, State) -> noreply(State); handle_cast(Msg, State) -> - emqx_logger:error("Unexpected msg: ~p", [Msg]), + emqx_logger:error("Unexpected cast: ~p", [Msg]), noreply(State). handle_info(Info, State) -> - emqx_logger:error("Unexpected info: ~p", [Info]), + emqx_logger:error("unexpected info: ~p", [Info]), noreply(State). terminate(_Reason, _State) -> @@ -124,9 +116,9 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal Function -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ noreply(State) -> {noreply, State, hibernate}. diff --git a/src/emqx_flapping.erl b/src/emqx_flapping.erl index bf19c50ee..56dac9110 100644 --- a/src/emqx_flapping.erl +++ b/src/emqx_flapping.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,8 +11,8 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- +%% @doc TODO: %% 1. Flapping Detection %% 2. Conflict Detection? -module(emqx_flapping). diff --git a/src/emqx_flow_control.erl b/src/emqx_flow_control.erl index 6effb1d53..e5042e9a7 100644 --- a/src/emqx_flow_control.erl +++ b/src/emqx_flow_control.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_flow_control). diff --git a/src/emqx_frame.erl b/src/emqx_frame.erl index ae2ab010d..0a261db6e 100644 --- a/src/emqx_frame.erl +++ b/src/emqx_frame.erl @@ -1,25 +1,26 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_frame). -include("emqx.hrl"). - -include("emqx_mqtt.hrl"). +-export([initial_state/0, initial_state/1]). +-export([parse/2]). +-export([serialize/1, serialize/2]). + -type(options() :: #{max_packet_size => 1..?MAX_PACKET_SIZE, version => mqtt_version()}). @@ -30,16 +31,11 @@ -export_type([options/0, parse_state/0]). --export([initial_state/0, initial_state/1]). --export([parse/2]). --export([serialize/1, serialize/2]). +-define(DEFAULT_OPTIONS, #{max_packet_size => ?MAX_PACKET_SIZE, version => ?MQTT_PROTO_V4}). --define(DEFAULT_OPTIONS, #{max_packet_size => ?MAX_PACKET_SIZE, - version => ?MQTT_PROTO_V4}). - -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Init parse state -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(initial_state() -> {none, options()}). initial_state() -> @@ -52,12 +48,11 @@ initial_state(Options) when is_map(Options) -> merge_opts(Options) -> maps:merge(?DEFAULT_OPTIONS, Options). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Parse MQTT Frame -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ --spec(parse(binary(), parse_state()) - -> {ok, mqtt_packet(), binary()} | {more, cont_fun(binary())}). +-spec(parse(binary(), parse_state()) -> {ok, mqtt_packet(), binary()} | {more, cont_fun(binary())}). parse(<<>>, {none, Options}) -> {more, fun(Bin) -> parse(Bin, {none, Options}) end}; parse(<>, {none, Options}) -> @@ -357,9 +352,9 @@ parse_utf8_string(<>) -> parse_binary_data(<>) -> {Data, Rest}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Serialize MQTT Packet -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(serialize(mqtt_packet()) -> iodata()). serialize(Packet) -> @@ -369,8 +364,7 @@ serialize(Packet) -> serialize(#mqtt_packet{header = Header, variable = Variable, payload = Payload}, Options) when is_map(Options) -> - serialize(Header, serialize_variable(Variable, merge_opts(Options)), - serialize_payload(Payload)). + serialize(Header, serialize_variable(Variable, merge_opts(Options)), serialize_payload(Payload)). serialize(#mqtt_packet_header{type = Type, dup = Dup, @@ -622,10 +616,6 @@ serialize_variable_byte_integer(N) when N =< ?LOWBITS -> serialize_variable_byte_integer(N) -> <<1:1, (N rem ?HIGHBIT):7, (serialize_variable_byte_integer(N div ?HIGHBIT))/binary>>. -%%-------------------------------------------------------------------- -%% Internal functions -%%-------------------------------------------------------------------- - bool(0) -> false; bool(1) -> true. diff --git a/src/emqx_gc.erl b/src/emqx_gc.erl index 4901cce5e..2cc0b2a1a 100644 --- a/src/emqx_gc.erl +++ b/src/emqx_gc.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,12 +11,16 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- %% GC Utility functions. -module(emqx_gc). +%% Memory: (10, 100, 1000) +%% + +%%-record + -export([conn_max_gc_count/0, reset_conn_gc_count/2, maybe_force_gc/2, maybe_force_gc/3]). diff --git a/src/emqx_gen_mod.erl b/src/emqx_gen_mod.erl index 184b77fb8..42466fdd9 100644 --- a/src/emqx_gen_mod.erl +++ b/src/emqx_gen_mod.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_gen_mod). diff --git a/src/emqx_guid.erl b/src/emqx_guid.erl index 02941baa3..43855c734 100644 --- a/src/emqx_guid.erl +++ b/src/emqx_guid.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,15 +11,14 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- %% @doc Generate global unique id for mqtt message. %% %% -------------------------------------------------------- -%% | Timestamp | NodeID + PID | Sequence | +%% | Timestamp | NodeID + PID | Sequence | %% |<------- 64bits ------->|<--- 48bits --->|<- 16bits ->| %% -------------------------------------------------------- -%% +%% %% 1. Timestamp: erlang:system_time if Erlang >= R18, otherwise os:timestamp %% 2. NodeId: encode node() to 2 bytes integer %% 3. Pid: encode pid to 4 bytes integer diff --git a/src/emqx_hooks.erl b/src/emqx_hooks.erl index 06bd0eabe..0aa3e274c 100644 --- a/src/emqx_hooks.erl +++ b/src/emqx_hooks.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_hooks). diff --git a/src/emqx_inflight.erl b/src/emqx_inflight.erl index e2d77d95b..3353983d8 100644 --- a/src/emqx_inflight.erl +++ b/src/emqx_inflight.erl @@ -1,90 +1,89 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_inflight). -export([new/1, contain/2, lookup/2, insert/3, update/3, delete/2, values/1, to_list/1, size/1, max_size/1, is_full/1, is_empty/1, window/1]). --type(inflight() :: {max_size, gb_trees:tree()}). +-type(max_size() :: pos_integer()). +-type(inflight() :: {?MODULE, max_size(), gb_trees:tree()}). -export_type([inflight/0]). -spec(new(non_neg_integer()) -> inflight()). new(MaxSize) when MaxSize >= 0 -> - {MaxSize, gb_trees:empty()}. + {?MODULE, MaxSize, gb_trees:empty()}. -spec(contain(Key :: term(), inflight()) -> boolean()). -contain(Key, {_MaxSize, Tree}) -> +contain(Key, {?MODULE, _MaxSize, Tree}) -> gb_trees:is_defined(Key, Tree). -spec(lookup(Key :: term(), inflight()) -> {value, term()} | none). -lookup(Key, {_MaxSize, Tree}) -> +lookup(Key, {?MODULE, _MaxSize, Tree}) -> gb_trees:lookup(Key, Tree). -spec(insert(Key :: term(), Value :: term(), inflight()) -> inflight()). -insert(Key, Value, {MaxSize, Tree}) -> - {MaxSize, gb_trees:insert(Key, Value, Tree)}. +insert(Key, Value, {?MODULE, MaxSize, Tree}) -> + {?MODULE, MaxSize, gb_trees:insert(Key, Value, Tree)}. -spec(delete(Key :: term(), inflight()) -> inflight()). -delete(Key, {MaxSize, Tree}) -> - {MaxSize, gb_trees:delete(Key, Tree)}. +delete(Key, {?MODULE, MaxSize, Tree}) -> + {?MODULE, MaxSize, gb_trees:delete(Key, Tree)}. -spec(update(Key :: term(), Val :: term(), inflight()) -> inflight()). -update(Key, Val, {MaxSize, Tree}) -> - {MaxSize, gb_trees:update(Key, Val, Tree)}. +update(Key, Val, {?MODULE, MaxSize, Tree}) -> + {?MODULE, MaxSize, gb_trees:update(Key, Val, Tree)}. -spec(is_full(inflight()) -> boolean()). -is_full({0, _Tree}) -> +is_full({?MODULE, 0, _Tree}) -> false; -is_full({MaxSize, Tree}) -> +is_full({?MODULE, MaxSize, Tree}) -> MaxSize =< gb_trees:size(Tree). -spec(is_empty(inflight()) -> boolean()). -is_empty({_MaxSize, Tree}) -> +is_empty({?MODULE, _MaxSize, Tree}) -> gb_trees:is_empty(Tree). -spec(smallest(inflight()) -> {K :: term(), V :: term()}). -smallest({_MaxSize, Tree}) -> +smallest({?MODULE, _MaxSize, Tree}) -> gb_trees:smallest(Tree). -spec(largest(inflight()) -> {K :: term(), V :: term()}). -largest({_MaxSize, Tree}) -> +largest({?MODULE, _MaxSize, Tree}) -> gb_trees:largest(Tree). -spec(values(inflight()) -> list()). -values({_MaxSize, Tree}) -> +values({?MODULE, _MaxSize, Tree}) -> gb_trees:values(Tree). -spec(to_list(inflight()) -> list({K :: term(), V :: term()})). -to_list({_MaxSize, Tree}) -> +to_list({?MODULE, _MaxSize, Tree}) -> gb_trees:to_list(Tree). -spec(window(inflight()) -> list()). -window(Inflight = {_MaxSize, Tree}) -> +window(Inflight = {?MODULE, _MaxSize, Tree}) -> case gb_trees:is_empty(Tree) of true -> []; false -> [Key || {Key, _Val} <- [smallest(Inflight), largest(Inflight)]] end. -spec(size(inflight()) -> non_neg_integer()). -size({_MaxSize, Tree}) -> +size({?MODULE, _MaxSize, Tree}) -> gb_trees:size(Tree). -spec(max_size(inflight()) -> non_neg_integer()). -max_size({MaxSize, _Tree}) -> +max_size({?MODULE, MaxSize, _Tree}) -> MaxSize. diff --git a/src/emqx_json.erl b/src/emqx_json.erl index e3b4241d6..9c0740b33 100644 --- a/src/emqx_json.erl +++ b/src/emqx_json.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_json). diff --git a/src/emqx_keepalive.erl b/src/emqx_keepalive.erl index ae38d28bc..25740b099 100644 --- a/src/emqx_keepalive.erl +++ b/src/emqx_keepalive.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_keepalive). diff --git a/src/emqx_kernel_sup.erl b/src/emqx_kernel_sup.erl index 486c20705..96dde598c 100644 --- a/src/emqx_kernel_sup.erl +++ b/src/emqx_kernel_sup.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_kernel_sup). @@ -36,8 +34,18 @@ init([]) -> child_spec(emqx_tracer, worker)]}}. child_spec(M, worker) -> - {M, {M, start_link, []}, permanent, 5000, worker, [M]}; + #{id => M, + start => {M, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [M]}; child_spec(M, supervisor) -> - {M, {M, start_link, []}, - permanent, infinity, supervisor, [M]}. + #{id => M, + start => {M, start_link, []}, + restart => permanent, + shutdown => infinity, + type => supervisor, + modules => [M]}. + diff --git a/src/emqx_lager_backend.erl b/src/emqx_lager_backend.erl index a307d5d8b..b002ff7af 100644 --- a/src/emqx_lager_backend.erl +++ b/src/emqx_lager_backend.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_lager_backend). diff --git a/src/emqx_listeners.erl b/src/emqx_listeners.erl index d63a6d620..02de39123 100644 --- a/src/emqx_listeners.erl +++ b/src/emqx_listeners.erl @@ -1,97 +1,62 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% @doc start/stop MQTT listeners. -module(emqx_listeners). -include("emqx_mqtt.hrl"). --export([start/0, restart/0, stop/0]). +-export([start_all/0, restart_all/0, stop_all/0]). -export([start_listener/1, stop_listener/1, restart_listener/1]). --export([all/0]). -type(listener() :: {atom(), esockd:listen_on(), [esockd:option()]}). -%%-------------------------------------------------------------------- -%% Start/Stop Listeners -%%-------------------------------------------------------------------- - -%% @doc Start Listeners. --spec(start() -> ok). -start() -> +%% @doc Start all listeners +-spec(start_all() -> ok). +start_all() -> lists:foreach(fun start_listener/1, emqx_config:get_env(listeners, [])). -%% Start mqtt listener --spec(start_listener(listener()) -> {ok, pid()} | {error, any()}). -start_listener({tcp, ListenOn, Opts}) -> - start_listener('mqtt:tcp', ListenOn, Opts); +%% Start MQTT/TCP listener +-spec(start_listener(listener()) -> {ok, pid()} | {error, term()}). +start_listener({tcp, ListenOn, Options}) -> + start_mqtt_listener('mqtt:tcp', ListenOn, Options); +%% Start MQTT/TLS listener +start_listener({Proto, ListenOn, Options}) when Proto == ssl; Proto == tls -> + start_mqtt_listener('mqtt:tls', ListenOn, Options); +%% Start MQTT/WS listener +start_listener({Proto, ListenOn, Options}) when Proto == http; Proto == ws -> + start_http_listener('mqtt:ws', ListenOn, Options); +%% Start MQTT/WSS listener +start_listener({Proto, ListenOn, Options}) when Proto == https; Proto == wss -> + start_http_listener('mqtt:wss', ListenOn, Options). -%% Start mqtt(SSL) listener -start_listener({ssl, ListenOn, Opts}) -> - start_listener('mqtt:ssl', ListenOn, Opts); +start_mqtt_listener(Name, ListenOn, Options) -> + {ok, _} = esockd:open(Name, ListenOn, merge_sockopts(Options), {emqx_connection, start_link, []}). -%% Start http listener -start_listener({Proto, ListenOn, Opts}) when Proto == http; Proto == ws -> - {ok, _} = mochiweb:start_http('mqtt:ws', ListenOn, Opts, {emqx_ws, handle_request, []}); +start_http_listener(Name, ListenOn, Options) -> + {ok, _} = mochiweb:start_http(Name, ListenOn, Options, {emqx_ws, handle_request, []}). -%% Start https listener -start_listener({Proto, ListenOn, Opts}) when Proto == https; Proto == wss -> - {ok, _} = mochiweb:start_http('mqtt:wss', ListenOn, Opts, {emqx_ws, handle_request, []}). - -start_listener(Proto, ListenOn, Opts) -> - Env = lists:append(emqx_config:get_env(client, []), - emqx_config:get_env(protocol, [])), - MFArgs = {emqx_connection, start_link, [Env]}, - {ok, _} = esockd:open(Proto, ListenOn, merge_sockopts(Opts), MFArgs). - -all() -> - [Listener || Listener = {{Proto, _}, _Pid} <- esockd:listeners(), is_mqtt(Proto)]. - -is_mqtt('mqtt:tcp') -> true; -is_mqtt('mqtt:ssl') -> true; -is_mqtt('mqtt:ws') -> true; -is_mqtt('mqtt:wss') -> true; -is_mqtt(_Proto) -> false. - -%% @doc Stop Listeners --spec(stop() -> ok). -stop() -> - lists:foreach(fun stop_listener/1, emqx_config:get_env(listeners, [])). - --spec(stop_listener(listener()) -> ok | {error, any()}). -stop_listener({tcp, ListenOn, _Opts}) -> - esockd:close('mqtt:tcp', ListenOn); -stop_listener({ssl, ListenOn, _Opts}) -> - esockd:close('mqtt:ssl', ListenOn); -stop_listener({Proto, ListenOn, _Opts}) when Proto == http; Proto == ws -> - mochiweb:stop_http('mqtt:ws', ListenOn); -stop_listener({Proto, ListenOn, _Opts}) when Proto == https; Proto == wss -> - mochiweb:stop_http('mqtt:wss', ListenOn); -stop_listener({Proto, ListenOn, _Opts}) -> - esockd:close(Proto, ListenOn). - -%% @doc Restart Listeners --spec(restart() -> ok). -restart() -> +%% @doc Restart all listeners +-spec(restart_all() -> ok). +restart_all() -> lists:foreach(fun restart_listener/1, emqx_config:get_env(listeners, [])). -spec(restart_listener(listener()) -> any()). restart_listener({tcp, ListenOn, _Opts}) -> esockd:reopen('mqtt:tcp', ListenOn); -restart_listener({ssl, ListenOn, _Opts}) -> - esockd:reopen('mqtt:ssl', ListenOn); +restart_listener({Proto, ListenOn, _Opts}) when Proto == ssl; Proto == tls -> + esockd:reopen('mqtt:tls', ListenOn); restart_listener({Proto, ListenOn, _Opts}) when Proto == http; Proto == ws -> mochiweb:restart_http('mqtt:ws', ListenOn); restart_listener({Proto, ListenOn, _Opts}) when Proto == https; Proto == wss -> @@ -99,10 +64,36 @@ restart_listener({Proto, ListenOn, _Opts}) when Proto == https; Proto == wss -> restart_listener({Proto, ListenOn, _Opts}) -> esockd:reopen(Proto, ListenOn). +%% @doc Stop all listeners +-spec(stop_all() -> ok). +stop_all() -> + lists:foreach(fun stop_listener/1, emqx_config:get_env(listeners, [])). + +-spec(stop_listener(listener()) -> ok | {error, any()}). +stop_listener({tcp, ListenOn, _Opts}) -> + esockd:close('mqtt:tcp', ListenOn); +stop_listener({Proto, ListenOn, _Opts}) when Proto == ssl; Proto == tls -> + esockd:close('mqtt:tls', ListenOn); +stop_listener({Proto, ListenOn, _Opts}) when Proto == http; Proto == ws -> + mochiweb:stop_http('mqtt:ws', ListenOn); +stop_listener({Proto, ListenOn, _Opts}) when Proto == https; Proto == wss -> + mochiweb:stop_http('mqtt:wss', ListenOn); +stop_listener({Proto, ListenOn, _Opts}) -> + esockd:close(Proto, ListenOn). + merge_sockopts(Options) -> - %%TODO: tcp_options? - SockOpts = emqx_misc:merge_opts( - ?MQTT_SOCKOPTS, proplists:get_value(sockopts, Options, [])), - emqx_misc:merge_opts(Options, [{sockopts, SockOpts}]). + case lists:keytake(tcp_options, 1, Options) of + {value, {tcp_options, TcpOpts}, Options1} -> + [{tcp_options, emqx_misc:merge_opts(?MQTT_SOCKOPTS, TcpOpts)} | Options1]; + false -> + [{tcp_options, ?MQTT_SOCKOPTS} | Options] + end. +%% all() -> +%% [Listener || Listener = {{Proto, _}, _Pid} <- esockd:listeners(), is_mqtt(Proto)]. +%%is_mqtt('mqtt:tcp') -> true; +%%is_mqtt('mqtt:tls') -> true; +%%is_mqtt('mqtt:ws') -> true; +%%is_mqtt('mqtt:wss') -> true; +%%is_mqtt(_Proto) -> false. diff --git a/src/emqx_logger.erl b/src/emqx_logger.erl index 0c5cf9240..2af5cd6b7 100644 --- a/src/emqx_logger.erl +++ b/src/emqx_logger.erl @@ -1,28 +1,26 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_logger). -compile({no_auto_import,[error/1]}). --export([debug/1, debug/2, debug/3, - info/1, info/2, info/3, - warning/1, warning/2, warning/3, - error/1, error/2, error/3, - critical/1, critical/2, critical/3]). +-export([debug/1, debug/2, debug/3]). +-export([info/1, info/2, info/3]). +-export([warning/1, warning/2, warning/3]). +-export([error/1, error/2, error/3]). +-export([critical/1, critical/2, critical/3]). debug(Msg) -> lager:debug(Msg). diff --git a/src/emqx_message.erl b/src/emqx_message.erl index 79adf6ad1..3a96f75a6 100644 --- a/src/emqx_message.erl +++ b/src/emqx_message.erl @@ -1,45 +1,46 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_message). -include("emqx.hrl"). -include("emqx_mqtt.hrl"). --export([make/2, make/3, make/4]). --export([get_flag/2, get_flag/3, set_flag/2, unset_flag/2]). +-export([new/2, new/3, new/4, new/5]). +-export([get_flag/2, get_flag/3, set_flag/2, set_flag/3, unset_flag/2]). -export([get_header/2, get_header/3, set_header/3]). -export([get_user_property/2, get_user_property/3, set_user_property/3]). --spec(make(topic(), payload()) -> message()). -make(Topic, Payload) -> - make(undefined, Topic, Payload). +-spec(new(topic(), payload()) -> message()). +new(Topic, Payload) -> + new(undefined, Topic, Payload). -%% Create a message --spec(make(atom() | client(), topic(), payload()) -> message()). -make(From, Topic, Payload) when is_atom(From); is_record(From, client) -> - make(From, ?QOS_0, Topic, Payload). +-spec(new(atom() | client(), topic(), payload()) -> message()). +new(From, Topic, Payload) when is_atom(From); is_record(From, client) -> + new(From, #{qos => ?QOS0}, Topic, Payload). -make(From, QoS, Topic, Payload) when is_atom(From); is_record(From, client) -> +-spec(new(atom() | client(), message_flags(), topic(), payload()) -> message()). +new(From, Flags, Topic, Payload) when is_atom(From); is_record(From, client) -> + new(From, Flags, #{}, Topic, Payload). + +-spec(new(atom() | client(), message_flags(), message_headers(), topic(), payload()) -> message()). +new(From, Flags, Headers, Topic, Payload) when is_atom(From); is_record(From, client) -> #message{id = msgid(), - qos = ?QOS_I(QoS), from = From, sender = self(), - flags = #{}, - headers = #{}, + flags = Flags, + headers = Headers, topic = Topic, properties = #{}, payload = Payload, @@ -58,6 +59,10 @@ get_flag(Flag, #message{flags = Flags}, Default) -> set_flag(Flag, Msg = #message{flags = Flags}) when is_atom(Flag) -> Msg#message{flags = maps:put(Flag, true, Flags)}. +-spec(set_flag(message_flag(), boolean() | integer(), message()) -> message()). +set_flag(Flag, Val, Msg = #message{flags = Flags}) when is_atom(Flag) -> + Msg#message{flags = maps:put(Flag, Val, Flags)}. + %% @doc Unset flag -spec(unset_flag(message_flag(), message()) -> message()). unset_flag(Flag, Msg = #message{flags = Flags}) -> diff --git a/src/emqx_metrics.erl b/src/emqx_metrics.erl index c356e62d7..519b96fe4 100644 --- a/src/emqx_metrics.erl +++ b/src/emqx_metrics.erl @@ -1,35 +1,30 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_metrics). -include("emqx_mqtt.hrl"). -export([start_link/0]). - -export([new/1, all/0]). - -export([val/1, inc/1, inc/2, inc/3, dec/2, dec/3, set/2]). - %% Received/sent metrics -export([received/1, sent/1]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {}). @@ -86,7 +81,6 @@ ]). -define(TAB, ?MODULE). - -define(SERVER, ?MODULE). %% @doc Start the metrics server @@ -94,9 +88,9 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Metrics API -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ new({gauge, Name}) -> ets:insert(?TAB, {{Name, 0}, 0}); @@ -168,9 +162,9 @@ key(counter, Metric) -> update_counter(Key, UpOp) -> ets:update_counter(?TAB, Key, UpOp). -%%-------------------------------------------------------------------- -%% Receive/Sent metrics -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- +%% Received/Sent metrics +%%----------------------------------------------------------------------------- %% @doc Count packets received. -spec(received(mqtt_packet()) -> ok). @@ -248,9 +242,9 @@ qos_sent(?QOS_1) -> qos_sent(?QOS_2) -> inc('messages/qos2/sent'). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([]) -> % Create metrics table @@ -259,15 +253,15 @@ init([]) -> {ok, #state{}, hibernate}. handle_call(Req, _From, State) -> - emqx_logger:error("[METRICS] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Metrics] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[METRICS] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Metrics] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info(Info, State) -> - emqx_logger:error("[METRICS] Unexpected info: ~p", [Info]), + emqx_logger:error("[Metrics] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{}) -> diff --git a/src/emqx_misc.erl b/src/emqx_misc.erl index b61a06c60..e2b60a156 100644 --- a/src/emqx_misc.erl +++ b/src/emqx_misc.erl @@ -1,25 +1,23 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_misc). -export([merge_opts/2, start_timer/2, start_timer/3, cancel_timer/1, proc_name/2, proc_stats/0, proc_stats/1]). -%% @doc Merge Options +%% @doc Merge options -spec(merge_opts(list(), list()) -> list()). merge_opts(Defaults, Options) -> lists:foldl( @@ -42,7 +40,8 @@ cancel_timer(undefined) -> ok; cancel_timer(Timer) -> case catch erlang:cancel_timer(Timer) of - false -> receive {timeout, Timer, _} -> ok after 0 -> ok end; + false -> + receive {timeout, Timer, _} -> ok after 0 -> ok end; _ -> ok end. diff --git a/src/emqx_mod_presence.erl b/src/emqx_mod_presence.erl index ca3f83e8f..e41bd0587 100644 --- a/src/emqx_mod_presence.erl +++ b/src/emqx_mod_presence.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_mod_presence). @@ -21,14 +19,13 @@ -include("emqx.hrl"). -export([load/1, unload/1]). - -export([on_client_connected/3, on_client_disconnected/3]). load(Env) -> emqx:hook('client.connected', fun ?MODULE:on_client_connected/3, [Env]), emqx:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Env]). -on_client_connected(ConnAck, Client = #client{client_id = ClientId, +on_client_connected(ConnAck, Client = #client{id = ClientId, username = Username, peername = {IpAddr, _} %%clean_sess = CleanSess, @@ -36,7 +33,7 @@ on_client_connected(ConnAck, Client = #client{client_id = ClientId, }, Env) -> case emqx_json:safe_encode([{clientid, ClientId}, {username, Username}, - {ipaddress, iolist_to_binary(emqx_net:ntoa(IpAddr))}, + {ipaddress, iolist_to_binary(esockd_net:ntoa(IpAddr))}, %%{clean_sess, CleanSess}, %%TODO:: fixme later %%{protocol, ProtoVer}, {connack, ConnAck}, @@ -49,8 +46,7 @@ on_client_connected(ConnAck, Client = #client{client_id = ClientId, end, {ok, Client}. -on_client_disconnected(Reason, #client{client_id = ClientId, - username = Username}, Env) -> +on_client_disconnected(Reason, #client{id = ClientId, username = Username}, Env) -> case emqx_json:safe_encode([{clientid, ClientId}, {username, Username}, {reason, reason(Reason)}, diff --git a/src/emqx_mod_rewrite.erl b/src/emqx_mod_rewrite.erl index 671fe7311..8ddd07f6c 100644 --- a/src/emqx_mod_rewrite.erl +++ b/src/emqx_mod_rewrite.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_mod_rewrite). diff --git a/src/emqx_mod_subscription.erl b/src/emqx_mod_subscription.erl index d7669b274..6db5e30f3 100644 --- a/src/emqx_mod_subscription.erl +++ b/src/emqx_mod_subscription.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_mod_subscription). @@ -33,9 +31,7 @@ load(Topics) -> emqx:hook('client.connected', fun ?MODULE:on_client_connected/3, [Topics]). -on_client_connected(RC, Client = #client{client_id = ClientId, - client_pid = ClientPid, - username = Username}, Topics) +on_client_connected(RC, Client = #client{id = ClientId, pid = ClientPid, username = Username}, Topics) when RC < 16#80 -> Replace = fun(Topic) -> rep(<<"%u">>, Username, rep(<<"%c">>, ClientId, Topic)) end, TopicTable = [{Replace(Topic), Qos} || {Topic, Qos} <- Topics], diff --git a/src/emqx_mod_sup.erl b/src/emqx_mod_sup.erl index d45a33810..ca5a3d61c 100644 --- a/src/emqx_mod_sup.erl +++ b/src/emqx_mod_sup.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,27 +11,17 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_mod_sup). -behaviour(supervisor). --include("emqx.hrl"). - -%% API -export([start_link/0, start_child/1, start_child/2, stop_child/1]). - -%% Supervisor callbacks -export([init/1]). %% Helper macro for declaring children of supervisor -define(CHILD(Mod, Type), {Mod, {Mod, start_link, []}, permanent, 5000, Type, [Mod]}). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). @@ -49,10 +38,9 @@ stop_child(ChildId) -> Error -> Error end. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Supervisor callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> {ok, {{one_for_one, 10, 100}, []}}. - diff --git a/src/emqx_modules.erl b/src/emqx_modules.erl index cd5523280..09e732f68 100644 --- a/src/emqx_modules.erl +++ b/src/emqx_modules.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_modules). diff --git a/src/emqx_mqtt_properties.erl b/src/emqx_mqtt_properties.erl index 8ef559a37..4634d5bdc 100644 --- a/src/emqx_mqtt_properties.erl +++ b/src/emqx_mqtt_properties.erl @@ -1,19 +1,18 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% @doc MQTT5 Properties -module(emqx_mqtt_properties). -include("emqx_mqtt.hrl"). diff --git a/src/emqx_mqueue.erl b/src/emqx_mqueue.erl index 4f46526ed..e6bd16540 100644 --- a/src/emqx_mqueue.erl +++ b/src/emqx_mqueue.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,8 +11,8 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- +%% TODO: should be a bound queue. %% @doc A Simple in-memory message queue. %% %% Notice that MQTT is not an enterprise messaging queue. MQTT assume that client @@ -155,7 +154,7 @@ stats(#mqueue{type = Type, q = Q, max_len = MaxLen, len = Len, dropped = Dropped %% @doc Enqueue a message. -spec(in(message(), mqueue()) -> mqueue()). -in(#message{qos = ?QOS_0}, MQ = #mqueue{qos0 = false}) -> +in(#message{flags = #{qos := ?QOS_0}}, MQ = #mqueue{qos0 = false}) -> MQ; in(Msg, MQ = #mqueue{type = simple, q = Q, len = Len, max_len = 0}) -> MQ#mqueue{q = queue:in(Msg, Q), len = Len + 1}; @@ -167,8 +166,8 @@ in(Msg, MQ = #mqueue{type = simple, q = Q, len = Len}) -> maybe_set_alarm(MQ#mqueue{q = queue:in(Msg, Q), len = Len + 1}); in(Msg = #message{topic = Topic}, MQ = #mqueue{type = priority, q = Q, - priorities = Priorities, - max_len = 0}) -> + priorities = Priorities, + max_len = 0}) -> case lists:keysearch(Topic, 1, Priorities) of {value, {_, Pri}} -> MQ#mqueue{q = ?PQUEUE:in(Msg, Pri, Q)}; diff --git a/src/emqx_net.erl b/src/emqx_net.erl deleted file mode 100644 index ea5bb2462..000000000 --- a/src/emqx_net.erl +++ /dev/null @@ -1,232 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%%-------------------------------------------------------------------- - --module(emqx_net). - --include_lib("kernel/include/inet.hrl"). - --export([tcp_name/3, tcp_host/1, getopts/2, setopts/2, getaddr/2, - port_to_listeners/1]). - --export([peername/1, sockname/1, format/2, format/1, ntoa/1, - connection_string/2]). - --define(FIRST_TEST_BIND_PORT, 10000). - -%%-------------------------------------------------------------------- - -%% inet_parse:address takes care of ip string, like "0.0.0.0" -%% inet:getaddr returns immediately for ip tuple {0,0,0,0}, -%% and runs 'inet_gethost' port process for dns lookups. -%% On Windows inet:getaddr runs dns resolver for ip string, which may fail. -getaddr(Host, Family) -> - case inet_parse:address(Host) of - {ok, IPAddress} -> [{IPAddress, resolve_family(IPAddress, Family)}]; - {error, _} -> gethostaddr(Host, Family) - end. - -gethostaddr(Host, auto) -> - Lookups = [{Family, inet:getaddr(Host, Family)} || Family <- [inet, inet6]], - case [{IP, Family} || {Family, {ok, IP}} <- Lookups] of - [] -> host_lookup_error(Host, Lookups); - IPs -> IPs - end; - -gethostaddr(Host, Family) -> - case inet:getaddr(Host, Family) of - {ok, IPAddress} -> [{IPAddress, Family}]; - {error, Reason} -> host_lookup_error(Host, Reason) - end. - -host_lookup_error(Host, Reason) -> - error_logger:error_msg("invalid host ~p - ~p~n", [Host, Reason]), - throw({error, {invalid_host, Host, Reason}}). - -resolve_family({_,_,_,_}, auto) -> inet; -resolve_family({_,_,_,_,_,_,_,_}, auto) -> inet6; -resolve_family(IP, auto) -> throw({error, {strange_family, IP}}); -resolve_family(_, F) -> F. - -%%-------------------------------------------------------------------- - -%% There are three kinds of machine (for our purposes). -%% -%% * Those which treat IPv4 addresses as a special kind of IPv6 address -%% ("Single stack") -%% - Linux by default, Windows Vista and later -%% - We also treat any (hypothetical?) IPv6-only machine the same way -%% * Those which consider IPv6 and IPv4 to be completely separate things -%% ("Dual stack") -%% - OpenBSD, Windows XP / 2003, Linux if so configured -%% * Those which do not support IPv6. -%% - Ancient/weird OSes, Linux if so configured -%% -%% How to reconfigure Linux to test this: -%% Single stack (default): -%% echo 0 > /proc/sys/net/ipv6/bindv6only -%% Dual stack: -%% echo 1 > /proc/sys/net/ipv6/bindv6only -%% IPv4 only: -%% add ipv6.disable=1 to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub then -%% sudo update-grub && sudo reboot -%% -%% This matters in (and only in) the case where the sysadmin (or the -%% app descriptor) has only supplied a port and we wish to bind to -%% "all addresses". This means different things depending on whether -%% we're single or dual stack. On single stack binding to "::" -%% implicitly includes all IPv4 addresses, and subsequently attempting -%% to bind to "0.0.0.0" will fail. On dual stack, binding to "::" will -%% only bind to IPv6 addresses, and we need another listener bound to -%% "0.0.0.0" for IPv4. Finally, on IPv4-only systems we of course only -%% want to bind to "0.0.0.0". -%% -%% Unfortunately it seems there is no way to detect single vs dual stack -%% apart from attempting to bind to the port. -port_to_listeners(Port) -> - IPv4 = {"0.0.0.0", Port, inet}, - IPv6 = {"::", Port, inet6}, - case ipv6_status(?FIRST_TEST_BIND_PORT) of - single_stack -> [IPv6]; - ipv6_only -> [IPv6]; - dual_stack -> [IPv6, IPv4]; - ipv4_only -> [IPv4] - end. - -ipv6_status(TestPort) -> - IPv4 = [inet, {ip, {0,0,0,0}}], - IPv6 = [inet6, {ip, {0,0,0,0,0,0,0,0}}], - case gen_tcp:listen(TestPort, IPv6) of - {ok, LSock6} -> - case gen_tcp:listen(TestPort, IPv4) of - {ok, LSock4} -> - %% Dual stack - gen_tcp:close(LSock6), - gen_tcp:close(LSock4), - dual_stack; - %% Checking the error here would only let us - %% distinguish single stack IPv6 / IPv4 vs IPv6 only, - %% which we figure out below anyway. - {error, _} -> - gen_tcp:close(LSock6), - case gen_tcp:listen(TestPort, IPv4) of - %% Single stack - {ok, LSock4} -> gen_tcp:close(LSock4), - single_stack; - %% IPv6-only machine. Welcome to the future. - {error, eafnosupport} -> ipv6_only; %% Linux - {error, eprotonosupport}-> ipv6_only; %% FreeBSD - %% Dual stack machine with something already - %% on IPv4. - {error, _} -> ipv6_status(TestPort + 1) - end - end; - %% IPv4-only machine. Welcome to the 90s. - {error, eafnosupport} -> %% Linux - ipv4_only; - {error, eprotonosupport} -> %% FreeBSD - ipv4_only; - %% Port in use - {error, _} -> - ipv6_status(TestPort + 1) - end. - -tcp_name(Prefix, IPAddress, Port) - when is_atom(Prefix) andalso is_number(Port) -> - list_to_atom( - lists:flatten( - io_lib:format( - "~w_~s:~w", [Prefix, inet_parse:ntoa(IPAddress), Port]))). - -connection_string(Sock, Direction) -> - case socket_ends(Sock, Direction) of - {ok, {FromAddress, FromPort, ToAddress, ToPort}} -> - {ok, lists:flatten( - io_lib:format( - "~s:~p -> ~s:~p", - [maybe_ntoab(FromAddress), FromPort, - maybe_ntoab(ToAddress), ToPort]))}; - Error -> - Error - end. - -socket_ends(Sock, Direction) -> - {From, To} = sock_funs(Direction), - case {From(Sock), To(Sock)} of - {{ok, {FromAddress, FromPort}}, {ok, {ToAddress, ToPort}}} -> - {ok, {rdns(FromAddress), FromPort, - rdns(ToAddress), ToPort}}; - {{error, _Reason} = Error, _} -> - Error; - {_, {error, _Reason} = Error} -> - Error - end. - -maybe_ntoab(Addr) when is_tuple(Addr) -> ntoab(Addr); -maybe_ntoab(Host) -> Host. - -rdns(Addr) -> Addr. - -sock_funs(inbound) -> {fun peername/1, fun sockname/1}; -sock_funs(outbound) -> {fun sockname/1, fun peername/1}. - -getopts(Sock, Options) when is_port(Sock) -> - inet:getopts(Sock, Options). - -setopts(Sock, Options) when is_port(Sock) -> - inet:setopts(Sock, Options). - -sockname(Sock) when is_port(Sock) -> inet:sockname(Sock). - -peername(Sock) when is_port(Sock) -> inet:peername(Sock). - -format(sockname, SockName) -> - format(SockName); -format(peername, PeerName) -> - format(PeerName). -format({Addr, Port}) -> - lists:flatten(io_lib:format("~s:~p", [maybe_ntoab(Addr), Port])). - -ntoa({0,0,0,0,0,16#ffff,AB,CD}) -> - inet_parse:ntoa({AB bsr 8, AB rem 256, CD bsr 8, CD rem 256}); -ntoa(IP) -> - inet_parse:ntoa(IP). - -ntoab(IP) -> - Str = ntoa(IP), - case string:str(Str, ":") of - 0 -> Str; - _ -> "[" ++ Str ++ "]" - end. - -tcp_host({0,0,0,0}) -> - hostname(); - -tcp_host({0,0,0,0,0,0,0,0}) -> - hostname(); - -tcp_host(IPAddress) -> - case inet:gethostbyaddr(IPAddress) of - {ok, #hostent{h_name = Name}} -> Name; - {error, _Reason} -> ntoa(IPAddress) - end. - -hostname() -> - {ok, Hostname} = inet:gethostname(), - case inet:gethostbyname(Hostname) of - {ok, #hostent{h_name = Name}} -> Name; - {error, _Reason} -> Hostname - end. - diff --git a/src/emqx_packet.erl b/src/emqx_packet.erl index 655bdd504..dc88d59d7 100644 --- a/src/emqx_packet.erl +++ b/src/emqx_packet.erl @@ -1,5 +1,4 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -%%-------------------------------------------------------------------- -module(emqx_packet). @@ -21,9 +19,7 @@ -include("emqx_mqtt.hrl"). -export([protocol_name/1, type_name/1]). - -export([format/1]). - -export([to_message/1, from_message/1]). %% @doc Protocol name of version @@ -39,9 +35,8 @@ type_name(Type) when Type > ?RESERVED andalso Type =< ?AUTH -> %% @doc From Message to Packet -spec(from_message(message()) -> mqtt_packet()). -from_message(Msg = #message{qos = Qos, - topic = Topic, - payload = Payload}) -> +from_message(Msg = #message{topic = Topic, payload = Payload}) -> + Qos = emqx_message:get_flag(qos, Msg, 0), Dup = emqx_message:get_flag(dup, Msg, false), Retain = emqx_message:get_flag(retain, Msg, false), PacketId = emqx_message:get_header(packet_id, Msg), @@ -61,13 +56,12 @@ to_message(#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, dup = Dup}, variable = #mqtt_packet_publish{topic_name = Topic, packet_id = PacketId, - properties = Props}, + properties = Properties}, payload = Payload}) -> - Msg = emqx_message:make(undefined, Topic, Payload), - Msg#message{qos = Qos, - flags = #{dup => Dup, retain => Retain}, - headers = #{packet_id => PacketId}, - properties = Props}; + Flags = #{dup => Dup, retain => Retain, qos => Qos}, + Msg = emqx_message:new(undefined, Flags, #{packet_id => PacketId}, Topic, Payload), + Msg#message{properties = Properties}; + to_message(#mqtt_packet_connect{will_flag = false}) -> undefined; to_message(#mqtt_packet_connect{will_retain = Retain, @@ -75,10 +69,8 @@ to_message(#mqtt_packet_connect{will_retain = Retain, will_topic = Topic, will_props = Props, will_payload = Payload}) -> - Msg = emqx_message:make(undefined, Topic, Payload), - Msg#message{flags = #{retain => Retain}, - headers = #{qos => Qos}, - properties = Props}. + Msg = emqx_message:new(undefined, #{qos => Qos, retain => Retain}, Topic, Payload), + Msg#message{properties = Props}. %% @doc Format packet -spec(format(mqtt_packet()) -> iolist()). diff --git a/src/emqx_pmon.erl b/src/emqx_pmon.erl index f6b4611ec..8b421f20a 100644 --- a/src/emqx_pmon.erl +++ b/src/emqx_pmon.erl @@ -1,57 +1,52 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_pmon). -export([new/0]). - -export([monitor/2, monitor/3, demonitor/2, find/2, erase/2]). +-compile({no_auto_import,[monitor/3]}). --compile({no_auto_import,[monitor/3]}). --type(pmon() :: map()). - +-type(pmon() :: {?MODULE, map()}). -export_type([pmon/0]). -spec(new() -> pmon()). -new() -> - maps:new(). +new() -> {?MODULE, maps:new()}. -spec(monitor(pid(), pmon()) -> pmon()). monitor(Pid, PM) -> monitor(Pid, undefined, PM). -monitor(Pid, Val, PM) -> - case maps:is_key(Pid, PM) of - true -> PM; - false -> Ref = erlang:monitor(process, Pid), - maps:put(Pid, {Ref, Val}, PM) - end. +monitor(Pid, Val, {?MODULE, PM}) -> + {?MODULE, case maps:is_key(Pid, PM) of + true -> PM; + false -> Ref = erlang:monitor(process, Pid), + maps:put(Pid, {Ref, Val}, PM) + end}. -spec(demonitor(pid(), pmon()) -> pmon()). -demonitor(Pid, PM) -> - case maps:find(Pid, PM) of - {ok, {Ref, _Val}} -> - %% Don't flush - _ = erlang:demonitor(Ref), - maps:remove(Pid, PM); - error -> PM - end. +demonitor(Pid, {?MODULE, PM}) -> + {?MODULE, case maps:find(Pid, PM) of + {ok, {Ref, _Val}} -> + %% Don't flush + _ = erlang:demonitor(Ref), + maps:remove(Pid, PM); + error -> PM + end}. -spec(find(pid(), pmon()) -> undefined | term()). -find(Pid, PM) -> +find(Pid, {?MODULE, PM}) -> case maps:find(Pid, PM) of {ok, {_Ref, Val}} -> Val; @@ -59,6 +54,6 @@ find(Pid, PM) -> end. -spec(erase(pid(), pmon()) -> pmon()). -erase(Pid, PM) -> - maps:remove(Pid, PM). +erase(Pid, {?MODULE, PM}) -> + {?MODULE, maps:remove(Pid, PM)}. diff --git a/src/emqx_pool.erl b/src/emqx_pool.erl index 43f4ef845..8d927ddd9 100644 --- a/src/emqx_pool.erl +++ b/src/emqx_pool.erl @@ -1,50 +1,40 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_pool). -behaviour(gen_server). -%% Start the pool supervisor --export([start_link/0]). +-export([start_link/0, start_link/2]). +-export([submit/1, async_submit/1]). -%% API Exports --export([start_link/2, submit/1, async_submit/1]). - -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {pool, id}). -define(POOL, ?MODULE). -%% @doc Start Pooler Supervisor. +%% @doc Start pooler supervisor. start_link() -> emqx_pool_sup:start_link(?POOL, random, {?MODULE, start_link, []}). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - --spec(start_link(atom(), pos_integer()) - -> {ok, pid()} | ignore | {error, term()}). +%% @doc Start pool +-spec(start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id) -> - gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, - ?MODULE, [Pool, Id], []). + gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, ?MODULE, [Pool, Id], []). %% @doc Submit work to the pool -spec(submit(fun()) -> any()). @@ -59,45 +49,45 @@ async_submit(Fun) -> worker() -> gproc_pool:pick_worker(pool). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([Pool, Id]) -> - gproc_pool:connect_worker(Pool, {Pool, Id}), + true = gproc_pool:connect_worker(Pool, {Pool, Id}), {ok, #state{pool = Pool, id = Id}}. handle_call({submit, Fun}, _From, State) -> {reply, catch run(Fun), State}; handle_call(Req, _From, State) -> - emqx_logger:error("[POOL] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Pool] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({async_submit, Fun}, State) -> try run(Fun) - catch _:Error -> - emqx_logger:error("[POOL] Error: ~p, ~p", [Error, erlang:get_stacktrace()]) + catch _:Error:Stacktrace -> + emqx_logger:error("[Pool] error: ~p, ~p", [Error, Stacktrace]) end, {noreply, State}; handle_cast(Msg, State) -> - emqx_logger:error("[POOL] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Pool] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info(Info, State) -> - emqx_logger:error("[POOL] Unexpected info: ~p", [Info]), + emqx_logger:error("[Pool] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{pool = Pool, id = Id}) -> - gproc_pool:disconnect_worker(Pool, {Pool, Id}). + true = gproc_pool:disconnect_worker(Pool, {Pool, Id}). code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Internal functions -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- run({M, F, A}) -> erlang:apply(M, F, A); diff --git a/src/emqx_pool_sup.erl b/src/emqx_pool_sup.erl index 29f656c73..efcde5d2f 100644 --- a/src/emqx_pool_sup.erl +++ b/src/emqx_pool_sup.erl @@ -1,27 +1,23 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_pool_sup). -behaviour(supervisor). -%% API -export([spec/1, spec/2, start_link/3, start_link/4]). -%% Supervisor callbacks -export([init/1]). -spec(spec(list()) -> supervisor:child_spec()). @@ -35,8 +31,7 @@ spec(ChildId, Args) -> -spec(start_link(atom() | tuple(), atom(), mfa()) -> {ok, pid()} | {error, term()}). start_link(Pool, Type, MFA) -> - Schedulers = erlang:system_info(schedulers), - start_link(Pool, Type, Schedulers, MFA). + start_link(Pool, Type, emqx_vm:schedulers(schedulers), MFA). -spec(start_link(atom() | tuple(), atom(), pos_integer(), mfa()) -> {ok, pid()} | {error, term()}). start_link(Pool, Type, Size, MFA) when is_atom(Pool) -> @@ -49,8 +44,7 @@ init([Pool, Type, Size, {M, F, Args}]) -> {ok, {{one_for_one, 10, 3600}, [ begin ensure_pool_worker(Pool, {Pool, I}, I), - {{M, I}, {M, F, [Pool, I | Args]}, - transient, 5000, worker, [M]} + {{M, I}, {M, F, [Pool, I | Args]}, transient, 5000, worker, [M]} end || I <- lists:seq(1, Size)]}}. ensure_pool(Pool, Type, Opts) -> diff --git a/src/emqx_protocol.erl b/src/emqx_protocol.erl index 30fbb1848..c932089e7 100644 --- a/src/emqx_protocol.erl +++ b/src/emqx_protocol.erl @@ -129,11 +129,10 @@ client(#proto_state{client_id = ClientId, WillMsg =:= undefined -> undefined; true -> WillMsg#message.topic end, - #client{client_id = ClientId, - client_pid = ClientPid, - username = Username, - peername = Peername, - mountpoint = MountPoint}. + #client{id = ClientId, + pid = ClientPid, + username = Username, + peername = Peername}. session(#proto_state{session = Session}) -> Session. @@ -334,7 +333,7 @@ publish(Packet = ?PUBLISH_PACKET(?QOS_0, _PacketId), mountpoint = MountPoint, session = Session}) -> Msg = emqx_packet:to_message(Packet), - Msg1 = Msg#message{from = #client{client_id = ClientId, username = Username}}, + Msg1 = Msg#message{from = #client{id = ClientId, username = Username}}, emqx_session:publish(Session, mount(replvar(MountPoint, State), Msg1)); publish(Packet = ?PUBLISH_PACKET(?QOS_1, _PacketId), State) -> @@ -350,7 +349,7 @@ with_puback(Type, Packet = ?PUBLISH_PACKET(_Qos, PacketId), session = Session}) -> %% TODO: ... Msg = emqx_packet:to_message(Packet), - Msg1 = Msg#message{from = #client{client_id = ClientId, username = Username}}, + Msg1 = Msg#message{from = #client{id = ClientId, username = Username}}, case emqx_session:publish(Session, mount(replvar(MountPoint, State), Msg1)) of ok -> case Type of diff --git a/src/emqx_reason_codes.erl b/src/emqx_reason_codes.erl index 029914f48..335be3bd4 100644 --- a/src/emqx_reason_codes.erl +++ b/src/emqx_reason_codes.erl @@ -1,19 +1,18 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% @doc MQTT5 reason codes -module(emqx_reason_codes). -export([name/1, text/1]). @@ -61,7 +60,7 @@ name(16#9F) -> connection_rate_exceeded; name(16#A0) -> maximum_connect_time; name(16#A1) -> subscription_identifiers_not_supported; name(16#A2) -> wildcard_subscriptions_not_supported; -name(Code) -> list_to_atom("unkown_" ++ integer_to_list(Code)). +name(Code) -> list_to_atom("unkown_reason_code" ++ integer_to_list(Code)). text(16#00) -> <<"Success">>; text(16#01) -> <<"Granted QoS 1">>; @@ -106,5 +105,5 @@ text(16#9F) -> <<"Connection rate exceeded">>; text(16#A0) -> <<"Maximum connect time">>; text(16#A1) -> <<"Subscription Identifiers not supported">>; text(16#A2) -> <<"Wildcard Subscriptions not supported">>; -text(Code) -> iolist_to_binary(["Unkown", integer_to_list(Code)]). +text(Code) -> iolist_to_binary(["Unkown Reason Code:", integer_to_list(Code)]). diff --git a/src/emqx_router.erl b/src/emqx_router.erl index 7aff3a446..8f6375720 100644 --- a/src/emqx_router.erl +++ b/src/emqx_router.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_router). @@ -34,13 +32,11 @@ -export([get_routes/1]). -export([del_route/1, del_route/2, del_route/3]). -export([has_routes/1, match_routes/1, print_routes/1]). - -%% Topics -export([topics/0]). %% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -type(destination() :: node() | {binary(), node()}). @@ -49,15 +45,12 @@ -record(state, {pool, id, batch :: #batch{}}). -define(ROUTE, emqx_route). - -define(BATCH(Enabled), #batch{enabled = Enabled}). +-define(BATCH(Enabled, Pending), #batch{enabled = Enabled, pending = Pending}). --define(BATCH(Enabled, Pending), - #batch{enabled = Enabled, pending = Pending}). - -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Mnesia bootstrap -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- mnesia(boot) -> ok = ekka_mnesia:create_table(?ROUTE, [ @@ -65,23 +58,21 @@ mnesia(boot) -> {ram_copies, [node()]}, {record_name, route}, {attributes, record_info(fields, route)}]); - mnesia(copy) -> ok = ekka_mnesia:copy_table(?ROUTE). -%%-------------------------------------------------------------------- -%% Strat a Router -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ +%% Strat a router +%%------------------------------------------------------------------------------ --spec(start_link(atom(), pos_integer()) - -> {ok, pid()} | ignore | {error, term()}). +-spec(start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id) -> gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, ?MODULE, [Pool, Id], [{hibernate_after, 2000}]). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Route APIs -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(add_route(topic() | route()) -> ok). add_route(Topic) when is_binary(Topic) -> @@ -95,8 +86,7 @@ add_route(Topic, Dest) when is_binary(Topic) -> -spec(add_route({pid(), reference()}, topic(), destination()) -> ok). add_route(From, Topic, Dest) when is_binary(Topic) -> - Route = #route{topic = Topic, dest = Dest}, - cast(pick(Topic), {add_route, From, Route}). + cast(pick(Topic), {add_route, From, #route{topic = Topic, dest = Dest}}). -spec(get_routes(topic()) -> [route()]). get_routes(Topic) -> @@ -114,8 +104,7 @@ del_route(Topic, Dest) when is_binary(Topic) -> -spec(del_route({pid(), reference()}, topic(), destination()) -> ok). del_route(From, Topic, Dest) when is_binary(Topic) -> - Route = #route{topic = Topic, dest = Dest}, - cast(pick(Topic), {del_route, From, Route}). + cast(pick(Topic), {del_route, From, #route{topic = Topic, dest = Dest}}). -spec(has_routes(topic()) -> boolean()). has_routes(Topic) when is_binary(Topic) -> @@ -144,9 +133,9 @@ cast(Router, Msg) -> pick(Topic) -> gproc_pool:pick_worker(router, Topic). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([Pool, Id]) -> rand:seed(exsplus, erlang:timestamp()), @@ -156,12 +145,12 @@ init([Pool, Id]) -> {ok, ensure_batch_timer(#state{pool = Pool, id = Id, batch = Batch})}. handle_call(Req, _From, State) -> - emqx_logger:error("[Router] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Router] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({add_route, From, Route}, State) -> {noreply, NewState} = handle_cast({add_route, Route}, State), - gen_server:reply(From, ok), + _ = gen_server:reply(From, ok), {noreply, NewState}; handle_cast({add_route, Route = #route{topic = Topic, dest = Dest}}, State) -> @@ -178,7 +167,7 @@ handle_cast({add_route, Route = #route{topic = Topic, dest = Dest}}, State) -> handle_cast({del_route, From, Route}, State) -> {noreply, NewState} = handle_cast({del_route, Route}, State), - gen_server:reply(From, ok), + _ = gen_server:reply(From, ok), {noreply, NewState}; handle_cast({del_route, Route = #route{topic = Topic}}, State) -> @@ -194,7 +183,7 @@ handle_cast({del_route, Route = #route{topic = Topic}}, State) -> end}; handle_cast(Msg, State) -> - emqx_logger:error("[Router] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Router] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({timeout, _TRef, batch_delete}, State = #state{batch = Batch}) -> @@ -202,7 +191,7 @@ handle_info({timeout, _TRef, batch_delete}, State = #state{batch = Batch}) -> {noreply, ensure_batch_timer(State#state{batch = ?BATCH(true, sets:new())}), hibernate}; handle_info(Info, State) -> - emqx_logger:error("[Router] Unexpected info: ~p", [Info]), + emqx_logger:error("[Router] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{pool = Pool, id = Id, batch = Batch}) -> @@ -212,9 +201,9 @@ terminate(_Reason, #state{pool = Pool, id = Id, batch = Batch}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Internal functions -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- ensure_batch_timer(State = #state{batch = #batch{enabled = false}}) -> State; @@ -225,7 +214,7 @@ ensure_batch_timer(State = #state{batch = Batch}) -> cacel_batch_timer(#batch{enabled = false}) -> ok; cacel_batch_timer(#batch{enabled = true, timer = TRef}) -> - erlang:cancel_timer(TRef). + catch erlang:cancel_timer(TRef). add_direct_route(Route) -> mnesia:async_dirty(fun mnesia:write/3, [?ROUTE, Route, sticky_write]). @@ -275,6 +264,6 @@ trans(Fun, Args) -> end. log(ok) -> ok; -log({error, Error}) -> - emqx_logger:error("[Router] Mnesia aborted: ~p", [Error]). +log({error, Reason}) -> + emqx_logger:error("[Router] mnesia aborted: ~p", [Reason]). diff --git a/src/emqx_router_helper.erl b/src/emqx_router_helper.erl index 0606f70fd..d0d0e8075 100644 --- a/src/emqx_router_helper.erl +++ b/src/emqx_router_helper.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_router_helper). @@ -30,11 +28,10 @@ -export([start_link/0, monitor/1]). %% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(routing_node, {name, const = unused}). - -record(state, {nodes = []}). -compile({no_auto_import, [monitor/1]}). @@ -42,12 +39,11 @@ -define(SERVER, ?MODULE). -define(ROUTE, emqx_route). -define(ROUTING_NODE, emqx_routing_node). - -define(LOCK, {?MODULE, cleanup_routes}). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Mnesia bootstrap -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ mnesia(boot) -> ok = ekka_mnesia:create_table(?ROUTING_NODE, [ @@ -59,9 +55,9 @@ mnesia(boot) -> mnesia(copy) -> ok = ekka_mnesia:copy_table(?ROUTING_NODE). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% API -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% @doc Starts the router helper -spec(start_link() -> {ok, pid()} | ignore | {error, any()}). @@ -79,9 +75,9 @@ monitor(Node) when is_atom(Node) -> false -> mnesia:dirty_write(?ROUTING_NODE, #routing_node{name = Node}) end. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> ekka:monitor(membership), @@ -98,16 +94,15 @@ init([]) -> {ok, #state{nodes = Nodes}, hibernate}. handle_call(Req, _From, State) -> - emqx_logger:error("[RouterHelper] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[RouterHelper] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[RouterHelper] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[RouterHelper] unexpected cast: ~p", [Msg]), {noreply, State}. -handle_info({mnesia_table_event, {write, #routing_node{name = Node}, _}}, - State = #state{nodes = Nodes}) -> - emqx_logger:info("[RouterHelper] New routing node: ~s", [Node]), +handle_info({mnesia_table_event, {write, #routing_node{name = Node}, _}}, State = #state{nodes = Nodes}) -> + emqx_logger:info("[RouterHelper] write routing node: ~s", [Node]), case ekka:is_member(Node) orelse lists:member(Node, Nodes) of true -> {noreply, State}; false -> _ = erlang:monitor_node(Node, true), @@ -132,7 +127,7 @@ handle_info({membership, _Event}, State) -> {noreply, State}; handle_info(Info, State) -> - emqx_logger:error("[RouteHelper] Unexpected info: ~p", [Info]), + emqx_logger:error("[RouteHelper] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{}) -> @@ -143,9 +138,9 @@ terminate(_Reason, #state{}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ stats_fun() -> fun() -> diff --git a/src/emqx_router_sup.erl b/src/emqx_router_sup.erl index bc8daf4b4..004b88bb8 100644 --- a/src/emqx_router_sup.erl +++ b/src/emqx_router_sup.erl @@ -1,25 +1,22 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_router_sup). -behaviour(supervisor). -export([start_link/0]). - -export([init/1]). start_link() -> @@ -34,6 +31,5 @@ init([]) -> RouterPool = emqx_pool_sup:spec(emqx_router_pool, [router, hash, emqx_vm:schedulers(), {emqx_router, start_link, []}]), - {ok, {{one_for_all, 0, 1}, [Helper, RouterPool]}}. diff --git a/src/emqx_rpc.erl b/src/emqx_rpc.erl index f7c13fa4e..d4433bf6c 100644 --- a/src/emqx_rpc.erl +++ b/src/emqx_rpc.erl @@ -1,26 +1,24 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% @doc wrap gen_rpc? -module(emqx_rpc). -export([call/4, cast/4]). - -export([multicall/4]). --define(RPC, rpc). +-define(RPC, gen_rpc). call(Node, Mod, Fun, Args) -> ?RPC:call(Node, Mod, Fun, Args). diff --git a/src/emqx_session_sup.erl b/src/emqx_session_sup.erl index c1941207b..644e33f37 100644 --- a/src/emqx_session_sup.erl +++ b/src/emqx_session_sup.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_session_sup). @@ -37,6 +35,10 @@ start_session(Attrs) -> init([]) -> {ok, {{simple_one_for_one, 0, 1}, - [{session, {emqx_session, start_link, []}, - temporary, 5000, worker, [emqx_session]}]}}. + [#{id => session, + start => {emqx_session, start_link, []}, + restart => temporary, + shutdown => 5000, + type => worker, + modules => [emqx_session]}]}}. diff --git a/src/emqx_shared_sub.erl b/src/emqx_shared_sub.erl index 6825ca8d0..9380f38f7 100644 --- a/src/emqx_shared_sub.erl +++ b/src/emqx_shared_sub.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_shared_sub). @@ -33,20 +31,18 @@ -export([dispatch/3]). %% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -define(SERVER, ?MODULE). - -define(TAB, emqx_shared_subscription). -record(state, {pmon}). - -record(shared_subscription, {group, topic, subpid}). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Mnesia bootstrap -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ mnesia(boot) -> ok = ekka_mnesia:create_table(?TAB, [ @@ -58,15 +54,15 @@ mnesia(boot) -> mnesia(copy) -> ok = ekka_mnesia:copy_table(?TAB). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% API -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ --spec(start_link() -> {ok, pid()} | ignore | {error, any()}). +-spec(start_link() -> {ok, pid()} | ignore | {error, term()}). start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). --spec(strategy() -> random | hash). +-spec(strategy() -> round_robin | random | hash). strategy() -> emqx_config:get_env(shared_subscription_strategy, random). @@ -84,7 +80,7 @@ unsubscribe(Group, Topic, SubPid) when is_pid(SubPid) -> record(Group, Topic, SubPid) -> #shared_subscription{group = Group, topic = Topic, subpid = SubPid}. -%% TODO: ensure the delivery... +%% TODO: dispatch strategy, ensure the delivery... dispatch(Group, Topic, Delivery = #delivery{message = Msg, flows = Flows}) -> case pick(subscribers(Group, Topic)) of false -> Delivery; @@ -97,16 +93,15 @@ pick([]) -> pick([SubPid]) -> SubPid; pick(SubPids) -> - X = abs(erlang:monotonic_time() - bxor erlang:unique_integer()), + X = abs(erlang:monotonic_time() bxor erlang:unique_integer()), lists:nth((X rem length(SubPids)) + 1, SubPids). subscribers(Group, Topic) -> ets:select(?TAB, [{{shared_subscription, Group, Topic, '$1'}, [], ['$1']}]). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([]) -> {atomic, PMon} = mnesia:transaction(fun init_monitors/0), @@ -120,14 +115,14 @@ init_monitors() -> end, emqx_pmon:new(), ?TAB). handle_call(Req, _From, State) -> - emqx_logger:error("[Shared] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[SharedSub] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({monitor, SubPid}, State= #state{pmon = PMon}) -> {noreply, update_stats(State#state{pmon = emqx_pmon:monitor(SubPid, PMon)})}; handle_cast(Msg, State) -> - emqx_logger:error("[Shared] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[SharedSub] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({mnesia_table_event, {write, NewRecord, _}}, State = #state{pmon = PMon}) -> @@ -142,12 +137,12 @@ handle_info({mnesia_table_event, _Event}, State) -> {noreply, State}; handle_info({'DOWN', _MRef, process, SubPid, _Reason}, State = #state{pmon = PMon}) -> - emqx_logger:info("Shared subscription down: ~p", [SubPid]), + emqx_logger:info("[SharedSub] shared subscriber down: ~p", [SubPid]), mnesia:async_dirty(fun cleanup_down/1, [SubPid]), {noreply, update_stats(State#state{pmon = emqx_pmon:erase(SubPid, PMon)})}; handle_info(Info, State) -> - emqx_logger:error("[Shared] Unexpected info: ~p", [Info]), + emqx_logger:error("[SharedSub] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -161,8 +156,8 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- cleanup_down(SubPid) -> - Pat = #shared_subscription{_ = '_', subpid = SubPid}, - lists:foreach(fun(Record) -> mnesia:delete_object(?TAB, Record) end, mnesia:match_object(Pat)). + lists:foreach(fun(Record) -> mnesia:delete_object(?TAB, Record) end, + mnesia:match_object(#shared_subscription{_ = '_', subpid = SubPid})). update_stats(State) -> emqx_stats:setstat('subscriptions/shared/count', 'subscriptions/shared/max', ets:info(?TAB, size)), State. diff --git a/src/emqx_sm.erl b/src/emqx_sm.erl index 50ce9cb75..de16a2b0f 100644 --- a/src/emqx_sm.erl +++ b/src/emqx_sm.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sm). @@ -30,8 +28,8 @@ %% Internal functions for rpc -export([dispatch/3]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(state, {session_pmon}). @@ -50,7 +48,8 @@ start_link() -> %% @doc Open a session. -spec(open_session(map()) -> {ok, pid()} | {error, term()}). open_session(Attrs = #{clean_start := true, - client_id := ClientId, client_pid := ClientPid}) -> + client_id := ClientId, + client_pid := ClientPid}) -> CleanStart = fun(_) -> ok = discard_session(ClientId, ClientPid), emqx_session_sup:start_session(Attrs) @@ -58,7 +57,8 @@ open_session(Attrs = #{clean_start := true, emqx_sm_locker:trans(ClientId, CleanStart); open_session(Attrs = #{clean_start := false, - client_id := ClientId, client_pid := ClientPid}) -> + client_id := ClientId, + client_pid := ClientPid}) -> ResumeStart = fun(_) -> case resume_session(ClientId, ClientPid) of {ok, SessionPid} -> @@ -72,7 +72,7 @@ open_session(Attrs = #{clean_start := false, emqx_sm_locker:trans(ClientId, ResumeStart). %% @doc Discard all the sessions identified by the ClientId. --spec(discard_session(map()) -> ok). +-spec(discard_session(client_id()) -> ok). discard_session(ClientId) when is_binary(ClientId) -> discard_session(ClientId, self()). @@ -80,8 +80,8 @@ discard_session(ClientId, ClientPid) when is_binary(ClientId) -> lists:foreach( fun({_ClientId, SessionPid}) -> case catch emqx_session:discard(SessionPid, ClientPid) of - {'EXIT', Error} -> - emqx_logger:error("[SM] Failed to discard ~p: ~p", [SessionPid, Error]); + {Err, Reason} when Err =:= 'EXIT'; Err =:= error -> + emqx_logger:error("[SM] Failed to discard ~p: ~p", [SessionPid, Reason]); ok -> ok end end, lookup_session(ClientId)). @@ -126,7 +126,7 @@ register_session(Session = {ClientId, SessionPid}, Attrs) ets:insert(?SESSION_ATTRS, {Session, Attrs}), case proplists:get_value(clean_start, Attrs, true) of true -> ok; - false -> ets:insert(?SESSION_P, Session) + false -> ets:insert(?SESSION_P, Session) end, emqx_sm_registry:register_session(Session), notify({registered, ClientId, SessionPid}). @@ -197,11 +197,12 @@ safe_lookup_element(Tab, Key, Default) -> error:badarg -> Default end. -notify(Event) -> gen_server:cast(?SM, {notify, Event}). +notify(Event) -> + gen_server:cast(?SM, {notify, Event}). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> TabOpts = [public, set, {write_concurrency, true}], @@ -213,8 +214,8 @@ init([]) -> {ok, #state{session_pmon = emqx_pmon:new()}}. handle_call(Req, _From, State) -> - emqx_logger:error("[SM] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[SM] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({notify, {registered, ClientId, SessionPid}}, State = #state{session_pmon = PMon}) -> {noreply, State#state{session_pmon = emqx_pmon:monitor(SessionPid, ClientId, PMon)}}; @@ -223,7 +224,7 @@ handle_cast({notify, {unregistered, _ClientId, SessionPid}}, State = #state{sess {noreply, State#state{session_pmon = emqx_pmon:demonitor(SessionPid, PMon)}}; handle_cast(Msg, State) -> - emqx_logger:error("[SM] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[SM] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({'DOWN', _MRef, process, DownPid, _Reason}, State = #state{session_pmon = PMon}) -> @@ -235,24 +236,23 @@ handle_info({'DOWN', _MRef, process, DownPid, _Reason}, State = #state{session_p end; handle_info(Info, State) -> - emqx_logger:error("[SM] Unexpected info: ~p", [Info]), + emqx_logger:error("[SM] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, _State) -> - emqx_stats:cancel_update(cm_stats). + emqx_stats:cancel_update(sm_stats). code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ stats_fun() -> - fun () -> + fun() -> safe_update_stats(?SESSION, 'sessions/count', 'sessions/max'), - safe_update_stats(?SESSION_P, 'sessions/persistent/count', - 'sessions/persistent/max') + safe_update_stats(?SESSION_P, 'sessions/persistent/count', 'sessions/persistent/max') end. safe_update_stats(Tab, Stat, MaxStat) -> diff --git a/src/emqx_sm_locker.erl b/src/emqx_sm_locker.erl index 50b1fe462..050e6276c 100644 --- a/src/emqx_sm_locker.erl +++ b/src/emqx_sm_locker.erl @@ -1,27 +1,23 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sm_locker). -include("emqx.hrl"). -export([start_link/0]). - -export([trans/2, trans/3]). - -export([lock/1, lock/2, unlock/1]). -spec(start_link() -> {ok, pid()} | ignore | {error, term()}). @@ -32,9 +28,7 @@ start_link() -> trans(ClientId, Fun) -> trans(ClientId, Fun, undefined). --spec(trans(client_id() | undefined, - fun(([node()]) -> any()), - ekka_locker:piggyback()) -> any()). +-spec(trans(client_id() | undefined, fun(([node()]) -> any()), ekka_locker:piggyback()) -> any()). trans(undefined, Fun, _Piggyback) -> Fun([]); trans(ClientId, Fun, Piggyback) -> @@ -49,8 +43,7 @@ trans(ClientId, Fun, Piggyback) -> lock(ClientId) -> ekka_locker:aquire(?MODULE, ClientId, strategy()). --spec(lock(client_id(), ekka_locker:piggyback()) - -> ekka_locker:lock_result()). +-spec(lock(client_id(), ekka_locker:piggyback()) -> ekka_locker:lock_result()). lock(ClientId, Piggyback) -> ekka_locker:aquire(?MODULE, ClientId, strategy(), Piggyback). @@ -60,5 +53,5 @@ unlock(ClientId) -> -spec(strategy() -> local | one | quorum | all). strategy() -> - application:get_env(emqx, session_locking_strategy, quorum). + emqx_config:get_env(session_locking_strategy, quorum). diff --git a/src/emqx_sm_registry.erl b/src/emqx_sm_registry.erl index 085403d79..4a9be13c0 100644 --- a/src/emqx_sm_registry.erl +++ b/src/emqx_sm_registry.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sm_registry). @@ -20,25 +18,17 @@ -include("emqx.hrl"). -%% API -export([start_link/0]). - -export([is_enabled/0]). - -export([register_session/1, lookup_session/1, unregister_session/1]). - %% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(REGISTRY, ?MODULE). - -define(TAB, emqx_session_registry). - -define(LOCK, {?MODULE, cleanup_sessions}). -record(global_session, {sid, pid}). - -record(state, {}). -type(session_pid() :: pid()). @@ -58,21 +48,19 @@ lookup_session(ClientId) -> <- mnesia:dirty_read(?TAB, ClientId)]. -spec(register_session({client_id(), session_pid()}) -> ok). -register_session({ClientId, SessionPid}) when is_binary(ClientId), - is_pid(SessionPid) -> +register_session({ClientId, SessionPid}) when is_binary(ClientId), is_pid(SessionPid) -> mnesia:dirty_write(?TAB, record(ClientId, SessionPid)). -spec(unregister_session({client_id(), session_pid()}) -> ok). -unregister_session({ClientId, SessionPid}) when is_binary(ClientId), - is_pid(SessionPid) -> +unregister_session({ClientId, SessionPid}) when is_binary(ClientId), is_pid(SessionPid) -> mnesia:dirty_delete_object(?TAB, record(ClientId, SessionPid)). record(ClientId, SessionPid) -> #global_session{sid = ClientId, pid = SessionPid}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> ok = ekka_mnesia:create_table(?TAB, [ @@ -85,11 +73,11 @@ init([]) -> {ok, #state{}}. handle_call(Req, _From, State) -> - emqx_logger:error("[Registry] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Registry] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[Registry] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Registry] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({membership, {mnesia, down, Node}}, State) -> @@ -103,7 +91,7 @@ handle_info({membership, _Event}, State) -> {noreply, State}; handle_info(Info, State) -> - emqx_logger:error("[Registry] Unexpected info: ~p", [Info]), + emqx_logger:error("[Registry] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -112,9 +100,9 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ cleanup_sessions(Node) -> Pat = [{#global_session{pid = '$1', _ = '_'}, diff --git a/src/emqx_sm_sup.erl b/src/emqx_sm_sup.erl index b01f13e41..0be9facb0 100644 --- a/src/emqx_sm_sup.erl +++ b/src/emqx_sm_sup.erl @@ -1,18 +1,17 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sm_sup). @@ -26,17 +25,26 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - %% Session Locker - Locker = {locker, {emqx_sm_locker, start_link, []}, - permanent, 5000, worker, [emqx_sm_locker]}, - - %% Session Registry - Registry = {registry, {emqx_sm_registry, start_link, []}, - permanent, 5000, worker, [emqx_sm_registry]}, - + %% Session locker + Locker = #{id => locker, + start => {emqx_sm_locker, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_sm_locker]}, + %% Session registry + Registry = #{id => registry, + start => {emqx_sm_registry, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_sm_registry]}, %% Session Manager - Manager = {manager, {emqx_sm, start_link, []}, - permanent, 5000, worker, [emqx_sm]}, - + Manager = #{id => manager, + start => {emqx_sm, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_sm]}, {ok, {{rest_for_one, 10, 3600}, [Locker, Registry, Manager]}}. diff --git a/src/emqx_stats.erl b/src/emqx_stats.erl index 0bcf2e5b8..479021bf0 100644 --- a/src/emqx_stats.erl +++ b/src/emqx_stats.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_stats). @@ -27,15 +25,13 @@ %% Stats API. -export([statsfun/1, statsfun/2, getstats/0, getstat/1, setstat/2, setstat/3]). - -export([update_interval/2, update_interval/3, cancel_update/1]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(update, {name, countdown, interval, func}). - -record(state, {timer, updates :: #update{}}). -type(stats() :: list({atom(), non_neg_integer()})). @@ -85,10 +81,6 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - %% Get all stats. -spec(all() -> stats()). all() -> getstats(). @@ -97,7 +89,7 @@ all() -> getstats(). -spec(statsfun(Stat :: atom()) -> fun()). statsfun(Stat) -> fun(Val) -> setstat(Stat, Val) end. - + -spec(statsfun(Stat :: atom(), MaxStat :: atom()) -> fun()). statsfun(Stat, MaxStat) -> fun(Val) -> setstat(Stat, MaxStat, Val) end. @@ -147,23 +139,23 @@ rec(Name, Secs, UpFun) -> cast(Msg) -> gen_server:cast(?SERVER, Msg). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([]) -> _ = emqx_tables:new(?TAB, [set, public, {write_concurrency, true}]), Stats = lists:append([?CLIENT_STATS, ?SESSION_STATS, ?PUBSUB_STATS, ?ROUTE_STATS, ?RETAINED_STATS]), - ets:insert(?TAB, [{Name, 0} || Name <- Stats]), + true = ets:insert(?TAB, [{Name, 0} || Name <- Stats]), {ok, start_timer(#state{updates = []}), hibernate}. start_timer(State) -> State#state{timer = emqx_misc:start_timer(timer:seconds(1), tick)}. handle_call(Req, _From, State) -> - emqx_logger:error("[STATS] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Stats] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast({setstat, Stat, MaxStat, Val}, State) -> try ets:lookup_element(?TAB, MaxStat, 2) of @@ -177,11 +169,10 @@ handle_cast({setstat, Stat, MaxStat, Val}, State) -> safe_update_element(Stat, Val), {noreply, State}; -handle_cast({update_interval, Update = #update{name = Name}}, - State = #state{updates = Updates}) -> +handle_cast({update_interval, Update = #update{name = Name}}, State = #state{updates = Updates}) -> case lists:keyfind(Name, #update.name, Updates) of #update{} -> - emqx_logger:error("[STATS]: Duplicated update: ~s", [Name]), + emqx_logger:error("[Stats]: duplicated update: ~s", [Name]), {noreply, State}; false -> {noreply, State#state{updates = [Update | Updates]}} @@ -191,17 +182,16 @@ handle_cast({cancel_update, Name}, State = #state{updates = Updates}) -> {noreply, State#state{updates = lists:keydelete(Name, #update.name, Updates)}}; handle_cast(Msg, State) -> - emqx_logger:error("[STATS] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Stats] unexpected cast: ~p", [Msg]), {noreply, State}. -handle_info({timeout, TRef, tick}, State = #state{timer = TRef, - updates = Updates}) -> +handle_info({timeout, TRef, tick}, State = #state{timer= TRef, updates = Updates}) -> lists:foldl( fun(Update = #update{name = Name, countdown = C, interval = I, func = UpFun}, Acc) when C =< 0 -> try UpFun() catch _:Error -> - emqx_logger:error("[STATS] Update ~s error: ~p", [Name, Error]) + emqx_logger:error("[Stats] update ~s error: ~p", [Name, Error]) end, [Update#update{countdown = I} | Acc]; (Update = #update{countdown = C}, Acc) -> @@ -210,7 +200,7 @@ handle_info({timeout, TRef, tick}, State = #state{timer = TRef, {noreply, start_timer(State), hibernate}; handle_info(Info, State) -> - emqx_logger:error("[STATS] Unexpected info: ~p", [Info]), + emqx_logger:error("[Stats] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{timer = TRef}) -> @@ -219,9 +209,9 @@ terminate(_Reason, #state{timer = TRef}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Internal functions -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- safe_update_element(Key, Val) -> try ets:update_element(?TAB, Key, {2, Val}) diff --git a/src/emqx_sys.erl b/src/emqx_sys.erl index 65f361b95..8644f8801 100644 --- a/src/emqx_sys.erl +++ b/src/emqx_sys.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sys). @@ -21,13 +19,10 @@ -include("emqx.hrl"). -export([start_link/0]). - -export([version/0, uptime/0, datetime/0, sysdescr/0, sys_interval/0]). - -export([info/0]). - --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -import(emqx_topic, [systop/1]). -import(emqx_misc, [start_timer/2]). @@ -48,10 +43,6 @@ start_link() -> gen_server:start_link({local, ?SYS}, ?MODULE, [], []). -%%-------------------------------------------------------------------- -%% API -%%-------------------------------------------------------------------- - %% @doc Get sys version -spec(version() -> string()). version() -> @@ -64,7 +55,8 @@ sysdescr() -> %% @doc Get sys uptime -spec(uptime() -> string()). -uptime() -> gen_server:call(?SYS, uptime). +uptime() -> + gen_server:call(?SYS, uptime). %% @doc Get sys datetime -spec(datetime() -> string()). @@ -87,9 +79,9 @@ info() -> {uptime, uptime()}, {datetime, datetime()}]. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> State = #state{start_time = erlang:timestamp(), @@ -106,11 +98,11 @@ handle_call(uptime, _From, State) -> {reply, uptime(State), State}; handle_call(Req, _From, State) -> - emqx_logger:error("[SYS] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[SYS] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[SYS] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[SYS] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({timeout, TRef, heartbeat}, State = #state{heartbeat = TRef}) -> @@ -118,9 +110,7 @@ handle_info({timeout, TRef, heartbeat}, State = #state{heartbeat = TRef}) -> publish(datetime, iolist_to_binary(datetime())), {noreply, heartbeat(State)}; -handle_info({timeout, TRef, tick}, State = #state{ticker = TRef, - version = Version, - sysdescr = Descr}) -> +handle_info({timeout, TRef, tick}, State = #state{ticker = TRef, version = Version, sysdescr = Descr}) -> publish(version, Version), publish(sysdescr, Descr), publish(brokers, ekka_mnesia:running_nodes()), @@ -129,19 +119,18 @@ handle_info({timeout, TRef, tick}, State = #state{ticker = TRef, {noreply, tick(State), hibernate}; handle_info(Info, State) -> - emqx_logger:error("[SYS] Unexpected info: ~p", [Info]), + emqx_logger:error("[SYS] unexpected info: ~p", [Info]), {noreply, State}. -terminate(_Reason, #state{heartbeat = HBRef, ticker = TRef}) -> - emqx_misc:cancel_timer(HBRef), - emqx_misc:cancel_timer(TRef). +terminate(_Reason, #state{heartbeat = TRef1, ticker = TRef2}) -> + lists:foreach(fun emqx_misc:cancel_timer/1, [TRef1, TRef2]). code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% Internal functions -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- uptime(#state{start_time = Ts}) -> Secs = timer:now_diff(erlang:timestamp(), Ts) div 1000000, @@ -162,37 +151,26 @@ uptime(days, D) -> [integer_to_list(D), " days,"]. publish(uptime, Uptime) -> - safe_publish(systop(uptime), [sys], Uptime); + safe_publish(systop(uptime), Uptime); publish(datetime, Datetime) -> - safe_publish(systop(datatype), [sys], Datetime); + safe_publish(systop(datatype), Datetime); publish(version, Version) -> - safe_publish(systop(version), [sys, retain], Version); + safe_publish(systop(version), #{retain => true}, Version); publish(sysdescr, Descr) -> - safe_publish(systop(sysdescr), [sys, retain], Descr); + safe_publish(systop(sysdescr), #{retain => true}, Descr); publish(brokers, Nodes) -> Payload = string:join([atom_to_list(N) || N <- Nodes], ","), - safe_publish(<<"$SYS/brokers">>, [sys, retain], Payload); + safe_publish(<<"$SYS/brokers">>, #{retain => true}, Payload); publish(stats, Stats) -> - [begin - Topic = systop(lists:concat(['stats/', Stat])), - safe_publish(Topic, [sys], integer_to_binary(Val)) - end || {Stat, Val} <- Stats, is_atom(Stat), is_integer(Val)]; + [safe_publish(systop(lists:concat(['stats/', Stat])), integer_to_binary(Val)) + || {Stat, Val} <- Stats, is_atom(Stat), is_integer(Val)]; publish(metrics, Metrics) -> - [begin - Topic = systop(lists:concat(['metrics/', Metric])), - safe_publish(Topic, [sys], integer_to_binary(Val)) - end || {Metric, Val} <- Metrics, is_atom(Metric), is_integer(Val)]. + [safe_publish(systop(lists:concat(['metrics/', Metric])), integer_to_binary(Val)) + || {Metric, Val} <- Metrics, is_atom(Metric), is_integer(Val)]. +safe_publish(Topic, Payload) -> + safe_publish(Topic, #{}, Payload). safe_publish(Topic, Flags, Payload) -> - try do_publish(Topic, Flags, Payload) - catch - _:Error -> - emqx_logger:error("[SYS] Publish error: ~p", [Error]) - end. - -do_publish(Topic, Flags, Payload) -> - Msg0 = emqx_message:make(?SYS, Topic, iolist_to_binary(Payload)), - emqx_broker:publish(lists:foldl(fun(Flag, Msg) -> - emqx_message:set_flag(Flag, Msg) - end, Msg0, Flags)). + Flags1 = maps:merge(#{sys => true, qos => 0}, Flags), + emqx_broker:safe_publish(emqx_message:new(?SYS, Flags1, Topic, iolist_to_binary(Payload))). diff --git a/src/emqx_sys_mon.erl b/src/emqx_sys_mon.erl index 6e58f84bb..af6d39138 100644 --- a/src/emqx_sys_mon.erl +++ b/src/emqx_sys_mon.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sys_mon). @@ -20,30 +18,25 @@ -export([start_link/1]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {timer, events}). --define(LOG(Msg, ProcInfo), - emqx_logger:warning([{sysmon, true}], - "[SYSMON] ~s~n~p", [WarnMsg, ProcInfo])). - --define(LOG(Msg, ProcInfo, PortInfo), - emqx_logger:warning([{sysmon, true}], - "[SYSMON] ~s~n~p~n~p", [WarnMsg, ProcInfo, PortInfo])). - -define(SYSMON, ?MODULE). +-define(LOG(Msg, ProcInfo), + emqx_logger:warning([{sysmon, true}], "[SYSMON] ~s~n~p", [WarnMsg, ProcInfo])). +-define(LOG(Msg, ProcInfo, PortInfo), + emqx_logger:warning([{sysmon, true}], "[SYSMON] ~s~n~p~n~p", [WarnMsg, ProcInfo, PortInfo])). %% @doc Start system monitor --spec(start_link(Opts :: list(tuple())) - -> {ok, pid()} | ignore | {error, term()}). +-spec(start_link(Opts :: list(tuple())) -> {ok, pid()} | ignore | {error, term()}). start_link(Opts) -> gen_server:start_link({local, ?SYSMON}, ?MODULE, [Opts], []). -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- %% gen_server callbacks -%%-------------------------------------------------------------------- +%%----------------------------------------------------------------------------- init([Opts]) -> erlang:system_monitor(self(), parse_opt(Opts)), @@ -78,60 +71,66 @@ parse_opt([_Opt|Opts], Acc) -> parse_opt(Opts, Acc). handle_call(Req, _From, State) -> - emqx_logger:error("[SYSMON] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[SYSMON] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[SYSMON] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[SYSMON] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info({monitor, Pid, long_gc, Info}, State) -> - suppress({long_gc, Pid}, fun() -> - WarnMsg = io_lib:format("long_gc warning: pid = ~p, info: ~p", [Pid, Info]), - ?LOG(WarnMsg, procinfo(Pid)), - safe_publish(long_gc, WarnMsg) - end, State); + suppress({long_gc, Pid}, + fun() -> + WarnMsg = io_lib:format("long_gc warning: pid = ~p, info: ~p", [Pid, Info]), + ?LOG(WarnMsg, procinfo(Pid)), + safe_publish(long_gc, WarnMsg) + end, State); handle_info({monitor, Pid, long_schedule, Info}, State) when is_pid(Pid) -> - suppress({long_schedule, Pid}, fun() -> - WarnMsg = io_lib:format("long_schedule warning: pid = ~p, info: ~p", [Pid, Info]), - ?LOG(WarnMsg, procinfo(Pid)), - safe_publish(long_schedule, WarnMsg) - end, State); + suppress({long_schedule, Pid}, + fun() -> + WarnMsg = io_lib:format("long_schedule warning: pid = ~p, info: ~p", [Pid, Info]), + ?LOG(WarnMsg, procinfo(Pid)), + safe_publish(long_schedule, WarnMsg) + end, State); handle_info({monitor, Port, long_schedule, Info}, State) when is_port(Port) -> - suppress({long_schedule, Port}, fun() -> - WarnMsg = io_lib:format("long_schedule warning: port = ~p, info: ~p", [Port, Info]), - ?LOG(WarnMsg, erlang:port_info(Port)), - safe_publish(long_schedule, WarnMsg) - end, State); + suppress({long_schedule, Port}, + fun() -> + WarnMsg = io_lib:format("long_schedule warning: port = ~p, info: ~p", [Port, Info]), + ?LOG(WarnMsg, erlang:port_info(Port)), + safe_publish(long_schedule, WarnMsg) + end, State); handle_info({monitor, Pid, large_heap, Info}, State) -> - suppress({large_heap, Pid}, fun() -> - WarnMsg = io_lib:format("large_heap warning: pid = ~p, info: ~p", [Pid, Info]), - ?LOG(WarnMsg, procinfo(Pid)), - safe_publish(large_heap, WarnMsg) - end, State); + suppress({large_heap, Pid}, + fun() -> + WarnMsg = io_lib:format("large_heap warning: pid = ~p, info: ~p", [Pid, Info]), + ?LOG(WarnMsg, procinfo(Pid)), + safe_publish(large_heap, WarnMsg) + end, State); handle_info({monitor, SusPid, busy_port, Port}, State) -> - suppress({busy_port, Port}, fun() -> - WarnMsg = io_lib:format("busy_port warning: suspid = ~p, port = ~p", [SusPid, Port]), - ?LOG(WarnMsg, procinfo(SusPid), erlang:port_info(Port)), - safe_publish(busy_port, WarnMsg) - end, State); + suppress({busy_port, Port}, + fun() -> + WarnMsg = io_lib:format("busy_port warning: suspid = ~p, port = ~p", [SusPid, Port]), + ?LOG(WarnMsg, procinfo(SusPid), erlang:port_info(Port)), + safe_publish(busy_port, WarnMsg) + end, State); handle_info({monitor, SusPid, busy_dist_port, Port}, State) -> - suppress({busy_dist_port, Port}, fun() -> - WarnMsg = io_lib:format("busy_dist_port warning: suspid = ~p, port = ~p", [SusPid, Port]), - ?LOG(WarnMsg, procinfo(SusPid), erlang:port_info(Port)), - safe_publish(busy_dist_port, WarnMsg) - end, State); + suppress({busy_dist_port, Port}, + fun() -> + WarnMsg = io_lib:format("busy_dist_port warning: suspid = ~p, port = ~p", [SusPid, Port]), + ?LOG(WarnMsg, procinfo(SusPid), erlang:port_info(Port)), + safe_publish(busy_dist_port, WarnMsg) + end, State); handle_info(reset, State) -> {noreply, State#state{events = []}, hibernate}; handle_info(Info, State) -> - lager:error("[SYSMON] Unexpected Info: ~p", [Info]), + lager:error("[SYSMON] unexpected Info: ~p", [Info]), {noreply, State}. terminate(_Reason, #state{timer = TRef}) -> @@ -155,12 +154,9 @@ procinfo(Pid) -> end. safe_publish(Event, WarnMsg) -> - try - Topic = emqx_topic:systop(lists:concat(['sysmon/', Event])), - Msg = emqx_message:make(?SYSMON, Topic, iolist_to_binary(WarnMsg)), - emqx_broker:publish(emqx_message:set_flag(sys, Msg)) - catch - _:Error -> - emqx_logger:error("[SYSMON] Publish error: ~p", [Error]) - end. + Topic = emqx_topic:systop(lists:concat(['sysmon/', Event])), + emqx_broker:safe_publish(sysmon_msg(Topic, iolist_to_binary(WarnMsg))). + +sysmon_msg(Topic, Payload) -> + emqx_message:new(?SYSMON, #{sys => true, qos => 0}, Topic, Payload). diff --git a/src/emqx_sys_sup.erl b/src/emqx_sys_sup.erl index 69d6f4cb5..0e56e5fc5 100644 --- a/src/emqx_sys_sup.erl +++ b/src/emqx_sys_sup.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_sys_sup). @@ -26,11 +24,18 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - Sys = {sys, {emqx_sys, start_link, []}, - permanent, 5000, worker, [emqx_sys]}, - - {ok, Env} = emqx_config:get_env(sysmon), - Sysmon = {sys_mon, {emqx_sys_mon, start_link, [Env]}, - permanent, 5000, worker, [emqx_sys_mon]}, + Sys = #{id => sys, + start => {emqx_sys, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_sys]}, + Sysmon = #{id => sys_mon, + start => {emqx_sys_mon, start_link, + [emqx_config:get_env(sysmon, [])]}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_sys_mon]}, {ok, {{one_for_one, 10, 100}, [Sys, Sysmon]}}. diff --git a/src/emqx_tables.erl b/src/emqx_tables.erl index c5f249592..330c87d9c 100644 --- a/src/emqx_tables.erl +++ b/src/emqx_tables.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_tables). diff --git a/src/emqx_time.erl b/src/emqx_time.erl index 1d1405900..2e69638dc 100644 --- a/src/emqx_time.erl +++ b/src/emqx_time.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_time). diff --git a/src/emqx_topic.erl b/src/emqx_topic.erl index a642b5951..43ab8e0df 100644 --- a/src/emqx_topic.erl +++ b/src/emqx_topic.erl @@ -1,39 +1,31 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_topic). -include("emqx.hrl"). - -include("emqx_mqtt.hrl"). -import(lists, [reverse/1]). -export([match/2, validate/1, triples/1, words/1, wildcard/1]). - -export([join/1, feed_var/3, systop/1]). - -export([parse/1, parse/2]). +-type(word() :: '' | '+' | '#' | binary()). +-type(words() :: list(word())). -type(option() :: {qos, mqtt_qos()} | {share, '$queue' | binary()}). - --type(word() :: '' | '+' | '#' | binary()). - --type(words() :: list(word())). - -type(triple() :: {root | binary(), word(), binary()}). -export_type([option/0, word/0, triple/0]). @@ -110,14 +102,13 @@ validate3(<>) when C == $#; C == $+; C == 0 -> validate3(<<_/utf8, Rest/binary>>) -> validate3(Rest). -%% @doc Topic to Triples +%% @doc Topic to triples -spec(triples(topic()) -> list(triple())). triples(Topic) when is_binary(Topic) -> triples(words(Topic), root, []). triples([], _Parent, Acc) -> reverse(Acc); - triples([W|Words], Parent, Acc) -> Node = join(Parent, W), triples(Words, Node, [{Parent, W, Node}|Acc]). @@ -166,9 +157,9 @@ join([W]) -> join(Words) -> {_, Bin} = lists:foldr(fun(W, {true, Tail}) -> - {false, <>}; + {false, <>}; (W, {false, Tail}) -> - {false, <>} + {false, <>} end, {true, <<>>}, [bin(W) || W <- Words]), Bin. @@ -176,24 +167,16 @@ join(Words) -> parse(Topic) when is_binary(Topic) -> parse(Topic, []). -parse(Topic = <<"$fastlane/", Topic1/binary>>, Options) -> - case lists:member(fastlane, Options) of - true -> error({invalid_topic, Topic}); - false -> parse(Topic1, [fastlane | Options]) - end; - parse(Topic = <<"$queue/", Topic1/binary>>, Options) -> case lists:keyfind(share, 1, Options) of {share, _} -> error({invalid_topic, Topic}); false -> parse(Topic1, [{share, '$queue'} | Options]) end; - parse(Topic = <<"$share/", Topic1/binary>>, Options) -> case lists:keyfind(share, 1, Options) of {share, _} -> error({invalid_topic, Topic}); false -> [Group, Topic2] = binary:split(Topic1, <<"/">>), {Topic2, [{share, Group} | Options]} end; - parse(Topic, Options) -> {Topic, Options}. diff --git a/src/emqx_tracer.erl b/src/emqx_tracer.erl index 5e68ed4c5..0f16c858c 100644 --- a/src/emqx_tracer.erl +++ b/src/emqx_tracer.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_tracer). @@ -21,32 +19,29 @@ -include("emqx.hrl"). -export([start_link/0]). - -export([start_trace/2, lookup_traces/0, stop_trace/1]). -%% gen_server Function Exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). -record(state, {level, traces}). -type(trace_who() :: {client | topic, binary()}). +-define(TRACER, ?MODULE). -define(OPTIONS, [{formatter_config, [time, " [",severity,"] ", message, "\n"]}]). --define(TRACER, ?MODULE). - -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Start the tracer -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ -spec(start_link() -> {ok, pid()} | ignore | {error, term()}). start_link() -> gen_server:start_link({local, ?TRACER}, ?MODULE, [], []). -%%-------------------------------------------------------------------- -%% Start/Stop Trace -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ +%% Start/Stop trace +%%------------------------------------------------------------------------------ %% @doc Start to trace client or topic. -spec(start_trace(trace_who(), string()) -> ok | {error, term()}). @@ -55,8 +50,7 @@ start_trace({client, ClientId}, LogFile) -> start_trace({topic, Topic}, LogFile) -> start_trace({start_trace, {topic, Topic}, LogFile}). -start_trace(Req) -> - gen_server:call(?MODULE, Req, infinity). +start_trace(Req) -> gen_server:call(?MODULE, Req, infinity). %% @doc Stop tracing client or topic. -spec(stop_trace(trace_who()) -> ok | {error, term()}). @@ -70,26 +64,24 @@ stop_trace({topic, Topic}) -> lookup_traces() -> gen_server:call(?TRACER, lookup_traces). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% gen_server callbacks -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ init([]) -> - Level = emqx_config:get_env(trace_level, debug), - {ok, #state{level = Level, traces = #{}}}. + {ok, #state{level = emqx_config:get_env(trace_level, debug), traces = #{}}}. -handle_call({start_trace, Who, LogFile}, _From, - State = #state{level = Level, traces = Traces}) -> +handle_call({start_trace, Who, LogFile}, _From, State = #state{level = Level, traces = Traces}) -> case catch lager:trace_file(LogFile, [Who], Level, ?OPTIONS) of {ok, exists} -> - {reply, {error, alread_existed}, State}; + {reply, {error, already_existed}, State}; {ok, Trace} -> {reply, ok, State#state{traces = maps:put(Who, {Trace, LogFile}, Traces)}}; {error, Reason} -> - emqx_logger:error("[TRACER] trace error: ~p", [Reason]), + emqx_logger:error("[Tracer] trace error: ~p", [Reason]), {reply, {error, Reason}, State}; {'EXIT', Error} -> - emqx_logger:error("[TRACER] trace exit: ~p", [Error]), + emqx_logger:error("[Tracer] trace exit: ~p", [Error]), {reply, {error, Error}, State} end; @@ -98,27 +90,27 @@ handle_call({stop_trace, Who}, _From, State = #state{traces = Traces}) -> {ok, {Trace, _LogFile}} -> case lager:stop_trace(Trace) of ok -> ok; - {error, Error} -> lager:error("Stop trace ~p error: ~p", [Who, Error]) + {error, Error} -> + emqx_logger:error("[Tracer] stop trace ~p error: ~p", [Who, Error]) end, {reply, ok, State#state{traces = maps:remove(Who, Traces)}}; error -> - {reply, {error, trance_not_found}, State} + {reply, {error, not_found}, State} end; handle_call(lookup_traces, _From, State = #state{traces = Traces}) -> - {reply, [{Who, LogFile} || {Who, {_Trace, LogFile}} - <- maps:to_list(Traces)], State}; + {reply, [{Who, LogFile} || {Who, {_Trace, LogFile}} <- maps:to_list(Traces)], State}; handle_call(Req, _From, State) -> - emqx_logger:error("[TRACER] Unexpected request: ~p", [Req]), - {reply, ignore, State}. + emqx_logger:error("[Tracer] unexpected call: ~p", [Req]), + {reply, ignored, State}. handle_cast(Msg, State) -> - emqx_logger:error("[TRACER] Unexpected msg: ~p", [Msg]), + emqx_logger:error("[Tracer] unexpected cast: ~p", [Msg]), {noreply, State}. handle_info(Info, State) -> - emqx_logger:error("[TRACER] Unexpected info: ~p", [Info]), + emqx_logger:error("[Tracer] unexpected info: ~p", [Info]), {noreply, State}. terminate(_Reason, _State) -> diff --git a/src/emqx_trie.erl b/src/emqx_trie.erl index 595b38116..43e36c060 100644 --- a/src/emqx_trie.erl +++ b/src/emqx_trie.erl @@ -1,18 +1,16 @@ -%%%=================================================================== -%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%%% -%%% Licensed under the Apache License, Version 2.0 (the "License"); -%%% you may not use this file except in compliance with the License. -%%% You may obtain a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, software -%%% distributed under the License is distributed on an "AS IS" BASIS, -%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%%% See the License for the specific language governing permissions and -%%% limitations under the License. -%%%=================================================================== +%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(emqx_trie). @@ -31,9 +29,9 @@ -define(TRIE, emqx_trie). -define(TRIE_NODE, emqx_trie_node). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Mnesia bootstrap -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% @doc Create or replicate trie tables. -spec(mnesia(boot | copy) -> ok). @@ -55,9 +53,9 @@ mnesia(copy) -> %% Copy trie_node table ok = ekka_mnesia:copy_table(?TRIE_NODE). -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Trie APIs -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% @doc Insert a topic into the trie -spec(insert(Topic :: topic()) -> ok). @@ -94,13 +92,12 @@ delete(Topic) when is_binary(Topic) -> delete_path(lists:reverse(emqx_topic:triples(Topic))); [TrieNode] -> write_trie_node(TrieNode#trie_node{topic = undefined}); - [] -> - ok + [] -> ok end. -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% Internal functions -%%-------------------------------------------------------------------- +%%------------------------------------------------------------------------------ %% @private %% @doc Add a path to the trie. @@ -112,8 +109,7 @@ add_path({Node, Word, Child}) -> [] -> write_trie_node(TrieNode#trie_node{edge_count = Count + 1}), write_trie(#trie{edge = Edge, node_id = Child}); - [_] -> - ok + [_] -> ok end; [] -> write_trie_node(#trie_node{node_id = Node, edge_count = 1}), @@ -145,8 +141,7 @@ match_node(NodeId, [W|Words], ResAcc) -> case mnesia:read(?TRIE, #trie_edge{node_id = NodeId, word = '#'}) of [#trie{node_id = ChildId}] -> mnesia:read(?TRIE_NODE, ChildId) ++ ResAcc; - [] -> - ResAcc + [] -> ResAcc end. %% @private