]> granicus.if.org Git - ejabberd/commitdiff
Clean mod_last.erl from DB specific code
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 13 Apr 2016 06:59:39 +0000 (09:59 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 13 Apr 2016 06:59:39 +0000 (09:59 +0300)
include/mod_last.hrl [new file with mode: 0644]
src/mod_last.erl
src/mod_last_mnesia.erl [new file with mode: 0644]
src/mod_last_riak.erl [new file with mode: 0644]
src/mod_last_sql.erl [new file with mode: 0644]

diff --git a/include/mod_last.hrl b/include/mod_last.hrl
new file mode 100644 (file)
index 0000000..494bf7b
--- /dev/null
@@ -0,0 +1,3 @@
+-record(last_activity, {us = {<<"">>, <<"">>} :: {binary(), binary()},
+                        timestamp = 0 :: non_neg_integer(),
+                        status = <<"">> :: binary()}).
index 009a1cb06650be36ddf415abcabe62faffa5bded..1af1847b3b68cdb8262eb511055eae262160d6e8 100644 (file)
 -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 (file)
index 0000000..7a1610a
--- /dev/null
@@ -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 (file)
index 0000000..d25a3a1
--- /dev/null
@@ -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 (file)
index 0000000..edfa376
--- /dev/null
@@ -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
+%%%===================================================================