183 lines
5.3 KiB
Erlang
183 lines
5.3 KiB
Erlang
%%--------------------------------------------------------------------
|
|
%% Copyright (c) 2021-2024 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_gateway_sup).
|
|
|
|
-behaviour(supervisor).
|
|
|
|
-include("emqx_gateway.hrl").
|
|
|
|
-export([start_link/0]).
|
|
|
|
%% Gateway APIs
|
|
-export([
|
|
load_gateway/1,
|
|
unload_gateway/1,
|
|
lookup_gateway/1,
|
|
update_gateway/2,
|
|
start_gateway_insta/1,
|
|
stop_gateway_insta/1,
|
|
list_gateway_insta/0
|
|
]).
|
|
|
|
%% supervisor callbacks
|
|
-export([init/1]).
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% APIs
|
|
%%--------------------------------------------------------------------
|
|
|
|
start_link() ->
|
|
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
|
|
-spec load_gateway(gateway()) -> {ok, pid()} | {error, any()}.
|
|
load_gateway(Gateway = #{name := GwName}) ->
|
|
case emqx_gateway_registry:lookup(GwName) of
|
|
undefined ->
|
|
{error, {unknown_gateway_name, GwName}};
|
|
GwDscrptr ->
|
|
{ok, GwSup} = ensure_gateway_suptree_ready(GwName),
|
|
emqx_gateway_gw_sup:create_insta(GwSup, Gateway, GwDscrptr)
|
|
end.
|
|
|
|
-spec unload_gateway(gateway_name()) ->
|
|
ok
|
|
| {error, not_found}
|
|
| {error, any()}.
|
|
unload_gateway(GwName) ->
|
|
case lists:keyfind(GwName, 1, supervisor:which_children(?MODULE)) of
|
|
false ->
|
|
{error, not_found};
|
|
{_Id, Pid, _Type, _Mods} ->
|
|
_ = emqx_gateway_gw_sup:remove_insta(Pid, GwName),
|
|
_ = supervisor:terminate_child(?MODULE, GwName),
|
|
_ = supervisor:delete_child(?MODULE, GwName),
|
|
ok
|
|
end.
|
|
|
|
-spec lookup_gateway(gateway_name()) -> gateway() | undefined.
|
|
lookup_gateway(GwName) ->
|
|
case search_gateway_insta_proc(GwName) of
|
|
{ok, {_, GwInstaPid}} ->
|
|
emqx_gateway_insta_sup:info(GwInstaPid);
|
|
_ ->
|
|
undefined
|
|
end.
|
|
|
|
-spec update_gateway(gateway_name(), emqx_config:config()) ->
|
|
ok
|
|
| {error, any()}.
|
|
update_gateway(GwName, Config) ->
|
|
case emqx_gateway_utils:find_sup_child(?MODULE, GwName) of
|
|
{ok, GwSup} ->
|
|
emqx_gateway_gw_sup:update_insta(GwSup, GwName, Config);
|
|
_ ->
|
|
{error, not_found}
|
|
end.
|
|
|
|
start_gateway_insta(GwName) ->
|
|
case search_gateway_insta_proc(GwName) of
|
|
{ok, {GwSup, _}} ->
|
|
emqx_gateway_gw_sup:start_insta(GwSup, GwName);
|
|
_ ->
|
|
{error, not_found}
|
|
end.
|
|
|
|
-spec stop_gateway_insta(gateway_name()) -> ok | {error, any()}.
|
|
stop_gateway_insta(GwName) ->
|
|
case search_gateway_insta_proc(GwName) of
|
|
{ok, {GwSup, _}} ->
|
|
emqx_gateway_gw_sup:stop_insta(GwSup, GwName);
|
|
_ ->
|
|
{error, not_found}
|
|
end.
|
|
|
|
-spec list_gateway_insta() -> [gateway()].
|
|
list_gateway_insta() ->
|
|
lists:append(
|
|
lists:map(
|
|
fun(SupId) ->
|
|
emqx_gateway_gw_sup:list_insta(SupId)
|
|
end,
|
|
list_started_gateway()
|
|
)
|
|
).
|
|
|
|
-spec list_started_gateway() -> [gateway_name()].
|
|
list_started_gateway() ->
|
|
started_gateway().
|
|
|
|
%% Supervisor callback
|
|
|
|
init([]) ->
|
|
SupFlags = #{
|
|
strategy => one_for_one,
|
|
intensity => 10,
|
|
period => 60
|
|
},
|
|
ChildSpecs = [emqx_gateway_utils:childspec(worker, emqx_gateway_registry)],
|
|
{ok, {SupFlags, ChildSpecs}}.
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% Internal funcs
|
|
%%--------------------------------------------------------------------
|
|
|
|
ensure_gateway_suptree_ready(GwName) ->
|
|
case lists:keyfind(GwName, 1, supervisor:which_children(?MODULE)) of
|
|
false ->
|
|
ChildSpec = emqx_gateway_utils:childspec(
|
|
GwName,
|
|
supervisor,
|
|
emqx_gateway_gw_sup,
|
|
[GwName]
|
|
),
|
|
emqx_gateway_utils:supervisor_ret(
|
|
supervisor:start_child(?MODULE, ChildSpec)
|
|
);
|
|
{_Id, Pid, _Type, _Mods} ->
|
|
{ok, Pid}
|
|
end.
|
|
|
|
search_gateway_insta_proc(InstaId) ->
|
|
search_gateway_insta_proc(InstaId, started_gateway_pid()).
|
|
|
|
search_gateway_insta_proc(_InstaId, []) ->
|
|
{error, not_found};
|
|
search_gateway_insta_proc(InstaId, [SupPid | More]) ->
|
|
case emqx_gateway_utils:find_sup_child(SupPid, InstaId) of
|
|
{ok, InstaPid} -> {ok, {SupPid, InstaPid}};
|
|
_ -> search_gateway_insta_proc(InstaId, More)
|
|
end.
|
|
|
|
started_gateway() ->
|
|
lists:filtermap(
|
|
fun({Id, _, _, _}) ->
|
|
is_a_gateway_id(Id) andalso {true, Id}
|
|
end,
|
|
supervisor:which_children(?MODULE)
|
|
).
|
|
|
|
started_gateway_pid() ->
|
|
lists:filtermap(
|
|
fun({Id, Pid, _, _}) ->
|
|
is_a_gateway_id(Id) andalso {true, Pid}
|
|
end,
|
|
supervisor:which_children(?MODULE)
|
|
).
|
|
|
|
is_a_gateway_id(Id) ->
|
|
Id /= emqx_gateway_registry.
|