diff options
author | Alexey Shchepin <alexey@process-one.net> | 2004-09-10 20:57:00 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2004-09-10 20:57:00 +0000 |
commit | e0ede61e0ff46d72542ffd001f7b3e35f1184431 (patch) | |
tree | 2c4d64ec7d2b0565657e9250fab1c644f8794bc8 /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.erl | 119 |
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. + |