• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

processone / ejabberd / 1296

19 Jan 2026 11:25AM UTC coverage: 33.562% (+0.09%) from 33.468%
1296

push

github

badlop
mod_conversejs: Cosmetic change: sort paths alphabetically

0 of 4 new or added lines in 1 file covered. (0.0%)

11245 existing lines in 174 files now uncovered.

15580 of 46421 relevant lines covered (33.56%)

1074.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

42.92
/src/mod_muc_mnesia.erl
1
%%%-------------------------------------------------------------------
2
%%% File    : mod_muc_mnesia.erl
3
%%% Author  : Evgeny Khramtsov <ekhramtsov@process-one.net>
4
%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
5
%%%
6
%%%
7
%%% ejabberd, Copyright (C) 2002-2026   ProcessOne
8
%%%
9
%%% This program is free software; you can redistribute it and/or
10
%%% modify it under the terms of the GNU General Public License as
11
%%% published by the Free Software Foundation; either version 2 of the
12
%%% License, or (at your option) any later version.
13
%%%
14
%%% This program is distributed in the hope that it will be useful,
15
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
16
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
%%% General Public License for more details.
18
%%%
19
%%% You should have received a copy of the GNU General Public License along
20
%%% with this program; if not, write to the Free Software Foundation, Inc.,
21
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
%%%
23
%%%----------------------------------------------------------------------
24

25
-module(mod_muc_mnesia).
26

27

28
-behaviour(mod_muc).
29
-behaviour(mod_muc_room).
30
-behaviour(ejabberd_db_serialize).
31

32
%% API
33
-export([init/2, import/3, store_room/5, restore_room/3, forget_room/3,
34
         can_use_nick/4, get_rooms/2, get_nick/3, get_nicks/2, set_nick/4]).
35
-export([register_online_room/4, unregister_online_room/4, find_online_room/3,
36
         get_online_rooms/3, count_online_rooms/2, rsm_supported/0,
37
         register_online_user/4, unregister_online_user/4,
38
         count_online_rooms_by_user/3, get_online_rooms_by_user/3,
39
         find_online_room_by_pid/2]).
40
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
41
         get_affiliations/3, search_affiliation/4]).
42
%% gen_server callbacks
43
-export([start_link/2, init/1, handle_cast/2, handle_call/3, handle_info/2,
44
         terminate/2, code_change/3]).
45
-export([need_transform/1, transform/1]).
46
-export([serialize/3, deserialize_start/1, deserialize/2]).
47

48
-include("mod_muc.hrl").
49
-include("logger.hrl").
50

51
-include_lib("xmpp/include/xmpp.hrl").
52
-include_lib("stdlib/include/ms_transform.hrl").
53

54
-include("ejabberd_db_serialize.hrl").
55

56
-record(state, {}).
57

58
%%%===================================================================
59
%%% API
60
%%%===================================================================
61
init(Host, Opts) ->
62
    Spec = {?MODULE, {?MODULE, start_link, [Host, Opts]},
206✔
63
            transient, 5000, worker, [?MODULE]},
64
    case supervisor:start_child(ejabberd_backend_sup, Spec) of
206✔
65
        {ok, _Pid} -> ok;
11✔
66
        %% Maybe started for a vhost which only wanted mnesia for ram
67
        %% and this vhost wants mnesia for persitent storage too
68
        {error, {already_started, _Pid}} ->
69
            init([Host, Opts]);
195✔
70
        Err -> Err
×
71
    end.
72

73
start_link(Host, Opts) ->
74
    Name = gen_mod:get_module_proc(Host, ?MODULE),
11✔
75
    gen_server:start_link({local, Name}, ?MODULE, [Host, Opts], []).
11✔
76

77
store_room(_LServer, Host, Name, Opts, _) ->
UNCOV
78
    F = fun () ->
228✔
UNCOV
79
                mnesia:write(#muc_room{name_host = {Name, Host},
228✔
80
                                       opts = Opts})
81
        end,
UNCOV
82
    mnesia:transaction(F).
228✔
83

84
restore_room(_LServer, Host, Name) ->
UNCOV
85
    try mnesia:dirty_read(muc_room, {Name, Host}) of
