]> granicus.if.org Git - ejabberd/commitdiff
Add SQL as mod_muc RAM backend
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 29 Mar 2017 09:58:01 +0000 (12:58 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 29 Mar 2017 09:58:01 +0000 (12:58 +0300)
sql/lite.sql
sql/mssql.sql
sql/mysql.sql
sql/pg.sql
src/mod_muc.erl
src/mod_muc_mnesia.erl
src/mod_muc_riak.erl
src/mod_muc_sql.erl
test/ejabberd_SUITE_data/ejabberd.yml
test/muc_tests.erl

index c17d80ec53f5aae4559af22e31aadda3ca016e4e..8b59ef0a19adb7f49dd4c092766166f819c32057 100644 (file)
@@ -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,
index 7535da5acf685a8e5325365b63a11d934cbc43db..59c192b984f4dd484ff5cea75c427af533ab164c 100644 (file)
@@ -125,6 +125,30 @@ CREATE TABLE [dbo].[muc_room] (
 CREATE UNIQUE CLUSTERED INDEX [muc_room_name_host] ON [muc_room] (name, host)\r
 WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
 \r
+CREATE TABLE [dbo].[muc_online_room] (\r
+        [name] [varchar] (250) NOT NULL,\r
+       [host] [varchar] (250) NOT NULL,\r
+       [node] [text] NOT NULL,\r
+       [pid] [text] NOT NULL\r
+);\r
+\r
+CREATE UNIQUE CLUSTERED INDEX [muc_online_room_name_host] ON [muc_online_room] (name, host)\r
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
+\r
+CREATE TABLE [dbo].[muc_online_users] (\r
+    [username] [varchar] (250) NOT NULL,\r
+    [server] [varchar] (250) NOT NULL,\r
+    [resource] [varchar] (250) NOT NULL,\r
+    [name] [varchar] (250) NOT NULL,\r
+    [host] [varchar] (250) NOT NULL,\r
+    node text NOT NULL\r
+);\r
+\r
+CREATE UNIQUE CLUSTERED INDEX [muc_online_users_i] ON [muc_online_users] (username, server, resource, name, host)\r
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
+CREATE UNIQUE CLUSTERED INDEX [muc_online_users_us] ON [muc_online_users] (username, server);\r
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
+\r
 CREATE TABLE [dbo].[privacy_default_list] (\r
         [username] [varchar] (250) NOT NULL,\r
         [name] [varchar] (250) NOT NULL,\r
index 982df7ff539280d0be4efa9966c5606f8da46cac..edd205f0dbedadb0b8ec99c4de4a151b6640747c 100644 (file)
@@ -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,
index 8a8b77b1fb4f875bd4ec5e579bb4b394b7e0c357..6c099fc6b663f43865c2c7864000e44d384ac5fa 100644 (file)
@@ -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,
index 8bb9c4b8c55b9249a7566b80d8d278a66d709d07..9c8316e2e3c7b45351df0f4109f32f7a16b8a3e3 100644 (file)
 -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(
index eaf8da6c3b010f2865d0c56f035607d97a348eef..a87761665bdcd7370770180a99a82e76d9f2c83b 100644 (file)
 %% 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(
index 0577ef60b40e2e32cbbf1a34be021e9c6c789018..8dd1eddf888fbbc0e57a0dd9c01927ed34ba4c4e 100644 (file)
 %% 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">>,
index df1319ce36f28cc7d29505c980cd41faa1922139..14ff124844ac67dd2c8dffe11be7c86ef92bb9c2 100644 (file)
 -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]).
 
 %%%===================================================================
 %%% 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.
index efecf6df86e2d1dfdfc082c0ed393b0787c4f3b3..41bf24ab2c1f76258cc176f91c67fb186c819c86 100644 (file)
@@ -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: 
index 754d767a9383a28c521d3d788251e6ed799d496b..eb869cad657878cc565f2c029aaedf97739aa647 100644 (file)
@@ -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"),