./ct_report/coverage/ejabberd_sm_cets.COVER.html

1 -module(ejabberd_sm_cets).
2
3 -behavior(ejabberd_sm_backend).
4
5 -include("mongoose.hrl").
6 -include("session.hrl").
7
8 -export([init/1,
9 get_sessions/0,
10 get_sessions/1,
11 get_sessions/2,
12 get_sessions/3,
13 set_session/4,
14 delete_session/4,
15 cleanup/1,
16 total_count/0,
17 unique_count/0]).
18
19 -define(TABLE, cets_session).
20
21 -spec init(map()) -> any().
22 init(_Opts) ->
23 33 cets:start(?TABLE, #{}),
24 33 cets_discovery:add_table(mongoose_cets_discovery, ?TABLE).
25
26 -spec get_sessions() -> [ejabberd_sm:session()].
27 get_sessions() ->
28 118 tuples_to_sessions(ets:tab2list(?TABLE)).
29
30 -spec get_sessions(jid:lserver()) -> [ejabberd_sm:session()].
31 get_sessions(Server) ->
32 %% This is not a full table scan. From the ETS docs:
33 %% For ordered_set a partially bound key will limit the traversal to only
34 %% scan a subset of the table based on term order.
35 %% A partially bound key is either a list or a tuple with
36 %% a prefix that is fully bound.
37 66 R = {{Server, '_', '_', '_'}, '_', '_'},
38 66 Xs = ets:match_object(?TABLE, R),
39 66 tuples_to_sessions(Xs).
40
41 -spec get_sessions(jid:luser(), jid:lserver()) -> [ejabberd_sm:session()].
42 get_sessions(User, Server) ->
43 40837 R = {{Server, User, '_', '_'}, '_', '_'},
44 40837 Xs = ets:match_object(?TABLE, R),
45 40837 tuples_to_sessions(Xs).
46
47 -spec get_sessions(jid:luser(), jid:lserver(), jid:lresource()) ->
48 [ejabberd_sm:session()].
49 get_sessions(User, Server, Resource) ->
50 22701 R = {{Server, User, Resource, '_'}, '_', '_'},
51 22701 Xs = ets:match_object(?TABLE, R),
52 %% TODO these sessions should be deduplicated.
53 %% It is possible, that after merging two cets tables we could end up
54 %% with sessions from two nodes for the same full jid.
55 %% One of the sessions must be killed.
56 %% We can detect duplicates on the merging step or on reading (or both).
57 22701 tuples_to_sessions(Xs).
58
59 -spec set_session(User :: jid:luser(),
60 Server :: jid:lserver(),
61 Resource :: jid:lresource(),
62 Session :: ejabberd_sm:session()) -> ok | {error, term()}.
63 set_session(_User, _Server, _Resource, Session) ->
64 11901 cets:insert(?TABLE, session_to_tuple(Session)).
65
66 -spec delete_session(SID :: ejabberd_sm:sid(),
67 User :: jid:luser(),
68 Server :: jid:lserver(),
69 Resource :: jid:lresource()) -> ok.
70 delete_session(SID, User, Server, Resource) ->
71 5977 cets:delete(?TABLE, make_key(User, Server, Resource, SID)).
72
73 %% cleanup is called on each node in the cluster, when Node is down
74 -spec cleanup(atom()) -> any().
75 cleanup(Node) ->
76
:-(
KeyPattern = {'_', '_', '_', {'_', '$1'}},
77
:-(
Guard = {'==', {node, '$1'}, Node},
78
:-(
R = {KeyPattern, '_', '_'},
79
:-(
cets:ping_all(?TABLE),
80 %% This is a full table scan, but cleanup is rare.
81
:-(
Tuples = ets:select(?TABLE, [{R, [Guard], ['$_']}]),
82
:-(
lists:foreach(fun({_Key, _, _} = Tuple) ->
83
:-(
Session = tuple_to_session(Tuple),
84
:-(
ejabberd_sm:run_session_cleanup_hook(Session)
85 end, Tuples),
86 %% We don't need to replicate deletes
87 %% We remove the local content here
88
:-(
ets:select_delete(?TABLE, [{R, [Guard], [true]}]).
89
90 -spec total_count() -> integer().
91 total_count() ->
92 105 ets:info(?TABLE, size).
93
94 %% Counts merged by US
95 -spec unique_count() -> integer().
96 unique_count() ->
97 98 compute_unique(ets:first(?TABLE), 0).
98
99 compute_unique('$end_of_table', Sum) ->
100 97 Sum;
101 compute_unique({S, U, _, _} = Key, Sum) ->
102 131 Key2 = ets:next(?TABLE, Key),
103 131 case Key2 of
104 {S, U, _, _} ->
105 11 compute_unique(Key2, Sum);
106 _ ->
107 120 compute_unique(Key2, Sum + 1)
108 end.
109
110 session_to_tuple(#session{sid = SID, usr = {U, S, R}, priority = Prio, info = Info}) ->
111 11901 {make_key(U, S, R, SID), Prio, Info}.
112
113 make_key(User, Server, Resource, SID) ->
114 17878 {Server, User, Resource, SID}.
115
116 tuple_to_session({{S, U, R, SID}, Prio, Info}) ->
117 52424 #session{sid = SID, usr = {U, S, R}, us = {U, S}, priority = Prio, info = Info}.
118
119 tuples_to_sessions(Xs) ->
120 63722 [tuple_to_session(X) || X <- Xs].
Line Hits Source