136✔
86
        [#muc_room{opts = Opts}] -> Opts;
×
UNCOV
87
        _ -> error
136✔
88
    catch
89
        _:_ -> {error, db_failure}
×
90
    end.
91

92
forget_room(_LServer, Host, Name) ->
UNCOV
93
    F = fun () -> mnesia:delete({muc_room, {Name, Host}})
222✔
94
        end,
UNCOV
95
    mnesia:transaction(F).
222✔
96

97
can_use_nick(_LServer, ServiceOrRoom, JID, Nick) ->
UNCOV
98
    {LUser, LServer, _} = jid:tolower(JID),
264✔
UNCOV
99
    LUS = {LUser, LServer},
264✔
UNCOV
100
    MatchSpec = case (jid:decode(ServiceOrRoom))#jid.lserver of
264✔
101
        ServiceOrRoom -> [{'==', {element, 2, '$1'}, ServiceOrRoom}];
×
UNCOV
102
        Service -> [{'orelse',
264✔
103
                    {'==', {element, 2, '$1'}, Service},
104
                    {'==', {element, 2, '$1'}, ServiceOrRoom} }]
105
                end,
UNCOV
106
    case catch mnesia:dirty_select(muc_registered,
264✔
107
                                   [{#muc_registered{us_host = '$1',
108
                                                     nick = Nick, _ = '_'},
109
                                     MatchSpec,
110
                                     ['$_']}])
111
        of
112
      {'EXIT', _Reason} -> true;
×
UNCOV
113
      [] -> true;
264✔
114
      [#muc_registered{us_host = {U, _Host}}] -> U == LUS
×
115
    end.
116

117
get_rooms(_LServer, Host) ->
118
    mnesia:dirty_select(muc_room,
103✔
119
                        [{#muc_room{name_host = {'_', Host},
120
                                    _ = '_'},
121
                          [], ['$_']}]).
122

123
get_nick(_LServer, Host, From) ->
UNCOV
124
    {LUser, LServer, _} = jid:tolower(From),
42✔
UNCOV
125
    LUS = {LUser, LServer},
42✔
UNCOV
126
    case mnesia:dirty_read(muc_registered, {LUS, Host}) of
42✔
UNCOV
127
        [] -> error;
18✔
UNCOV
128
        [#muc_registered{nick = Nick}] -> Nick
24✔
129
    end.
130

131
get_nicks(_LServer, Host) ->
132
    mnesia:dirty_select(muc_registered,
×
133
                        [{#muc_registered{us_host = {{'$1', '$2'}, Host},
134
                                          nick = '$3', _ = '_'},
135
                          [],
136
                          [{{'$1', '$2', '$3'}}]
137
                         }]).
138

139
set_nick(_LServer, ServiceOrRoom, From, Nick) ->
140
    {LUser, LServer, _} = jid:tolower(From),
176✔
141
    LUS = {LUser, LServer},
176✔
142
    F = fun () ->
176✔
143
                case Nick of
176✔
144
                    <<"">> ->
145
                        mnesia:delete({muc_registered, {LUS, ServiceOrRoom}}),
164✔
146
                        ok;
164✔
147
                    _ ->
UNCOV
148
                        Service = (jid:decode(ServiceOrRoom))#jid.lserver,
12✔
UNCOV
149
                        MatchSpec = case (ServiceOrRoom == Service) of
12✔
UNCOV
150
                            true -> [{'==', {element, 2, '$1'}, ServiceOrRoom}];
12✔
151
                            false -> [{'orelse',
×
152
                                        {'==', {element, 2, '$1'}, Service},
153
                                        {'==', {element, 2, '$1'}, ServiceOrRoom} }]
154
                                    end,
UNCOV
155
                        Allow = case mnesia:select(
12✔
156
                                       muc_registered,
157
                                       [{#muc_registered{us_host = '$1', nick = Nick, _ = '_'},
158
                                         MatchSpec,
159
                                         ['$_']}]) of
160
                                    [] when (ServiceOrRoom == Service) ->
UNCOV
161
                                        NickRegistrations = mnesia:select(
9✔
162
                                            muc_registered,
163
                                            [{#muc_registered{us_host = '$1', nick = Nick, _ = '_'},
164
                                                [],
165
                                                ['$_']}]),
