aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sql/lite.new.sql1
-rw-r--r--sql/lite.sql1
-rw-r--r--sql/mssql.sql34
-rw-r--r--sql/mysql.new.sql1
-rw-r--r--sql/mysql.sql1
-rw-r--r--sql/pg.new.sql1
-rw-r--r--sql/pg.sql1
-rw-r--r--src/mod_muc.erl32
-rw-r--r--src/mod_muc_admin.erl17
-rw-r--r--src/mod_muc_room.erl18
-rw-r--r--src/mod_muc_sql.erl34
11 files changed, 99 insertions, 42 deletions
diff --git a/sql/lite.new.sql b/sql/lite.new.sql
index febef6247..f4b73dcb2 100644
--- a/sql/lite.new.sql
+++ b/sql/lite.new.sql
@@ -285,6 +285,7 @@ CREATE TABLE muc_room (
);
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host);
+CREATE INDEX i_muc_room_host_created_at ON muc_room USING btree (host, created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/sql/lite.sql b/sql/lite.sql
index 18ee5915a..b62295120 100644
--- a/sql/lite.sql
+++ b/sql/lite.sql
@@ -260,6 +260,7 @@ CREATE TABLE muc_room (
);
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host);
+CREATE INDEX i_muc_room_host_created_at ON muc_room USING btree (host, created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/sql/mssql.sql b/sql/mssql.sql
index 782e492ce..e05a7b51d 100644
--- a/sql/mssql.sql
+++ b/sql/mssql.sql
@@ -32,7 +32,7 @@ CREATE TABLE [dbo].[archive] (
[kind] [varchar] (10) NULL,
[nick] [varchar] (250) NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [archive_PK] PRIMARY KEY CLUSTERED
+ CONSTRAINT [archive_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -56,7 +56,7 @@ CREATE TABLE [dbo].[archive_prefs] (
[always] [text] NOT NULL,
[never] [text] NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [archive_prefs_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [archive_prefs_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -76,7 +76,7 @@ CREATE TABLE [dbo].[last] (
[username] [varchar] (250) NOT NULL,
[seconds] [text] NOT NULL,
[state] [text] NOT NULL,
- CONSTRAINT [last_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [last_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -86,7 +86,7 @@ CREATE TABLE [dbo].[motd] (
[username] [varchar] (250) NOT NULL,
[xml] [text] NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [motd_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [motd_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -114,6 +114,8 @@ CREATE TABLE [dbo].[muc_room] (
CREATE UNIQUE CLUSTERED INDEX [muc_room_name_host] ON [muc_room] (name, host)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
+CREATE INDEX [muc_room_host_created_at] ON [muc_registered] (host, nick)
+ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
CREATE TABLE [dbo].[muc_online_room] (
[name] [varchar] (250) NOT NULL,
@@ -155,7 +157,7 @@ CREATE INDEX [muc_room_subscribers_jid] ON [muc_room_subscribers] (jid);
CREATE TABLE [dbo].[privacy_default_list] (
[username] [varchar] (250) NOT NULL,
[name] [varchar] (250) NOT NULL,
- CONSTRAINT [privacy_default_list_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [privacy_default_list_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -166,7 +168,7 @@ CREATE TABLE [dbo].[privacy_list] (
[name] [varchar] (250) NOT NULL,
[id] [bigint] IDENTITY(1,1) NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [privacy_list_PK] PRIMARY KEY CLUSTERED
+ CONSTRAINT [privacy_list_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -245,7 +247,7 @@ CREATE TABLE [dbo].[pubsub_state] (
[affiliation] [char] (1) NOT NULL,
[subscriptions] [text] NOT NULL DEFAULT '',
[stateid] [bigint] IDENTITY(1,1) NOT NULL,
- CONSTRAINT [pubsub_state_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [pubsub_state_PRIMARY] PRIMARY KEY CLUSTERED
(
[stateid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -272,7 +274,7 @@ CREATE TABLE [dbo].[pubsub_node] (
[parent] [varchar] (255) NOT NULL DEFAULT '',
[plugin] [text] NOT NULL,
[nodeid] [bigint] IDENTITY(1,1) NOT NULL,
- CONSTRAINT [pubsub_node_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [pubsub_node_PRIMARY] PRIMARY KEY CLUSTERED
(
[nodeid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -287,7 +289,7 @@ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW
CREATE TABLE [dbo].[roster_version] (
[username] [varchar] (250) NOT NULL,
[version] [text] NOT NULL,
- CONSTRAINT [roster_version_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [roster_version_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -348,7 +350,7 @@ CREATE TABLE [dbo].[spool] (
[xml] [text] NOT NULL,
[seq] [bigint] IDENTITY(1,1) NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [spool_PK] PRIMARY KEY CLUSTERED
+ CONSTRAINT [spool_PK] PRIMARY KEY CLUSTERED
(
[seq] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -365,7 +367,7 @@ CREATE TABLE [dbo].[sr_group] (
[name] [varchar] (250) NOT NULL,
[opts] [text] NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [sr_group_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [sr_group_PRIMARY] PRIMARY KEY CLUSTERED
(
[name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -393,7 +395,7 @@ CREATE TABLE [dbo].[users] (
[salt] [text] NOT NULL DEFAULT '',
[iterationcount] [smallint] NOT NULL DEFAULT 0,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [users_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [users_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -403,7 +405,7 @@ CREATE TABLE [dbo].[vcard] (
[username] [varchar] (250) NOT NULL,
[vcard] [text] NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
- CONSTRAINT [vcard_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [vcard_PRIMARY] PRIMARY KEY CLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -434,7 +436,7 @@ CREATE TABLE [dbo].[vcard_search] (
[lorgname] [varchar] (250) NOT NULL,
[orgunit] [text] NOT NULL,
[lorgunit] [varchar] (250) NOT NULL,
- CONSTRAINT [vcard_search_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [vcard_search_PRIMARY] PRIMARY KEY CLUSTERED
(
[lusername] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -502,7 +504,7 @@ CREATE TABLE [dbo].[oauth_token] (
[jid] [text] NOT NULL,
[scope] [text] NOT NULL,
[expire] [bigint] NOT NULL,
- CONSTRAINT [oauth_token_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [oauth_token_PRIMARY] PRIMARY KEY CLUSTERED
(
[token] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
@@ -526,7 +528,7 @@ CREATE TABLE [dbo].[bosh] (
[sid] [varchar] (255) NOT NULL,
[node] [varchar] (255) NOT NULL,
[pid] [varchar](100) NOT NULL
- CONSTRAINT [bosh_PRIMARY] PRIMARY KEY CLUSTERED
+ CONSTRAINT [bosh_PRIMARY] PRIMARY KEY CLUSTERED
(
[sid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
diff --git a/sql/mysql.new.sql b/sql/mysql.new.sql
index a5d03c8c7..dc514becf 100644
--- a/sql/mysql.new.sql
+++ b/sql/mysql.new.sql
@@ -301,6 +301,7 @@ CREATE TABLE muc_room (
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE UNIQUE INDEX i_muc_room_name_host USING BTREE ON muc_room(name(75), host(75));
+CREATE INDEX i_muc_room_host_created_at ON muc_room(host(75), created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/sql/mysql.sql b/sql/mysql.sql
index c4ae52de7..ae4a73312 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -276,6 +276,7 @@ CREATE TABLE muc_room (
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE UNIQUE INDEX i_muc_room_name_host USING BTREE ON muc_room(name(75), host(75));
+CREATE INDEX i_muc_room_host_created_at ON muc_room(host(75), created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/sql/pg.new.sql b/sql/pg.new.sql
index c7d22c66a..b69e6ddfa 100644
--- a/sql/pg.new.sql
+++ b/sql/pg.new.sql
@@ -450,6 +450,7 @@ CREATE TABLE muc_room (
);
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room USING btree (name, host);
+CREATE INDEX i_muc_room_host_created_at ON muc_room USING btree (host, created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/sql/pg.sql b/sql/pg.sql
index 44bea2e03..4cf4f0cbd 100644
--- a/sql/pg.sql
+++ b/sql/pg.sql
@@ -278,6 +278,7 @@ CREATE TABLE muc_room (
);
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room USING btree (name, host);
+CREATE INDEX i_muc_room_host_created_at ON muc_room USING btree (host, created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 6e69987dc..ec55e3c14 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -402,10 +402,10 @@ init([Host, Worker]) ->
{stop, normal, ok, state()}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
-handle_call({unhibernate, Room, Host}, _From,
+handle_call({unhibernate, Room, Host, ResetHibernationTime}, _From,
#{server_host := ServerHost} = State) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- {reply, load_room(RMod, Host, ServerHost, Room), State};
+ {reply, load_room(RMod, Host, ServerHost, Room, ResetHibernationTime), State};
handle_call({create, Room, Host, Opts}, _From,
#{server_host := ServerHost} = State) ->
?DEBUG("MUC: create new room '~ts'~n", [Room]),
@@ -579,11 +579,15 @@ extract_password(#iq{} = IQ) ->
-spec unhibernate_room(binary(), binary(), binary()) -> {ok, pid()} | error.
unhibernate_room(ServerHost, Host, Room) ->
+ unhibernate_room(ServerHost, Host, Room, true).
+
+-spec unhibernate_room(binary(), binary(), binary(), boolean()) -> {ok, pid()} | error.
+unhibernate_room(ServerHost, Host, Room, ResetHibernationTime) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
case RMod:find_online_room(ServerHost, Room, Host) of
error ->
Proc = procname(ServerHost, {Room, Host}),
- case ?GEN_SERVER:call(Proc, {unhibernate, Room, Host}, 20000) of
+ case ?GEN_SERVER:call(Proc, {unhibernate, Room, Host, ResetHibernationTime}, 20000) of
{ok, _} = R -> R;
_ -> error
end;
@@ -605,7 +609,7 @@ route_to_room(Packet, ServerHost) ->
Err = xmpp:err_item_not_found(ErrText, Lang),
ejabberd_router:route_error(Packet, Err);
StartType ->
- case load_room(RMod, Host, ServerHost, Room) of
+ case load_room(RMod, Host, ServerHost, Room, true) of
{error, notfound} when StartType == start ->
case check_create_room(ServerHost, Host, Room, From) of
true ->
@@ -849,28 +853,36 @@ load_permanent_rooms(Hosts, ServerHost, Opts) ->
lists:foreach(
fun(R) ->
{Room, _} = R#muc_room.name_host,
- unhibernate_room(ServerHost, Host, Room)
+ unhibernate_room(ServerHost, Host, Room, false)
end, get_rooms(ServerHost, Host))
end, Hosts);
false ->
ok
end.
--spec load_room(module(), binary(), binary(), binary()) -> {ok, pid()} |
- {error, notfound | term()}.
-load_room(RMod, Host, ServerHost, Room) ->
+-spec load_room(module(), binary(), binary(), binary(), boolean()) ->
+ {ok, pid()} | {error, notfound | term()}.
+load_room(RMod, Host, ServerHost, Room, ResetHibernationTime) ->
case restore_room(ServerHost, Host, Room) of
error ->
{error, notfound};
Opts0 ->
+ Mod = gen_mod:db_mod(ServerHost, mod_muc),
case proplists:get_bool(persistent, Opts0) of
true ->
?DEBUG("Restore room: ~ts", [Room]),
- start_room(RMod, Host, ServerHost, Room, Opts0);
+ Res2 = start_room(RMod, Host, ServerHost, Room, Opts0),
+ case {Res2, ResetHibernationTime} of
+ {{ok, _}, true} ->
+ NewOpts = lists:keyreplace(hibernation_time, 1, Opts0, {hibernation_time, undefined}),
+ store_room(ServerHost, Host, Room, NewOpts, []);
+ _ ->
+ ok
+ end,
+ Res2;
_ ->
?DEBUG("Restore hibernated non-persistent room: ~ts", [Room]),
Res = start_room(RMod, Host, ServerHost, Room, Opts0),
- Mod = gen_mod:db_mod(ServerHost, mod_muc),
case erlang:function_exported(Mod, get_subscribed_rooms, 3) of
true ->
ok;
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 2db1d95f1..434559001 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -858,7 +858,7 @@ rooms_report(Method, Action, Service, Days) ->
muc_unused(Method, Action, Service, Last_allowed) ->
%% Get all required info about all existing rooms
- Rooms_all = get_all_rooms(Service),
+ Rooms_all = get_all_rooms(Service, erlang:system_time(microsecond) - Last_allowed*24*60*60*1000),
%% Decide which ones pass the requirements
Rooms_pass = decide_rooms(Method, Rooms_all, Last_allowed),
@@ -883,14 +883,14 @@ get_online_rooms(ServiceArg) ->
|| {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)]
end, Hosts).
-get_all_rooms(ServiceArg) ->
+get_all_rooms(ServiceArg, Timestamp) ->
Hosts = find_services(ServiceArg),
lists:flatmap(
fun(Host) ->
- get_all_rooms2(Host)
+ get_all_rooms2(Host, Timestamp)
end, Hosts).
-get_all_rooms2(Host) ->
+get_all_rooms2(Host, Timestamp) ->
ServerHost = ejabberd_router:host_of_route(Host),
OnlineRooms = get_online_rooms(Host),
OnlineMap = lists:foldl(
@@ -900,8 +900,11 @@ get_all_rooms2(Host) ->
Mod = gen_mod:db_mod(ServerHost, mod_muc),
DbRooms =
- case erlang:function_exported(Mod, get_rooms_without_subscribers, 2) of
- true ->
+ case {erlang:function_exported(Mod, get_rooms_without_subscribers, 2),
+ erlang:function_exported(Mod, get_hibernated_rooms_older_than, 3)} of
+ {_, true} ->
+ Mod:get_hibernated_rooms_older_than(ServerHost, Host, Timestamp);
+ {true, _} ->
Mod:get_rooms_without_subscribers(ServerHost, Host);
_ ->
Mod:get_rooms(ServerHost, Host)
@@ -956,6 +959,8 @@ decide_room(unused, {_Room_name, _Host, ServerHost, Room_pid}, Last_allowed) ->
case lists:keyfind(hibernation_time, 1, Opts) of
false ->
{NodeStartTime, 0};
+ {_, undefined} ->
+ {NodeStartTime, 0};
{_, T} ->
{T, 0}
end
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index 6e65574ce..3e3c0cfed 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -644,7 +644,7 @@ normal_state({route, ToNick,
normal_state(hibernate, StateData) ->
case maps:size(StateData#state.users) of
0 ->
- store_room_no_checks(StateData, []),
+ store_room_no_checks(StateData, [], erlang:system_time(microsecond)),
?INFO_MSG("Hibernating room ~ts@~ts", [StateData#state.room, StateData#state.host]),
{stop, normal, StateData#state{hibernate_timer = hibernating}};
_ ->
@@ -3997,8 +3997,8 @@ set_vcard_xupdate(State) ->
-define(MAKE_CONFIG_OPT(Opt),
{get_config_opt_name(Opt), element(Opt, Config)}).
--spec make_opts(state()) -> [{atom(), any()}].
-make_opts(StateData) ->
+-spec make_opts(state(), integer | undefined) -> [{atom(), any()}].
+make_opts(StateData, HibernationTime) ->
Config = StateData#state.config,
Subscribers = muc_subscribers_fold(
fun(_LJID, Sub, Acc) ->
@@ -4042,7 +4042,7 @@ make_opts(StateData) ->
{hats_users,
lists:map(fun({U, H}) -> {U, maps:to_list(H)} end,
maps:to_list(StateData#state.hats_users))},
- {hibernation_time, erlang:system_time(microsecond)},
+ {hibernation_time, HibernationTime},
{subscribers, Subscribers}].
expand_opts(CompactOpts) ->
@@ -5004,13 +5004,13 @@ add_to_log(Type, Data, StateData)
when Type == roomconfig_change_disabledlogging ->
mod_muc_log:add_to_log(StateData#state.server_host,
roomconfig_change, Data, StateData#state.jid,
- make_opts(StateData));
+ make_opts(StateData, undefined));
add_to_log(Type, Data, StateData) ->
case (StateData#state.config)#config.logging of
true ->
mod_muc_log:add_to_log(StateData#state.server_host,
Type, Data, StateData#state.jid,
- make_opts(StateData));
+ make_opts(StateData, undefined));
false -> ok
end.
@@ -5075,16 +5075,16 @@ store_room(StateData, ChangesHints) ->
StateData#state.host, StateData#state.room,
ChangesHints);
_ ->
- store_room_no_checks(StateData, ChangesHints)
+ store_room_no_checks(StateData, ChangesHints, undefined)
end;
true ->
ok
end.
-store_room_no_checks(StateData, ChangesHints) ->
+store_room_no_checks(StateData, ChangesHints, HibernationTime) ->
mod_muc:store_room(StateData#state.server_host,
StateData#state.host, StateData#state.room,
- make_opts(StateData),
+ make_opts(StateData, HibernationTime),
ChangesHints).
-spec send_subscriptions_change_notifications(jid(), binary(), subscribe|unsubscribe, state()) -> ok.
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl
index 03022e924..db829f6aa 100644
--- a/src/mod_muc_sql.erl
+++ b/src/mod_muc_sql.erl
@@ -38,6 +38,7 @@
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_hibernated_rooms_older_than/3,
find_online_room_by_pid/2, remove_user/2]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
@@ -64,13 +65,19 @@ store_room(LServer, Host, Name, Opts, ChangesHints) ->
_ -> {[], Opts}
end,
SOpts = misc:term_to_expr(Opts2),
+ Timestamp = case lists:keyfind(hibernation_time, 1, Opts) of
+ false -> <<"1900-01-01 00:00:00">>;
+ {_, undefined} -> <<"1900-01-01 00:00:00">>;
+ {_, Time} -> usec_to_sql_timestamp(Time)
+ end,
F = fun () ->
?SQL_UPSERT_T(
"muc_room",
["!name=%(Name)s",
"!host=%(Host)s",
"server_host=%(LServer)s",
- "opts=%(SOpts)s"]),
+ "opts=%(SOpts)s",
+ "created_at=%(Timestamp)s"]),
case ChangesHints of
Changes when is_list(Changes) ->
[change_room(Host, Name, Change) || Change <- Changes];
@@ -179,6 +186,23 @@ get_rooms_without_subscribers(LServer, Host) ->
[]
end.
+get_hibernated_rooms_older_than(LServer, Host, Timestamp) ->
+ TimestampS = usec_to_sql_timestamp(Timestamp),
+ case catch ejabberd_sql:sql_query(
+ LServer,
+ ?SQL("select @(name)s, @(opts)s from muc_room"
+ " where host=%(Host)s and created_at < %(TimestampS)s and created_at > '1900-01-01 00:00:00'")) of
+ {selected, RoomOpts} ->
+ lists:map(
+ fun({Room, Opts}) ->
+ OptsD = ejabberd_sql:decode_term(Opts),
+ #muc_room{name_host = {Room, Host},
+ opts = mod_muc:opts_to_binary(OptsD)}
+ end, RoomOpts);
+ _Err ->
+ []
+ end.
+
get_rooms(LServer, Host) ->
case catch ejabberd_sql:sql_query(
LServer,
@@ -497,3 +521,11 @@ clean_tables(ServerHost) ->
?ERROR_MSG("Failed to clean 'muc_online_users' table: ~p", [Err2]),
Err2
end.
+
+usec_to_sql_timestamp(Timestamp) ->
+ case calendar:system_time_to_universal_time(Timestamp, microsecond) of
+ {{Year, Month, Day}, {Hour, Minute, Second}} ->
+ list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0B "
+ "~2..0B:~2..0B:~2..0B",
+ [Year, Month, Day, Hour, Minute, Second]))
+ end.