From 814b80c644fa425990dc63875e1da841d698b0fa Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 23 Jul 2016 01:08:05 +0200 Subject: Preserve PID for offline sessions Don't set the PID to 'undefined' when a session goes offline, as this looses the information which node created the session table entry. Fixes #1196. --- src/ejabberd_sm.erl | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'src/ejabberd_sm.erl') diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 8d94bc6aa..16e0f9114 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -270,25 +270,28 @@ get_session_pid(User, Server, Resource) -> -spec set_offline_info(sid(), binary(), binary(), binary(), info()) -> ok. -set_offline_info({Time, _Pid}, User, Server, Resource, Info) -> - SID = {Time, undefined}, +set_offline_info(SID, User, Server, Resource, Info) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), - set_session(SID, LUser, LServer, LResource, undefined, Info). + set_session(SID, LUser, LServer, LResource, undefined, [offline | Info]). -spec get_offline_info(erlang:timestamp(), binary(), binary(), binary()) -> none | info(). get_offline_info(Time, User, Server, Resource) -> - SID = {Time, undefined}, LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of - [#session{sid = SID, info = Info}] -> - Info; + [#session{sid = {Time, _}, info = Info}] -> + case proplists:get_bool(offline, Info) of + true -> + Info; + false -> + none + end; _ -> none end. @@ -425,11 +428,12 @@ set_session(SID, User, Server, Resource, Priority, Info) -> -spec online([#session{}]) -> [#session{}]. online(Sessions) -> - lists:filter(fun(#session{sid = {_, undefined}}) -> - false; - (_) -> - true - end, Sessions). + lists:filter(fun is_online/1, Sessions). + +-spec is_online(#session{}) -> boolean(). + +is_online(#session{info = Info}) -> + not proplists:get_bool(offline, Info). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -678,15 +682,17 @@ check_for_sessions_to_replace(User, Server, Resource) -> check_max_sessions(LUser, LServer). check_existing_resources(LUser, LServer, LResource) -> - SIDs = get_resource_sessions(LUser, LServer, LResource), - if SIDs == [] -> ok; + Mod = get_sm_backend(LServer), + Ss = Mod:get_sessions(LUser, LServer, LResource), + {OnlineSs, OfflineSs} = lists:partition(fun is_online/1, Ss), + lists:foreach(fun(#session{sid = S}) -> + Mod:delete_session(LUser, LServer, LResource, S) + end, OfflineSs), + if OnlineSs == [] -> ok; true -> + SIDs = [SID || #session{sid = SID} <- OnlineSs], MaxSID = lists:max(SIDs), - lists:foreach(fun ({_, undefined} = S) -> - Mod = get_sm_backend(LServer), - Mod:delete_session(LUser, LServer, LResource, - S); - ({_, Pid} = S) when S /= MaxSID -> + lists:foreach(fun ({_, Pid} = S) when S /= MaxSID -> Pid ! replaced; (_) -> ok end, -- cgit v1.2.3