./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(mongoooseim:host_type(), gen_mod:module_opts()) -> ok.
44 init(_HostType, _Opts) ->
45 1 mnesia:create_table(offline_msg,
46 [{disc_only_copies, [node()]},
47 {type, bag},
48 {attributes, record_info(fields, offline_msg)}]),
49 1 mnesia:add_table_copy(offline_msg, node(), disc_only_copies),
50 1 upgrade_table(),
51 1 ok.
52
53 -spec pop_messages(mongooseim:host_type(), jid:jid()) ->
54 {ok, [mod_offline:msg()]} | {error, any()}.
55 pop_messages(_HostType, To) ->
56 100 US = jid:to_lus(To),
57 100 F = fun() ->
58 100 Rs = mnesia:wread({offline_msg, US}),
59 100 mnesia:delete({offline_msg, US}),
60 100 Rs
61 end,
62 100 case mnesia:transaction(F) of
63 {atomic, Rs} ->
64 100 {ok, Rs};
65 {aborted, Reason} ->
66
:-(
{error, Reason}
67 end.
68
69 -spec fetch_messages(mongooseim:host_type(), jid:jid()) ->
70 {ok, [mod_offline:msg()]} | {error, any()}.
71 fetch_messages(_HostType, To) ->
72
:-(
US = jid:to_lus(To),
73
:-(
F = fun() -> mnesia:wread({offline_msg, US}) end,
74
:-(
case mnesia:transaction(F) of
75 {atomic, Rs} ->
76
:-(
{ok, Rs};
77 {aborted, Reason} ->
78
:-(
{error, Reason}
79 end.
80
81 -spec write_messages(mongooseim:host_type(), jid:luser(), jid:lserver(), [mod_offline:msg()]) ->
82 ok | {error, any()}.
83 write_messages(_HostType, _LUser, _LServer, Msgs) ->
84 8 F = fun() -> write_messages_t(Msgs) end,
85 8 case mnesia:transaction(F) of
86 {atomic, Result} ->
87 8 Result;
88 {aborted, Reason} ->
89
:-(
{error, {aborted, Reason}}
90 end.
91
92 write_messages_t(Msgs) ->
93 8 Len = length(Msgs),
94 8 write_all_messages_t(Len, Msgs).
95
96 write_all_messages_t(Len, Msgs) ->
97 8 case Len >= ?OFFLINE_TABLE_LOCK_THRESHOLD of
98
:-(
true -> mnesia:write_lock_table(offline_msg);
99 8 false -> ok
100 end,
101 8 [mnesia:write(M) || M <- Msgs],
102 8 ok.
103
104 -spec count_offline_messages(mongooseim:host_type(), jid:luser(), jid:lserver(),
105 mod_offline:msg_count()) ->
106 mod_offline:msg_count().
107 count_offline_messages(_HostType, LUser, LServer, _MaxNeeded) ->
108 8 US = {LUser, LServer},
109 8 F = fun () ->
110 8 Result = mnesia:read(offline_msg, US, read),
111 8 length(Result)
112 end,
113 8 case catch mnesia:async_dirty(F) of
114 8 I when is_integer(I) -> I;
115
:-(
_ -> 0
116 end.
117
118 -spec remove_expired_messages(mongooseim:host_type(), jid:lserver()) ->
119 {ok, mod_offline:msg_count()} | {error, any()}.
120 remove_expired_messages(_HostType, LServer) ->
121
:-(
TimeStamp = erlang:system_time(microsecond),
122
:-(
F = fun() ->
123
:-(
mnesia:write_lock_table(offline_msg),
124
:-(
mnesia:foldl(
125 fun(Rec, Acc) ->
126
:-(
Acc + remove_expired_message(LServer, TimeStamp, Rec)
127 end, 0, offline_msg)
128 end,
129
:-(
case mnesia:transaction(F) of
130 {aborted, Reason} ->
131
:-(
{error, Reason};
132 {atomic, Result} ->
133
:-(
{ok, Result}
134 end.
135
136 -spec remove_old_messages(mongooseim:host_type(), jid:lserver(), mod_offline:timestamp()) ->
137 {ok, mod_offline:msg_count()} | {error, any()}.
138 remove_old_messages(_HostType, LServer, TimeStamp) ->
139
:-(
F = fun() ->
140
:-(
mnesia:write_lock_table(offline_msg),
141
:-(
mnesia:foldl(
142 fun(Rec, Acc) ->
143
:-(
Acc + remove_old_message(LServer, TimeStamp, Rec)
144 end, 0, offline_msg)
145 end,
146
:-(
case mnesia:transaction(F) of
147 {aborted, Reason} ->
148
:-(
{error, Reason};
149 {atomic, Result} ->
150
:-(
{ok, Result}
151 end.
152
153 remove_expired_message(LServer, TimeStamp, Rec = #offline_msg{us = {_, LServer}}) ->
154
:-(
case mod_offline:is_expired_message(TimeStamp, Rec) of
155 true ->
156
:-(
mnesia:delete_object(Rec),
157
:-(
1;
158 false ->
159
:-(
0
160 end;
161
:-(
remove_expired_message(_, _, _) -> 0.
162
163 remove_old_message(LServer, TimeStamp, Rec = #offline_msg{us = {_, LServer}}) ->
164
:-(
case is_old_message(TimeStamp, Rec) of
165 true ->
166
:-(
mnesia:delete_object(Rec),
167
:-(
1;
168 false ->
169
:-(
0
170 end;
171
:-(
remove_old_message(_, _, _) -> 0.
172
173 is_old_message(MaxAllowedTimeStamp, #offline_msg{timestamp=TimeStamp}) ->
174
:-(
TimeStamp < MaxAllowedTimeStamp.
175
176 -spec remove_user(mongooseim:host_type(), jid:luser(), jid:lserver()) -> ok.
177 remove_user(_HostType, LUser, LServer) ->
178
:-(
US = {LUser, LServer},
179
:-(
F = fun() ->
180
:-(
mnesia:delete({offline_msg, US})
181 end,
182
:-(
mnesia:transaction(F),
183
:-(
ok.
184
185 upgrade_table() ->
186 1 Fields = record_info(fields, offline_msg),
187 1 case mnesia:table_info(offline_msg, attributes) of
188 Fields ->
189 1 ok;
190 [us, timestamp, expire, from, to, packet] -> %% MongooseIM 3.5.0 and older
191
:-(
mnesia:transform_table(offline_msg, fun transform_from_3_5_0_to_next/1, Fields)
192 end.
193
194 transform_from_3_5_0_to_next(Record) ->
195
:-(
erlang:append_element(Record, []).
Line Hits Source