diff --git a/apps/iot/src/iot_router.erl b/apps/iot/src/iot_router.erl index c339616..d295bbc 100644 --- a/apps/iot/src/iot_router.erl +++ b/apps/iot/src/iot_router.erl @@ -8,29 +8,35 @@ %%%------------------------------------------------------------------- -module(iot_router). -author("licheng5"). +-include("iot.hrl"). -behaviour(gen_server). %% API --export([start_link/0]). +-export([start_link/2]). +-export([get_name/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(SERVER, ?MODULE). --record(iot_router_state, {}). +-record(state, { + +}). + +get_name(Id) when is_integer(Id) -> + list_to_atom("iot_router:" ++ integer_to_list(Id)). %%%=================================================================== %%% API %%%=================================================================== %% @doc Spawns the server and registers the local name (unique) --spec(start_link() -> +-spec(start_link(Name :: atom(), Router :: #router{}) -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). +start_link(Name, Router = #router{}) -> + gen_server:start_link({global, Name}, ?MODULE, [Router], []). %%%=================================================================== %%% gen_server callbacks @@ -39,40 +45,41 @@ start_link() -> %% @private %% @doc Initializes the server -spec(init(Args :: term()) -> - {ok, State :: #iot_router_state{}} | {ok, State :: #iot_router_state{}, timeout() | hibernate} | + {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). -init([]) -> - {ok, #iot_router_state{}}. +init([Router]) -> + lager:debug("router is: ~p", [Router]), + {ok, #state{}}. %% @private %% @doc Handling call messages -spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()}, - State :: #iot_router_state{}) -> - {reply, Reply :: term(), NewState :: #iot_router_state{}} | - {reply, Reply :: term(), NewState :: #iot_router_state{}, timeout() | hibernate} | - {noreply, NewState :: #iot_router_state{}} | - {noreply, NewState :: #iot_router_state{}, timeout() | hibernate} | - {stop, Reason :: term(), Reply :: term(), NewState :: #iot_router_state{}} | - {stop, Reason :: term(), NewState :: #iot_router_state{}}). -handle_call(_Request, _From, State = #iot_router_state{}) -> + State :: #state{}) -> + {reply, Reply :: term(), NewState :: #state{}} | + {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} | + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | + {stop, Reason :: term(), NewState :: #state{}}). +handle_call(_Request, _From, State = #state{}) -> {reply, ok, State}. %% @private %% @doc Handling cast messages --spec(handle_cast(Request :: term(), State :: #iot_router_state{}) -> - {noreply, NewState :: #iot_router_state{}} | - {noreply, NewState :: #iot_router_state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #iot_router_state{}}). -handle_cast(_Request, State = #iot_router_state{}) -> +-spec(handle_cast(Request :: term(), State :: #state{}) -> + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), NewState :: #state{}}). +handle_cast(_Request, State = #state{}) -> {noreply, State}. %% @private %% @doc Handling all non call/cast messages --spec(handle_info(Info :: timeout() | term(), State :: #iot_router_state{}) -> - {noreply, NewState :: #iot_router_state{}} | - {noreply, NewState :: #iot_router_state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #iot_router_state{}}). -handle_info(_Info, State = #iot_router_state{}) -> +-spec(handle_info(Info :: timeout() | term(), State :: #state{}) -> + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), NewState :: #state{}}). +handle_info(_Info, State = #state{}) -> {noreply, State}. %% @private @@ -81,16 +88,16 @@ handle_info(_Info, State = #iot_router_state{}) -> %% necessary cleaning up. When it returns, the gen_server terminates %% with Reason. The return value is ignored. -spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), - State :: #iot_router_state{}) -> term()). -terminate(_Reason, _State = #iot_router_state{}) -> + State :: #state{}) -> term()). +terminate(_Reason, _State = #state{}) -> ok. %% @private %% @doc Convert process state when code is changed --spec(code_change(OldVsn :: term() | {down, term()}, State :: #iot_router_state{}, +-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, Extra :: term()) -> - {ok, NewState :: #iot_router_state{}} | {error, Reason :: term()}). -code_change(_OldVsn, State = #iot_router_state{}, _Extra) -> + {ok, NewState :: #state{}} | {error, Reason :: term()}). +code_change(_OldVsn, State = #state{}, _Extra) -> {ok, State}. %%%=================================================================== diff --git a/apps/iot/src/iot_router_sup.erl b/apps/iot/src/iot_router_sup.erl index 56848a4..e369e8b 100644 --- a/apps/iot/src/iot_router_sup.erl +++ b/apps/iot/src/iot_router_sup.erl @@ -8,11 +8,12 @@ %%%------------------------------------------------------------------- -module(iot_router_sup). -author("licheng5"). +-include("iot.hrl"). -behaviour(supervisor). %% API --export([start_link/0]). +-export([start_link/0, start_new_router/1]). %% Supervisor callbacks -export([init/1]). @@ -45,17 +46,37 @@ start_link() -> init([]) -> SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, - AChild = #{ - id => 'iot_router', - start => {'iot_router', start_link, []}, - restart => permanent, - shutdown => 2000, - type => worker, - modules => ['iot_router'] - }, + %% 启动目前生效的全部转发规则 + {ok, Routers} = router_model:get_all_valid_routers(), + Specs = lists:map(fun generate_router_spec/1, Routers), - {ok, {SupFlags, [AChild]}}. + {ok, {SupFlags, Specs}}. %%%=================================================================== %%% Internal functions %%%=================================================================== + +%% 动态启动一个转发规则 +-spec start_new_router(Router :: #router{}) -> {ok, Pid :: pid()} | {error, Reason :: any()}. +start_new_router(Router = #router{}) -> + Spec = generate_router_spec(Router), + case supervisor:start_child(?MODULE, Spec) of + {ok, Pid} -> + {ok, Pid}; + {error, {already_started, Pid}} -> + {ok, Pid}; + {error, Error} -> + lager:debug("start router get a error: ~p", [Error]), + {error, Error} + end. + +generate_router_spec(Router = #router{router_id = RouterId}) -> + Id = iot_router:get_name(RouterId), + #{ + id => Id, + start => {'iot_router', start_link, [Id, Router]}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => ['iot_router'] + }. \ No newline at end of file