1 |
|
-module(mod_muc_online_mnesia). |
2 |
|
-behaviour(mod_muc_online_backend). |
3 |
|
|
4 |
|
-export([start/2, |
5 |
|
stop/1, |
6 |
|
register_room/4, |
7 |
|
room_destroyed/4, |
8 |
|
find_room_pid/3, |
9 |
|
get_online_rooms/2, |
10 |
|
node_cleanup/2, |
11 |
|
clear_table/1]). |
12 |
|
|
13 |
|
-include_lib("mod_muc.hrl"). |
14 |
|
|
15 |
|
-spec start(mongooseim:host_type(), gen_mod:module_opts()) -> ok. |
16 |
|
start(_HostType, _Opts) -> |
17 |
23 |
mongoose_mnesia:create_table(muc_online_room, |
18 |
|
[{ram_copies, [node()]}, |
19 |
|
{attributes, record_info(fields, muc_online_room)}]), |
20 |
23 |
ok. |
21 |
|
|
22 |
|
-spec stop(mongooseim:host_type()) -> ok. |
23 |
23 |
stop(_HostType) -> ok. |
24 |
|
|
25 |
|
-spec register_room( |
26 |
|
HostType :: mongooseim:host_type(), |
27 |
|
MucHost :: jid:lserver(), |
28 |
|
Room :: mod_muc:room(), |
29 |
|
Pid :: pid()) -> ok | {exists, pid()} | {error, term()}. |
30 |
|
register_room(HostType, MucHost, Room, Pid) -> |
31 |
250 |
F = fun() -> |
32 |
250 |
case mnesia:read(muc_online_room, {Room, MucHost}, write) of |
33 |
|
[] -> |
34 |
247 |
mnesia:write(#muc_online_room{name_host = {Room, MucHost}, |
35 |
|
host_type = HostType, |
36 |
|
pid = Pid}); |
37 |
|
[R] -> |
38 |
3 |
{exists, R#muc_online_room.pid} |
39 |
|
end |
40 |
|
end, |
41 |
250 |
simple_transaction_result(mnesia:transaction(F)). |
42 |
|
|
43 |
|
%% Race condition is possible between register and room_destroyed |
44 |
|
%% (Because register is outside of the room process) |
45 |
|
-spec room_destroyed(mongooseim:host_type(), jid:lserver(), mod_muc:room(), pid()) -> ok. |
46 |
|
room_destroyed(HostType, MucHost, Room, Pid) -> |
47 |
197 |
Obj = #muc_online_room{name_host = {Room, MucHost}, |
48 |
|
host_type = HostType, pid = Pid}, |
49 |
197 |
F = fun() -> mnesia:delete_object(Obj) end, |
50 |
197 |
{atomic, ok} = mnesia:transaction(F), |
51 |
197 |
ok. |
52 |
|
|
53 |
|
simple_transaction_result({atomic, Res}) -> |
54 |
250 |
Res; |
55 |
|
simple_transaction_result({aborted, Reason}) -> |
56 |
:-( |
{error, Reason}. |
57 |
|
|
58 |
|
-spec find_room_pid(mongooseim:host_type(), jid:server(), mod_muc:room()) -> |
59 |
|
{ok, pid()} | {error, not_found}. |
60 |
|
find_room_pid(_HostType, MucHost, Room) -> |
61 |
1032 |
case mnesia:dirty_read(muc_online_room, {Room, MucHost}) of |
62 |
|
[R] -> |
63 |
969 |
{ok, R#muc_online_room.pid}; |
64 |
|
[] -> |
65 |
63 |
{error, not_found} |
66 |
|
end. |
67 |
|
|
68 |
|
-spec get_online_rooms(mongooseim:host_type(), jid:lserver()) -> |
69 |
|
[mod_muc:muc_online_room()]. |
70 |
|
get_online_rooms(_HostType, MucHost) -> |
71 |
37 |
mnesia:dirty_select(muc_online_room, |
72 |
|
[{#muc_online_room{name_host = '$1', _ = '_'}, |
73 |
|
[{'==', {element, 2, '$1'}, MucHost}], |
74 |
|
['$_']}]). |
75 |
|
|
76 |
|
-spec node_cleanup(mongooseim:host_type(), node()) -> ok. |
77 |
|
node_cleanup(HostType, Node) -> |
78 |
:-( |
F = fun() -> |
79 |
:-( |
Es = mnesia:select( |
80 |
|
muc_online_room, |
81 |
|
[{#muc_online_room{pid = '$1', |
82 |
|
host_type = HostType, |
83 |
|
_ = '_'}, |
84 |
|
[{'==', {node, '$1'}, Node}], |
85 |
|
['$_']}]), |
86 |
:-( |
lists:foreach(fun(E) -> |
87 |
:-( |
mnesia:delete_object(E) |
88 |
|
end, Es) |
89 |
|
end, |
90 |
:-( |
mnesia:async_dirty(F), |
91 |
:-( |
ok. |
92 |
|
|
93 |
|
%% Clear table for tests |
94 |
|
-spec clear_table(mongooseim:host_type()) -> ok. |
95 |
|
clear_table(_HostType) -> |
96 |
9 |
mnesia:clear_table(muc_online_room), |
97 |
9 |
ok. |