aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-13 09:59:39 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-13 09:59:39 +0300
commit7fd4808cdea6d22cd520bbfd1d0e12344fea7092 (patch)
tree46b6eb2fe391290fd903d1e4b3086aae7a9e5750 /src
parentMake it possible to get DB backend of a module (diff)
Clean mod_last.erl from DB specific code
Diffstat (limited to 'src')
-rw-r--r--src/mod_last.erl152
-rw-r--r--src/mod_last_mnesia.erl72
-rw-r--r--src/mod_last_riak.erl53
-rw-r--r--src/mod_last_sql.erl75
4 files changed, 224 insertions, 128 deletions
diff --git a/src/mod_last.erl b/src/mod_last.erl
index 009a1cb06..1af1847b3 100644
--- a/src/mod_last.erl
+++ b/src/mod_last.erl
@@ -45,23 +45,21 @@
-include("jlib.hrl").
-include("mod_privacy.hrl").
+-include("mod_last.hrl").
--record(last_activity, {us = {<<"">>, <<"">>} :: {binary(), binary()},
- timestamp = 0 :: non_neg_integer(),
- status = <<"">> :: binary()}).
+-callback init(binary(), gen_mod:opts()) -> any().
+-callback import(binary(), #last_activity{}) -> ok | pass.
+-callback get_last(binary(), binary()) ->
+ {ok, non_neg_integer(), binary()} | not_found | {error, any()}.
+-callback store_last_info(binary(), binary(), non_neg_integer(), binary()) ->
+ {atomic, any()}.
+-callback remove_user(binary(), binary()) -> {atomic, any()}.
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
one_queue),
- case gen_mod:db_type(Host, Opts) of
- mnesia ->
- mnesia:create_table(last_activity,
- [{disc_copies, [node()]},
- {attributes,
- record_info(fields, last_activity)}]),
- update_table();
- _ -> ok
- end,
+ Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
+ Mod:init(Host, Opts),
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
?NS_LAST, ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
@@ -163,38 +161,8 @@ process_sm_iq(From, To,
%% @spec (LUser::string(), LServer::string()) ->
%% {ok, TimeStamp::integer(), Status::string()} | not_found | {error, Reason}
get_last(LUser, LServer) ->
- get_last(LUser, LServer,
- gen_mod:db_type(LServer, ?MODULE)).
-
-get_last(LUser, LServer, mnesia) ->
- case catch mnesia:dirty_read(last_activity,
- {LUser, LServer})
- of
- {'EXIT', Reason} -> {error, Reason};
- [] -> not_found;
- [#last_activity{timestamp = TimeStamp,
- status = Status}] ->
- {ok, TimeStamp, Status}
- end;
-get_last(LUser, LServer, riak) ->
- case ejabberd_riak:get(last_activity, last_activity_schema(),
- {LUser, LServer}) of
- {ok, #last_activity{timestamp = TimeStamp,
- status = Status}} ->
- {ok, TimeStamp, Status};
- {error, notfound} ->
- not_found;
- Err ->
- Err
- end;
-get_last(LUser, LServer, odbc) ->
- case catch odbc_queries:get_last(LServer, LUser) of
- {selected, []} ->
- not_found;
- {selected, [{TimeStamp, Status}]} ->
- {ok, TimeStamp, Status};
- Reason -> {error, {invalid_result, Reason}}
- end.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:get_last(LUser, LServer).
get_last_iq(#iq{lang = Lang} = IQ, SubEl, LUser, LServer) ->
case ejabberd_sm:get_user_resources(LUser, LServer) of
@@ -237,29 +205,8 @@ on_presence_update(User, Server, _Resource, Status) ->
store_last_info(User, Server, TimeStamp, Status) ->
LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server),
- DBType = gen_mod:db_type(LServer, ?MODULE),
- store_last_info(LUser, LServer, TimeStamp, Status,
- DBType).
-
-store_last_info(LUser, LServer, TimeStamp, Status,
- mnesia) ->
- US = {LUser, LServer},
- F = fun () ->
- mnesia:write(#last_activity{us = US,
- timestamp = TimeStamp,
- status = Status})
- end,
- mnesia:transaction(F);
-store_last_info(LUser, LServer, TimeStamp, Status,
- riak) ->
- US = {LUser, LServer},
- {atomic, ejabberd_riak:put(#last_activity{us = US,
- timestamp = TimeStamp,
- status = Status},
- last_activity_schema())};
-store_last_info(LUser, LServer, TimeStamp, Status,
- odbc) ->
- odbc_queries:set_last_t(LServer, LUser, TimeStamp, Status).
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:store_last_info(LUser, LServer, TimeStamp, Status).
%% @spec (LUser::string(), LServer::string()) ->
%% {ok, TimeStamp::integer(), Status::string()} | not_found
@@ -272,71 +219,20 @@ get_last_info(LUser, LServer) ->
remove_user(User, Server) ->
LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server),
- DBType = gen_mod:db_type(LServer, ?MODULE),
- remove_user(LUser, LServer, DBType).
-
-remove_user(LUser, LServer, mnesia) ->
- US = {LUser, LServer},
- F = fun () -> mnesia:delete({last_activity, US}) end,
- mnesia:transaction(F);
-remove_user(LUser, LServer, odbc) ->
- odbc_queries:del_last(LServer, LUser);
-remove_user(LUser, LServer, riak) ->
- {atomic, ejabberd_riak:delete(last_activity, {LUser, LServer})}.
-
-update_table() ->
- Fields = record_info(fields, last_activity),
- case mnesia:table_info(last_activity, attributes) of
- Fields ->
- ejabberd_config:convert_table_to_binary(
- last_activity, Fields, set,
- fun(#last_activity{us = {U, _}}) -> U end,
- fun(#last_activity{us = {U, S}, status = Status} = R) ->
- R#last_activity{us = {iolist_to_binary(U),
- iolist_to_binary(S)},
- status = iolist_to_binary(Status)}
- end);
- _ ->
- ?INFO_MSG("Recreating last_activity table", []),
- mnesia:transform_table(last_activity, ignore, Fields)
- end.
-
-last_activity_schema() ->
- {record_info(fields, last_activity), #last_activity{}}.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:remove_user(LUser, LServer).
-export(_Server) ->
- [{last_activity,
- fun(Host, #last_activity{us = {LUser, LServer},
- timestamp = TimeStamp, status = Status})
- when LServer == Host ->
- Username = ejabberd_odbc:escape(LUser),
- Seconds =
- ejabberd_odbc:escape(jlib:integer_to_binary(TimeStamp)),
- State = ejabberd_odbc:escape(Status),
- [[<<"delete from last where username='">>, Username, <<"';">>],
- [<<"insert into last(username, seconds, "
- "state) values ('">>,
- Username, <<"', '">>, Seconds, <<"', '">>, State,
- <<"');">>]];
- (_Host, _R) ->
- []
- end}].
+export(LServer) ->
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:export(LServer).
import(LServer) ->
- [{<<"select username, seconds, state from last">>,
- fun([LUser, TimeStamp, State]) ->
- #last_activity{us = {LUser, LServer},
- timestamp = jlib:binary_to_integer(
- TimeStamp),
- status = State}
- end}].
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:import(LServer).
-import(_LServer, mnesia, #last_activity{} = LA) ->
- mnesia:dirty_write(LA);
-import(_LServer, riak, #last_activity{} = LA) ->
- ejabberd_riak:put(LA, last_activity_schema());
-import(_, _, _) ->
- pass.
+import(LServer, DBType, LA) ->
+ Mod = gen_mod:db_mod(DBType, ?MODULE),
+ Mod:import(LServer, LA).
transform_options(Opts) ->
lists:foldl(fun transform_options/2, [], Opts).
diff --git a/src/mod_last_mnesia.erl b/src/mod_last_mnesia.erl
new file mode 100644
index 000000000..7a1610abb
--- /dev/null
+++ b/src/mod_last_mnesia.erl
@@ -0,0 +1,72 @@
+%%%-------------------------------------------------------------------
+%%% @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_last_mnesia).
+-behaviour(mod_last).
+
+%% API
+-export([init/2, import/2, get_last/2, store_last_info/4, remove_user/2]).
+
+-include("mod_last.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ mnesia:create_table(last_activity,
+ [{disc_copies, [node()]},
+ {attributes,
+ record_info(fields, last_activity)}]),
+ update_table().
+
+get_last(LUser, LServer) ->
+ case mnesia:dirty_read(last_activity, {LUser, LServer}) of
+ [] ->
+ not_found;
+ [#last_activity{timestamp = TimeStamp,
+ status = Status}] ->
+ {ok, TimeStamp, Status}
+ end.
+
+store_last_info(LUser, LServer, TimeStamp, Status) ->
+ US = {LUser, LServer},
+ F = fun () ->
+ mnesia:write(#last_activity{us = US,
+ timestamp = TimeStamp,
+ status = Status})
+ end,
+ mnesia:transaction(F).
+
+remove_user(LUser, LServer) ->
+ US = {LUser, LServer},
+ F = fun () -> mnesia:delete({last_activity, US}) end,
+ mnesia:transaction(F).
+
+import(_LServer, #last_activity{} = LA) ->
+ mnesia:dirty_write(LA).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+update_table() ->
+ Fields = record_info(fields, last_activity),
+ case mnesia:table_info(last_activity, attributes) of
+ Fields ->
+ ejabberd_config:convert_table_to_binary(
+ last_activity, Fields, set,
+ fun(#last_activity{us = {U, _}}) -> U end,
+ fun(#last_activity{us = {U, S}, status = Status} = R) ->
+ R#last_activity{us = {iolist_to_binary(U),
+ iolist_to_binary(S)},
+ status = iolist_to_binary(Status)}
+ end);
+ _ ->
+ ?INFO_MSG("Recreating last_activity table", []),
+ mnesia:transform_table(last_activity, ignore, Fields)
+ end.
diff --git a/src/mod_last_riak.erl b/src/mod_last_riak.erl
new file mode 100644
index 000000000..d25a3a156
--- /dev/null
+++ b/src/mod_last_riak.erl
@@ -0,0 +1,53 @@
+%%%-------------------------------------------------------------------
+%%% @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_last_riak).
+-behaviour(mod_last).
+
+%% API
+-export([init/2, import/2, get_last/2, store_last_info/4, remove_user/2]).
+
+-include("mod_last.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+get_last(LUser, LServer) ->
+ case ejabberd_riak:get(last_activity, last_activity_schema(),
+ {LUser, LServer}) of
+ {ok, #last_activity{timestamp = TimeStamp,
+ status = Status}} ->
+ {ok, TimeStamp, Status};
+ {error, notfound} ->
+ not_found;
+ Err ->
+ Err
+ end.
+
+store_last_info(LUser, LServer, TimeStamp, Status) ->
+ US = {LUser, LServer},
+ {atomic, ejabberd_riak:put(#last_activity{us = US,
+ timestamp = TimeStamp,
+ status = Status},
+ last_activity_schema())}.
+
+remove_user(LUser, LServer) ->
+ {atomic, ejabberd_riak:delete(last_activity, {LUser, LServer})}.
+
+import(_LServer, #last_activity{} = LA) ->
+ ejabberd_riak:put(LA, last_activity_schema()).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+last_activity_schema() ->
+ {record_info(fields, last_activity), #last_activity{}}.
diff --git a/src/mod_last_sql.erl b/src/mod_last_sql.erl
new file mode 100644
index 000000000..edfa37639
--- /dev/null
+++ b/src/mod_last_sql.erl
@@ -0,0 +1,75 @@
+%%%-------------------------------------------------------------------
+%%% @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_last_sql).
+-behaviour(mod_last).
+
+%% API
+-export([init/2, get_last/2, store_last_info/4, remove_user/2,
+ import/1, import/2, export/1]).
+
+-include("mod_last.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+get_last(LUser, LServer) ->
+ case catch odbc_queries:get_last(LServer, LUser) of
+ {selected, []} ->
+ not_found;
+ {selected, [{TimeStamp, Status}]} ->
+ {ok, TimeStamp, Status};
+ Reason ->
+ ?ERROR_MSG("failed to get last for user ~s@~s: ~p",
+ [LUser, LServer, Reason]),
+ {error, {invalid_result, Reason}}
+ end.
+
+store_last_info(LUser, LServer, TimeStamp, Status) ->
+ odbc_queries:set_last_t(LServer, LUser, TimeStamp, Status).
+
+remove_user(LUser, LServer) ->
+ odbc_queries:del_last(LServer, LUser).
+
+import(_LServer, _LA) ->
+ pass.
+
+export(_Server) ->
+ [{last_activity,
+ fun(Host, #last_activity{us = {LUser, LServer},
+ timestamp = TimeStamp, status = Status})
+ when LServer == Host ->
+ Username = ejabberd_odbc:escape(LUser),
+ Seconds =
+ ejabberd_odbc:escape(jlib:integer_to_binary(TimeStamp)),
+ State = ejabberd_odbc:escape(Status),
+ [[<<"delete from last where username='">>, Username, <<"';">>],
+ [<<"insert into last(username, seconds, "
+ "state) values ('">>,
+ Username, <<"', '">>, Seconds, <<"', '">>, State,
+ <<"');">>]];
+ (_Host, _R) ->
+ []
+ end}].
+
+import(LServer) ->
+ [{<<"select username, seconds, state from last">>,
+ fun([LUser, TimeStamp, State]) ->
+ #last_activity{us = {LUser, LServer},
+ timestamp = jlib:binary_to_integer(
+ TimeStamp),
+ status = State}
+ end}].
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================