aboutsummaryrefslogtreecommitdiff
path: root/src/mod_offline.erl
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2004-09-10 20:57:00 +0000
committerAlexey Shchepin <alexey@process-one.net>2004-09-10 20:57:00 +0000
commite0ede61e0ff46d72542ffd001f7b3e35f1184431 (patch)
tree2c4d64ec7d2b0565657e9250fab1c644f8794bc8 /src/mod_offline.erl
parent* doc/guide.tex: Fix (thanks to Sander Devrieze) (diff)
* tools/ejabberdctl: Added call to "exec" (thanks to Sergei
Golovan) * src/msgs/ru.msg: Updated (thanks to Sergei Golovan) * src/mod_vcard.erl: Support for searching of prefix substring and limiting of result items (thanks to Sergei Golovan) * src/mod_offline.erl: Support for message expiration (JEP-0023) (thanks to Sergei Golovan) * src/jlib.hrl: Added NS_EXPIRE macros (thanks to Sergei Golovan) * src/ejabberd_logger_h.erl: Added reopen_log/0 (thanks to Sergei Golovan) * src/ejabberd_ctl.erl: Added return codes, updated "reopen-log" command, added "delete-expired-messages" and "status" commands (thanks to Sergei Golovan) * doc/guide.tex: Updated (thanks to Sergei Golovan) SVN Revision: 264
Diffstat (limited to '')
-rw-r--r--src/mod_offline.erl119
1 files changed, 105 insertions, 14 deletions
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index 89ee0765c..6959dbcef 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -17,12 +17,14 @@
store_packet/3,
resend_offline_messages/1,
pop_offline_messages/2,
+ remove_expired_messages/0,
remove_old_messages/1,
remove_user/1]).
+-include("ejabberd.hrl").
-include("jlib.hrl").
--record(offline_msg, {user, timestamp, from, to, packet}).
+-record(offline_msg, {user, timestamp, expire, from, to, packet}).
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
@@ -32,6 +34,7 @@ start(_) ->
[{disc_only_copies, [node()]},
{type, bag},
{attributes, record_info(fields, offline_msg)}]),
+ update_table(),
ejabberd_hooks:add(offline_message_hook,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook,
@@ -92,8 +95,11 @@ store_packet(From, To, Packet) ->
true ->
#jid{luser = LUser} = To,
TimeStamp = now(),
+ {xmlelement, _Name, _Attrs, Els} = Packet,
+ Expire = find_x_expire(TimeStamp, Els),
?PROCNAME ! #offline_msg{user = LUser,
timestamp = TimeStamp,
+ expire = Expire,
from = From,
to = To,
packet = Packet},
@@ -150,6 +156,34 @@ find_x_event([El | Els]) ->
find_x_event(Els)
end.
+find_x_expire(_, []) ->
+ never;
+find_x_expire(TimeStamp, [{xmlcdata, _} | Els]) ->
+ find_x_expire(TimeStamp, Els);
+find_x_expire(TimeStamp, [El | Els]) ->
+ case xml:get_tag_attr_s("xmlns", El) of
+ ?NS_EXPIRE ->
+ case xml:get_tag_attr_s("seconds", El) of
+ Val ->
+ case catch list_to_integer(Val) of
+ {'EXIT', _} ->
+ never;
+ Int when Int > 0 ->
+ {MegaSecs, Secs, MicroSecs} = TimeStamp,
+ S = MegaSecs * 1000000 + Secs + Int,
+ MegaSecs1 = S div 1000000,
+ Secs1 = S rem 1000000,
+ {MegaSecs1, Secs1, MicroSecs};
+ _ ->
+ never
+ end;
+ _ ->
+ never
+ end;
+ _ ->
+ find_x_expire(TimeStamp, Els)
+ end.
+
resend_offline_messages(User) ->
LUser = jlib:nodeprep(User),
@@ -187,23 +221,54 @@ pop_offline_messages(Ls, User) ->
end,
case mnesia:transaction(F) of
{atomic, Rs} ->
- lists:map(
- fun(R) ->
- {xmlelement, Name, Attrs, Els} = R#offline_msg.packet,
- {route,
- R#offline_msg.from,
- R#offline_msg.to,
- {xmlelement, Name, Attrs,
- Els ++
- [jlib:timestamp_to_xml(
- calendar:now_to_universal_time(
- R#offline_msg.timestamp))]}}
- end,
- Ls ++ lists:keysort(#offline_msg.timestamp, Rs));
+ TS = now(),
+ Ls ++ lists:map(
+ fun(R) ->
+ {xmlelement, Name, Attrs, Els} = R#offline_msg.packet,
+ {route,
+ R#offline_msg.from,
+ R#offline_msg.to,
+ {xmlelement, Name, Attrs,
+ Els ++
+ [jlib:timestamp_to_xml(
+ calendar:now_to_universal_time(
+ R#offline_msg.timestamp))]}}
+ end,
+ lists:filter(
+ fun(R) ->
+ case R#offline_msg.expire of
+ never ->
+ true;
+ TimeStamp ->
+ TS < TimeStamp
+ end
+ end,
+ lists:keysort(#offline_msg.timestamp, Rs)));
_ ->
Ls
end.
+remove_expired_messages() ->
+ TimeStamp = now(),
+ F = fun() ->
+ mnesia:write_lock_table(offline_msg),
+ mnesia:foldl(
+ fun(Rec, _Acc) ->
+ case Rec#offline_msg.expire of
+ never ->
+ ok;
+ TS ->
+ if
+ TS < TimeStamp ->
+ mnesia:delete_object(Rec);
+ true ->
+ ok
+ end
+ end
+ end, ok, offline_msg)
+ end,
+ mnesia:transaction(F).
+
remove_old_messages(Days) ->
{MegaSecs, Secs, _MicroSecs} = now(),
S = MegaSecs * 1000000 + Secs - 60 * 60 * 24 * Days,
@@ -227,3 +292,29 @@ remove_user(User) ->
mnesia:delete({offline_msg, LUser})
end,
mnesia:transaction(F).
+
+update_table() ->
+ Fields = record_info(fields, offline_msg),
+ case mnesia:table_info(offline_msg, attributes) of
+ Fields ->
+ ok;
+ [user, timestamp, from, to, packet] ->
+ ?INFO_MSG("Converting offline_msg table from "
+ "{user, timestamp, from, to, packet} format", []),
+ mnesia:transform_table(
+ offline_msg,
+ fun({_, U, TS, F, T, P}) ->
+ {xmlelement, _Name, _Attrs, Els} = P,
+ Expire = find_x_expire(TS, Els),
+ #offline_msg{user = U,
+ timestamp = TS,
+ expire = Expire,
+ from = F,
+ to = T,
+ packet = P}
+ end, Fields);
+ _ ->
+ ?INFO_MSG("Recreating offline_msg table", []),
+ mnesia:transform_table(last_activity, ignore, Fields)
+ end.
+