./ct_report/coverage/mod_global_distrib_mapping.COVER.html

1 %%==============================================================================
2 %% Copyright 2017 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16
17 -module(mod_global_distrib_mapping).
18 -author('konrad.zemek@erlang-solutions.com').
19
20 -behaviour(gen_mod).
21 -behaviour(mongoose_module_metrics).
22
23 -include("mongoose.hrl").
24 -include("jlib.hrl").
25 -include("global_distrib_metrics.hrl").
26
27 -define(DOMAIN_TAB, mod_global_distrib_domain_cache_tab).
28 -define(JID_TAB, mod_global_distrib_jid_cache_tab).
29
30 -export([start/2, stop/1, hooks/1, deps/2]).
31 -export([for_domain/1, insert_for_domain/1, insert_for_domain/2, insert_for_domain/3,
32 cache_domain/2, delete_for_domain/1, all_domains/0, public_domains/0]).
33 -export([for_jid/1, insert_for_jid/1, cache_jid/2, delete_for_jid/1, clear_cache/1]).
34 -export([register_subhost/3, unregister_subhost/3, packet_to_component/3,
35 session_opened/3, session_closed/3]).
36 -export([endpoints/1, hosts/0]).
37
38 -ignore_xref([
39 delete_for_domain/1, delete_for_jid/1, insert_for_domain/1,
40 insert_for_domain/2, insert_for_domain/3, insert_for_jid/1
41 ]).
42
43 -type endpoint() :: mod_global_distrib_utils:endpoint().
44
45 %%--------------------------------------------------------------------
46 %% API
47 %%--------------------------------------------------------------------
48
49 -spec for_domain(Domain :: binary()) -> {ok, Host :: jid:lserver()} | error.
50 for_domain(Domain) when is_binary(Domain) ->
51
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_FETCHES, 1),
52
:-(
{Time, R} = timer:tc(ets_cache, lookup, [?DOMAIN_TAB, Domain, fun() -> get_domain(Domain) end]),
53
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_FETCH_TIME, Time),
54
:-(
R.
55
56 -spec insert_for_domain(Domain :: binary()) -> ok.
57 insert_for_domain(Domain) when is_binary(Domain) ->
58
:-(
insert_for_domain(Domain, false).
59
60 -spec insert_for_domain(Domain :: binary(), IsHidden :: boolean()) -> ok.
61 insert_for_domain(Domain, IsHidden) when is_binary(Domain) ->
62
:-(
LocalHost = opt(local_host),
63
:-(
insert_for_domain(Domain, LocalHost, IsHidden).
64
65 -spec insert_for_domain(Domain :: binary(), Host :: binary(), IsHidden :: boolean()) -> ok.
66 insert_for_domain(Domain, Host, IsHidden) when is_binary(Domain), is_binary(Host) ->
67
:-(
do_insert_for_domain(Domain, Host, fun(ToStore) -> put_domain(ToStore, IsHidden) end).
68
69 -spec cache_domain(Domain :: binary(), Host :: binary()) -> ok.
70 cache_domain(Domain, Host) when is_binary(Domain), is_binary(Host) ->
71
:-(
do_insert_for_domain(Domain, Host, fun(_) -> ok end).
72
73 -spec delete_for_domain(Domain :: binary()) -> ok.
74 delete_for_domain(Domain) when is_binary(Domain) ->
75
:-(
delete_domain(Domain),
76
:-(
ets_cache:delete(?DOMAIN_TAB, Domain).
77
78 -spec for_jid(jid:jid() | jid:ljid()) -> {ok, Host :: jid:lserver()} | error.
79
:-(
for_jid(#jid{} = Jid) -> for_jid(jid:to_lower(Jid));
80 for_jid({_, _, _} = Jid) ->
81
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_FETCHES, 1),
82
:-(
{Time, R} = timer:tc(fun do_lookup_jid/1, [Jid]),
83
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_FETCH_TIME, Time),
84
:-(
R.
85
86 -spec insert_for_jid(jid:jid() | jid:ljid()) -> ok.
87 insert_for_jid(Jid) ->
88
:-(
LocalHost = opt(local_host),
89
:-(
do_insert_for_jid(Jid, LocalHost, fun put_session/1).
90
91 -spec cache_jid(jid:jid() | jid:ljid(), Host :: jid:lserver()) -> ok.
92 cache_jid(Jid, Host) when is_binary(Host) ->
93
:-(
do_insert_for_jid(Jid, Host, fun(_) -> ok end).
94
95 -spec clear_cache(jid:jid()) -> ok.
96 clear_cache(#jid{} = Jid) ->
97
:-(
GlobalHost = opt(global_host),
98
:-(
case jid:to_lower(Jid) of
99 {_, GlobalHost, _} = LJid ->
100
:-(
[ets_cache:delete(?JID_TAB, J) || J <- normalize_jid(LJid)];
101 {_, SubHost, _} ->
102
:-(
ets_cache:delete(?DOMAIN_TAB, SubHost)
103 end.
104
105 -spec delete_for_jid(jid:jid() | jid:ljid()) -> ok.
106
:-(
delete_for_jid(#jid{} = Jid) -> delete_for_jid(jid:to_lower(Jid));
107 delete_for_jid({_, _, _} = Jid) ->
108
:-(
lists:foreach(
109 fun(BinJid) ->
110
:-(
delete_session(BinJid),
111
:-(
ets_cache:delete(?JID_TAB, BinJid)
112 end,
113 normalize_jid(Jid)).
114
115 -spec all_domains() -> [jid:lserver()].
116 all_domains() ->
117
:-(
mod_global_distrib_mapping_backend:get_domains().
118
119 -spec public_domains() -> [jid:lserver()].
120 public_domains() ->
121
:-(
mod_global_distrib_mapping_backend:get_public_domains().
122
123 -spec endpoints(Host :: jid:lserver()) -> [endpoint()].
124 endpoints(Host) ->
125
:-(
mod_global_distrib_mapping_backend:get_endpoints(Host).
126
127 -spec hosts() -> [Host :: jid:lserver()].
128 hosts() ->
129
:-(
mod_global_distrib_mapping_backend:get_hosts().
130
131 %%--------------------------------------------------------------------
132 %% gen_mod API
133 %%--------------------------------------------------------------------
134
135 -spec start(mongooseim:host_type(), gen_mod:module_opts()) -> any().
136 start(_HostType, Opts = #{cache := CacheOpts}) ->
137
:-(
mod_global_distrib_mapping_backend:start(Opts#{backend => redis}),
138
139
:-(
mongoose_metrics:ensure_metric(global, ?GLOBAL_DISTRIB_MAPPING_FETCH_TIME, histogram),
140
:-(
mongoose_metrics:ensure_metric(global, ?GLOBAL_DISTRIB_MAPPING_FETCHES, spiral),
141
:-(
mongoose_metrics:ensure_metric(global, ?GLOBAL_DISTRIB_MAPPING_CACHE_MISSES, spiral),
142
143
:-(
#{cache_missed := CacheMissed,
144 domain_lifetime_seconds := DomainLifetimeSec,
145 jid_lifetime_seconds := JidLifeTimeSec,
146 max_jids := MaxJids} = CacheOpts,
147
:-(
DomainLifetime = timer:seconds(DomainLifetimeSec),
148
:-(
JidLifetime = timer:seconds(JidLifeTimeSec),
149
150
151
:-(
ets_cache:new(?DOMAIN_TAB, [{cache_missed, CacheMissed}, {life_time, DomainLifetime}]),
152
:-(
ets_cache:new(?JID_TAB, [{cache_missed, CacheMissed}, {life_time, JidLifetime},
153 {max_size, MaxJids}]).
154
155 -spec stop(mongooseim:host_type()) -> any().
156 stop(_HostType) ->
157
:-(
ets_cache:delete(?JID_TAB),
158
:-(
ets_cache:delete(?DOMAIN_TAB),
159
:-(
mod_global_distrib_mapping_backend:stop().
160
161 -spec deps(mongooseim:host_type(), gen_mod:module_opts()) -> gen_mod_deps:deps().
162 deps(_HostType, Opts) ->
163
:-(
[{mod_global_distrib_utils, Opts, hard},
164 {mod_global_distrib_receiver, Opts, hard}].
165
166 %%--------------------------------------------------------------------
167 %% Hooks implementation
168 %%--------------------------------------------------------------------
169
170 -spec session_opened(Acc, Params, Extra) -> {ok, Acc} when
171 Acc :: any(),
172 Params :: #{jid := jid:jid()},
173 Extra :: gen_hook:extra().
174 session_opened(Acc, #{jid := UserJid}, _) ->
175
:-(
insert_for_jid(UserJid),
176
:-(
{ok, Acc}.
177
178 -spec session_closed(Acc, Params, Extra) -> {ok, Acc} when
179 Acc :: mongoose_acc:t(),
180 Params :: #{jid := jid:jid()},
181 Extra :: gen_hook:extra().
182 session_closed(Acc, #{jid := UserJid}, _) ->
183
:-(
delete_for_jid(UserJid),
184
:-(
{ok, Acc}.
185
186 -spec packet_to_component(Acc, Params, Extra) -> {ok, Acc} when
187 Acc :: mongoose_acc:t(),
188 Params :: #{from := jid:jid()},
189 Extra :: gen_hook:extra().
190 packet_to_component(Acc, #{from := From}, _) ->
191
:-(
mod_global_distrib_utils:maybe_update_mapping(From, Acc),
192
:-(
{ok, Acc}.
193
194 -spec register_subhost(Acc, Params, Extra) -> {ok, ok} when
195 Acc :: any(),
196 Params :: #{ldomain := binary(), is_hidden := boolean()},
197 Extra :: gen_hook:extra().
198 register_subhost(_, #{ldomain := SubHost, is_hidden := IsHidden}, _) ->
199
:-(
IsSubhostOf =
200 fun(Host) ->
201
:-(
case binary:match(SubHost, Host) of
202
:-(
{Start, Length} -> Start + Length == byte_size(SubHost);
203
:-(
_ -> false
204 end
205 end,
206
207
:-(
GlobalHost = opt(global_host),
208
:-(
NewAcc = case lists:filter(IsSubhostOf, ?MYHOSTS) of
209
:-(
[GlobalHost] -> insert_for_domain(SubHost, IsHidden);
210
:-(
_ -> ok
211 end,
212
:-(
{ok, NewAcc}.
213
214 -spec unregister_subhost(Acc, Params, Extra) -> {ok, ok} when
215 Acc :: any(),
216 Params :: #{ldomain := binary()},
217 Extra :: gen_hook:extra().
218 unregister_subhost(_, #{ldomain := SubHost}, _) ->
219
:-(
{ok, delete_for_domain(SubHost)}.
220
221 %%--------------------------------------------------------------------
222 %% Helpers
223 %%--------------------------------------------------------------------
224
225 hooks(HostType) ->
226
:-(
[{register_subhost, global, fun ?MODULE:register_subhost/3, #{}, 90},
227 {unregister_subhost, global, fun ?MODULE:unregister_subhost/3, #{}, 90},
228 {packet_to_component, global, fun ?MODULE:packet_to_component/3, #{}, 90},
229 {sm_register_connection_hook, HostType, fun ?MODULE:session_opened/3, #{}, 90},
230 {sm_remove_connection_hook, HostType, fun ?MODULE:session_closed/3, #{}, 90}].
231
232 -spec normalize_jid(jid:ljid()) -> [binary()].
233 normalize_jid({_, _, _} = FullJid) ->
234
:-(
case jid:to_bare(FullJid) of
235
:-(
FullJid -> [jid:to_binary(FullJid)];
236
:-(
BareJid -> [jid:to_binary(FullJid), jid:to_binary(BareJid)]
237 end.
238
239 -spec opt(Key :: atom()) -> term().
240 opt(Key) ->
241
:-(
mod_global_distrib_utils:opt(?MODULE, Key).
242
243 -spec get_session(Key :: binary()) -> {ok, term()} | error.
244 get_session(Key) ->
245
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_CACHE_MISSES, 1),
246
:-(
mod_global_distrib_mapping_backend:get_session(Key).
247
248 -spec put_session(Key :: binary()) -> ok.
249 put_session(Key) ->
250
:-(
?LOG_DEBUG(#{what => gd_mapper_put_session, key => Key}),
251
:-(
mod_global_distrib_mapping_backend:put_session(Key).
252
253 -spec delete_session(Key :: binary()) -> ok.
254 delete_session(Key) ->
255
:-(
?LOG_DEBUG(#{what => gd_mapper_delete_session, key => Key}),
256
:-(
mod_global_distrib_mapping_backend:delete_session(Key).
257
258 -spec get_domain(Key :: binary()) -> {ok, term()} | error.
259 get_domain(Key) ->
260
:-(
mongoose_metrics:update(global, ?GLOBAL_DISTRIB_MAPPING_CACHE_MISSES, 1),
261
:-(
mod_global_distrib_mapping_backend:get_domain(Key).
262
263 -spec put_domain(Key :: binary(), IsHidden :: boolean()) -> ok.
264 put_domain(Key, IsHidden) ->
265
:-(
mod_global_distrib_mapping_backend:put_domain(Key, IsHidden).
266
267 -spec delete_domain(Key :: binary()) -> ok.
268 delete_domain(Key) ->
269
:-(
mod_global_distrib_mapping_backend:delete_domain(Key).
270
271 -spec do_insert_for_jid(jid:jid() | jid:ljid(), Host :: jid:lserver(),
272 PutSession :: fun((binary()) -> ok | error)) -> ok.
273 do_insert_for_jid(#jid{} = Jid, Host, PutSession) ->
274
:-(
do_insert_for_jid(jid:to_lower(Jid), Host, PutSession);
275 do_insert_for_jid({_, _, _} = Jid, Host, PutSession) ->
276
:-(
lists:foreach(
277 fun(BinJid) ->
278
:-(
ets_cache:update(?JID_TAB, BinJid, {ok, Host}, fun() -> PutSession(BinJid) end)
279 end,
280 normalize_jid(Jid)).
281
282 -spec do_insert_for_domain(Domain :: binary(), Host :: jid:lserver(),
283 PutDomain :: fun((binary()) -> ok | error)) -> ok.
284 do_insert_for_domain(Domain, Host, PutDomain) ->
285
:-(
ets_cache:update(?DOMAIN_TAB, Domain, {ok, Host}, fun() -> PutDomain(Domain) end).
286
287 -spec do_lookup_jid(jid:ljid()) -> {ok, Host :: jid:lserver()} | error.
288 do_lookup_jid({_, _, _} = Jid) ->
289
:-(
BinJid = jid:to_binary(Jid),
290
:-(
LookupInDB = fun(BJid) -> fun() -> get_session(BJid) end end,
291
:-(
case ets_cache:lookup(?JID_TAB, BinJid, LookupInDB(BinJid)) of
292
:-(
{ok, _} = Result -> Result;
293 Other ->
294
:-(
case jid:to_bare(Jid) of
295
:-(
Jid -> Other;
296
:-(
BareJid -> ets_cache:lookup(?JID_TAB, BinJid, LookupInDB(jid:to_binary(BareJid)))
297 end
298 end.
Line Hits Source