aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Chmielowski <pchmielowski@process-one.net>2021-03-03 11:30:43 +0100
committerPaweł Chmielowski <pchmielowski@process-one.net>2021-03-03 11:32:05 +0100
commitca5d5f3b4caf64be6de272e33617364c32465e6d (patch)
treebf86d9d7ef2bc3f70b4d3afd137575b63e861972
parentMerge pull request #3507 from slezakattack/master (diff)
Use monitors to track muc rooms
This should prevent keeping rooms that were hard killed from in online table.
Diffstat (limited to '')
-rw-r--r--src/mod_muc.erl67
-rw-r--r--src/mod_muc_admin.erl52
-rw-r--r--src/mod_muc_mnesia.erl16
-rw-r--r--src/mod_muc_room.erl4
-rw-r--r--src/mod_muc_sql.erl18
5 files changed, 94 insertions, 63 deletions
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index b256c726d..80fb7d9e3 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -42,6 +42,7 @@
store_room/5,
restore_room/3,
forget_room/3,
+ create_room/3,
create_room/5,
shutdown_rooms/1,
process_disco_info/1,
@@ -99,6 +100,7 @@
-callback register_online_room(binary(), binary(), binary(), pid()) -> any().
-callback unregister_online_room(binary(), binary(), binary(), pid()) -> any().
-callback find_online_room(binary(), binary(), binary()) -> {ok, pid()} | error.
+-callback find_online_room_by_pid(binary(), pid()) -> {ok, binary(), binary()} | error.
-callback get_online_rooms(binary(), binary(), undefined | rsm_set()) -> [{binary(), binary(), pid()}].
-callback count_online_rooms(binary(), binary()) -> non_neg_integer().
-callback rsm_supported() -> boolean().
@@ -295,6 +297,14 @@ create_room(Host, Name, From, Nick, Opts) ->
Proc = procname(ServerHost, {Name, Host}),
?GEN_SERVER:call(Proc, {create, Name, Host, From, Nick, Opts}).
+%% @doc Create a room.
+%% If Opts = default, the default room options are used.
+%% Else use the passed options as defined in mod_muc_room.
+create_room(Host, Name, Opts) ->
+ ServerHost = ejabberd_router:host_of_route(Host),
+ Proc = procname(ServerHost, {Name, Host}),
+ ?GEN_SERVER:call(Proc, {create, Name, Host, Opts}).
+
store_room(ServerHost, Host, Name, Opts) ->
store_room(ServerHost, Host, Name, Opts, undefined).
@@ -379,6 +389,25 @@ init([Host, Worker]) ->
{stop, normal, ok, state()}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
+handle_call({unhibernate, Room, Host}, _From,
+ #{server_host := ServerHost} = State) ->
+ RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
+ {reply, load_room(RMod, Host, ServerHost, Room), State};
+handle_call({create, Room, Host, Opts}, _From,
+ #{server_host := ServerHost} = State) ->
+ ?DEBUG("MUC: create new room '~ts'~n", [Room]),
+ NewOpts = case Opts of
+ default -> mod_muc_opt:default_room_options(ServerHost);
+ _ -> Opts
+ end,
+ RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
+ case start_room(RMod, Host, ServerHost, Room, NewOpts) of
+ {ok, _} ->
+ ejabberd_hooks:run(create_room, ServerHost, [ServerHost, Room, Host]),
+ {reply, ok, State};
+ Err ->
+ {reply, Err, State}
+ end;
handle_call({create, Room, Host, From, Nick, Opts}, _From,
#{server_host := ServerHost} = State) ->
?DEBUG("MUC: create new room '~ts'~n", [Room]),
@@ -437,6 +466,15 @@ handle_info({route, Packet}, #{server_host := ServerHost} = State) ->
handle_info({room_destroyed, {Room, Host}, Pid}, State) ->
%% For backward compat
handle_cast({room_destroyed, {Room, Host}, Pid}, State);
+handle_info({'DOWN', _Ref, process, Pid, _Reason},
+ #{server_host := ServerHost} = State) ->
+ RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
+ case RMod:find_online_room_by_pid(ServerHost, Pid) of
+ {ok, Room, Host} ->
+ handle_cast({room_destroyed, {Room, Host}, Pid}, State);
+ _ ->
+ {noreply, State}
+ end;
handle_info(Info, State) ->
?ERROR_MSG("Unexpected info: ~p", [Info]),
{noreply, State}.
@@ -531,7 +569,8 @@ unhibernate_room(ServerHost, Host, Room) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
case RMod:find_online_room(ServerHost, Room, Host) of
error ->
- case load_room(RMod, Host, ServerHost, Room) of
+ Proc = procname(ServerHost, {Room, Host}),
+ case ?GEN_SERVER:call(Proc, {unhibernate, Room, Host}) of
{ok, _} = R -> R;
_ -> error
end;
@@ -791,27 +830,15 @@ get_rooms(ServerHost, Host) ->
load_permanent_rooms(Hosts, ServerHost, Opts) ->
case mod_muc_opt:preload_rooms(Opts) of
true ->
- Access = get_access(Opts),
- HistorySize = mod_muc_opt:history_size(Opts),
- QueueType = mod_muc_opt:queue_type(Opts),
- RoomShaper = mod_muc_opt:room_shaper(Opts),
- RMod = gen_mod:ram_db_mod(Opts, ?MODULE),
lists:foreach(
- fun(Host) ->
- ?DEBUG("Loading rooms at ~ts", [Host]),
- lists:foreach(
+ fun(Host) ->
+ ?DEBUG("Loading rooms at ~ts", [Host]),
+ lists:foreach(
fun(R) ->
- {Room, _} = R#muc_room.name_host,
- case RMod:find_online_room(ServerHost, Room, Host) of
- error ->
- start_room(RMod, Host, ServerHost, Access,
- Room, HistorySize, RoomShaper,
- R#muc_room.opts, QueueType);
- {ok, _} ->
- ok
- end
+ {Room, _} = R#muc_room.name_host,
+ unhibernate_room(ServerHost, Host, Room)
end, get_rooms(ServerHost, Host))
- end, Hosts);
+ end, Hosts);
false ->
ok
end.
@@ -877,6 +904,7 @@ start_room(Mod, Host, ServerHost, Access, Room,
case mod_muc_room:start(Host, ServerHost, Access, Room,
HistorySize, RoomShaper, DefOpts, QueueType) of
{ok, Pid} ->
+ erlang:monitor(process, Pid),
Mod:register_online_room(ServerHost, Room, Host, Pid),
{ok, Pid};
Err ->
@@ -889,6 +917,7 @@ start_room(Mod, Host, ServerHost, Access, Room, HistorySize,
HistorySize, RoomShaper,
Creator, Nick, DefOpts, QueueType) of
{ok, Pid} ->
+ erlang:monitor(process, Pid),
Mod:register_online_room(ServerHost, Room, Host, Pid),
{ok, Pid};
Err ->
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 939a1d206..9d3d4e765 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -653,47 +653,21 @@ create_room_with_opts(Name1, Host1, ServerHost1, CustomRoomOpts) ->
{_, _, error} ->
throw({error, "Invalid 'serverhost'"});
{Name, Host, ServerHost} ->
- %% Get the default room options from the muc configuration
- DefRoomOpts = mod_muc_opt:default_room_options(ServerHost),
- %% Change default room options as required
- FormattedRoomOpts = [format_room_option(Opt, Val) || {Opt, Val}<-CustomRoomOpts],
- RoomOpts = lists:ukeymerge(1,
- lists:keysort(1, FormattedRoomOpts),
- lists:keysort(1, DefRoomOpts)),
-
-
- %% Get all remaining mod_muc parameters that might be utilized
- Access = mod_muc_opt:access(ServerHost),
- AcCreate = mod_muc_opt:access_create(ServerHost),
- AcAdmin = mod_muc_opt:access_admin(ServerHost),
- AcPer = mod_muc_opt:access_persistent(ServerHost),
- AcMam = mod_muc_opt:access_mam(ServerHost),
- HistorySize = mod_muc_opt:history_size(ServerHost),
- RoomShaper = mod_muc_opt:room_shaper(ServerHost),
- QueueType = mod_muc_opt:queue_type(ServerHost),
-
- %% If the room does not exist yet in the muc_online_room
case get_room_pid(Name, Host) of
room_not_found ->
- %% Store the room on the server, it is not started yet though at this point
- case lists:keyfind(persistent, 1, RoomOpts) of
- {persistent, true} ->
- mod_muc:store_room(ServerHost, Host, Name, RoomOpts);
- _ ->
- ok
- end,
- %% Start the room
- {ok, Pid} = mod_muc_room:start(
- Host,
- ServerHost,
- {Access, AcCreate, AcAdmin, AcPer, AcMam},
- Name,
- HistorySize,
- RoomShaper,
- RoomOpts,
- QueueType),
- mod_muc:register_online_room(Name, Host, Pid),
- ok;
+ %% Get the default room options from the muc configuration
+ DefRoomOpts = mod_muc_opt:default_room_options(ServerHost),
+ %% Change default room options as required
+ FormattedRoomOpts = [format_room_option(Opt, Val) || {Opt, Val}<-CustomRoomOpts],
+ RoomOpts = lists:ukeymerge(1,
+ lists:keysort(1, FormattedRoomOpts),
+ lists:keysort(1, DefRoomOpts)),
+ case mod_muc:create_room(Host, Name, RoomOpts) of
+ ok ->
+ ok;
+ {error, _} ->
+ throw({error, "Unable to start room"})
+ end;
_ ->
throw({error, "Room already exists"})
end
diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl
index 8d64df714..c822acc68 100644
--- a/src/mod_muc_mnesia.erl
+++ b/src/mod_muc_mnesia.erl
@@ -33,7 +33,8 @@
-export([register_online_room/4, unregister_online_room/4, find_online_room/3,
get_online_rooms/3, count_online_rooms/2, rsm_supported/0,
register_online_user/4, unregister_online_user/4,
- count_online_rooms_by_user/3, get_online_rooms_by_user/3]).
+ count_online_rooms_by_user/3, get_online_rooms_by_user/3,
+ find_online_room_by_pid/2]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
%% gen_server callbacks
@@ -181,6 +182,19 @@ find_online_room(Room, Host) ->
[#muc_online_room{pid = Pid}] -> {ok, Pid}
end.
+find_online_room_by_pid(_ServerHost, Pid) ->
+ Res =
+ mnesia:dirty_select(
+ muc_online_room,
+ ets:fun2ms(
+ fun(#muc_online_room{name_host = {Name, Host}, pid = PidS})
+ when PidS == Pid -> {Name, Host}
+ end)),
+ case Res of
+ [{Name, Host}] -> {ok, Name, Host};
+ _ -> error
+ end.
+
count_online_rooms(_ServerHost, Host) ->
ets:select_count(
muc_online_room,
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index 3e06e2846..50ad9dd1a 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -913,11 +913,9 @@ terminate(Reason, _StateName,
_ ->
ok
end
- end,
- mod_muc:room_destroyed(Host, Room, self(), LServer)
+ end
catch ?EX_RULE(E, R, St) ->
StackTrace = ?EX_STACK(St),
- mod_muc:room_destroyed(Host, Room, self(), LServer),
?ERROR_MSG("Got exception on room termination:~n** ~ts",
[misc:format_exception(2, E, R, StackTrace)])
end.
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl
index c91154921..569cfac49 100644
--- a/src/mod_muc_sql.erl
+++ b/src/mod_muc_sql.erl
@@ -36,7 +36,8 @@
get_online_rooms/3, count_online_rooms/2, rsm_supported/0,
register_online_user/4, unregister_online_user/4,
count_online_rooms_by_user/3, get_online_rooms_by_user/3,
- get_subscribed_rooms/3, get_rooms_without_subscribers/2]).
+ get_subscribed_rooms/3, get_rooms_without_subscribers/2,
+ find_online_room_by_pid/2]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
@@ -306,6 +307,21 @@ find_online_room(ServerHost, Room, Host) ->
error
end.
+find_online_room_by_pid(ServerHost, Pid) ->
+ PidS = misc:encode_pid(Pid),
+ NodeS = erlang:atom_to_binary(node(Pid), latin1),
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(name)s, @(host)s from muc_online_room where "
+ "node=%(NodeS)s and pid=%(PidS)s")) of
+ {selected, [{Room, Host}]} ->
+ {ok, Room, Host};
+ {selected, []} ->
+ error;
+ _Err ->
+ error
+ end.
+
count_online_rooms(ServerHost, Host) ->
case ejabberd_sql:sql_query(
ServerHost,