./ct_report/coverage/ejabberd_sm_mnesia.COVER.html

1 %%%-------------------------------------------------------------------
2 %%% @author Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
3 %%% @copyright (C) 2011, Erlang Solutions Ltd.
4 %%% @doc Implementation of Mnesia-based session manager
5 %%%
6 %%% @end
7 %%% Created : 17 Nov 2011 by Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
8 %%%-------------------------------------------------------------------
9 -module(ejabberd_sm_mnesia).
10
11 -behavior(ejabberd_sm_backend).
12
13 -include("mongoose.hrl").
14 -include("session.hrl").
15
16 -export([init/1,
17 get_sessions/0,
18 get_sessions/1,
19 get_sessions/2,
20 get_sessions/3,
21 create_session/4,
22 update_session/4,
23 delete_session/4,
24 cleanup/1,
25 total_count/0,
26 unique_count/0]).
27
28 -spec init(map()) -> any().
29 init(_Opts) ->
30 76 mnesia:create_table(session,
31 [{ram_copies, [node()]},
32 {attributes, record_info(fields, session)}]),
33 76 mnesia:add_table_index(session, usr),
34 76 mnesia:add_table_index(session, us),
35 76 mnesia:add_table_copy(session, node(), ram_copies).
36
37 -spec get_sessions() -> [ejabberd_sm:session()].
38 get_sessions() ->
39 80 mnesia:activity(transaction,
40 fun() ->
41 80 mnesia:foldl(fun(Session, AccIn) -> [Session | AccIn] end,
42 [], session)
43 end).
44
45 -spec get_sessions(jid:lserver()) -> [ejabberd_sm:session()].
46 get_sessions(Server) ->
47 36 mnesia:dirty_select(
48 session,
49 [{#session{usr = '$1', sid='$2', priority='$3', info='$4', _ = '_' },
50 [{'==', {element, 2, '$1'}, Server}],
51 ['$_']}]).
52
53 -spec get_sessions(jid:luser(), jid:lserver()) -> [ejabberd_sm:session()].
54 get_sessions(User, Server) ->
55 29940 mnesia:dirty_index_read(session, {User, Server}, #session.us).
56
57 -spec get_sessions(jid:luser(), jid:lserver(), jid:lresource()
58 ) -> [ejabberd_sm:session()].
59 get_sessions(User, Server, Resource) ->
60 47094 mnesia:dirty_index_read(session, {User, Server, Resource}, #session.usr).
61
62 -spec create_session(_User :: jid:luser(),
63 _Server :: jid:lserver(),
64 _Resource :: jid:lresource(),
65 Session :: ejabberd_sm:session()) -> ok | {error, term()}.
66 create_session(User, Server, Resource, Session) ->
67 8643 case get_sessions(User, Server, Resource) of
68 4544 [] -> mnesia:sync_dirty(fun() -> mnesia:write(Session) end);
69 Sessions when is_list(Sessions) ->
70 %% Fix potential race condition during XMPP bind, where
71 %% multiple calls (> 2) to ejabberd_sm:open_session
72 %% have been made, resulting in >1 sessions for this resource
73 4099 MergedSession = mongoose_session:merge_info
74 (Session, hd(lists:sort(Sessions))),
75 4099 mnesia:sync_dirty(fun() -> mnesia:write(MergedSession) end)
76 end.
77
78 -spec update_session(_User :: jid:luser(),
79 _Server :: jid:lserver(),
80 _Resource :: jid:lresource(),
81 Session :: ejabberd_sm:session()) -> ok | {error, term()}.
82 update_session(_User, _Server, _Resource, Session) ->
83 207 mnesia:sync_dirty(fun() -> mnesia:write(Session) end).
84
85 -spec delete_session(ejabberd_sm:sid(),
86 _User :: jid:luser(),
87 _Server :: jid:lserver(),
88 _Resource :: jid:lresource()) -> ok.
89 delete_session(SID, _User, _Server, _Resource) ->
90 4550 mnesia:sync_dirty(fun() ->
91 4550 mnesia:delete({session, SID})
92 end).
93
94 -spec cleanup(atom()) -> any().
95 cleanup(Node) ->
96
:-(
F = fun() ->
97
:-(
Es = mnesia:select(
98 session,
99 [{#session{sid = {'_', '$1'}, _ = '_'},
100 [{'==', {node, '$1'}, Node}],
101 ['$_']}]),
102
:-(
lists:foreach(fun(#session{sid = SID} = Session) ->
103
:-(
mnesia:delete({session, SID}),
104
:-(
ejabberd_sm:run_session_cleanup_hook(Session)
105 end, Es)
106 end,
107
:-(
mnesia:async_dirty(F).
108
109 -spec total_count() -> integer().
110 total_count() ->
111 97 mnesia:table_info(session, size).
112
113 -spec unique_count() -> integer().
114 unique_count() ->
115 94 compute_unique(mnesia:dirty_first(session),
116 sets:new()).
117
118 -spec compute_unique(term(), sets:set()) -> integer().
119 compute_unique('$end_of_table', Set) ->
120 94 sets:size(Set);
121 compute_unique(Key, Set) ->
122 14 NewSet = case mnesia:dirty_read(session, Key) of
123 [Session] ->
124 14 sets:add_element(Session#session.us, Set);
125 _ ->
126
:-(
Set
127 end,
128 14 compute_unique(mnesia:dirty_next(session, Key), NewSet).
Line Hits Source