Clean mod_caps.erl from DB specific code

This commit is contained in:
Evgeniy Khramtsov 2016-04-13 11:41:04 +03:00
parent 2d7e03f5e1
commit cd094bc903
5 changed files with 203 additions and 123 deletions

4
include/mod_caps.hrl Normal file
View File

@ -0,0 +1,4 @@
-record(caps_features,
{node_pair = {<<"">>, <<"">>} :: {binary(), binary()},
features = [] :: [binary()] | pos_integer()
}).

View File

@ -80,6 +80,12 @@
-record(state, {host = <<"">> :: binary()}).
-callback init(binary(), gen_mod:opts()) -> any().
-callback caps_read(binary(), {binary(), binary()}) ->
{ok, non_neg_integer() | [binary()]} | error.
-callback caps_write(binary(), {binary(), binary()},
non_neg_integer() | [binary()]) -> any().
start_link(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
gen_server:start_link({local, Proc}, ?MODULE,
@ -300,28 +306,9 @@ c2s_broadcast_recipients(InAcc, Host, C2SState,
end;
c2s_broadcast_recipients(Acc, _, _, _, _, _) -> Acc.
init_db(mnesia, _Host) ->
case catch mnesia:table_info(caps_features, storage_type) of
{'EXIT', _} ->
ok;
disc_only_copies ->
ok;
_ ->
mnesia:delete_table(caps_features)
end,
mnesia:create_table(caps_features,
[{disc_only_copies, [node()]},
{local_content, true},
{attributes,
record_info(fields, caps_features)}]),
update_table(),
mnesia:add_table_copy(caps_features, node(),
disc_only_copies);
init_db(_, _) ->
ok.
init([Host, Opts]) ->
init_db(gen_mod:db_type(Host, Opts), Host),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
MaxSize = gen_mod:get_opt(cache_size, Opts,
fun(I) when is_integer(I), I>0 -> I end,
1000),
@ -450,65 +437,13 @@ feature_response(_IQResult, Host, From, Caps,
caps_read_fun(Host, Node) ->
LServer = jid:nameprep(Host),
DBType = gen_mod:db_type(LServer, ?MODULE),
caps_read_fun(LServer, Node, DBType).
caps_read_fun(_LServer, Node, mnesia) ->
fun () ->
case mnesia:dirty_read({caps_features, Node}) of
[#caps_features{features = Features}] -> {ok, Features};
_ -> error
end
end;
caps_read_fun(_LServer, Node, riak) ->
fun() ->
case ejabberd_riak:get(caps_features, caps_features_schema(), Node) of
{ok, #caps_features{features = Features}} -> {ok, Features};
_ -> error
end
end;
caps_read_fun(LServer, {Node, SubNode}, odbc) ->
fun() ->
SNode = ejabberd_odbc:escape(Node),
SSubNode = ejabberd_odbc:escape(SubNode),
case ejabberd_odbc:sql_query(
LServer, [<<"select feature from caps_features where ">>,
<<"node='">>, SNode, <<"' and subnode='">>,
SSubNode, <<"';">>]) of
{selected, [<<"feature">>], [[H]|_] = Fs} ->
case catch jlib:binary_to_integer(H) of
Int when is_integer(Int), Int>=0 ->
{ok, Int};
_ ->
{ok, lists:flatten(Fs)}
end;
_ ->
error
end
end.
Mod = gen_mod:db_mod(LServer, ?MODULE),
fun() -> Mod:caps_read(LServer, Node) end.
caps_write_fun(Host, Node, Features) ->
LServer = jid:nameprep(Host),
DBType = gen_mod:db_type(LServer, ?MODULE),
caps_write_fun(LServer, Node, Features, DBType).
caps_write_fun(_LServer, Node, Features, mnesia) ->
fun () ->
mnesia:dirty_write(#caps_features{node_pair = Node,
features = Features})
end;
caps_write_fun(_LServer, Node, Features, riak) ->
fun () ->
ejabberd_riak:put(#caps_features{node_pair = Node,
features = Features},
caps_features_schema())
end;
caps_write_fun(LServer, NodePair, Features, odbc) ->
fun () ->
ejabberd_odbc:sql_transaction(
LServer,
sql_write_features_t(NodePair, Features))
end.
Mod = gen_mod:db_mod(LServer, ?MODULE),
fun() -> Mod:caps_write(LServer, Node, Features) end.
make_my_disco_hash(Host) ->
JID = jid:make(<<"">>, Host, <<"">>),
@ -658,61 +593,20 @@ is_valid_node(Node) ->
false
end.
update_table() ->
Fields = record_info(fields, caps_features),
case mnesia:table_info(caps_features, attributes) of
Fields ->
ejabberd_config:convert_table_to_binary(
caps_features, Fields, set,
fun(#caps_features{node_pair = {N, _}}) -> N end,
fun(#caps_features{node_pair = {N, P},
features = Fs} = R) ->
NewFs = if is_integer(Fs) ->
Fs;
true ->
[iolist_to_binary(F) || F <- Fs]
end,
R#caps_features{node_pair = {iolist_to_binary(N),
iolist_to_binary(P)},
features = NewFs}
end);
_ ->
?INFO_MSG("Recreating caps_features table", []),
mnesia:transform_table(caps_features, ignore, Fields)
end.
sql_write_features_t({Node, SubNode}, Features) ->
SNode = ejabberd_odbc:escape(Node),
SSubNode = ejabberd_odbc:escape(SubNode),
NewFeatures = if is_integer(Features) ->
[jlib:integer_to_binary(Features)];
true ->
Features
end,
[[<<"delete from caps_features where node='">>,
SNode, <<"' and subnode='">>, SSubNode, <<"';">>]|
[[<<"insert into caps_features(node, subnode, feature) ">>,
<<"values ('">>, SNode, <<"', '">>, SSubNode, <<"', '">>,
ejabberd_odbc:escape(F), <<"');">>] || F <- NewFeatures]].
caps_features_schema() ->
{record_info(fields, caps_features), #caps_features{}}.
export(_Server) ->
[{caps_features,
fun(_Host, #caps_features{node_pair = NodePair,
features = Features}) ->
sql_write_features_t(NodePair, Features);
(_Host, _R) ->
[]
end}].
export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer).
import_info() ->
[{<<"caps_features">>, 4}].
import_start(LServer, DBType) ->
ets:new(caps_features_tmp, [private, named_table, bag]),
init_db(DBType, LServer),
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []),
ok.
import(_LServer, {odbc, _}, _DBType, <<"caps_features">>,

73
src/mod_caps_mnesia.erl Normal file
View File

@ -0,0 +1,73 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2016, Evgeny Khramtsov
%%% @doc
%%%
%%% @end
%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(mod_caps_mnesia).
-behaviour(mod_caps).
%% API
-export([init/2, caps_read/2, caps_write/3]).
-include("mod_caps.hrl").
-include("logger.hrl").
%%%===================================================================
%%% API
%%%===================================================================
init(_Host, _Opts) ->
case catch mnesia:table_info(caps_features, storage_type) of
{'EXIT', _} ->
ok;
disc_only_copies ->
ok;
_ ->
mnesia:delete_table(caps_features)
end,
mnesia:create_table(caps_features,
[{disc_only_copies, [node()]},
{local_content, true},
{attributes,
record_info(fields, caps_features)}]),
update_table(),
mnesia:add_table_copy(caps_features, node(),
disc_only_copies).
caps_read(_LServer, Node) ->
case mnesia:dirty_read({caps_features, Node}) of
[#caps_features{features = Features}] -> {ok, Features};
_ -> error
end.
caps_write(_LServer, Node, Features) ->
mnesia:dirty_write(#caps_features{node_pair = Node,
features = Features}).
%%%===================================================================
%%% Internal functions
%%%===================================================================
update_table() ->
Fields = record_info(fields, caps_features),
case mnesia:table_info(caps_features, attributes) of
Fields ->
ejabberd_config:convert_table_to_binary(
caps_features, Fields, set,
fun(#caps_features{node_pair = {N, _}}) -> N end,
fun(#caps_features{node_pair = {N, P},
features = Fs} = R) ->
NewFs = if is_integer(Fs) ->
Fs;
true ->
[iolist_to_binary(F) || F <- Fs]
end,
R#caps_features{node_pair = {iolist_to_binary(N),
iolist_to_binary(P)},
features = NewFs}
end);
_ ->
?INFO_MSG("Recreating caps_features table", []),
mnesia:transform_table(caps_features, ignore, Fields)
end.

