mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Use monitors to track muc rooms
This should prevent keeping rooms that were hard killed from in online table.
This commit is contained in:
parent
7209486386
commit
ca5d5f3b4c
@ -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 ->
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user