UNCOV
166
                                        not lists:any(fun({_, {_NRUS, NRServiceOrRoom}, _Nick}) ->
9✔
167
                                                              Service == (jid:decode(NRServiceOrRoom))#jid.lserver end,
×
168
                                                      NickRegistrations);
169
                                    [] -> true;
×
170
                                    [#muc_registered{us_host = {_U, Host}}]
171
                                      when (Host == Service) and (ServiceOrRoom /= Service) ->
172
                                        false;
×
173
                                    [#muc_registered{us_host = {U, _Host}}] ->
UNCOV
174
                                        U == LUS
3✔
175
                                end,
UNCOV
176
                        if Allow ->
12✔
UNCOV
177
                                mnesia:write(#muc_registered{
9✔
178
                                                us_host = {LUS, ServiceOrRoom},
179
                                                nick = Nick}),
UNCOV
180
                                ok;
9✔
181
                           true ->
UNCOV
182
                                false
3✔
183
                        end
184
                end
185
        end,
186
    mnesia:transaction(F).
176✔
187

188
set_affiliation(_ServerHost, _Room, _Host, _JID, _Affiliation, _Reason) ->
UNCOV
189
    {error, not_implemented}.
18✔
190

191
set_affiliations(_ServerHost, _Room, _Host, _Affiliations) ->
UNCOV
192
    {error, not_implemented}.
88✔
193

194
get_affiliation(_ServerHost, _Room, _Host, _LUser, _LServer) ->
UNCOV
195
    {error, not_implemented}.
826✔
196

197
get_affiliations(_ServerHost, _Room, _Host) ->
UNCOV
198
    {error, not_implemented}.
86✔
199

200
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
UNCOV
201
    {error, not_implemented}.
22✔
202

203
register_online_room(_ServerHost, Room, Host, Pid) ->
UNCOV
204
    F = fun() ->
136✔
UNCOV
205
                mnesia:write(
136✔
206
                  #muc_online_room{name_host = {Room, Host}, pid = Pid})
207
        end,
UNCOV
208
    mnesia:transaction(F).
136✔
209

210
unregister_online_room(_ServerHost, Room, Host, Pid) ->
UNCOV
211
    F = fun () ->
136✔
UNCOV
212
                mnesia:delete_object(
136✔
213
                  #muc_online_room{name_host = {Room, Host}, pid = Pid})
214
        end,
UNCOV
215
    mnesia:transaction(F).
136✔
216

217
find_online_room(_ServerHost, Room, Host) ->
UNCOV
218
    find_online_room(Room, Host).
1,428✔
219

220
find_online_room(Room, Host) ->
UNCOV
221
    case mnesia:dirty_read(muc_online_room, {Room, Host}) of
1,428✔
UNCOV
222
        [] -> error;
290✔
UNCOV
223
        [#muc_online_room{pid = Pid}] -> {ok, Pid}
1,138✔
224
    end.
225

226
find_online_room_by_pid(_ServerHost, Pid) ->
UNCOV
227
    Res =
136✔
228
    mnesia:dirty_select(
229
        muc_online_room,
230
        ets:fun2ms(
231
            fun(#muc_online_room{name_host = {Name, Host}, pid = PidS})
232
                   when PidS == Pid -> {Name, Host}
233
            end)),
UNCOV
234
    case Res of
136✔
UNCOV
235
        [{Name, Host}] -> {ok, Name, Host};
136✔
236
        _ -> error
×
237
    end.
238

239
count_online_rooms(_ServerHost, Host) ->
UNCOV
240
    ets:select_count(
12✔
241
      muc_online_room,
242
      ets:fun2ms(
243
        fun(#muc_online_room{name_host = {_, H}}) ->
244
                H == Host
245
        end)).
246

247
get_online_rooms(_ServerHost, Host,
248
                 #rsm_set{max = Max, 'after' = After, before = undefined})
249
  when is_binary(After), After /= <<"">> ->
UNCOV
250
    lists:reverse(get_online_rooms(next, {After, Host}, Host, 0, Max, []));
3✔
251
get_online_rooms(_ServerHost, Host,
252
                 #rsm_set{max = Max, 'after' = undefined, before = Before})
253
  when is_binary(Before), Before /= <<"">> ->
254
    get_online_rooms(prev, {Before, Host}, Host, 0, Max, []);
×
255
get_online_rooms(_ServerHost, Host,
256
                 #rsm_set{max = Max, 'after' = undefined, before = <<"">>}) ->
257
    get_online_rooms(last, {<<"">>, Host}, Host, 0, Max, []);
×
258
get_online_rooms(_ServerHost, Host, #rsm_set{max = Max}) ->
259
    lists:reverse(get_online_rooms(first, {<<"">>, Host}, Host, 0, Max, []));
×
260
get_online_rooms(_ServerHost, Host, undefined) ->
261
    mnesia:dirty_select(
28✔
262
      muc_online_room,
263
      ets:fun2ms(
264
        fun(#muc_online_room{name_host = {Name, H}, pid = Pid})
265
              when H == Host -> {Name, Host, Pid}
266
        end)).
267

268
-spec get_online_rooms(prev | next | last | first,
269
                       {binary(), binary()}, binary(),
270
                       non_neg_integer(), non_neg_integer() | undefined,
271
                       [{binary(), binary(), pid()}]) ->
272
                              [{binary(), binary(), pid()}].
273
get_online_rooms(_Action, _Key, _Host, Count, Max, Items) when Count >= Max ->
274
    Items;
×
275
get_online_rooms(Action, Key, Host, Count, Max, Items) ->
UNCOV
276
    Call = fun() ->
3✔
UNCOV
277
                   case Action of
3✔
278
                       prev -> mnesia:dirty_prev(muc_online_room, Key);
×
UNCOV
279
                       next -> mnesia:dirty_next(muc_online_room, Key);
3✔
280
                       last -> mnesia:dirty_last(muc_online_room);
×
281
                       first -> mnesia:dirty_first(muc_online_room)
×
282
                   end
283
           end,
UNCOV
284
    NewAction = case Action of
3✔
285
                    last -> prev;
×
286
                    first -> next;
×
UNCOV
287
                    _ -> Action
3✔
288
                end,
UNCOV
289
    try Call() of
3✔
290
        '$end_of_table' ->
UNCOV
291
            Items;
3✔
292
        {Room, Host} = NewKey ->
293
            case find_online_room(Room, Host) of
×
294
                {ok, Pid} ->
295
                    get_online_rooms(NewAction, NewKey, Host,
×
296
                                     Count + 1, Max, [{Room, Host, Pid}|Items]);
297
                error ->
298
                    get_online_rooms(NewAction, NewKey, Host,
×
299
                                     Count, Max, Items)
300
            end;
301
        NewKey ->
302
            get_online_rooms(NewAction, NewKey, Host, Count, Max, Items)
×
303
    catch _:{aborted, {badarg, _}} ->
304
            Items
×
305
    end.
306

307
rsm_supported() ->
UNCOV
308
    true.
18✔
309

310
register_online_user(_ServerHost, {U, S, R}, Room, Host) ->
UNCOV
311
    ets:insert(muc_online_users,
223✔
312
               #muc_online_users{us = {U, S}, resource = R,
313
                                 room = Room, host = Host}).
314

315
unregister_online_user(_ServerHost, {U, S, R}, Room, Host) ->
UNCOV
316
    ets:delete_object(muc_online_users,
223✔
317
                      #muc_online_users{us = {U, S}, resource = R,
318
                                        room = Room, host = Host}).
319

320
count_online_rooms_by_user(ServerHost, U, S) ->
UNCOV
321
    MucHost = hd(gen_mod:get_module_opt_hosts(ServerHost, mod_muc)),
258✔
UNCOV
322
    ets:select_count(
258✔
323
      muc_online_users,
324
      ets:fun2ms(
325
        fun(#muc_online_users{us = {U1, S1}, host = Host}) ->
326
                U == U1 andalso S == S1 andalso MucHost == Host
327
        end)).
328

329
get_online_rooms_by_user(ServerHost, U, S) ->
330
    MucHost = hd(gen_mod:get_module_opt_hosts(ServerHost, mod_muc)),
×
331
    ets:select(
×
332
      muc_online_users,
333
      ets:fun2ms(
334
        fun(#muc_online_users{us = {U1, S1}, room = Room, host = Host})
335
              when U == U1 andalso S == S1 andalso MucHost == Host -> {Room, Host}
336
        end)).
337

338
import(_LServer, <<"muc_room">>,
339
       [Name, RoomHost, SOpts, _TimeStamp]) ->
340
    Opts = mod_muc:opts_to_binary(ejabberd_sql:decode_term(SOpts)),
×
341
    mnesia:dirty_write(
×
342
      #muc_room{name_host = {Name, RoomHost},
343
                opts = Opts});
344
import(_LServer, <<"muc_registered">>,
345
       [J, RoomHost, Nick, _TimeStamp]) ->
346
    #jid{user = U, server = S} = jid:decode(J),
×
347
    mnesia:dirty_write(
×
348
      #muc_registered{us_host = {{U, S}, RoomHost},
349
                      nick = Nick}).
350

351
%%%===================================================================
352
%%% gen_server callbacks
353
%%%===================================================================
354
init([_Host, Opts]) ->
355
    MyHosts = mod_muc_opt:hosts(Opts),
206✔
356
    case gen_mod:db_mod(Opts, mod_muc) of
206✔
357
        ?MODULE ->
358
            ejabberd_mnesia:create(?MODULE, muc_room,
206✔
359
                                   [{disc_copies, [node()]},
360
                                    {attributes,
361
                                     record_info(fields, muc_room)}]),
362
            ejabberd_mnesia:create(?MODULE, muc_registered,
206✔
363
                                   [{disc_copies, [node()]},
364
                                    {attributes,
365
                                     record_info(fields, muc_registered)},
366
                                    {index, [nick]}]);
367
        _ ->
368
            ok
×
369
    end,
370
    case gen_mod:ram_db_mod(Opts, mod_muc) of
206✔
371
        ?MODULE ->
372
            ejabberd_mnesia:create(?MODULE, muc_online_room,
206✔
373
                                   [{ram_copies, [node()]},
374
                                    {type, ordered_set},
375
                                    {attributes, record_info(fields, muc_online_room)}]),
376
            catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]),
206✔
377
            lists:foreach(
206✔
378
              fun(MyHost) ->
379
                      clean_table_from_bad_node(node(), MyHost)
206✔
380
              end, MyHosts),
381
            mnesia:subscribe(system);
206✔
382
        _ ->
383
            ok
×
384
    end,
385
    {ok, #state{}}.
206✔
386

387
handle_call(Request, From, State) ->
388
    ?WARNING_MSG("Unexpected call from ~p: ~p", [From, Request]),
×
389
    {noreply, State}.
×
390

391
handle_cast(Msg, State) ->
392
    ?WARNING_MSG("Unexpected cast: ~p", [Msg]),
×
393
    {noreply, State}.
×
394

395
handle_info({mnesia_system_event, {mnesia_down, Node}}, State) ->
396
    clean_table_from_bad_node(Node),
×
397
    {noreply, State};
×
398
handle_info({mnesia_system_event, {mnesia_up, _Node}}, State) ->
399
    {noreply, State};
×
400
handle_info(Info, State) ->
401
    ?WARNING_MSG("Unexpected info: ~p", [Info]),
×
402
    {noreply, State}.
×
403

404
terminate(_Reason, _State) ->
405
    ok.
×
406

407
code_change(_OldVsn, State, _Extra) ->
408
    {ok, State}.
×
409

410
%%%===================================================================
411
%%% Internal functions
412
%%%===================================================================
413
clean_table_from_bad_node(Node) ->
414
    F = fun() ->
×
415
                Es = mnesia:select(
×
416
                       muc_online_room,
417
                       [{#muc_online_room{pid = '$1', _ = '_'},
418
                         [{'==', {node, '$1'}, Node}],
419
                         ['$_']}]),
420
                lists:foreach(fun(E) ->
×
421
                                      mnesia:delete_object(E)
×
422
                              end, Es)
423
        end,
424
    mnesia:async_dirty(F).
×
425

426
clean_table_from_bad_node(Node, Host) ->
427
    F = fun() ->
206✔
428
                Es = mnesia:select(
206✔
429
                       muc_online_room,
430
                       [{#muc_online_room{pid = '$1',
431
                                          name_host = {'_', Host},
432
                                          _ = '_'},
433
                         [{'==', {node, '$1'}, Node}],
434
                         ['$_']}]),
435
                lists:foreach(fun(E) ->
206✔
436
                                      mnesia:delete_object(E)
×
437
                              end, Es)
438
        end,
439
    mnesia:async_dirty(F).
206✔
440

441
need_transform({muc_room, {N, H}, _})
442
  when is_list(N) orelse is_list(H) ->
443
    ?INFO_MSG("Mnesia table 'muc_room' will be converted to binary", []),
×
444
    true;
×
445
need_transform({muc_room, {_N, _H}, Opts}) ->
446
    case {lists:keymember(allow_private_messages, 1, Opts),
×
447
          lists:keymember(hats_defs, 1, Opts)} of
448
        {true, _} ->
449
            ?INFO_MSG("Mnesia table 'muc_room' will be converted to allowpm", []),
×
450
            true;
×
451
        {false, false} ->
452
            ?INFO_MSG("Mnesia table 'muc_room' will be converted to Hats 0.3.0", []),
×
453
            true;
×
454
        {false, true} ->
455
            false
×
456
    end;
457

458
need_transform({muc_registered, {{U, S}, H}, Nick})
459
  when is_list(U) orelse is_list(S) orelse is_list(H) orelse is_list(Nick) ->
460
    ?INFO_MSG("Mnesia table 'muc_registered' will be converted to binary", []),
×
461
    true;
×
462
need_transform(_) ->
463
    false.
×
464

465
transform({muc_room, {N, H}, Opts} = R)
466
  when is_list(N) orelse is_list(H) ->
467
    R#muc_room{name_host = {iolist_to_binary(N), iolist_to_binary(H)},
×
468
               opts = mod_muc:opts_to_binary(Opts)};
469
transform(#muc_room{opts = Opts} = R) ->
470
    Opts2 = case lists:keyfind(allow_private_messages, 1, Opts) of
×
471
        {_, Value} when is_boolean(Value) ->
472
            Value2 = case Value of
×
473
                         true -> anyone;
×
474
                         false -> none
×
475
                     end,
476
            lists:keyreplace(allow_private_messages, 1, Opts, {allowpm, Value2});
×
477
        _ ->
478
            Opts
×
479
    end,
480
    Opts4 =
×
481
        case lists:keyfind(hats_defs, 1, Opts2) of
482
            false ->
483
                {hats_users, HatsUsers} = lists:keyfind(hats_users, 1, Opts2),
×
484
                {HatsDefs, HatsUsers2} =
×
485
                    lists:foldl(fun({Jid, UriTitleList}, {Defs, Assigns}) ->
486
                                   Defs2 =
×
487
                                       lists:foldl(fun({Uri, Title}, AccDef) ->
488
                                                      maps:put(Uri, {Title, <<"">>}, AccDef)
×
489
                                                   end,
490
                                                   Defs,
491
                                                   UriTitleList),
492
                                   Assigns2 =
×
493
                                       maps:put(Jid,
494
                                                [Uri || {Uri, _Title} <- UriTitleList],
×
495
                                                Assigns),
496
                                   {Defs2, Assigns2}
×
497
                                end,
498
                                {maps:new(), maps:new()},
499
                                HatsUsers),
500
                Opts3 =
×
501
                    lists:keyreplace(hats_users, 1, Opts2, {hats_users, maps:to_list(HatsUsers2)}),
502
                [{hats_defs, maps:to_list(HatsDefs)} | Opts3];
×
503
            {_, _} ->
504
                Opts2
×
505
        end,
506
    R#muc_room{opts = Opts4};
×
507
transform(#muc_registered{us_host = {{U, S}, H}, nick = Nick} = R) ->
508
    R#muc_registered{us_host = {{iolist_to_binary(U), iolist_to_binary(S)},
×
509
                                iolist_to_binary(H)},
510
                     nick = iolist_to_binary(Nick)}.
511

512

513
serialize(LServer, BatchSize, undefined) ->
514
    Hosts = gen_mod:get_module_opt_hosts(LServer, mod_muc),
×
515
    MucRoomConv =
×
516
        fun([]) -> skip;
×
517
           ([#muc_room{name_host = {Name, Host}, opts = Opts}]) ->
518
                case lists:member(Host, Hosts) of
×
519
                    true ->
520
                        {ok, #serialize_muc_room_v1{
×
521
                               serverhost = LServer,
522
                               host = Host,
523
                               name = Name,
524
                               options = mod_muc:opts_to_binary(
525
                                           Opts)
526
                              }};
527
                    _ -> skip
×
528
                end;
529
           (_) -> skip
×
530
        end,
531
    RegistrationsConv =
×
532
        fun([]) -> skip;
×
533
           ([#muc_registered{us_host = {{U, S}, Host}, nick = Nick}]) ->
534
                case lists:member(Host, Hosts) of
×
535
                    true ->
536
                        {ok, #serialize_muc_registrations_v1{
×
537
                               serverhost = LServer,
538
                               host = Host,
539
                               jid = jid:encode({U, S, <<>>}),
540
                               nick = Nick
541
                              }};
542
                    _ -> skip
×
543
                end;
544
           (_) -> skip
×
545
        end,
546
    ejabberd_db_serialize:iter_records([ejabberd_db_serialize:mnesia_iter(muc_room, MucRoomConv),
×
547
                                        ejabberd_db_serialize:mnesia_iter(muc_registered, RegistrationsConv)],
548
                                       [],
549
                                       BatchSize);
550
serialize(_LServer, BatchSize, Key) ->
551
    ejabberd_db_serialize:iter_records(Key, [], BatchSize).
×
552

553

554
is_subdomain(Domain, SubDomain) ->
555
    LenDiff = byte_size(SubDomain) - byte_size(Domain) - 1,
×
556
    case SubDomain of
×
557
        _ when SubDomain == Domain -> true;
×
558
        _ when LenDiff =< 0 -> false;
×
559
        <<_:LenDiff/binary, ".", SPart/binary>> when SPart == Domain -> true;
×
560
        _ -> false
×
561
    end.
562

563

564
deserialize_start(LServer) ->
565
    mnesia:transaction(fun() ->
×
566
                               RoomKeys = lists:filter(fun({_, Service}) ->
×
567
                                                               is_subdomain(LServer, Service)
×
568
                                                       end,
569
                                                       mnesia:all_keys(muc_room)),
570
                               NickKeys = lists:filter(fun({_, Service}) ->
×
571
                                                               is_subdomain(LServer, Service)
×
572
                                                       end,
573
                                                       mnesia:all_keys(muc_registered)),
574
                               lists:foreach(fun(Key) -> mnesia:delete(muc_room, Key, write) end, RoomKeys),
×
575
                               lists:foreach(fun(Key) -> mnesia:delete(muc_registered, Key, write) end, NickKeys)
×
576
                       end),
577
    ok.
×
578

579

580
deserialize(LServer, Batch) ->
581
    lists:foldl(
×
582
      fun(_, {error, _} = Err) ->
583
              Err;
×
584
         (#serialize_muc_room_v1{name = Name, host = Host, options = Opts}, _) ->
585
              case store_room(LServer, Host, Name, Opts, undefined) of
×
586
                  {atomic, _} ->
587
                      ok;
×
588
                  _ -> {error, io_lib:format("Error when writing muc room data", [])}
×
589
              end;
590
         (#serialize_muc_registrations_v1{host = Host, jid = Jid, nick = Nick}, _) ->
591
              #jid{luser = L, lserver = S} = jid:decode(Jid),
×
592
              case mnesia:transaction(
×
593
                     fun() ->
594
                             mnesia:write(#muc_registered{
×
595
                                            us_host = {{L, S}, Host},
596
                                            nick = Nick
597
                                           })
598
                     end) of
599
                  {atomic, _} ->
600
                      ok;
×
601
                  _ -> {error, io_lib:format("Error when writing muc registration data", [])}
×
602
              end
603
      end,
604
      ok,
605
      Batch).
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc