mqtt_local_session
This commit is contained in:
parent
162b7ec229
commit
766f74692d
|
@ -26,7 +26,7 @@
|
||||||
%% API Exports
|
%% API Exports
|
||||||
-export([start_link/3]).
|
-export([start_link/3]).
|
||||||
|
|
||||||
-export([lookup/1, lookup_proc/1, register/1, unregister/1]).
|
-export([lookup/1, lookup_proc/1, reg/1, unreg/1]).
|
||||||
|
|
||||||
%% gen_server Function Exports
|
%% gen_server Function Exports
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
@ -44,23 +44,17 @@
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
%% @doc Start Client Manager
|
%% @doc Start Client Manager
|
||||||
-spec(start_link(Pool, Id, StatsFun) -> {ok, pid()} | ignore | {error, any()} when
|
-spec(start_link(atom(), pos_integer(), fun()) -> {ok, pid()} | ignore | {error, any()}).
|
||||||
Pool :: atom(),
|
|
||||||
Id :: pos_integer(),
|
|
||||||
StatsFun :: fun()).
|
|
||||||
start_link(Pool, Id, StatsFun) ->
|
start_link(Pool, Id, StatsFun) ->
|
||||||
gen_server2:start_link(?MODULE, [Pool, Id, StatsFun], []).
|
gen_server2:start_link(?MODULE, [Pool, Id, StatsFun], []).
|
||||||
|
|
||||||
%% @doc Lookup Client by ClientId
|
%% @doc Lookup Client by ClientId
|
||||||
-spec(lookup(ClientId :: binary()) -> mqtt_client() | undefined).
|
-spec(lookup(binary()) -> mqtt_client() | undefined).
|
||||||
lookup(ClientId) when is_binary(ClientId) ->
|
lookup(ClientId) when is_binary(ClientId) ->
|
||||||
case ets:lookup(mqtt_client, ClientId) of
|
case ets:lookup(mqtt_client, ClientId) of [Client] -> Client; [] -> undefined end.
|
||||||
[Client] -> Client;
|
|
||||||
[] -> undefined
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% @doc Lookup client pid by clientId
|
%% @doc Lookup client pid by clientId
|
||||||
-spec(lookup_proc(ClientId :: binary()) -> pid() | undefined).
|
-spec(lookup_proc(binary()) -> pid() | undefined).
|
||||||
lookup_proc(ClientId) when is_binary(ClientId) ->
|
lookup_proc(ClientId) when is_binary(ClientId) ->
|
||||||
try ets:lookup_element(mqtt_client, ClientId, #mqtt_client.client_pid)
|
try ets:lookup_element(mqtt_client, ClientId, #mqtt_client.client_pid)
|
||||||
catch
|
catch
|
||||||
|
@ -68,14 +62,14 @@ lookup_proc(ClientId) when is_binary(ClientId) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Register ClientId with Pid.
|
%% @doc Register ClientId with Pid.
|
||||||
-spec(register(Client :: mqtt_client()) -> ok).
|
-spec(reg(mqtt_client()) -> ok).
|
||||||
register(Client = #mqtt_client{client_id = ClientId}) ->
|
reg(Client = #mqtt_client{client_id = ClientId}) ->
|
||||||
gen_server2:call(pick(ClientId), {register, Client}, 120000).
|
gen_server2:call(pick(ClientId), {reg, Client}, 120000).
|
||||||
|
|
||||||
%% @doc Unregister clientId with pid.
|
%% @doc Unregister clientId with pid.
|
||||||
-spec(unregister(ClientId :: binary()) -> ok).
|
-spec(unreg(binary()) -> ok).
|
||||||
unregister(ClientId) when is_binary(ClientId) ->
|
unreg(ClientId) when is_binary(ClientId) ->
|
||||||
gen_server2:cast(pick(ClientId), {unregister, ClientId, self()}).
|
gen_server2:cast(pick(ClientId), {unreg, ClientId, self()}).
|
||||||
|
|
||||||
pick(ClientId) -> gproc_pool:pick_worker(?POOL, ClientId).
|
pick(ClientId) -> gproc_pool:pick_worker(?POOL, ClientId).
|
||||||
|
|
||||||
|
@ -88,21 +82,15 @@ init([Pool, Id, StatsFun]) ->
|
||||||
{ok, #state{pool = Pool, id = Id, statsfun = StatsFun, monitors = dict:new()}}.
|
{ok, #state{pool = Pool, id = Id, statsfun = StatsFun, monitors = dict:new()}}.
|
||||||
|
|
||||||
prioritise_call(Req, _From, _Len, _State) ->
|
prioritise_call(Req, _From, _Len, _State) ->
|
||||||
case Req of
|
case Req of {reg, _Client} -> 2; _ -> 1 end.
|
||||||
{register, _Client} -> 2;
|
|
||||||
_ -> 1
|
|
||||||
end.
|
|
||||||
|
|
||||||
prioritise_cast(Msg, _Len, _State) ->
|
prioritise_cast(Msg, _Len, _State) ->
|
||||||
case Msg of
|
case Msg of {unreg, _ClientId, _Pid} -> 9; _ -> 1 end.
|
||||||
{unregister, _ClientId, _Pid} -> 9;
|
|
||||||
_ -> 1
|
|
||||||
end.
|
|
||||||
|
|
||||||
prioritise_info(_Msg, _Len, _State) ->
|
prioritise_info(_Msg, _Len, _State) ->
|
||||||
3.
|
3.
|
||||||
|
|
||||||
handle_call({register, Client = #mqtt_client{client_id = ClientId,
|
handle_call({reg, Client = #mqtt_client{client_id = ClientId,
|
||||||
client_pid = Pid}}, _From, State) ->
|
client_pid = Pid}}, _From, State) ->
|
||||||
case lookup_proc(ClientId) of
|
case lookup_proc(ClientId) of
|
||||||
Pid ->
|
Pid ->
|
||||||
|
@ -115,7 +103,7 @@ handle_call({register, Client = #mqtt_client{client_id = ClientId,
|
||||||
handle_call(Req, _From, State) ->
|
handle_call(Req, _From, State) ->
|
||||||
?UNEXPECTED_REQ(Req, State).
|
?UNEXPECTED_REQ(Req, State).
|
||||||
|
|
||||||
handle_cast({unregister, ClientId, Pid}, State) ->
|
handle_cast({unreg, ClientId, Pid}, State) ->
|
||||||
case lookup_proc(ClientId) of
|
case lookup_proc(ClientId) of
|
||||||
Pid ->
|
Pid ->
|
||||||
ets:delete(mqtt_client, ClientId),
|
ets:delete(mqtt_client, ClientId),
|
||||||
|
|
|
@ -32,9 +32,7 @@
|
||||||
%% API Function Exports
|
%% API Function Exports
|
||||||
-export([start_link/2]).
|
-export([start_link/2]).
|
||||||
|
|
||||||
-export([start_session/2, lookup_session/1]).
|
-export([start_session/2, lookup_session/1, register_session/3, unregister_session/1]).
|
||||||
|
|
||||||
-export([register_session/3, unregister_session/2]).
|
|
||||||
|
|
||||||
-export([dispatch/3]).
|
-export([dispatch/3]).
|
||||||
|
|
||||||
|
@ -60,14 +58,14 @@
|
||||||
|
|
||||||
mnesia(boot) ->
|
mnesia(boot) ->
|
||||||
%% Global Session Table
|
%% Global Session Table
|
||||||
ok = emqttd_mnesia:create_table(session, [
|
ok = emqttd_mnesia:create_table(mqtt_session, [
|
||||||
{type, set},
|
{type, set},
|
||||||
{ram_copies, [node()]},
|
{ram_copies, [node()]},
|
||||||
{record_name, mqtt_session},
|
{record_name, mqtt_session},
|
||||||
{attributes, record_info(fields, mqtt_session)}]);
|
{attributes, record_info(fields, mqtt_session)}]);
|
||||||
|
|
||||||
mnesia(copy) ->
|
mnesia(copy) ->
|
||||||
ok = emqttd_mnesia:copy_table(session).
|
ok = emqttd_mnesia:copy_table(mqtt_session).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% API
|
%% API
|
||||||
|
@ -93,32 +91,22 @@ lookup_session(ClientId) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Register a session with info.
|
%% @doc Register a session with info.
|
||||||
-spec(register_session(CleanSess, ClientId, Info) -> ok when
|
-spec(register_session(boolean(), binary(), [tuple()]) -> true).
|
||||||
CleanSess :: boolean(),
|
register_session(CleanSess, ClientId, Properties) ->
|
||||||
ClientId :: binary(),
|
ets:insert(mqtt_local_session, {ClientId, self(), CleanSess, Properties}).
|
||||||
Info :: [tuple()]).
|
|
||||||
register_session(CleanSess, ClientId, Info) ->
|
|
||||||
ets:insert(sesstab(CleanSess), {{ClientId, self()}, Info}).
|
|
||||||
|
|
||||||
%% @doc Unregister a session.
|
%% @doc Unregister a session.
|
||||||
-spec(unregister_session(CleanSess, ClientId) -> ok when
|
-spec(unregister_session(binary()) -> true).
|
||||||
CleanSess :: boolean(),
|
unregister_session(ClientId) ->
|
||||||
ClientId :: binary()).
|
ets:delete(mqtt_local_session, ClientId).
|
||||||
unregister_session(CleanSess, ClientId) ->
|
|
||||||
ets:delete(sesstab(CleanSess), {ClientId, self()}).
|
|
||||||
|
|
||||||
%%TODO: FIXME...
|
dispatch(ClientId, Topic, Msg) ->
|
||||||
dispatch(Id, Topic, Msg) ->
|
try ets:lookup_element(mqtt_local_session, ClientId, 2) of
|
||||||
case lookup_session(Id) of
|
Pid -> Pid ! {dispatch, Topic, Msg}
|
||||||
#mqtt_session{sess_pid = Pid} ->
|
catch
|
||||||
Pid ! {dispatch, Topic, Msg};
|
error:badarg -> ok %%TODO: How??
|
||||||
undefined ->
|
|
||||||
ok
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
sesstab(true) -> mqtt_transient_session;
|
|
||||||
sesstab(false) -> mqtt_persistent_session.
|
|
||||||
|
|
||||||
call(SM, Req) ->
|
call(SM, Req) ->
|
||||||
gen_server2:call(SM, Req, ?TIMEOUT). %%infinity).
|
gen_server2:call(SM, Req, ?TIMEOUT). %%infinity).
|
||||||
|
|
||||||
|
@ -217,9 +205,7 @@ create_session({CleanSess, ClientId, ClientPid}, State) ->
|
||||||
create_session(CleanSess, ClientId, ClientPid) ->
|
create_session(CleanSess, ClientId, ClientPid) ->
|
||||||
case emqttd_session_sup:start_session(CleanSess, ClientId, ClientPid) of
|
case emqttd_session_sup:start_session(CleanSess, ClientId, ClientPid) of
|
||||||
{ok, SessPid} ->
|
{ok, SessPid} ->
|
||||||
Session = #mqtt_session{client_id = ClientId,
|
Session = #mqtt_session{client_id = ClientId, sess_pid = SessPid, persistent = not CleanSess},
|
||||||
sess_pid = SessPid,
|
|
||||||
persistent = not CleanSess},
|
|
||||||
case insert_session(Session) of
|
case insert_session(Session) of
|
||||||
{aborted, {conflict, ConflictPid}} ->
|
{aborted, {conflict, ConflictPid}} ->
|
||||||
%% Conflict with othe node?
|
%% Conflict with othe node?
|
||||||
|
@ -244,8 +230,7 @@ insert_session(Session = #mqtt_session{client_id = ClientId}) ->
|
||||||
end).
|
end).
|
||||||
|
|
||||||
%% Local node
|
%% Local node
|
||||||
resume_session(Session = #mqtt_session{client_id = ClientId,
|
resume_session(Session = #mqtt_session{client_id = ClientId, sess_pid = SessPid}, ClientPid)
|
||||||
sess_pid = SessPid}, ClientPid)
|
|
||||||
when node(SessPid) =:= node() ->
|
when node(SessPid) =:= node() ->
|
||||||
|
|
||||||
case is_process_alive(SessPid) of
|
case is_process_alive(SessPid) of
|
||||||
|
|
|
@ -83,5 +83,5 @@ code_change(_OldVsn, State, _Extra) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
setstats(State = #state{stats_fun = StatsFun}) ->
|
setstats(State = #state{stats_fun = StatsFun}) ->
|
||||||
StatsFun(ets:info(mqtt_persistent_session, size)), State.
|
StatsFun(ets:info(mqtt_local_session, size)), State.
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
|
|
||||||
-define(HELPER, emqttd_sm_helper).
|
-define(HELPER, emqttd_sm_helper).
|
||||||
|
|
||||||
-define(TABS, [mqtt_transient_session, mqtt_persistent_session]).
|
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_link/0]).
|
-export([start_link/0]).
|
||||||
|
|
||||||
|
@ -38,7 +36,7 @@ start_link() ->
|
||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
%% Create session tables
|
%% Create session tables
|
||||||
create_session_tabs(),
|
ets:new(mqtt_local_session, [public, ordered_set, named_table, {write_concurrency, true}]),
|
||||||
|
|
||||||
%% Helper
|
%% Helper
|
||||||
StatsFun = emqttd_stats:statsfun('sessions/count', 'sessions/max'),
|
StatsFun = emqttd_stats:statsfun('sessions/count', 'sessions/max'),
|
||||||
|
@ -51,8 +49,3 @@ init([]) ->
|
||||||
|
|
||||||
{ok, {{one_for_all, 10, 3600}, [Helper, PoolSup]}}.
|
{ok, {{one_for_all, 10, 3600}, [Helper, PoolSup]}}.
|
||||||
|
|
||||||
create_session_tabs() ->
|
|
||||||
Opts = [ordered_set, named_table, public,
|
|
||||||
{write_concurrency, true}],
|
|
||||||
[ets:new(Tab, Opts) || Tab <- ?TABS].
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue