aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-03-29 12:58:01 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-03-29 12:58:01 +0300
commit12e01a51196a656955d79869a05ec3db1fc2f9bb (patch)
treefa10a2a65f65f1ec51faae466cdec594bb68375f
parentAdd Redis as mod_bosh RAM backend (diff)
Add SQL as mod_muc RAM backend
-rw-r--r--sql/lite.sql21
-rw-r--r--sql/mssql.sql24
-rw-r--r--sql/mysql.sql21
-rw-r--r--sql/pg.sql21
-rw-r--r--src/mod_muc.erl48
-rw-r--r--src/mod_muc_mnesia.erl35
-rw-r--r--src/mod_muc_riak.erl26
-rw-r--r--src/mod_muc_sql.erl193
-rw-r--r--test/ejabberd_SUITE_data/ejabberd.yml3
-rw-r--r--test/muc_tests.erl2
10 files changed, 316 insertions, 78 deletions
diff --git a/sql/lite.sql b/sql/lite.sql
index c17d80ec5..8b59ef0a1 100644
--- a/sql/lite.sql
+++ b/sql/lite.sql
@@ -275,6 +275,27 @@ CREATE TABLE muc_registered (
CREATE INDEX i_muc_registered_nick ON muc_registered (nick);
CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered (jid, host);
+CREATE TABLE muc_online_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host ON muc_online_room (name, host);
+
+CREATE TABLE muc_online_users (
+ username text NOT NULL,
+ server text NOT NULL,
+ resource text NOT NULL,
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_users ON muc_online_users (username, server, resource, name, host);
+CREATE INDEX i_muc_online_users_us ON muc_online_users (username, server);
+
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
diff --git a/sql/mssql.sql b/sql/mssql.sql
index 7535da5ac..59c192b98 100644
--- a/sql/mssql.sql
+++ b/sql/mssql.sql
@@ -125,6 +125,30 @@ 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 TABLE [dbo].[muc_online_room] (
+ [name] [varchar] (250) NOT NULL,
+ [host] [varchar] (250) NOT NULL,
+ [node] [text] NOT NULL,
+ [pid] [text] NOT NULL
+);
+
+CREATE UNIQUE CLUSTERED INDEX [muc_online_room_name_host] ON [muc_online_room] (name, host)
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
+
+CREATE TABLE [dbo].[muc_online_users] (
+ [username] [varchar] (250) NOT NULL,
+ [server] [varchar] (250) NOT NULL,
+ [resource] [varchar] (250) NOT NULL,
+ [name] [varchar] (250) NOT NULL,
+ [host] [varchar] (250) NOT NULL,
+ node text NOT NULL
+);
+
+CREATE UNIQUE CLUSTERED INDEX [muc_online_users_i] ON [muc_online_users] (username, server, resource, name, host)
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
+CREATE UNIQUE CLUSTERED INDEX [muc_online_users_us] ON [muc_online_users] (username, server);
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
+
CREATE TABLE [dbo].[privacy_default_list] (
[username] [varchar] (250) NOT NULL,
[name] [varchar] (250) NOT NULL,
diff --git a/sql/mysql.sql b/sql/mysql.sql
index 982df7ff5..edd205f0d 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -291,6 +291,27 @@ CREATE TABLE muc_registered (
CREATE INDEX i_muc_registered_nick USING BTREE ON muc_registered(nick(75));
CREATE UNIQUE INDEX i_muc_registered_jid_host USING BTREE ON muc_registered(jid(75), host(75));
+CREATE TABLE muc_online_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host USING BTREE ON muc_online_room(name(75), host(75));
+
+CREATE TABLE muc_online_users (
+ username text NOT NULL,
+ server text NOT NULL,
+ resource text NOT NULL,
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_muc_online_users USING BTREE ON muc_online_users(username(75), server(75), resource(75), name(75), host(75));
+CREATE INDEX i_muc_online_users_us USING BTREE ON muc_online_users(username(75), server(75));
+
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
diff --git a/sql/pg.sql b/sql/pg.sql
index 8a8b77b1f..6c099fc6b 100644
--- a/sql/pg.sql
+++ b/sql/pg.sql
@@ -293,6 +293,27 @@ CREATE TABLE muc_registered (
CREATE INDEX i_muc_registered_nick ON muc_registered USING btree (nick);
CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered USING btree (jid, host);
+CREATE TABLE muc_online_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host ON muc_online_room USING btree (name, host);
+
+CREATE TABLE muc_online_users (
+ username text NOT NULL,
+ server text NOT NULL,
+ resource text NOT NULL,
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_users ON muc_online_users USING btree (username, server, resource, name, host);
+CREATE INDEX i_muc_online_users_us ON muc_online_users USING btree (username, server);
+
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 8bb9c4b8c..9c8316e2e 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -94,16 +94,16 @@
-callback get_rooms(binary(), binary()) -> [#muc_room{}].
-callback get_nick(binary(), binary(), jid()) -> binary() | error.
-callback set_nick(binary(), binary(), jid(), binary()) -> {atomic, ok | false}.
--callback register_online_room(binary(), binary(), pid()) -> any().
--callback unregister_online_room(binary(), binary(), pid()) -> any().
--callback find_online_room(binary(), binary()) -> {ok, pid()} | error.
--callback get_online_rooms(binary(), undefined | rsm_set()) -> [{binary(), binary(), pid()}].
--callback count_online_rooms(binary()) -> non_neg_integer().
+-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 get_online_rooms(binary(), binary(), undefined | rsm_set()) -> [{binary(), binary(), pid()}].
+-callback count_online_rooms(binary(), binary()) -> non_neg_integer().
-callback rsm_supported() -> boolean().
--callback register_online_user(ljid(), binary(), binary()) -> any().
--callback unregister_online_user(ljid(), binary(), binary()) -> any().
--callback count_online_rooms_by_user(binary(), binary()) -> non_neg_integer().
--callback get_online_rooms_by_user(binary(), binary()) -> [{binary(), binary()}].
+-callback register_online_user(binary(), ljid(), binary(), binary()) -> any().
+-callback unregister_online_user(binary(), ljid(), binary(), binary()) -> any().
+-callback count_online_rooms_by_user(binary(), binary(), binary()) -> non_neg_integer().
+-callback get_online_rooms_by_user(binary(), binary(), binary()) -> [{binary(), binary()}].
%%====================================================================
%% API
@@ -127,7 +127,7 @@ shutdown_rooms(Host) ->
RMod = gen_mod:ram_db_mod(Host, ?MODULE),
MyHost = gen_mod:get_module_opt_host(Host, mod_muc,
<<"conference.@HOST@">>),
- Rooms = RMod:get_online_rooms(MyHost, undefined),
+ Rooms = RMod:get_online_rooms(Host, MyHost, undefined),
lists:flatmap(
fun({_, _, Pid}) when node(Pid) == node() ->
Pid ! shutdown,
@@ -180,13 +180,13 @@ can_use_nick(ServerHost, Host, JID, Nick) ->
find_online_room(Room, Host) ->
ServerHost = ejabberd_router:host_of_route(Host),
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:find_online_room(Room, Host).
+ RMod:find_online_room(ServerHost, Room, Host).
-spec register_online_room(binary(), binary(), pid()) -> any().
register_online_room(Room, Host, Pid) ->
ServerHost = ejabberd_router:host_of_route(Host),
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:register_online_room(Room, Host, Pid).
+ RMod:register_online_room(ServerHost, Room, Host, Pid).
-spec get_online_rooms(binary()) -> [{binary(), binary(), pid()}].
get_online_rooms(Host) ->
@@ -201,22 +201,22 @@ count_online_rooms(Host) ->
-spec register_online_user(binary(), ljid(), binary(), binary()) -> any().
register_online_user(ServerHost, LJID, Name, Host) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:register_online_user(LJID, Name, Host).
+ RMod:register_online_user(ServerHost, LJID, Name, Host).
-spec unregister_online_user(binary(), ljid(), binary(), binary()) -> any().
unregister_online_user(ServerHost, LJID, Name, Host) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:unregister_online_user(LJID, Name, Host).
+ RMod:unregister_online_user(ServerHost, LJID, Name, Host).
-spec count_online_rooms_by_user(binary(), binary(), binary()) -> non_neg_integer().
count_online_rooms_by_user(ServerHost, LUser, LServer) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:count_online_rooms_by_user(LUser, LServer).
+ RMod:count_online_rooms_by_user(ServerHost, LUser, LServer).
-spec get_online_rooms_by_user(binary(), binary(), binary()) -> [{binary(), binary()}].
get_online_rooms_by_user(ServerHost, LUser, LServer) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:get_online_rooms_by_user(LUser, LServer).
+ RMod:get_online_rooms_by_user(ServerHost, LUser, LServer).
%%====================================================================
%% gen_server callbacks
@@ -256,7 +256,7 @@ handle_call({create, Room, From, Nick, Opts}, _From,
RoomShaper, From,
Nick, NewOpts, QueueType),
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:register_online_room(Room, Host, Pid),
+ RMod:register_online_room(ServerHost, Room, Host, Pid),
{reply, ok, State}.
handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{host = OldHost}) ->
@@ -318,7 +318,7 @@ handle_info({route, Packet},
handle_info({room_destroyed, {Room, Host}, Pid}, State) ->
ServerHost = State#state.server_host,
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:unregister_online_room(Room, Host, Pid),
+ RMod:unregister_online_room(ServerHost, Room, Host, Pid),
{noreply, State};
handle_info(Info, State) ->
?ERROR_MSG("unexpected info: ~p", [Info]),
@@ -491,7 +491,7 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
{_AccessRoute, AccessCreate, _AccessAdmin, _AccessPersistent} = Access,
{Room, _, Nick} = jid:tolower(To),
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- case RMod:find_online_room(Room, Host) of
+ case RMod:find_online_room(ServerHost, Room, Host) of
error ->
case is_create_request(Packet) of
true ->
@@ -504,7 +504,7 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
Room, HistorySize,
RoomShaper, From, Nick, DefRoomOpts,
QueueType),
- RMod:register_online_room(Room, Host, Pid),
+ RMod:register_online_room(ServerHost, Room, Host, Pid),
mod_muc_room:route(Pid, Packet),
ok;
false ->
@@ -675,13 +675,13 @@ load_permanent_rooms(Host, ServerHost, Access,
lists:foreach(
fun(R) ->
{Room, Host} = R#muc_room.name_host,
- case RMod:find_online_room(Room, Host) of
+ case RMod:find_online_room(ServerHost, Room, Host) of
error ->
{ok, Pid} = mod_muc_room:start(Host,
ServerHost, Access, Room,
HistorySize, RoomShaper,
R#muc_room.opts, QueueType),
- RMod:register_online_room(Room, Host, Pid);
+ RMod:register_online_room(ServerHost, Room, Host, Pid);
{ok, _} ->
ok
end
@@ -856,12 +856,12 @@ get_online_rooms(ServerHost, Host) ->
[{binary(), binary(), pid()}].
get_online_rooms(ServerHost, Host, RSM) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:get_online_rooms(Host, RSM).
+ RMod:get_online_rooms(ServerHost, Host, RSM).
-spec count_online_rooms(binary(), binary()) -> non_neg_integer().
count_online_rooms(ServerHost, Host) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:count_online_rooms(Host).
+ RMod:count_online_rooms(ServerHost, Host).
opts_to_binary(Opts) ->
lists:map(
diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl
index eaf8da6c3..a87761665 100644
--- a/src/mod_muc_mnesia.erl
+++ b/src/mod_muc_mnesia.erl
@@ -30,10 +30,10 @@
%% API
-export([init/2, import/3, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
--export([register_online_room/3, unregister_online_room/3, find_online_room/2,
- get_online_rooms/2, count_online_rooms/1, rsm_supported/0,
- register_online_user/3, unregister_online_user/3,
- count_online_rooms_by_user/2, get_online_rooms_by_user/2]).
+-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]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
%% gen_server callbacks
@@ -157,27 +157,30 @@ get_affiliations(_ServerHost, _Room, _Host) ->
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
-register_online_room(Room, Host, Pid) ->
+register_online_room(_ServerHost, Room, Host, Pid) ->
F = fun() ->
mnesia:write(
#muc_online_room{name_host = {Room, Host}, pid = Pid})
end,
mnesia:transaction(F).
-unregister_online_room(Room, Host, Pid) ->
+unregister_online_room(_ServerHost, Room, Host, Pid) ->
F = fun () ->
mnesia:delete_object(
#muc_online_room{name_host = {Room, Host}, pid = Pid})
end,
mnesia:transaction(F).
+find_online_room(_ServerHost, Room, Host) ->
+ find_online_room(Room, Host).
+
find_online_room(Room, Host) ->
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
[] -> error;
[#muc_online_room{pid = Pid}] -> {ok, Pid}
end.
-count_online_rooms(Host) ->
+count_online_rooms(_ServerHost, Host) ->
ets:select_count(
muc_online_room,
ets:fun2ms(
@@ -185,20 +188,20 @@ count_online_rooms(Host) ->
H == Host
end)).
-get_online_rooms(Host,
+get_online_rooms(_ServerHost, Host,
#rsm_set{max = Max, 'after' = After, before = undefined})
when is_binary(After), After /= <<"">> ->
lists:reverse(get_online_rooms(next, {After, Host}, Host, 0, Max, []));
-get_online_rooms(Host,
+get_online_rooms(_ServerHost, Host,
#rsm_set{max = Max, 'after' = undefined, before = Before})
when is_binary(Before), Before /= <<"">> ->
get_online_rooms(prev, {Before, Host}, Host, 0, Max, []);
-get_online_rooms(Host,
+get_online_rooms(_ServerHost, Host,
#rsm_set{max = Max, 'after' = undefined, before = <<"">>}) ->
get_online_rooms(last, {<<"">>, Host}, Host, 0, Max, []);
-get_online_rooms(Host, #rsm_set{max = Max}) ->
+get_online_rooms(_ServerHost, Host, #rsm_set{max = Max}) ->
lists:reverse(get_online_rooms(first, {<<"">>, Host}, Host, 0, Max, []));
-get_online_rooms(Host, undefined) ->
+get_online_rooms(_ServerHost, Host, undefined) ->
mnesia:dirty_select(
muc_online_room,
ets:fun2ms(
@@ -248,17 +251,17 @@ get_online_rooms(Action, Key, Host, Count, Max, Items) ->
rsm_supported() ->
true.
-register_online_user({U, S, R}, Room, Host) ->
+register_online_user(_ServerHost, {U, S, R}, Room, Host) ->
ets:insert(muc_online_users,
#muc_online_users{us = {U, S}, resource = R,
room = Room, host = Host}).
-unregister_online_user({U, S, R}, Room, Host) ->
+unregister_online_user(_ServerHost, {U, S, R}, Room, Host) ->
ets:delete_object(muc_online_users,
#muc_online_users{us = {U, S}, resource = R,
room = Room, host = Host}).
-count_online_rooms_by_user(U, S) ->
+count_online_rooms_by_user(_ServerHost, U, S) ->
ets:select_count(
muc_online_users,
ets:fun2ms(
@@ -266,7 +269,7 @@ count_online_rooms_by_user(U, S) ->
U == U1 andalso S == S1
end)).
-get_online_rooms_by_user(U, S) ->
+get_online_rooms_by_user(_ServerHost, U, S) ->
ets:select(
muc_online_users,
ets:fun2ms(
diff --git a/src/mod_muc_riak.erl b/src/mod_muc_riak.erl
index 0577ef60b..8dd1eddf8 100644
--- a/src/mod_muc_riak.erl
+++ b/src/mod_muc_riak.erl
@@ -30,10 +30,10 @@
%% API
-export([init/2, import/3, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
--export([register_online_room/3, unregister_online_room/3, find_online_room/2,
- get_online_rooms/2, count_online_rooms/1, rsm_supported/0,
- register_online_user/3, unregister_online_user/3,
- count_online_rooms_by_user/2, get_online_rooms_by_user/2]).
+-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]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
@@ -140,34 +140,34 @@ get_affiliations(_ServerHost, _Room, _Host) ->
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
-register_online_room(_, _, _) ->
+register_online_room(_, _, _, _) ->
erlang:error(not_implemented).
-unregister_online_room(_, _, _) ->
+unregister_online_room(_, _, _, _) ->
erlang:error(not_implemented).
-find_online_room(_, _) ->
+find_online_room(_, _, _) ->
erlang:error(not_implemented).
-count_online_rooms(_) ->
+count_online_rooms(_, _) ->
erlang:error(not_implemented).
-get_online_rooms(_, _) ->
+get_online_rooms(_, _, _) ->
erlang:error(not_implemented).
rsm_supported() ->
false.
-register_online_user(_, _, _) ->
+register_online_user(_, _, _, _) ->
erlang:error(not_implemented).
-unregister_online_user(_, _, _) ->
+unregister_online_user(_, _, _, _) ->
erlang:error(not_implemented).
-count_online_rooms_by_user(_, _) ->
+count_online_rooms_by_user(_, _, _) ->
erlang:error(not_implemented).
-get_online_rooms_by_user(_, _) ->
+get_online_rooms_by_user(_, _, _) ->
erlang:error(not_implemented).
import(_LServer, <<"muc_room">>,
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl
index df1319ce3..14ff12484 100644
--- a/src/mod_muc_sql.erl
+++ b/src/mod_muc_sql.erl
@@ -33,10 +33,10 @@
-export([init/2, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4,
import/3, export/1]).
--export([register_online_room/3, unregister_online_room/3, find_online_room/2,
- get_online_rooms/2, count_online_rooms/1, rsm_supported/0,
- register_online_user/3, unregister_online_user/3,
- count_online_rooms_by_user/2, get_online_rooms_by_user/2]).
+-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]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
@@ -48,8 +48,13 @@
%%%===================================================================
%%% API
%%%===================================================================
-init(_Host, _Opts) ->
- ok.
+init(Host, Opts) ->
+ case gen_mod:ram_db_mod(Host, Opts, mod_muc) of
+ ?MODULE ->
+ clean_tables(Host);
+ _ ->
+ ok
+ end.
store_room(LServer, Host, Name, Opts) ->
SOpts = jlib:term_to_expr(Opts),
@@ -165,35 +170,126 @@ get_affiliations(_ServerHost, _Room, _Host) ->
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
-register_online_room(_, _, _) ->
- erlang:error(not_implemented).
+register_online_room(ServerHost, Room, Host, Pid) ->
+ PidS = enc_pid(Pid),
+ NodeS = erlang:atom_to_binary(node(Pid), latin1),
+ case ?SQL_UPSERT(ServerHost,
+ "muc_online_room",
+ ["!name=%(Room)s",
+ "!host=%(Host)s",
+ "node=%(NodeS)s",
+ "pid=%(PidS)s"]) of
+ ok ->
+ ok;
+ Err ->
+ ?ERROR_MSG("failed to update 'muc_online_room': ~p", [Err]),
+ Err
+ end.
-unregister_online_room(_, _, _) ->
- erlang:error(not_implemented).
+unregister_online_room(ServerHost, Room, Host, Pid) ->
+ %% TODO: report errors
+ PidS = enc_pid(Pid),
+ NodeS = erlang:atom_to_binary(node(Pid), latin1),
+ ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("delete from muc_online_room where name=%(Room)s and "
+ "host=%(Host)s and node=%(NodeS)s and pid=%(PidS)s")).
-find_online_room(_, _) ->
- erlang:error(not_implemented).
+find_online_room(ServerHost, Room, Host) ->
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(pid)s, @(node)s from muc_online_room where "
+ "name=%(Room)s and host=%(Host)s")) of
+ {selected, [{PidS, NodeS}]} ->
+ try {ok, dec_pid(PidS, NodeS)}
+ catch _:{node_down, _} -> error
+ end;
+ {selected, []} ->
+ error;
+ Err ->
+ ?ERROR_MSG("failed to select 'muc_online_room': ~p", [Err]),
+ error
+ end.
-count_online_rooms(_) ->
- erlang:error(not_implemented).
+count_online_rooms(ServerHost, Host) ->
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(count(*))d from muc_online_room "
+ "where host=%(Host)s")) of
+ {selected, [{Num}]} ->
+ Num;
+ Err ->
+ ?ERROR_MSG("failed to select 'muc_online_room': ~p", [Err]),
+ 0
+ end.
-get_online_rooms(_, _) ->
- erlang:error(not_implemented).
+get_online_rooms(ServerHost, Host, _RSM) ->
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(name)s, @(pid)s, @(node)s from muc_online_room "
+ "where host=%(Host)s")) of
+ {selected, Rows} ->
+ lists:flatmap(
+ fun({Room, PidS, NodeS}) ->
+ try [{Room, Host, dec_pid(PidS, NodeS)}]
+ catch _:{node_down, _} -> []
+ end
+ end, Rows);
+ Err ->
+ ?ERROR_MSG("failed to select 'muc_online_room': ~p", [Err]),
+ 0
+ end.
rsm_supported() ->
false.
-register_online_user(_, _, _) ->
- erlang:error(not_implemented).
+register_online_user(ServerHost, {U, S, R}, Room, Host) ->
+ NodeS = erlang:atom_to_binary(node(), latin1),
+ case ?SQL_UPSERT(ServerHost, "muc_online_users",
+ ["!username=%(U)s",
+ "!server=%(S)s",
+ "!resource=%(R)s",
+ "!name=%(Room)s",
+ "!host=%(Host)s",
+ "node=%(NodeS)s"]) of
+ ok ->
+ ok;
+ Err ->
+ ?ERROR_MSG("failed to update 'muc_online_users': ~p", [Err]),
+ Err
+ end.
-unregister_online_user(_, _, _) ->
- erlang:error(not_implemented).
+unregister_online_user(ServerHost, {U, S, R}, Room, Host) ->
+ %% TODO: report errors
+ ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("delete from muc_online_users where username=%(U)s and "
+ "server=%(S)s and resource=%(R)s and name=%(Room)s and "
+ "host=%(Host)s")).
-count_online_rooms_by_user(_, _) ->
- erlang:error(not_implemented).
+count_online_rooms_by_user(ServerHost, U, S) ->
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(count(*))d from muc_online_users where "
+ "username=%(U)s and server=%(S)s")) of
+ {selected, [{Num}]} ->
+ Num;
+ Err ->
+ ?ERROR_MSG("failed to select 'muc_online_users': ~p", [Err]),
+ 0
+ end.
-get_online_rooms_by_user(_, _) ->
- erlang:error(not_implemented).
+get_online_rooms_by_user(ServerHost, U, S) ->
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("select @(name)s, @(host)s from muc_online_users where "
+ "username=%(U)s and server=%(S)s")) of
+ {selected, Rows} ->
+ Rows;
+ Err ->
+ ?ERROR_MSG("failed to select 'muc_online_users': ~p", [Err]),
+ []
+ end.
export(_Server) ->
[{muc_room,
@@ -232,3 +328,52 @@ import(_, _, _) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
+-spec enc_pid(pid()) -> binary().
+enc_pid(Pid) ->
+ list_to_binary(erlang:pid_to_list(Pid)).
+
+-spec dec_pid(binary(), binary()) -> pid().
+dec_pid(PidBin, NodeBin) ->
+ PidStr = binary_to_list(PidBin),
+ Pid = erlang:list_to_pid(PidStr),
+ case erlang:binary_to_atom(NodeBin, latin1) of
+ Node when Node == node() ->
+ Pid;
+ Node ->
+ try set_node_id(PidStr, NodeBin)
+ catch _:badarg ->
+ erlang:error({node_down, Node})
+ end
+ end.
+
+-spec set_node_id(string(), binary()) -> pid().
+set_node_id(PidStr, NodeBin) ->
+ ExtPidStr = erlang:pid_to_list(
+ binary_to_term(
+ <<131,103,100,(size(NodeBin)):16,NodeBin/binary,0:72>>)),
+ [H|_] = string:tokens(ExtPidStr, "."),
+ [_|T] = string:tokens(PidStr, "."),
+ erlang:list_to_pid(string:join([H|T], ".")).
+
+clean_tables(ServerHost) ->
+ NodeS = erlang:atom_to_binary(node(), latin1),
+ ?INFO_MSG("Cleaning SQL muc_online_room table...", []),
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("delete from muc_online_room where node=%(NodeS)s")) of
+ {updated, _} ->
+ ok;
+ Err1 ->
+ ?ERROR_MSG("failed to clean 'muc_online_room' table: ~p", [Err1]),
+ Err1
+ end,
+ ?INFO_MSG("Cleaning SQL muc_online_users table...", []),
+ case ejabberd_sql:sql_query(
+ ServerHost,
+ ?SQL("delete from muc_online_users where node=%(NodeS)s")) of
+ {updated, _} ->
+ ok;
+ Err2 ->
+ ?ERROR_MSG("failed to clean 'muc_online_users' table: ~p", [Err2]),
+ Err2
+ end.
diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml
index efecf6df8..41bf24ab2 100644
--- a/test/ejabberd_SUITE_data/ejabberd.yml
+++ b/test/ejabberd_SUITE_data/ejabberd.yml
@@ -20,6 +20,7 @@ host_config:
db_type: sql
mod_muc:
db_type: sql
+ ram_db_type: sql
mod_offline:
db_type: sql
mod_privacy:
@@ -77,6 +78,7 @@ Welcome to this XMPP server."
db_type: sql
mod_muc:
db_type: sql
+ ram_db_type: sql
mod_offline:
db_type: sql
mod_privacy:
@@ -139,6 +141,7 @@ Welcome to this XMPP server."
db_type: sql
mod_muc:
db_type: sql
+ ram_db_type: sql
mod_offline:
db_type: sql
mod_privacy:
diff --git a/test/muc_tests.erl b/test/muc_tests.erl
index 754d767a9..eb869cad6 100644
--- a/test/muc_tests.erl
+++ b/test/muc_tests.erl
@@ -152,7 +152,7 @@ service_features(Config) ->
end,
RequiredFeatures = sets:from_list(
[?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
- ?NS_REGISTER, ?NS_MUC, ?NS_RSM,
+ ?NS_REGISTER, ?NS_MUC,
?NS_VCARD, ?NS_MUCSUB, ?NS_MUC_UNIQUE
| MAMFeatures]),
ct:comment("Checking if all needed disco features are set"),