]> granicus.if.org Git - ejabberd/commitdiff
Add SQL as mod_carboncopy RAM backend
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 30 Mar 2017 07:31:51 +0000 (10:31 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 30 Mar 2017 07:31:51 +0000 (10:31 +0300)
sql/lite.sql
sql/mssql.sql
sql/mysql.sql
sql/pg.sql
src/mod_carboncopy.erl
src/mod_carboncopy_sql.erl [new file with mode: 0644]
test/ejabberd_SUITE.erl
test/ejabberd_SUITE_data/ejabberd.yml

index 8b59ef0a19adb7f49dd4c092766166f819c32057..ddfb91ff0b256d2fc093cd6568051a269960c5ed 100644 (file)
@@ -359,3 +359,13 @@ CREATE TABLE bosh (
 );
 
 CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid);
+
+CREATE TABLE carboncopy (
+    username text NOT NULL,
+    resource text NOT NULL,
+    namespace text NOT NULL,
+    node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_carboncopy_ur ON carboncopy (username, resource);
+CREATE INDEX i_carboncopy_user ON carboncopy (username);
index 59c192b984f4dd484ff5cea75c427af533ab164c..72b490ecceebbbdc4319cb30486a7031c429614b 100644 (file)
@@ -520,7 +520,7 @@ CREATE TABLE [dbo].[route] (
     [server_host] [varchar] (255) NOT NULL,\r
     [node] [varchar] (255) NOT NULL,\r
     [pid] [varchar](100) NOT NULL,\r
-    [local_hint] text NOT NULL\r
+    [local_hint] [text] NOT NULL\r
 );\r
 \r
 CREATE UNIQUE CLUSTERED INDEX [route_i] ON [route] (domain, server_host, node, pid)\r
@@ -538,3 +538,16 @@ CREATE TABLE [dbo].[bosh] (
         [sid] ASC\r
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)\r
 ) TEXTIMAGE_ON [PRIMARY];\r
