25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Allow room_unused_list/destroy work on hibernated rooms

This required adding hibernation time to data stored for room to be able
determine how old was a room, rooms that aren't stored with that
information will use node start time as timestamp for that.
This commit is contained in:
Paweł Chmielowski 2020-11-16 15:25:01 +01:00
parent ff98cb4e15
commit 2e8023158d
2 changed files with 56 additions and 19 deletions

View File

@ -520,7 +520,7 @@ get_sort_query2(Q) ->
make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) -> make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) ->
Service = find_service(Host), Service = find_service(Host),
Rooms_names = get_rooms(Service), Rooms_names = get_online_rooms(Service),
Rooms_infos = build_info_rooms(Rooms_names), Rooms_infos = build_info_rooms(Rooms_names),
Rooms_sorted = sort_rooms(Sort_direction, Sort_column, Rooms_infos), Rooms_sorted = sort_rooms(Sort_direction, Sort_column, Rooms_infos),
Rooms_prepared = prepare_rooms_infos(Rooms_sorted), Rooms_prepared = prepare_rooms_infos(Rooms_sorted),
@ -811,7 +811,7 @@ rooms_report(Method, Action, Service, Days) ->
muc_unused(Method, Action, Service, Last_allowed) -> muc_unused(Method, Action, Service, Last_allowed) ->
%% Get all required info about all existing rooms %% Get all required info about all existing rooms
Rooms_all = get_rooms(Service), Rooms_all = get_all_rooms(Service),
%% Decide which ones pass the requirements %% Decide which ones pass the requirements
Rooms_pass = decide_rooms(Method, Rooms_all, Last_allowed), Rooms_pass = decide_rooms(Method, Rooms_all, Last_allowed),
@ -827,14 +827,35 @@ muc_unused(Method, Action, Service, Last_allowed) ->
%%--------------- %%---------------
%% Get info %% Get info
get_rooms(ServiceArg) -> get_online_rooms(ServiceArg) ->
Hosts = find_services(ServiceArg), Hosts = find_services(ServiceArg),
lists:flatmap( lists:flatmap(
fun(Host) -> fun(Host) ->
[{RoomName, RoomHost, ejabberd_router:host_of_route(Host), Pid} ServerHost = get_room_serverhost(Host),
[{RoomName, RoomHost, ServerHost, Pid}
|| {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)] || {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)]
end, Hosts). end, Hosts).
get_all_rooms(Host) ->
ServerHost = ejabberd_router:host_of_route(Host),
OnlineRooms = get_online_rooms(Host),
OnlineMap = lists:foldl(
fun({Room, _, _, _}, Map) ->
Map#{Room => 1}
end, #{}, OnlineRooms),
Mod = gen_mod:db_mod(ServerHost, mod_muc),
StoredRooms = lists:filtermap(
fun(#muc_room{name_host = {Room, _}, opts = Opts}) ->
case maps:is_key(Room, OnlineMap) of
true ->
false;
_ ->
{true, {Room, Host, ServerHost, Opts}}
end
end, Mod:get_rooms(ServerHost, Host)),
OnlineRooms ++ StoredRooms.
get_room_config(Room_pid) -> get_room_config(Room_pid) ->
{ok, R} = mod_muc_room:get_config(Room_pid), {ok, R} = mod_muc_room:get_config(Room_pid),
R. R.
@ -851,16 +872,24 @@ decide_rooms(Method, Rooms, Last_allowed) ->
lists:filter(Decide, Rooms). lists:filter(Decide, Rooms).
decide_room(unused, {_Room_name, _Host, ServerHost, Room_pid}, Last_allowed) -> decide_room(unused, {_Room_name, _Host, ServerHost, Room_pid}, Last_allowed) ->
NodeStartTime = erlang:system_time(microsecond) -
1000000*(erlang:monotonic_time(second)-ejabberd_config:get_node_start()),
{Persistent, Just_created, Num_users, History} =
case Room_pid of
Pid when is_pid(Pid) ->
C = get_room_config(Room_pid), C = get_room_config(Room_pid),
Persistent = C#config.persistent,
S = get_room_state(Room_pid), S = get_room_state(Room_pid),
Just_created = S#state.just_created, {C#config.persistent, S#state.just_created,
maps:size(S#state.users),
Room_users = S#state.users, (S#state.history)#lqueue.queue};
Num_users = maps:size(Room_users), Opts ->
case {lists:keyfind(persistent, 1, Opts), lists:keyfind(hibernation_time, 1, Opts)} of
History = (S#state.history)#lqueue.queue, {{_, V}, false} ->
{V, NodeStartTime, 0, p1_queue:new()};
{{_, V}, {_, T}} ->
{V, T, 0, p1_queue:new()}
end
end,
Ts_now = calendar:universal_time(), Ts_now = calendar:universal_time(),
HistorySize = mod_muc_opt:history_size(ServerHost), HistorySize = mod_muc_opt:history_size(ServerHost),
{Has_hist, Last} = case p1_queue:is_empty(History) of {Has_hist, Last} = case p1_queue:is_empty(History) of
@ -886,10 +915,15 @@ decide_room(unused, {_Room_name, _Host, ServerHost, Room_pid}, Last_allowed) ->
_ -> _ ->
false false
end; end;
decide_room(empty, {Room_name, Host, ServerHost, _Room_pid}, _Last_allowed) -> decide_room(empty, {Room_name, Host, ServerHost, Room_pid}, _Last_allowed) ->
case gen_mod:is_loaded(ServerHost, mod_mam) of case gen_mod:is_loaded(ServerHost, mod_mam) of
true -> true ->
Room_options = get_room_options(Room_name, Host), Room_options = case Room_pid of
_ when is_pid(Room_pid) ->
get_room_options(Room_pid);
Opts ->
Opts
end,
case lists:keyfind(<<"mam">>, 1, Room_options) of case lists:keyfind(<<"mam">>, 1, Room_options) of
{<<"mam">>, <<"true">>} -> {<<"mam">>, <<"true">>} ->
mod_mam:is_empty_for_room(ServerHost, Room_name, Host); mod_mam:is_empty_for_room(ServerHost, Room_name, Host);

View File

@ -3951,6 +3951,7 @@ make_opts(StateData) ->
maps:to_list(StateData#state.affiliations)}, maps:to_list(StateData#state.affiliations)},
{subject, StateData#state.subject}, {subject, StateData#state.subject},
{subject_author, StateData#state.subject_author}, {subject_author, StateData#state.subject_author},
{hibernation_time, erlang:system_time(microsecond)},
{subscribers, Subscribers}]. {subscribers, Subscribers}].
expand_opts(CompactOpts) -> expand_opts(CompactOpts) ->
@ -3974,13 +3975,15 @@ expand_opts(CompactOpts) ->
SubjectAuthor = proplists:get_value(subject_author, CompactOpts, <<"">>), SubjectAuthor = proplists:get_value(subject_author, CompactOpts, <<"">>),
Subject = proplists:get_value(subject, CompactOpts, <<"">>), Subject = proplists:get_value(subject, CompactOpts, <<"">>),
Subscribers = proplists:get_value(subscribers, CompactOpts, []), Subscribers = proplists:get_value(subscribers, CompactOpts, []),
HibernationTime = proplists:get_value(hibernation_time, CompactOpts, 0),
[{subject, Subject}, [{subject, Subject},
{subject_author, SubjectAuthor}, {subject_author, SubjectAuthor},
{subscribers, Subscribers} {subscribers, Subscribers},
{hibernation_time, HibernationTime}
| lists:reverse(Opts1)]. | lists:reverse(Opts1)].
config_fields() -> config_fields() ->
[subject, subject_author, subscribers | record_info(fields, config)]. [subject, subject_author, subscribers, hibernate_time | record_info(fields, config)].
-spec destroy_room(muc_destroy(), state()) -> {result, undefined, stop}. -spec destroy_room(muc_destroy(), state()) -> {result, undefined, stop}.
destroy_room(DEl, StateData) -> destroy_room(DEl, StateData) ->