1 |
|
%%%---------------------------------------------------------------------- |
2 |
|
%%% File : mod_last.erl |
3 |
|
%%% Author : MichaĆ Piotrowski <michal.piotrowski@erlang-solutions.com> |
4 |
|
%%% Purpose : mod_last rdbms backend (XEP-0012) |
5 |
|
%%% |
6 |
|
%%% |
7 |
|
%%% ejabberd, Copyright (C) 2002-2014 ProcessOne |
8 |
|
%%% MongooseIM, Copyright (C) 2014 Erlang Solutions Ltd. |
9 |
|
%%% |
10 |
|
%%%---------------------------------------------------------------------- |
11 |
|
|
12 |
|
|
13 |
|
-module(mod_last_rdbms). |
14 |
|
|
15 |
|
-behaviour(mod_last_backend). |
16 |
|
|
17 |
|
-include("mongoose.hrl"). |
18 |
|
|
19 |
|
%% API |
20 |
|
-export([init/2, |
21 |
|
get_last/3, |
22 |
|
count_active_users/3, |
23 |
|
set_last_info/5, |
24 |
|
remove_user/3, |
25 |
|
remove_domain/2]). |
26 |
|
|
27 |
|
-type host_type() :: mongooseim:host_type(). |
28 |
|
|
29 |
|
-spec init(host_type(), gen_mod:module_opts()) -> ok. |
30 |
|
init(HostType, _Opts) -> |
31 |
12 |
prepare_queries(HostType), |
32 |
12 |
ok. |
33 |
|
|
34 |
|
%% Prepared query functions |
35 |
|
prepare_queries(HostType) -> |
36 |
12 |
mongoose_rdbms:prepare(last_select, last, [server, username], |
37 |
|
<<"SELECT seconds, state FROM last WHERE server = ? AND username = ?">>), |
38 |
12 |
mongoose_rdbms:prepare(last_count_active, last, [server, seconds], |
39 |
|
<<"SELECT COUNT(*) FROM last WHERE server = ? AND seconds > ?">>), |
40 |
12 |
mongoose_rdbms:prepare(last_delete, last, [server, username], |
41 |
|
<<"DELETE FROM last WHERE server = ? AND username = ?">>), |
42 |
12 |
mongoose_rdbms:prepare(last_remove_domain, last, [server], |
43 |
|
<<"DELETE FROM last WHERE server = ?">>), |
44 |
12 |
rdbms_queries:prepare_upsert(HostType, last_upsert, last, |
45 |
|
[<<"server">>, <<"username">>, <<"seconds">>, <<"state">>], |
46 |
|
[<<"seconds">>, <<"state">>], |
47 |
|
[<<"server">>, <<"username">>]). |
48 |
|
|
49 |
|
-spec execute_get_last(host_type(), jid:lserver(), jid:luser()) -> mongoose_rdbms:query_result(). |
50 |
|
execute_get_last(HostType, LServer, LUser) -> |
51 |
38 |
mongoose_rdbms:execute_successfully(HostType, last_select, [LServer, LUser]). |
52 |
|
|
53 |
|
-spec execute_count_active_users(host_type(), jid:lserver(), mod_last:timestamp()) -> |
54 |
|
mongoose_rdbms:query_result(). |
55 |
|
execute_count_active_users(HostType, LServer, Seconds) -> |
56 |
9 |
mongoose_rdbms:execute_successfully(HostType, last_count_active, [LServer, Seconds]). |
57 |
|
|
58 |
|
-spec execute_remove_user(host_type(), jid:lserver(), jid:luser()) -> mongoose_rdbms:query_result(). |
59 |
|
execute_remove_user(HostType, LServer, LUser) -> |
60 |
77 |
mongoose_rdbms:execute_successfully(HostType, last_delete, [LServer, LUser]). |
61 |
|
|
62 |
|
-spec execute_upsert_last(host_type(), jid:lserver(), jid:luser(), |
63 |
|
mod_last:timestamp(), mod_last:status()) -> |
64 |
|
mongoose_rdbms:query_result(). |
65 |
|
execute_upsert_last(HostType, LServer, LUser, Seconds, State) -> |
66 |
89 |
InsertParams = [LServer, LUser, Seconds, State], |
67 |
89 |
UpdateParams = [Seconds, State], |
68 |
89 |
UniqueKeyValues = [LServer, LUser], |
69 |
89 |
rdbms_queries:execute_upsert(HostType, last_upsert, |
70 |
|
InsertParams, UpdateParams, UniqueKeyValues). |
71 |
|
|
72 |
|
%% API functions |
73 |
|
-spec get_last(host_type(), jid:luser(), jid:lserver()) -> |
74 |
|
{ok, mod_last:timestamp(), mod_last:status()} | not_found. |
75 |
|
get_last(HostType, LUser, LServer) -> |
76 |
38 |
Result = execute_get_last(HostType, LServer, LUser), |
77 |
38 |
decode_last_result(Result). |
78 |
|
|
79 |
|
-spec count_active_users(host_type(), jid:lserver(), mod_last:timestamp()) -> non_neg_integer(). |
80 |
|
count_active_users(HostType, LServer, Seconds) -> |
81 |
9 |
Result = execute_count_active_users(HostType, LServer, Seconds), |
82 |
9 |
mongoose_rdbms:selected_to_integer(Result). |
83 |
|
|
84 |
|
-spec set_last_info(host_type(), jid:luser(), jid:lserver(), |
85 |
|
mod_last:timestamp(), mod_last:status()) -> |
86 |
|
ok | {error, term()}. |
87 |
|
set_last_info(HostType, LUser, LServer, Seconds, State) -> |
88 |
89 |
wrap_rdbms_result(execute_upsert_last(HostType, LServer, LUser, Seconds, State)). |
89 |
|
|
90 |
|
-spec remove_user(host_type(), jid:luser(), jid:lserver()) -> ok | {error, term()}. |
91 |
|
remove_user(HostType, LUser, LServer) -> |
92 |
77 |
wrap_rdbms_result(execute_remove_user(HostType, LServer, LUser)). |
93 |
|
|
94 |
|
-spec remove_domain(host_type(), jid:lserver()) -> ok | {error, term()}. |
95 |
|
remove_domain(HostType, Domain) -> |
96 |
1 |
mongoose_rdbms:execute(HostType, last_remove_domain, [Domain]). |
97 |
|
|
98 |
|
%% Helper functions |
99 |
|
decode_last_result({selected, []}) -> |
100 |
9 |
not_found; |
101 |
|
decode_last_result({selected, [{DbSeconds, State}]}) -> |
102 |
29 |
Seconds = mongoose_rdbms:result_to_integer(DbSeconds), |
103 |
29 |
{ok, Seconds, State}. |
104 |
|
|
105 |
|
-spec wrap_rdbms_result({error, term()} | any()) -> ok | {error, term()}. |
106 |
:-( |
wrap_rdbms_result({error, _} = Error) -> Error; |
107 |
166 |
wrap_rdbms_result(_) -> ok. |