+\r
+CREATE TABLE [dbo].[carboncopy] (\r
+    [username] [varchar] (255) NOT NULL,\r
+    [resource] [varchar] (255) NOT NULL,\r
+    [namespace] [varchar] (255) NOT NULL,\r
+    [node] [varchar] (255) NOT NULL\r
+);\r
+\r
+CREATE UNIQUE CLUSTERED INDEX [carboncopy_ur] ON [carboncopy] (username, resource)\r
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
+\r
+CREATE INDEX [carboncopy_user] ON [carboncopy] (username)\r
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);\r
index edd205f0dbedadb0b8ec99c4de4a151b6640747c..e09c39be55e124b0cc9f278413e6f380c48b99d3 100644 (file)
@@ -375,3 +375,13 @@ CREATE TABLE bosh (
 ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
 
 CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
+
+CREATE TABLE carboncopy (
+    username text NOT NULL,
+    resource text NOT NULL,
+    namespace text NOT NULL,
+    node text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_carboncopy_ur ON carboncopy (username(75), resource(75));
+CREATE INDEX i_carboncopy_user ON carboncopy (username(75));
index 6c099fc6b663f43865c2c7864000e44d384ac5fa..796391c74db2baa1df41226f8b3d3061d96b938b 100644 (file)
@@ -379,3 +379,13 @@ CREATE TABLE bosh (
 );
 
 CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
+
+CREATE TABLE carboncopy (
+    username text NOT NULL,
+    resource text NOT NULL,
+    namespace text NOT NULL,
+    node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_carboncopy_ur ON carboncopy USING btree (username, resource);
+CREATE INDEX i_carboncopy_user ON carboncopy USING btree (username);
index 03fe475f2aa148b289201033701048e0325a52ac..a7ae37f454dff677aca4d48827ddbd5a1b39d922 100644 (file)
@@ -58,7 +58,7 @@ is_carbon_copy(_) ->
 start(Host, Opts) ->
     IQDisc = gen_mod:get_opt(iqdisc, Opts,fun gen_iq_handler:check_type/1, one_queue),
     ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
-    Mod = gen_mod:db_mod(Host, ?MODULE),
+    Mod = gen_mod:ram_db_mod(Host, ?MODULE),
     Mod:init(Host, Opts),
     ejabberd_hooks:add(unset_presence_hook,Host, ?MODULE, remove_connection, 10),
     %% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
@@ -75,8 +75,8 @@ stop(Host) ->
     ejabberd_hooks:delete(unset_presence_hook,Host, ?MODULE, remove_connection, 10).
 
 reload(Host, NewOpts, OldOpts) ->
-    NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
-    OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+    NewMod = gen_mod:ram_db_mod(Host, NewOpts, ?MODULE),
+    OldMod = gen_mod:ram_db_mod(Host, OldOpts, ?MODULE),
     if NewMod /= OldMod ->
            NewMod:init(Host, NewOpts);
        true ->
@@ -246,13 +246,13 @@ build_forward_packet(JID, #message{type = T} = Msg, Sender, Dest, Direction) ->
 -spec enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
 enable(Host, U, R, CC)->
     ?DEBUG("enabling for ~p", [U]),
-    Mod = gen_mod:db_mod(Host, ?MODULE),
+    Mod = gen_mod:ram_db_mod(Host, ?MODULE),
     Mod:enable(U, Host, R, CC).
 
 -spec disable(binary(), binary(), binary()) -> ok | {error, any()}.
 disable(Host, U, R)->
     ?DEBUG("disabling for ~p", [U]),
-    Mod = gen_mod:db_mod(Host, ?MODULE),
+    Mod = gen_mod:ram_db_mod(Host, ?MODULE),
     Mod:disable(U, Host, R).
 
 -spec complete_packet(jid(), message(), direction()) -> message().
@@ -279,12 +279,12 @@ is_muc_pm(_To, Packet) ->
 -spec list(binary(), binary()) -> [{binary(), binary()}].
 %% list {resource, cc_version} with carbons enabled for given user and host
 list(User, Server) ->
-    Mod = gen_mod:db_mod(Server, ?MODULE),
+    Mod = gen_mod:ram_db_mod(Server, ?MODULE),
     Mod:list(User, Server).
 
 depends(_Host, _Opts) ->
     [].
 
 mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
-mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
-mod_opt_type(_) -> [db_type, iqdisc].
+mod_opt_type(ram_db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
+mod_opt_type(_) -> [ram_db_type, iqdisc].
diff --git a/src/mod_carboncopy_sql.erl b/src/mod_carboncopy_sql.erl
new file mode 100644 (file)
index 0000000..2770d40
--- /dev/null
@@ -0,0 +1,93 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% Created : 29 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%
+%%%
+%%% ejabberd, Copyright (C) 2002-2017   ProcessOne
+%%%
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the GNU General Public License as
+%%% published by the Free Software Foundation; either version 2 of the
+%%% License, or (at your option) any later version.
+%%%
+%%% This program is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%%% General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License along
+%%% with this program; if not, write to the Free Software Foundation, Inc.,
+%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+%%%
+%%%-------------------------------------------------------------------
+-module(mod_carboncopy_sql).
+-behaviour(mod_carboncopy).
+
+-compile([{parse_transform, ejabberd_sql_pt}]).
+
+%% API
+-export([init/2, enable/4, disable/3, list/2]).
+
+-include("ejabberd.hrl").
+-include("logger.hrl").
+-include("ejabberd_sql_pt.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(Host, _Opts) ->
+    clean_table(Host).
+
+enable(LUser, LServer, LResource, NS) ->
+    NodeS = erlang:atom_to_binary(node(), latin1),
+    case ?SQL_UPSERT(LServer, "carboncopy",
+                    ["!username=%(LUser)s",
+                     "!resource=%(LResource)s",
+                     "namespace=%(NS)s",
+                     "node=%(NodeS)s"]) of
+       ok ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to update 'carboncopy' table: ~p", [Err]),
+           Err
+    end.
+
+disable(LUser, LServer, LResource) ->
+    case ejabberd_sql:sql_query(
+          LServer,
+          ?SQL("delete from carboncopy where username=%(LUser)s "
+               "and resource=%(LResource)s")) of
+       {updated, _} ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to delete from 'carboncopy' table: ~p", [Err]),
+           Err
+    end.
+
+list(LUser, LServer) ->
+    case ejabberd_sql:sql_query(
+          LServer,
+          ?SQL("select @(resource)s, @(namespace)s from carboncopy "
+               "where username=%(LUser)s")) of
+       {selected, Rows} ->
+           Rows;
+       Err ->
+           ?ERROR_MSG("failed to select from 'carboncopy' table: ~p", [Err]),
+           []
+    end.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+clean_table(LServer) ->
+    NodeS = erlang:atom_to_binary(node(), latin1),
+    ?INFO_MSG("Cleaning SQL 'carboncopy' table...", []),
+    case ejabberd_sql:sql_query(
+          LServer,
+          ?SQL("delete from carboncopy where node=%(NodeS)s")) of
+       {updated, _} ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to clean 'carboncopy' table: ~p", [Err]),
+           Err
+    end.
index 43f0f34dbb5b97563cf4d91a98d2ae985c9f4cad..36a306b59e00875a894390cf6525ee1b722537f1 100644 (file)
@@ -443,7 +443,6 @@ db_tests(DB) when DB == mnesia; DB == redis ->
      carbons_tests:master_slave_cases(),
      csi_tests:master_slave_cases()];
 db_tests(_) ->
-    %% No support for carboncopy
     [{single_user, [sequence],
       [test_register,
        legacy_auth_tests(),
@@ -469,7 +468,8 @@ db_tests(_) ->
      mam_tests:master_slave_cases(),
      mix_tests:master_slave_cases(),
      vcard_tests:master_slave_cases(),
-     announce_tests:master_slave_cases()].
+     announce_tests:master_slave_cases(),
+     carbons_tests:master_slave_cases()].
 
 ldap_tests() ->
     [{ldap_tests, [sequence],
index 41bf24ab2c1f76258cc176f91c67fb186c819c86..f58a429aed5101f175d7028f6df05d6f70654093 100644 (file)
@@ -47,6 +47,8 @@ host_config:
         db_type: sql
       mod_vcard_xupdate:
         db_type: sql
+      mod_carboncopy:
+        ram_db_type: sql
       mod_adhoc: []
       mod_configure: []
       mod_disco: []
@@ -105,6 +107,8 @@ Welcome to this XMPP server."
         db_type: sql
       mod_vcard_xupdate:
         db_type: sql
+      mod_carboncopy:
+        ram_db_type: sql
       mod_adhoc: []
       mod_configure: []
       mod_disco: []
@@ -168,6 +172,8 @@ Welcome to this XMPP server."
         db_type: sql
       mod_vcard_xupdate:
         db_type: sql
+      mod_carboncopy:
+        ram_db_type: sql
       mod_adhoc: []
       mod_configure: []
       mod_disco: []
@@ -222,7 +228,8 @@ Welcome to this XMPP server."
         db_type: internal
       mod_vcard_xupdate:
         db_type: internal
-      mod_carboncopy: []
+      mod_carboncopy:
+        ram_db_type: internal
       mod_client_state:
         queue_presence: true
         queue_chat_states: true
@@ -282,7 +289,8 @@ Welcome to this XMPP server."
         db_type: internal
       mod_vcard_xupdate:
         db_type: internal
-      mod_carboncopy: []
+      mod_carboncopy:
+        ram_db_type: internal
       mod_client_state:
         queue_presence: true
         queue_chat_states: true