./ct_report/coverage/mod_stream_management_mnesia.COVER.html

1 -module(mod_stream_management_mnesia).
2 -behaviour(mod_stream_management_backend).
3
4 -include("mongoose.hrl").
5 -include_lib("stdlib/include/ms_transform.hrl").
6
7 -export([init/2,
8 stop/1,
9 register_smid/3,
10 unregister_smid/2,
11 get_sid/2]).
12
13 -export([read_stale_h/2,
14 write_stale_h/3,
15 delete_stale_h/2]).
16
17 %% Internal exports
18 -export([clear_table/2]).
19
20 -record(stream_mgmt_stale_h,
21 {smid :: mod_stream_management:smid(),
22 h :: non_neg_integer(),
23 stamp :: non_neg_integer() }).
24
25 -record(sm_session,
26 {smid :: mod_stream_management:smid(),
27 sid :: ejabberd_sm:sid() }).
28
29 init(HostType, #{stale_h := StaleOpts}) ->
30 487 mongoose_mnesia:create_table(sm_session,
31 [{ram_copies, [node()]},
32 {attributes, record_info(fields, sm_session)}]),
33 487 mnesia:add_table_index(sm_session, sid),
34 487 maybe_init_stale_h(HostType, StaleOpts),
35 487 ok.
36
37 stop(HostType) ->
38 487 stop_cleaner(HostType).
39
40 maybe_init_stale_h(HostType, StaleOpts = #{enabled := true}) ->
41 3 ?LOG_INFO(#{what => stream_mgmt_stale_h_start}),
42 3 mongoose_mnesia:create_table(stream_mgmt_stale_h,
43 [{ram_copies, [node()]},
44 {attributes, record_info(fields, stream_mgmt_stale_h)}]),
45 3 start_cleaner(HostType, StaleOpts);
46 484 maybe_init_stale_h(_, _) -> ok.
47
48 -spec register_smid(HostType, SMID, SID) ->
49 ok | {error, term()} when
50 HostType :: mongooseim:host_type(),
51 SMID :: mod_stream_management:smid(),
52 SID :: ejabberd_sm:sid().
53 register_smid(_HostType, SMID, SID) ->
54 57 try
55 57 mnesia:sync_dirty(fun mnesia:write/1,
56 [#sm_session{smid = SMID, sid = SID}]),
57 57 ok
58 catch exit:Reason ->
59
:-(
{error, Reason}
60 end.
61
62 -spec unregister_smid(mongooseim:host_type(), ejabberd_sm:sid()) ->
63 {ok, SMID :: mod_stream_management:smid()} | {error, smid_not_found}.
64 unregister_smid(_HostType, SID) ->
65 149 case mnesia:dirty_index_read(sm_session, SID, #sm_session.sid) of
66 [] ->
67 97 {error, smid_not_found};
68 [#sm_session{smid = SMID}] ->
69 52 mnesia:dirty_delete(sm_session, SMID),
70 52 {ok, SMID}
71 end.
72
73 -spec get_sid(mongooseim:host_type(), mod_stream_management:smid()) ->
74 {sid, ejabberd_sm:sid()} | {error, smid_not_found}.
75 get_sid(_HostType, SMID) ->
76 24 case mnesia:dirty_read(sm_session, SMID) of
77 15 [#sm_session{sid = SID}] -> {sid, SID};
78 9 [] -> {error, smid_not_found}
79 end.
80
81 %% stale_h functions
82
83 -spec read_stale_h(HostType, SMID) ->
84 {stale_h, non_neg_integer()} | {error, smid_not_found} when
85 HostType :: mongooseim:host_type(),
86 SMID :: mod_stream_management:smid().
87 read_stale_h(_HostType, SMID) ->
88 25 try
89 25 case mnesia:dirty_read(stream_mgmt_stale_h, SMID) of
90 24 [#stream_mgmt_stale_h{h = H}] -> {stale_h, H};
91 1 [] -> {error, smid_not_found}
92 end
93 catch exit:_Reason ->
94
:-(
{error, smid_not_found}
95 end.
96
97 -spec write_stale_h(HostType, SMID, H) -> ok | {error, any()} when
98 HostType :: mongooseim:host_type(),
99 SMID :: mod_stream_management:smid(),
100 H :: non_neg_integer().
101 write_stale_h(_HostType, SMID, H) ->
102 8 try
103 8 Stamp = erlang:monotonic_time(second),
104 8 mnesia:dirty_write(#stream_mgmt_stale_h{smid = SMID, h = H, stamp = Stamp})
105 catch exit:Reason ->
106
:-(
{error, Reason}
107 end.
108
109 -spec delete_stale_h(HostType, SMID) -> ok | {error, any()} when
110 HostType :: mongooseim:host_type(),
111 SMID :: mod_stream_management:smid().
112 delete_stale_h(_HostType, SMID) ->
113
:-(
try
114
:-(
mnesia:dirty_delete(stream_mgmt_stale_h, SMID)
115 catch exit:Reason ->
116
:-(
{error, Reason}
117 end.
118
119 %% stale_h cleaning logic
120
121 start_cleaner(HostType, #{repeat_after := Interval, geriatric := TTL}) ->
122 %% TODO cleaner should be a service
123 3 WOpts = #{host_type => HostType, action => fun ?MODULE:clear_table/2,
124 opts => TTL, interval => timer:seconds(Interval)},
125 3 mongoose_collector:start_common(?MODULE, HostType, WOpts).
126
127 stop_cleaner(HostType) ->
128 487 mongoose_collector:stop_common(?MODULE, HostType).
129
130 clear_table(_HostType, GeriatricAge) ->
131 2 TimeToDie = erlang:monotonic_time(second) - GeriatricAge,
132 2 MS = ets:fun2ms(fun(#stream_mgmt_stale_h{stamp = S}) when S < TimeToDie -> true end),
133 2 ets:select_delete(stream_mgmt_stale_h, MS).
Line Hits Source