aboutsummaryrefslogtreecommitdiff
path: root/src/mod_last.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_last.erl')
-rw-r--r--src/mod_last.erl185
1 files changed, 37 insertions, 148 deletions
diff --git a/src/mod_last.erl b/src/mod_last.erl
index d76b60491..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,
@@ -86,10 +84,11 @@ stop(Host) ->
%%%
process_local_iq(_From, _To,
- #iq{type = Type, sub_el = SubEl} = IQ) ->
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+ IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
get ->
Sec = get_node_uptime(),
IQ#iq{type = result,
@@ -123,10 +122,11 @@ now_to_seconds({MegaSecs, Secs, _MicroSecs}) ->
%%%
process_sm_iq(From, To,
- #iq{type = Type, sub_el = SubEl} = IQ) ->
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+ IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
get ->
User = To#jid.luser,
Server = To#jid.lserver,
@@ -153,62 +153,29 @@ process_sm_iq(From, To,
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
end;
true ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
+ Txt = <<"Not subscribed">>,
+ IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
end
end.
%% @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)).
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:get_last(LUser, LServer).
-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) ->
- Username = ejabberd_odbc:escape(LUser),
- case catch odbc_queries:get_last(LServer, Username) of
- {selected, [<<"seconds">>, <<"state">>], []} ->
- not_found;
- {selected, [<<"seconds">>, <<"state">>],
- [[STimeStamp, Status]]} ->
- case catch jlib:binary_to_integer(STimeStamp) of
- TimeStamp when is_integer(TimeStamp) ->
- {ok, TimeStamp, Status};
- Reason -> {error, {invalid_timestamp, Reason}}
- end;
- Reason -> {error, {invalid_result, Reason}}
- end.
-
-get_last_iq(IQ, SubEl, LUser, LServer) ->
+get_last_iq(#iq{lang = Lang} = IQ, SubEl, LUser, LServer) ->
case ejabberd_sm:get_user_resources(LUser, LServer) of
[] ->
case get_last(LUser, LServer) of
{error, _Reason} ->
+ Txt = <<"Database failure">>,
IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
+ sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]};
not_found ->
+ Txt = <<"No info about last activity found">>,
IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
+ sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]};
{ok, TimeStamp, Status} ->
TimeStamp2 = p1_time_compat:system_time(seconds),
Sec = TimeStamp2 - TimeStamp,
@@ -238,34 +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) ->
- Username = ejabberd_odbc:escape(LUser),
- Seconds =
- ejabberd_odbc:escape(iolist_to_binary(integer_to_list(TimeStamp))),
- State = ejabberd_odbc:escape(Status),
- odbc_queries:set_last_t(LServer, Username, Seconds,
- State).
+ 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
@@ -278,72 +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) ->
- Username = ejabberd_odbc:escape(LUser),
- odbc_queries:del_last(LServer, Username);
-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).