38
src/mod_caps_riak.erl Normal file
View File

@ -0,0 +1,38 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2016, Evgeny Khramtsov
%%% @doc
%%%
%%% @end
%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(mod_caps_riak).
-behaviour(mod_caps).
%% API
-export([init/2, caps_read/2, caps_write/3]).
-include("mod_caps.hrl").
%%%===================================================================
%%% API
%%%===================================================================
init(_Host, _Opts) ->
ok.
caps_read(_LServer, Node) ->
case ejabberd_riak:get(caps_features, caps_features_schema(), Node) of
{ok, #caps_features{features = Features}} -> {ok, Features};
_ -> error
end.
caps_write(_LServer, Node, Features) ->
ejabberd_riak:put(#caps_features{node_pair = Node,
features = Features},
caps_features_schema()).
%%%===================================================================
%%% Internal functions
%%%===================================================================
caps_features_schema() ->
{record_info(fields, caps_features), #caps_features{}}.

71
src/mod_caps_sql.erl Normal file
View File

@ -0,0 +1,71 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2016, Evgeny Khramtsov
%%% @doc
%%%
%%% @end
%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(mod_caps_sql).
-behaviour(mod_caps).
%% API
-export([init/2, caps_read/2, caps_write/3, export/1]).
-include("mod_caps.hrl").
%%%===================================================================
%%% API
%%%===================================================================
init(_Host, _Opts) ->
ok.
caps_read(LServer, {Node, SubNode}) ->
SNode = ejabberd_odbc:escape(Node),
SSubNode = ejabberd_odbc:escape(SubNode),
case ejabberd_odbc:sql_query(
LServer, [<<"select feature from caps_features where ">>,
<<"node='">>, SNode, <<"' and subnode='">>,
SSubNode, <<"';">>]) of
{selected, [<<"feature">>], [[H]|_] = Fs} ->
case catch jlib:binary_to_integer(H) of
Int when is_integer(Int), Int>=0 ->
{ok, Int};
_ ->
{ok, lists:flatten(Fs)}
end;
_ ->
error
end.
caps_write(LServer, NodePair, Features) ->
ejabberd_odbc:sql_transaction(
LServer,
sql_write_features_t(NodePair, Features)).
export(_Server) ->
[{caps_features,
fun(_Host, #caps_features{node_pair = NodePair,
features = Features}) ->
sql_write_features_t(NodePair, Features);
(_Host, _R) ->
[]
end}].
%%%===================================================================
%%% Internal functions
%%%===================================================================
sql_write_features_t({Node, SubNode}, Features) ->
SNode = ejabberd_odbc:escape(Node),
SSubNode = ejabberd_odbc:escape(SubNode),
NewFeatures = if is_integer(Features) ->
[jlib:integer_to_binary(Features)];
true ->
Features
end,
[[<<"delete from caps_features where node='">>,
SNode, <<"' and subnode='">>, SSubNode, <<"';">>]|
[[<<"insert into caps_features(node, subnode, feature) ">>,
<<"values ('">>, SNode, <<"', '">>, SSubNode, <<"', '">>,
ejabberd_odbc:escape(F), <<"');">>] || F <- NewFeatures]].