./ct_report/coverage/mod_offline_mnesia.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% Copyright notice from the originam mod_offline.erl
3 %%%
4 %%% File : mod_offline.erl
5 %%% Author : Alexey Shchepin <alexey@process-one.net>
6 %%% Purpose : Store and manage offline messages in Mnesia database.
7 %%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
8 %%%
9 %%%
10 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
11 %%%
12 %%% This program is free software; you can redistribute it and/or
13 %%% modify it under the terms of the GNU General Public License as
14 %%% published by the Free Software Foundation; either version 2 of the
15 %%% License, or (at your option) any later version.
16 %%%
17 %%% This program is distributed in the hope that it will be useful,
18 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
19 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 %%% General Public License for more details.
21 %%%
22 %%% You should have received a copy of the GNU General Public License
23 %%% along with this program; if not, write to the Free Software
24 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 %%%
26 %%%----------------------------------------------------------------------
27
28 -module(mod_offline_mnesia).
29 -behaviour(mod_offline_backend).
30 -export([init/2,
31 pop_messages/2,
32 fetch_messages/2,
33 write_messages/4,
34 count_offline_messages/4,
35 remove_expired_messages/2,
36 remove_old_messages/3,
37 remove_user/3]).
38
39 -include("mod_offline.hrl").
40
41 -define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
42
43 -spec init(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
44 init(_HostType, _Opts) ->
45 2 mongoose_mnesia:create_table(offline_msg,
46 [{disc_only_copies, [node()]}, {type, bag},
47 {attributes, record_info(fields, offline_msg)}]),
48 2 upgrade_table(),
49 2 ok.
50
51 -spec pop_messages(mongooseim:host_type(), jid:jid()) ->
52 {ok, [mod_offline:msg()]} | {error, any()}.
53 pop_messages(_HostType, To) ->
54 34 US = jid:to_lus(To),
55 34 F = fun() ->
56 34 Rs = mnesia:wread({offline_msg, US}),
57 34 mnesia:delete({offline_msg, US}),
58 34 Rs
59 end,
60 34 case mnesia:transaction(F) of
61 {atomic, Rs} ->
62 34 {ok, Rs};
63 {aborted, Reason} ->
64
:-(
{error, Reason}
65 end.
66
67 -spec fetch_messages(mongooseim:host_type(), jid:jid()) ->
68 {ok, [mod_offline:msg()]} | {error, any()}.
69 fetch_messages(_HostType, To) ->
70 30 US = jid:to_lus(To),
71 30 F = fun() -> mnesia:wread({offline_msg, US}) end,
72 30 case mnesia:transaction(F) of
73 {atomic, Rs} ->
74 30 {ok, Rs};
75 {aborted, Reason} ->
76
:-(
{error, Reason}
77 end.
78
79 -spec write_messages(mongooseim:host_type(), jid:luser(), jid:lserver(), [mod_offline:msg()]) ->
80 ok | {error, any()}.
81 write_messages(_HostType, _LUser, _LServer, Msgs) ->
82 5 F = fun() -> write_messages_t(Msgs) end,
83 5 case mnesia:transaction(F) of
84 {atomic, Result} ->
85 5 Result;
86 {aborted, Reason} ->
87
:-(
{error, {aborted, Reason}}
88 end.
89
90 write_messages_t(Msgs) ->
91 5 Len = length(Msgs),
92 5 write_all_messages_t(Len, Msgs).
93
94 write_all_messages_t(Len, Msgs) ->
95 5 case Len >= ?OFFLINE_TABLE_LOCK_THRESHOLD of
96
:-(
true -> mnesia:write_lock_table(offline_msg);
97 5 false -> ok
98 end,
99 5 [mnesia:write(M) || M <- Msgs],
100 5 ok.
101
102 -spec count_offline_messages(mongooseim:host_type(), jid:luser(), jid:lserver(),
103 mod_offline:msg_count()) ->
104 mod_offline:msg_count().
105 count_offline_messages(_HostType, LUser, LServer, _MaxNeeded) ->
106 9 US = {LUser, LServer},
107 9 F = fun () ->
108 9 Result = mnesia:read(offline_msg, US, read),
109 9 length(Result)
110 end,
111 9 case catch mnesia:async_dirty(F) of
112 9 I when is_integer(I) -> I;
113
:-(
_ -> 0
114 end.
115
116 -spec remove_expired_messages(mongooseim:host_type(), jid:lserver()) ->
117 {ok, mod_offline:msg_count()} | {error, any()}.
118 remove_expired_messages(_HostType, LServer) ->
119
:-(
TimeStamp = erlang:system_time(microsecond),
120
:-(
F = fun() ->
121
:-(
mnesia:write_lock_table(offline_msg),
122
:-(
mnesia:foldl(
123 fun(Rec, Acc) ->
124
:-(
Acc + remove_expired_message(LServer, TimeStamp, Rec)
125 end, 0, offline_msg)
126 end,
127
:-(
case mnesia:transaction(F) of
128 {aborted, Reason} ->
129
:-(
{error, Reason};
130 {atomic, Result} ->
131
:-(
{ok, Result}
132 end.
133
134 -spec remove_old_messages(mongooseim:host_type(), jid:lserver(), mod_offline:timestamp()) ->
135 {ok, mod_offline:msg_count()} | {error, any()}.
136 remove_old_messages(_HostType, LServer, TimeStamp) ->
137
:-(
F = fun() ->
138
:-(
mnesia:write_lock_table(offline_msg),
139
:-(
mnesia:foldl(
140 fun(Rec, Acc) ->
141
:-(
Acc + remove_old_message(LServer, TimeStamp, Rec)
142 end, 0, offline_msg)
143 end,
144
:-(
case mnesia:transaction(F) of
145 {aborted, Reason} ->
146
:-(
{error, Reason};
147 {atomic, Result} ->
148
:-(
{ok, Result}
149 end.
150
151 remove_expired_message(LServer, TimeStamp, Rec = #offline_msg{us = {_, LServer}}) ->
152
:-(
case mod_offline:is_expired_message(TimeStamp, Rec) of
153 true ->
154
:-(
mnesia:delete_object(Rec),
155
:-(
1;
156 false ->
157
:-(
0
158 end;
159
:-(
remove_expired_message(_, _, _) -> 0.
160
161 remove_old_message(LServer, TimeStamp, Rec = #offline_msg{us = {_, LServer}}) ->
162
:-(
case is_old_message(TimeStamp, Rec) of
163 true ->
164
:-(
mnesia:delete_object(Rec),
165
:-(
1;
166 false ->
167
:-(
0
168 end;
169
:-(
remove_old_message(_, _, _) -> 0.
170
171 is_old_message(MaxAllowedTimeStamp, #offline_msg{timestamp=TimeStamp}) ->
172
:-(
TimeStamp < MaxAllowedTimeStamp.
173
174 -spec remove_user(mongooseim:host_type(), jid:luser(), jid:lserver()) -> ok.
175 remove_user(_HostType, LUser, LServer) ->
176 34 US = {LUser, LServer},
177 34 F = fun() ->
178 34 mnesia:delete({offline_msg, US})
179 end,
180 34 mnesia:transaction(F),
181 34 ok.
182
183 upgrade_table() ->
184 2 Fields = record_info(fields, offline_msg),
185 2 case mnesia:table_info(offline_msg, attributes) of
186 Fields ->
187 2 ok;
188 [us, timestamp, expire, from, to, packet] -> %% MongooseIM 3.5.0 and older
189
:-(
mnesia:transform_table(offline_msg, fun transform_from_3_5_0_to_next/1, Fields)
190 end.
191
192 transform_from_3_5_0_to_next(Record) ->
193
:-(
erlang:append_element(Record, []).
Line Hits Source