remove mnesia index

This commit is contained in:
Feng 2015-12-06 20:32:03 +08:00
parent c29fd68dd5
commit f4d09c973d
1 changed files with 55 additions and 30 deletions

View File

@ -51,11 +51,11 @@
%% gen_server2 priorities %% gen_server2 priorities
-export([prioritise_call/4, prioritise_cast/3, prioritise_info/3]). -export([prioritise_call/4, prioritise_cast/3, prioritise_info/3]).
-record(state, {pool, id}). -record(state, {pool, id, monitors}).
-define(POOL, ?MODULE). -define(POOL, ?MODULE).
-define(TIMEOUT, 60000). -define(TIMEOUT, 120000).
-define(LOG(Level, Format, Args, Session), -define(LOG(Level, Format, Args, Session),
lager:Level("SM(~s): " ++ Format, [Session#mqtt_session.client_id | Args])). lager:Level("SM(~s): " ++ Format, [Session#mqtt_session.client_id | Args])).
@ -67,12 +67,11 @@
mnesia(boot) -> mnesia(boot) ->
%% Global Session Table %% Global Session Table
ok = emqttd_mnesia:create_table(session, [ ok = emqttd_mnesia:create_table(session, [
{type, ordered_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)}]);
%% TODO: index_read is slow...
{index, [sess_pid]}]);
mnesia(copy) -> mnesia(copy) ->
ok = emqttd_mnesia:copy_table(session). ok = emqttd_mnesia:copy_table(session).
@ -144,7 +143,8 @@ call(SM, Req) ->
init([Pool, Id]) -> init([Pool, Id]) ->
?GPROC_POOL(join, Pool, Id), ?GPROC_POOL(join, Pool, Id),
{ok, #state{pool = Pool, id = Id}}. {ok, #state{pool = Pool, id = Id,
monitors = dict:new()}}.
prioritise_call(_Msg, _From, _Len, _State) -> prioritise_call(_Msg, _From, _Len, _State) ->
1. 1.
@ -155,43 +155,57 @@ prioritise_cast(_Msg, _Len, _State) ->
prioritise_info(_Msg, _Len, _State) -> prioritise_info(_Msg, _Len, _State) ->
2. 2.
%% persistent session %% Persistent Session
handle_call({start_session, {false, ClientId, ClientPid}}, _From, State) -> handle_call({start_session, Client = {false, ClientId, ClientPid}}, _From, State) ->
case lookup_session(ClientId) of case lookup_session(ClientId) of
undefined -> undefined ->
%% create session locally %% Create session locally
reply(create_session(false, ClientId, ClientPid), false, State); create_session(Client, State);
Session -> Session ->
reply(resume_session(Session, ClientPid), true, State) case resume_session(Session, ClientPid) of
{ok, SessPid} ->
{reply, {ok, SessPid, true}, State};
{error, Erorr} ->
{reply, {error, Erorr}, State}
end
end; end;
%% transient session %% Transient Session
handle_call({start_session, {true, ClientId, ClientPid}}, _From, State) -> handle_call({start_session, Client = {true, ClientId, _ClientPid}}, _From, State) ->
case lookup_session(ClientId) of case lookup_session(ClientId) of
undefined -> undefined ->
reply(create_session(true, ClientId, ClientPid), false, State); create_session(Client, State);
Session -> Session ->
case destroy_session(Session) of case destroy_session(Session) of
ok -> ok ->
reply(create_session(true, ClientId, ClientPid), false, State); create_session(Client, State);
{error, Error} -> {error, Error} ->
{reply, {error, Error}, State} {reply, {error, Error}, State}
end end
end; end;
handle_call(_Request, _From, State) -> handle_call(Req, _From, State) ->
{reply, ok, State}. ?UNEXPECTED_REQ(Req, State).
handle_cast(Msg, State) -> handle_cast(Msg, State) ->
?UNEXPECTED_MSG(Msg, State). ?UNEXPECTED_MSG(Msg, State).
%%TODO: fix this issue that index_read is really slow... handle_info({'DOWN', MRef, process, DownPid, _Reason}, State) ->
handle_info({'DOWN', _MRef, process, DownPid, _Reason}, State) -> case dict:find(MRef, State#state.monitors) of
{ok, ClientId} ->
mnesia:transaction(fun() -> mnesia:transaction(fun() ->
[mnesia:delete_object(session, Sess, write) || Sess case mnesia:wread({session, ClientId}) of
<- mnesia:index_read(session, DownPid, #mqtt_session.sess_pid)] [] -> ok;
[Sess = #mqtt_session{sess_pid = DownPid}] ->
mnesia:delete_object(session, Sess, write);
[_Sess] -> ok
end
end), end),
{noreply, State}; {noreply, erase_monitor(MRef, State)};
error ->
lager:error("MRef of session ~p not found", [DownPid]),
{noreply, State}
end;
handle_info(Info, State) -> handle_info(Info, State) ->
?UNEXPECTED_INFO(Info, State). ?UNEXPECTED_INFO(Info, State).
@ -206,6 +220,16 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions %%% Internal functions
%%%============================================================================= %%%=============================================================================
%% Create Session Locally
create_session({CleanSess, ClientId, ClientPid}, State) ->
case create_session(CleanSess, ClientId, ClientPid) of
{ok, SessPid} ->
{reply, {ok, SessPid, false},
monitor_session(ClientId, SessPid, State)};
{error, Error} ->
{reply, {error, Error}, State}
end.
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} ->
@ -218,7 +242,6 @@ create_session(CleanSess, ClientId, ClientPid) ->
lager:error("SM(~s): Conflict with ~p", [ClientId, ConflictPid]), lager:error("SM(~s): Conflict with ~p", [ClientId, ConflictPid]),
{error, mnesia_conflict}; {error, mnesia_conflict};
{atomic, ok} -> {atomic, ok} ->
erlang:monitor(process, SessPid),
{ok, SessPid} {ok, SessPid}
end; end;
{error, Error} -> {error, Error} ->
@ -293,8 +316,10 @@ remove_session(Session) ->
{aborted, Error} -> {error, Error} {aborted, Error} -> {error, Error}
end. end.
reply({ok, SessPid}, SP, State) -> monitor_session(ClientId, SessPid, State = #state{monitors = Monitors}) ->
{reply, {ok, SessPid, SP}, State}; MRef = erlang:monitor(process, SessPid),
reply({error, Error}, _SP, State) -> State#state{monitors = dict:store(MRef, ClientId, Monitors)}.
{reply, {error, Error}, State}.
erase_monitor(MRef, State = #state{monitors = Monitors}) ->
State#state{monitors = dict:erase(MRef, Monitors)}.