mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Keep info about carbons inside session table
Accordingly, Mnesia/SQL/Riak table 'carboncopy' is not used anymore and can be safely removed. As a consequence, the commit deprecates the following options of mod_carboncopy: - ram_db_type - use_cache - cache_size - cache_missed - cache_life_time Fixes #2663
This commit is contained in:
parent
a9539fef22
commit
109ed8f2f6
@ -1,27 +0,0 @@
|
|||||||
%%%----------------------------------------------------------------------
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 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.
|
|
||||||
%%%
|
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-type matchspec_atom() :: '_' | '$1' | '$2' | '$3' | '$4'.
|
|
||||||
-record(carboncopy, {us :: {binary(), binary()} | matchspec_atom(),
|
|
||||||
resource :: binary() | matchspec_atom(),
|
|
||||||
version :: binary() | matchspec_atom(),
|
|
||||||
node = node() :: node() | matchspec_atom()}).
|
|
||||||
|
|
||||||
-define(CARBONCOPY_CACHE, carboncopy_cache).
|
|
@ -387,17 +387,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid);
|
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid);
|
||||||
|
|
||||||
CREATE TABLE carboncopy (
|
|
||||||
username text NOT NULL,
|
|
||||||
server_host text NOT NULL,
|
|
||||||
resource text NOT NULL,
|
|
||||||
namespace text NOT NULL,
|
|
||||||
node text NOT NULL,
|
|
||||||
PRIMARY KEY (server_host, username, resource)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX i_carboncopy_sh_user ON carboncopy (server_host, username);
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
10
sql/lite.sql
10
sql/lite.sql
@ -357,16 +357,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid);
|
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);
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
@ -531,19 +531,6 @@ CREATE TABLE [dbo].[bosh] (
|
|||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE [dbo].[carboncopy] (
|
|
||||||
[username] [varchar] (255) NOT NULL,
|
|
||||||
[resource] [varchar] (255) NOT NULL,
|
|
||||||
[namespace] [varchar] (255) NOT NULL,
|
|
||||||
[node] [varchar] (255) NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE CLUSTERED INDEX [carboncopy_ur] ON [carboncopy] (username, resource)
|
|
||||||
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
|
|
||||||
|
|
||||||
CREATE INDEX [carboncopy_user] ON [carboncopy] (username)
|
|
||||||
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
|
|
||||||
|
|
||||||
CREATE TABLE [dbo].[push_session] (
|
CREATE TABLE [dbo].[push_session] (
|
||||||
[username] [varchar] (255) NOT NULL,
|
[username] [varchar] (255) NOT NULL,
|
||||||
[timestamp] [bigint] NOT NULL,
|
[timestamp] [bigint] NOT NULL,
|
||||||
|
@ -403,17 +403,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
|
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
|
||||||
|
|
||||||
CREATE TABLE carboncopy (
|
|
||||||
username text NOT NULL,
|
|
||||||
server_host text NOT NULL,
|
|
||||||
resource text NOT NULL,
|
|
||||||
namespace text NOT NULL,
|
|
||||||
node text NOT NULL,
|
|
||||||
PRIMARY KEY (server_host(191), username(191), resource(191))
|
|
||||||
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
CREATE INDEX i_carboncopy_sh_user ON carboncopy (server_host(191), username(75));
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
@ -373,16 +373,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
|
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));
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
@ -156,13 +156,6 @@
|
|||||||
-- CREATE INDEX i_sm_sh_username ON sm USING btree (server_host, username);
|
-- CREATE INDEX i_sm_sh_username ON sm USING btree (server_host, username);
|
||||||
-- ALTER TABLE sm ALTER COLUMN server_host DROP DEFAULT;
|
-- ALTER TABLE sm ALTER COLUMN server_host DROP DEFAULT;
|
||||||
|
|
||||||
-- ALTER TABLE carboncopy ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
|
|
||||||
-- DROP INDEX i_carboncopy_ur;
|
|
||||||
-- DROP INDEX i_carboncopy_user;
|
|
||||||
-- ALTER TABLE carboncopy ADD PRIMARY KEY (server_host, username, resource);
|
|
||||||
-- CREATE INDEX i_carboncopy_sh_user ON carboncopy USING btree (server_host, username);
|
|
||||||
-- ALTER TABLE carboncopy ALTER COLUMN server_host DROP DEFAULT;
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
@ -555,17 +548,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
|
CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
|
||||||
|
|
||||||
CREATE TABLE carboncopy (
|
|
||||||
username text NOT NULL,
|
|
||||||
server_host text NOT NULL,
|
|
||||||
resource text NOT NULL,
|
|
||||||
namespace text NOT NULL,
|
|
||||||
node text NOT NULL,
|
|
||||||
PRIMARY KEY (server_host, username, resource)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX i_carboncopy_sh_user ON carboncopy USING btree (server_host, username);
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
10
sql/pg.sql
10
sql/pg.sql
@ -377,16 +377,6 @@ CREATE TABLE bosh (
|
|||||||
|
|
||||||
CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
|
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);
|
|
||||||
|
|
||||||
CREATE TABLE proxy65 (
|
CREATE TABLE proxy65 (
|
||||||
sid text NOT NULL,
|
sid text NOT NULL,
|
||||||
pid_t text NOT NULL,
|
pid_t text NOT NULL,
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
get_session_sids/2,
|
get_session_sids/2,
|
||||||
get_user_info/2,
|
get_user_info/2,
|
||||||
get_user_info/3,
|
get_user_info/3,
|
||||||
|
set_user_info/5,
|
||||||
|
del_user_info/4,
|
||||||
get_user_ip/3,
|
get_user_ip/3,
|
||||||
get_max_user_sessions/2,
|
get_max_user_sessions/2,
|
||||||
get_all_pids/0,
|
get_all_pids/0,
|
||||||
@ -266,6 +268,44 @@ get_user_info(User, Server, Resource) ->
|
|||||||
|Session#session.info]
|
|Session#session.info]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec set_user_info(binary(), binary(), binary(), atom(), term()) -> ok | {error, any()}.
|
||||||
|
set_user_info(User, Server, Resource, Key, Val) ->
|
||||||
|
LUser = jid:nodeprep(User),
|
||||||
|
LServer = jid:nameprep(Server),
|
||||||
|
LResource = jid:resourceprep(Resource),
|
||||||
|
Mod = get_sm_backend(LServer),
|
||||||
|
case get_sessions(Mod, LUser, LServer, LResource) of
|
||||||
|
[] -> {error, notfound};
|
||||||
|
Ss ->
|
||||||
|
lists:foldl(
|
||||||
|
fun(#session{sid = {_, Pid},
|
||||||
|
info = Info} = Session, _) when Pid == self() ->
|
||||||
|
Info1 = lists:keystore(Key, 1, Info, {Key, Val}),
|
||||||
|
set_session(Session#session{info = Info1});
|
||||||
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, {error, not_owner}, Ss)
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec del_user_info(binary(), binary(), binary(), atom()) -> ok | {error, any()}.
|
||||||
|
del_user_info(User, Server, Resource, Key) ->
|
||||||
|
LUser = jid:nodeprep(User),
|
||||||
|
LServer = jid:nameprep(Server),
|
||||||
|
LResource = jid:resourceprep(Resource),
|
||||||
|
Mod = get_sm_backend(LServer),
|
||||||
|
case get_sessions(Mod, LUser, LServer, LResource) of
|
||||||
|
[] -> {error, notfound};
|
||||||
|
Ss ->
|
||||||
|
lists:foldl(
|
||||||
|
fun(#session{sid = {_, Pid},
|
||||||
|
info = Info} = Session, _) when Pid == self() ->
|
||||||
|
Info1 = lists:keydelete(Key, 1, Info),
|
||||||
|
set_session(Session#session{info = Info1});
|
||||||
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, {error, not_owner}, Ss)
|
||||||
|
end.
|
||||||
|
|
||||||
-spec set_presence(sid(), binary(), binary(), binary(),
|
-spec set_presence(sid(), binary(), binary(), binary(),
|
||||||
prio(), presence(), info()) -> ok.
|
prio(), presence(), info()) -> ok.
|
||||||
|
|
||||||
@ -483,9 +523,13 @@ set_session(SID, User, Server, Resource, Priority, Info) ->
|
|||||||
LResource = jid:resourceprep(Resource),
|
LResource = jid:resourceprep(Resource),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
USR = {LUser, LServer, LResource},
|
USR = {LUser, LServer, LResource},
|
||||||
|
set_session(#session{sid = SID, usr = USR, us = US,
|
||||||
|
priority = Priority, info = Info}).
|
||||||
|
|
||||||
|
-spec set_session(#session{}) -> ok | {error, any()}.
|
||||||
|
set_session(#session{us = {LUser, LServer}} = Session) ->
|
||||||
Mod = get_sm_backend(LServer),
|
Mod = get_sm_backend(LServer),
|
||||||
case Mod:set_session(#session{sid = SID, usr = USR, us = US,
|
case Mod:set_session(Session) of
|
||||||
priority = Priority, info = Info}) of
|
|
||||||
ok ->
|
ok ->
|
||||||
case use_cache(Mod, LServer) of
|
case use_cache(Mod, LServer) of
|
||||||
true ->
|
true ->
|
||||||
|
@ -35,38 +35,25 @@
|
|||||||
-export([start/2, stop/1, reload/3]).
|
-export([start/2, stop/1, reload/3]).
|
||||||
|
|
||||||
-export([user_send_packet/1, user_receive_packet/1,
|
-export([user_send_packet/1, user_receive_packet/1,
|
||||||
iq_handler/1, remove_connection/4, disco_features/5,
|
iq_handler/1, disco_features/5,
|
||||||
is_carbon_copy/1, mod_opt_type/1, depends/2, clean_cache/1,
|
is_carbon_copy/1, mod_opt_type/1, depends/2,
|
||||||
mod_options/1]).
|
mod_options/1]).
|
||||||
|
%% For debugging purposes
|
||||||
|
-export([list/2]).
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("mod_carboncopy.hrl").
|
|
||||||
|
|
||||||
-type direction() :: sent | received.
|
-type direction() :: sent | received.
|
||||||
|
|
||||||
-callback init(binary(), gen_mod:opts()) -> any().
|
|
||||||
-callback enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
|
|
||||||
-callback disable(binary(), binary(), binary()) -> ok | {error, any()}.
|
|
||||||
-callback list(binary(), binary()) -> [{binary(), binary(), node()}].
|
|
||||||
-callback use_cache(binary()) -> boolean().
|
|
||||||
-callback cache_nodes(binary()) -> [node()].
|
|
||||||
|
|
||||||
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
|
||||||
|
|
||||||
-spec is_carbon_copy(stanza()) -> boolean().
|
-spec is_carbon_copy(stanza()) -> boolean().
|
||||||
is_carbon_copy(#message{meta = #{carbon_copy := true}}) ->
|
is_carbon_copy(#message{meta = #{carbon_copy := true}}) ->
|
||||||
true;
|
true;
|
||||||
is_carbon_copy(_) ->
|
is_carbon_copy(_) ->
|
||||||
false.
|
false.
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, _Opts) ->
|
||||||
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
||||||
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
|
|
||||||
init_cache(Mod, Host, Opts),
|
|
||||||
Mod:init(Host, Opts),
|
|
||||||
clean_cache(),
|
|
||||||
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)
|
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
||||||
ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
||||||
ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
||||||
@ -77,23 +64,10 @@ stop(Host) ->
|
|||||||
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
|
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
|
||||||
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
||||||
ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
||||||
ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89).
|
||||||
ejabberd_hooks:delete(unset_presence_hook,Host, ?MODULE, remove_connection, 10).
|
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(_Host, _NewOpts, _OldOpts) ->
|
||||||
NewMod = gen_mod:ram_db_mod(Host, NewOpts, ?MODULE),
|
ok.
|
||||||
OldMod = gen_mod:ram_db_mod(Host, OldOpts, ?MODULE),
|
|
||||||
if NewMod /= OldMod ->
|
|
||||||
NewMod:init(Host, NewOpts);
|
|
||||||
true ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
case use_cache(NewMod, Host) of
|
|
||||||
true ->
|
|
||||||
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(NewOpts));
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec disco_features({error, stanza_error()} | {result, [binary()]} | empty,
|
-spec disco_features({error, stanza_error()} | {result, [binary()]} | empty,
|
||||||
jid(), jid(), binary(), binary()) ->
|
jid(), jid(), binary(), binary()) ->
|
||||||
@ -113,19 +87,13 @@ iq_handler(#iq{type = set, lang = Lang, from = From,
|
|||||||
is_record(El, carbons_disable) ->
|
is_record(El, carbons_disable) ->
|
||||||
{U, S, R} = jid:tolower(From),
|
{U, S, R} = jid:tolower(From),
|
||||||
Result = case El of
|
Result = case El of
|
||||||
#carbons_enable{} ->
|
#carbons_enable{} -> enable(S, U, R, ?NS_CARBONS_2);
|
||||||
?DEBUG("Carbons enabled for user ~s@~s/~s", [U,S,R]),
|
#carbons_disable{} -> disable(S, U, R)
|
||||||
enable(S, U, R, ?NS_CARBONS_2);
|
|
||||||
#carbons_disable{} ->
|
|
||||||
?DEBUG("Carbons disabled for user ~s@~s/~s", [U,S,R]),
|
|
||||||
disable(S, U, R)
|
|
||||||
end,
|
end,
|
||||||
case Result of
|
case Result of
|
||||||
ok ->
|
ok ->
|
||||||
?DEBUG("carbons IQ result: ok", []),
|
|
||||||
xmpp:make_iq_result(IQ);
|
xmpp:make_iq_result(IQ);
|
||||||
{error,_Error} ->
|
{error, _} ->
|
||||||
?ERROR_MSG("Error enabling / disabling carbons: ~p", [Result]),
|
|
||||||
Txt = <<"Database failure">>,
|
Txt = <<"Database failure">>,
|
||||||
xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang))
|
xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang))
|
||||||
end;
|
end;
|
||||||
@ -180,12 +148,6 @@ check_and_forward(JID, To, Packet, Direction)->
|
|||||||
Packet
|
Packet
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec remove_connection(binary(), binary(), binary(), binary()) -> ok.
|
|
||||||
remove_connection(User, Server, Resource, _Status)->
|
|
||||||
disable(Server, User, Resource),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
|
|
||||||
%%% Internal
|
%%% Internal
|
||||||
%% Direction = received | sent <received xmlns='urn:xmpp:carbons:1'/>
|
%% Direction = received | sent <received xmlns='urn:xmpp:carbons:1'/>
|
||||||
-spec send_copies(jid(), jid(), message(), direction()) -> ok.
|
-spec send_copies(jid(), jid(), message(), direction()) -> ok.
|
||||||
@ -248,22 +210,26 @@ build_forward_packet(JID, #message{type = T} = Msg, Sender, Dest, Direction) ->
|
|||||||
|
|
||||||
-spec enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
|
-spec enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
|
||||||
enable(Host, U, R, CC)->
|
enable(Host, U, R, CC)->
|
||||||
?DEBUG("enabling for ~p", [U]),
|
?DEBUG("Enabling carbons for ~s@~s/~s", [U, Host, R]),
|
||||||
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
|
case ejabberd_sm:set_user_info(U, Host, R, carboncopy, CC) of
|
||||||
case Mod:enable(U, Host, R, CC) of
|
ok -> ok;
|
||||||
ok ->
|
{error, Reason} = Err ->
|
||||||
delete_cache(Mod, U, Host);
|
?ERROR_MSG("Failed to disable carbons for ~s@~s/~s: ~p",
|
||||||
{error, _} = Err ->
|
[U, Host, R, Reason]),
|
||||||
Err
|
Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec disable(binary(), binary(), binary()) -> ok | {error, any()}.
|
-spec disable(binary(), binary(), binary()) -> ok | {error, any()}.
|
||||||
disable(Host, U, R)->
|
disable(Host, U, R)->
|
||||||
?DEBUG("disabling for ~p", [U]),
|
?DEBUG("Disabling carbons for ~s@~s/~s", [U, Host, R]),
|
||||||
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
|
case ejabberd_sm:del_user_info(U, Host, R, carboncopy) of
|
||||||
Res = Mod:disable(U, Host, R),
|
ok -> ok;
|
||||||
delete_cache(Mod, U, Host),
|
{error, notfound} -> ok;
|
||||||
Res.
|
{error, Reason} = Err ->
|
||||||
|
?ERROR_MSG("Failed to disable carbons for ~s@~s/~s: ~p",
|
||||||
|
[U, Host, R, Reason]),
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
-spec complete_packet(jid(), message(), direction()) -> message().
|
-spec complete_packet(jid(), message(), direction()) -> message().
|
||||||
complete_packet(From, #message{from = undefined} = Msg, sent) ->
|
complete_packet(From, #message{from = undefined} = Msg, sent) ->
|
||||||
@ -291,99 +257,30 @@ is_received_muc_pm(_To, Packet, received) ->
|
|||||||
|
|
||||||
-spec list(binary(), binary()) -> [{Resource :: binary(), Namespace :: binary()}].
|
-spec list(binary(), binary()) -> [{Resource :: binary(), Namespace :: binary()}].
|
||||||
list(User, Server) ->
|
list(User, Server) ->
|
||||||
Mod = gen_mod:ram_db_mod(Server, ?MODULE),
|
lists:filtermap(
|
||||||
case use_cache(Mod, Server) of
|
fun({Resource, Info}) ->
|
||||||
true ->
|
case lists:keyfind(carboncopy, 1, Info) of
|
||||||
case ets_cache:lookup(
|
{_, NS} -> {true, {Resource, NS}};
|
||||||
?CARBONCOPY_CACHE, {User, Server},
|
false -> false
|
||||||
fun() ->
|
end
|
||||||
case Mod:list(User, Server) of
|
end, ejabberd_sm:get_user_info(User, Server)).
|
||||||
{ok, L} when L /= [] -> {ok, L};
|
|
||||||
_ -> error
|
|
||||||
end
|
|
||||||
end) of
|
|
||||||
{ok, L} -> [{Resource, NS} || {Resource, NS, _} <- L];
|
|
||||||
error -> []
|
|
||||||
end;
|
|
||||||
false ->
|
|
||||||
case Mod:list(User, Server) of
|
|
||||||
{ok, L} -> [{Resource, NS} || {Resource, NS, _} <- L];
|
|
||||||
error -> []
|
|
||||||
end
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
|
|
||||||
init_cache(Mod, Host, Opts) ->
|
|
||||||
case use_cache(Mod, Host) of
|
|
||||||
true ->
|
|
||||||
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Opts));
|
|
||||||
false ->
|
|
||||||
ets_cache:delete(?CARBONCOPY_CACHE)
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
|
||||||
cache_opts(Opts) ->
|
|
||||||
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
|
||||||
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
|
||||||
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
|
||||||
infinity -> infinity;
|
|
||||||
I -> timer:seconds(I)
|
|
||||||
end,
|
|
||||||
[{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}].
|
|
||||||
|
|
||||||
-spec use_cache(module(), binary()) -> boolean().
|
|
||||||
use_cache(Mod, Host) ->
|
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
|
||||||
true -> Mod:use_cache(Host);
|
|
||||||
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
|
||||||
cache_nodes(Mod, Host) ->
|
|
||||||
case erlang:function_exported(Mod, cache_nodes, 1) of
|
|
||||||
true -> Mod:cache_nodes(Host);
|
|
||||||
false -> ejabberd_cluster:get_nodes()
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec clean_cache(node()) -> non_neg_integer().
|
|
||||||
clean_cache(Node) ->
|
|
||||||
ets_cache:filter(
|
|
||||||
?CARBONCOPY_CACHE,
|
|
||||||
fun(_, error) ->
|
|
||||||
false;
|
|
||||||
(_, {ok, L}) ->
|
|
||||||
not lists:any(fun({_, _, N}) -> N == Node end, L)
|
|
||||||
end).
|
|
||||||
|
|
||||||
-spec clean_cache() -> ok.
|
|
||||||
clean_cache() ->
|
|
||||||
ejabberd_cluster:eval_everywhere(?MODULE, clean_cache, [node()]).
|
|
||||||
|
|
||||||
-spec delete_cache(module(), binary(), binary()) -> ok.
|
|
||||||
delete_cache(Mod, User, Server) ->
|
|
||||||
case use_cache(Mod, Server) of
|
|
||||||
true ->
|
|
||||||
ets_cache:delete(?CARBONCOPY_CACHE, {User, Server},
|
|
||||||
cache_nodes(Mod, Server));
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
depends(_Host, _Opts) ->
|
depends(_Host, _Opts) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
mod_opt_type(ram_db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
|
mod_opt_type(O) when O == cache_size; O == cache_life_time;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
O == use_cache; O == cache_missed;
|
||||||
fun(B) when is_boolean(B) -> B end;
|
O == ram_db_type ->
|
||||||
mod_opt_type(O) when O == cache_size; O == cache_life_time ->
|
fun(deprecated) -> deprecated;
|
||||||
fun(I) when is_integer(I), I>0 -> I;
|
(_) ->
|
||||||
(unlimited) -> infinity;
|
?WARNING_MSG("Option ~s of ~s has no effect anymore "
|
||||||
(infinity) -> infinity
|
"and will be ingored", [O, ?MODULE]),
|
||||||
|
deprecated
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_options(Host) ->
|
mod_options(_) ->
|
||||||
[{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
|
[{ram_db_type, deprecated},
|
||||||
{use_cache, ejabberd_config:use_cache(Host)},
|
{use_cache, deprecated},
|
||||||
{cache_size, ejabberd_config:cache_size(Host)},
|
{cache_size, deprecated},
|
||||||
{cache_missed, ejabberd_config:cache_missed(Host)},
|
{cache_missed, deprecated},
|
||||||
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
{cache_life_time, deprecated}].
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% File : mod_carboncopy_mnesia.erl
|
|
||||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 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_mnesia).
|
|
||||||
|
|
||||||
-behaviour(mod_carboncopy).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([init/2, enable/4, disable/3, list/2, use_cache/1]).
|
|
||||||
|
|
||||||
-include("mod_carboncopy.hrl").
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
init(_Host, _Opts) ->
|
|
||||||
Fields = record_info(fields, carboncopy),
|
|
||||||
try mnesia:table_info(carboncopy, attributes) of
|
|
||||||
Fields ->
|
|
||||||
ok;
|
|
||||||
_ ->
|
|
||||||
%% recreate..
|
|
||||||
mnesia:delete_table(carboncopy)
|
|
||||||
catch _:_Error ->
|
|
||||||
%% probably table don't exist
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
ejabberd_mnesia:create(?MODULE, carboncopy,
|
|
||||||
[{ram_copies, [node()]},
|
|
||||||
{attributes, record_info(fields, carboncopy)},
|
|
||||||
{type, bag}]).
|
|
||||||
|
|
||||||
enable(LUser, LServer, LResource, NS) ->
|
|
||||||
mnesia:dirty_write(
|
|
||||||
#carboncopy{us = {LUser, LServer},
|
|
||||||
resource = LResource,
|
|
||||||
version = NS}).
|
|
||||||
|
|
||||||
disable(LUser, LServer, LResource) ->
|
|
||||||
ToDelete = mnesia:dirty_match_object(
|
|
||||||
#carboncopy{us = {LUser, LServer},
|
|
||||||
resource = LResource,
|
|
||||||
_ = '_'}),
|
|
||||||
lists:foreach(fun mnesia:dirty_delete_object/1, ToDelete).
|
|
||||||
|
|
||||||
list(LUser, LServer) ->
|
|
||||||
{ok, mnesia:dirty_select(
|
|
||||||
carboncopy,
|
|
||||||
[{#carboncopy{us = {LUser, LServer}, resource = '$2',
|
|
||||||
version = '$3', node = '$4'},
|
|
||||||
[], [{{'$2','$3','$4'}}]}])}.
|
|
||||||
|
|
||||||
use_cache(_LServer) ->
|
|
||||||
false.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
@ -1,176 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% Created : 30 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 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_redis).
|
|
||||||
-behaviour(mod_carboncopy).
|
|
||||||
-behaviour(gen_server).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([init/2, enable/4, disable/3, list/2, cache_nodes/1]).
|
|
||||||
%% gen_server callbacks
|
|
||||||
-export([init/1, handle_cast/2, handle_call/3, handle_info/2,
|
|
||||||
terminate/2, code_change/3, start_link/0]).
|
|
||||||
|
|
||||||
-include("logger.hrl").
|
|
||||||
-include("mod_carboncopy.hrl").
|
|
||||||
|
|
||||||
-define(CARBONCOPY_KEY, <<"ejabberd:carboncopy">>).
|
|
||||||
|
|
||||||
-record(state, {}).
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
init(_Host, _Opts) ->
|
|
||||||
Spec = {?MODULE, {?MODULE, start_link, []},
|
|
||||||
transient, 5000, worker, [?MODULE]},
|
|
||||||
case supervisor:start_child(ejabberd_backend_sup, Spec) of
|
|
||||||
{ok, _Pid} -> ok;
|
|
||||||
Err -> Err
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec start_link() -> {ok, pid()} | {error, any()}.
|
|
||||||
start_link() ->
|
|
||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
||||||
|
|
||||||
cache_nodes(_LServer) ->
|
|
||||||
[node()].
|
|
||||||
|
|
||||||
enable(LUser, LServer, LResource, NS) ->
|
|
||||||
USKey = us_key(LUser, LServer),
|
|
||||||
NodeKey = node_key(),
|
|
||||||
JID = jid:encode({LUser, LServer, LResource}),
|
|
||||||
Data = term_to_binary({NS, node()}),
|
|
||||||
case ejabberd_redis:multi(
|
|
||||||
fun() ->
|
|
||||||
ejabberd_redis:hset(USKey, LResource, Data),
|
|
||||||
ejabberd_redis:sadd(NodeKey, [JID]),
|
|
||||||
ejabberd_redis:publish(
|
|
||||||
?CARBONCOPY_KEY,
|
|
||||||
term_to_binary({delete, {LUser, LServer}}))
|
|
||||||
end) of
|
|
||||||
{ok, _} ->
|
|
||||||
ok;
|
|
||||||
{error, _} ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
disable(LUser, LServer, LResource) ->
|
|
||||||
USKey = us_key(LUser, LServer),
|
|
||||||
NodeKey = node_key(),
|
|
||||||
JID = jid:encode({LUser, LServer, LResource}),
|
|
||||||
case ejabberd_redis:multi(
|
|
||||||
fun() ->
|
|
||||||
ejabberd_redis:hdel(USKey, [LResource]),
|
|
||||||
ejabberd_redis:srem(NodeKey, [JID]),
|
|
||||||
ejabberd_redis:publish(
|
|
||||||
?CARBONCOPY_KEY,
|
|
||||||
term_to_binary({delete, {LUser, LServer}}))
|
|
||||||
end) of
|
|
||||||
{ok, _} ->
|
|
||||||
ok;
|
|
||||||
{error, _} ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
list(LUser, LServer) ->
|
|
||||||
USKey = us_key(LUser, LServer),
|
|
||||||
case ejabberd_redis:hgetall(USKey) of
|
|
||||||
{ok, Pairs} ->
|
|
||||||
{ok, lists:flatmap(
|
|
||||||
fun({Resource, Data}) ->
|
|
||||||
try
|
|
||||||
{NS, Node} = binary_to_term(Data),
|
|
||||||
[{Resource, NS, Node}]
|
|
||||||
catch _:_ ->
|
|
||||||
?ERROR_MSG("invalid term stored in Redis "
|
|
||||||
"(key = ~s): ~p",
|
|
||||||
[USKey, Data]),
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
end, Pairs)};
|
|
||||||
{error, _} ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% gen_server callbacks
|
|
||||||
%%%===================================================================
|
|
||||||
init([]) ->
|
|
||||||
ejabberd_redis:subscribe([?CARBONCOPY_KEY]),
|
|
||||||
clean_table(),
|
|
||||||
{ok, #state{}}.
|
|
||||||
|
|
||||||
handle_call(_Request, _From, State) ->
|
|
||||||
Reply = ok,
|
|
||||||
{reply, Reply, State}.
|
|
||||||
|
|
||||||
handle_cast(_Msg, State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
handle_info({redis_message, ?CARBONCOPY_KEY, Data}, State) ->
|
|
||||||
case binary_to_term(Data) of
|
|
||||||
{delete, Key} ->
|
|
||||||
ets_cache:delete(?CARBONCOPY_CACHE, Key);
|
|
||||||
Msg ->
|
|
||||||
?WARNING_MSG("unexpected redis message: ~p", [Msg])
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
|
||||||
handle_info(Info, State) ->
|
|
||||||
?ERROR_MSG("unexpected info: ~p", [Info]),
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
|
||||||
{ok, State}.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
||||||
clean_table() ->
|
|
||||||
?DEBUG("Cleaning Redis 'carboncopy' table...", []),
|
|
||||||
NodeKey = node_key(),
|
|
||||||
case ejabberd_redis:smembers(NodeKey) of
|
|
||||||
{ok, JIDs} ->
|
|
||||||
ejabberd_redis:multi(
|
|
||||||
fun() ->
|
|
||||||
lists:foreach(
|
|
||||||
fun(JID) ->
|
|
||||||
{U, S, R} = jid:split(jid:decode(JID)),
|
|
||||||
USKey = us_key(U, S),
|
|
||||||
ejabberd_redis:hdel(USKey, [R])
|
|
||||||
end, JIDs)
|
|
||||||
end);
|
|
||||||
{error, _} ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
ejabberd_redis:del([NodeKey]),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
us_key(LUser, LServer) ->
|
|
||||||
<<"ejabberd:carboncopy:users:", LUser/binary, $@, LServer/binary>>.
|
|
||||||
|
|
||||||
node_key() ->
|
|
||||||
Node = erlang:atom_to_binary(node(), latin1),
|
|
||||||
<<"ejabberd:carboncopy:nodes:", Node/binary>>.
|
|
@ -1,82 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% Created : 15 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 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_riak).
|
|
||||||
-behaviour(mod_carboncopy).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([init/2, enable/4, disable/3, list/2]).
|
|
||||||
|
|
||||||
-include("logger.hrl").
|
|
||||||
-include("mod_carboncopy.hrl").
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
init(_Host, _Opts) ->
|
|
||||||
clean_table().
|
|
||||||
|
|
||||||
enable(LUser, LServer, LResource, NS) ->
|
|
||||||
ejabberd_riak:put(#carboncopy{us = {LUser, LServer},
|
|
||||||
resource = LResource,
|
|
||||||
version = NS},
|
|
||||||
carboncopy_schema(),
|
|
||||||
[{i, {LUser, LServer, LResource}},
|
|
||||||
{'2i', [{<<"us">>, {LUser, LServer}}]}]).
|
|
||||||
|
|
||||||
disable(LUser, LServer, LResource) ->
|
|
||||||
ejabberd_riak:delete(carboncopy, {LUser, LServer, LResource}).
|
|
||||||
|
|
||||||
list(LUser, LServer) ->
|
|
||||||
case ejabberd_riak:get_by_index(
|
|
||||||
carboncopy, carboncopy_schema(),
|
|
||||||
<<"us">>, {LUser, LServer}) of
|
|
||||||
{ok, Rs} ->
|
|
||||||
{ok, [{Resource, NS, Node}
|
|
||||||
|| #carboncopy{resource = Resource,
|
|
||||||
version = NS,
|
|
||||||
node = Node} <- Rs]};
|
|
||||||
{error, _} = Err ->
|
|
||||||
Err
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
||||||
carboncopy_schema() ->
|
|
||||||
{record_info(fields, carboncopy), #carboncopy{}}.
|
|
||||||
|
|
||||||
clean_table() ->
|
|
||||||
?DEBUG("Cleaning Riak 'carboncopy' table...", []),
|
|
||||||
case ejabberd_riak:get(carboncopy, carboncopy_schema()) of
|
|
||||||
{ok, Rs} ->
|
|
||||||
lists:foreach(
|
|
||||||
fun(#carboncopy{us = {U, S}, resource = R, node = Node})
|
|
||||||
when Node == node() ->
|
|
||||||
ejabberd_riak:delete(carboncopy, {U, S, R});
|
|
||||||
(_) ->
|
|
||||||
ok
|
|
||||||
end, Rs);
|
|
||||||
{error, Reason} = Err ->
|
|
||||||
?ERROR_MSG("Failed to clean Riak 'carboncopy' table: ~p", [Reason]),
|
|
||||||
Err
|
|
||||||
end.
|
|
@ -1,91 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% Created : 29 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 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("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",
|
|
||||||
"!server_host=%(LServer)s",
|
|
||||||
"!resource=%(LResource)s",
|
|
||||||
"namespace=%(NS)s",
|
|
||||||
"node=%(NodeS)s"]) of
|
|
||||||
ok ->
|
|
||||||
ok;
|
|
||||||
_Err ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
disable(LUser, LServer, LResource) ->
|
|
||||||
case ejabberd_sql:sql_query(
|
|
||||||
LServer,
|
|
||||||
?SQL("delete from carboncopy where username=%(LUser)s "
|
|
||||||
"and %(LServer)H and resource=%(LResource)s")) of
|
|
||||||
{updated, _} ->
|
|
||||||
ok;
|
|
||||||
_Err ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
list(LUser, LServer) ->
|
|
||||||
case ejabberd_sql:sql_query(
|
|
||||||
LServer,
|
|
||||||
?SQL("select @(resource)s, @(namespace)s, @(node)s from carboncopy "
|
|
||||||
"where username=%(LUser)s and %(LServer)H")) of
|
|
||||||
{selected, Rows} ->
|
|
||||||
{ok, [{Resource, NS, binary_to_atom(Node, latin1)}
|
|
||||||
|| {Resource, NS, Node} <- Rows]};
|
|
||||||
_Err ->
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
||||||
clean_table(LServer) ->
|
|
||||||
NodeS = erlang:atom_to_binary(node(), latin1),
|
|
||||||
?DEBUG("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]),
|
|
||||||
{error, db_failure}
|
|
||||||
end.
|
|
Loading…
Reference in New Issue
Block a user