emqx/apps/emqx_gateway/src/emqx_gateway_gw_sup.erl

140 lines
4.3 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2021-2023 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 The Gateway Top supervisor.
%%
%% This supervisor has monitor a bunch of process/resources depended by
%% gateway runtime
%%
-module(emqx_gateway_gw_sup).
-behaviour(supervisor).
-include("emqx_gateway.hrl").
-export([start_link/1]).
-export([
create_insta/3,
remove_insta/2,
update_insta/3,
start_insta/2,
stop_insta/2,
list_insta/1
]).
%% Supervisor callbacks
-export([init/1]).
%%--------------------------------------------------------------------
%% APIs
%%--------------------------------------------------------------------
start_link(GwName) ->
supervisor:start_link({local, GwName}, ?MODULE, [GwName]).
-spec create_insta(pid(), gateway(), map()) -> {ok, GwInstaPid :: pid()} | {error, any()}.
create_insta(Sup, Gateway = #{name := Name}, GwDscrptr) ->
case emqx_gateway_utils:find_sup_child(Sup, Name) of
{ok, _GwInstaPid} ->
{error, alredy_existed};
false ->
Ctx = ctx(Sup, Name),
ChildSpec = emqx_gateway_utils:childspec(
Name,
worker,
emqx_gateway_insta_sup,
[Gateway, Ctx, GwDscrptr]
),
emqx_gateway_utils:supervisor_ret(
supervisor:start_child(Sup, ChildSpec)
)
end.
-spec remove_insta(pid(), Name :: gateway_name()) -> ok | {error, any()}.
remove_insta(Sup, Name) ->
case emqx_gateway_utils:find_sup_child(Sup, Name) of
false ->
ok;
{ok, _GwInstaPid} ->
ok = supervisor:terminate_child(Sup, Name),
ok = supervisor:delete_child(Sup, Name)
end.
-spec update_insta(pid(), gateway_name(), emqx_config:config()) ->
ok | {error, any()}.
update_insta(Sup, Name, Config) ->
case emqx_gateway_utils:find_sup_child(Sup, Name) of
false -> {error, not_found};
{ok, GwInstaPid} -> emqx_gateway_insta_sup:update(GwInstaPid, Config)
end.
-spec start_insta(pid(), gateway_name()) -> ok | {error, any()}.
start_insta(Sup, Name) ->
case emqx_gateway_utils:find_sup_child(Sup, Name) of
false -> {error, not_found};
{ok, GwInstaPid} -> emqx_gateway_insta_sup:enable(GwInstaPid)
end.
-spec stop_insta(pid(), gateway_name()) -> ok | {error, any()}.
stop_insta(Sup, Name) ->
case emqx_gateway_utils:find_sup_child(Sup, Name) of
false -> {error, not_found};
{ok, GwInstaPid} -> emqx_gateway_insta_sup:disable(GwInstaPid)
end.
-spec list_insta(pid()) -> [gateway()].
list_insta(Sup) ->
lists:filtermap(
fun({Name, GwInstaPid, _Type, _Mods}) ->
is_gateway_insta_id(Name) andalso
{true, emqx_gateway_insta_sup:info(GwInstaPid)}
end,
supervisor:which_children(Sup)
).
%% Supervisor callback
%% @doc Initialize Top Supervisor for a Protocol
init([GwName]) ->
SupFlags = #{
strategy => one_for_one,
intensity => 10,
period => 60
},
CmOpts = [{gwname, GwName}],
CM = emqx_gateway_utils:childspec(worker, emqx_gateway_cm, [CmOpts]),
Metrics = emqx_gateway_utils:childspec(worker, emqx_gateway_metrics, [GwName]),
{ok, {SupFlags, [CM, Metrics]}}.
%%--------------------------------------------------------------------
%% Internal funcs
%%--------------------------------------------------------------------
ctx(Sup, Name) ->
{ok, CM} = emqx_gateway_utils:find_sup_child(Sup, emqx_gateway_cm),
#{
gwname => Name,
cm => CM
}.
is_gateway_insta_id(emqx_gateway_cm) ->
false;
is_gateway_insta_id(emqx_gateway_metrics) ->
false;
is_gateway_insta_id(_Id) ->
true.