mirror of
https://github.com/processone/ejabberd.git
synced 2024-10-19 15:32:08 +02:00
mod_mam_mnesia: Use transactions when writing
Let mod_mam_mnesia use transactions when storing or deleting messages. If old messages of a user are to be removed, delete the user's archive and rewrite it from scratch, as that seems to be much faster than removing individual records with delete_object/1. Closes #1065.
This commit is contained in:
parent
70452ba25a
commit
3f3ecad981
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
-include_lib("stdlib/include/ms_transform.hrl").
|
-include_lib("stdlib/include/ms_transform.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
-include("logger.hrl").
|
||||||
-include("mod_mam.hrl").
|
-include("mod_mam.hrl").
|
||||||
|
|
||||||
-define(BIN_GREATER_THAN(A, B),
|
-define(BIN_GREATER_THAN(A, B),
|
||||||
@ -49,16 +50,34 @@ remove_room(_LServer, LName, LHost) ->
|
|||||||
remove_user(LName, LHost).
|
remove_user(LName, LHost).
|
||||||
|
|
||||||
delete_old_messages(global, TimeStamp, Type) ->
|
delete_old_messages(global, TimeStamp, Type) ->
|
||||||
MS = ets:fun2ms(fun(#archive_msg{timestamp = MsgTS,
|
delete_old_user_messages(mnesia:dirty_first(archive_msg), TimeStamp, Type).
|
||||||
type = MsgType} = Msg)
|
|
||||||
when MsgTS < TimeStamp,
|
delete_old_user_messages('$end_of_table', _TimeStamp, _Type) ->
|
||||||
MsgType == Type orelse Type == all ->
|
ok;
|
||||||
Msg
|
delete_old_user_messages(User, TimeStamp, Type) ->
|
||||||
end),
|
F = fun() ->
|
||||||
OldMsgs = mnesia:dirty_select(archive_msg, MS),
|
Msgs = mnesia:read(archive_msg, User),
|
||||||
lists:foreach(fun(Rec) ->
|
Keep = lists:filter(
|
||||||
ok = mnesia:dirty_delete_object(Rec)
|
fun(#archive_msg{timestamp = MsgTS,
|
||||||
end, OldMsgs).
|
type = MsgType}) ->
|
||||||
|
MsgTS >= TimeStamp orelse (Type /= all andalso
|
||||||
|
Type /= MsgType)
|
||||||
|
end, Msgs),
|
||||||
|
if length(Keep) < length(Msgs) ->
|
||||||
|
mnesia:delete({archive_msg, User}),
|
||||||
|
lists:foreach(fun(Msg) -> mnesia:write(Msg) end, Keep);
|
||||||
|
true ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{atomic, ok} ->
|
||||||
|
delete_old_user_messages(mnesia:dirty_next(archive_msg, User),
|
||||||
|
TimeStamp, Type);
|
||||||
|
{aborted, Err} ->
|
||||||
|
?ERROR_MSG("Cannot delete old MAM messages: ~s", [Err]),
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
extended_fields() ->
|
extended_fields() ->
|
||||||
[].
|
[].
|
||||||
@ -67,18 +86,22 @@ store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir) ->
|
|||||||
LPeer = {PUser, PServer, _} = jid:tolower(Peer),
|
LPeer = {PUser, PServer, _} = jid:tolower(Peer),
|
||||||
TS = p1_time_compat:timestamp(),
|
TS = p1_time_compat:timestamp(),
|
||||||
ID = jlib:integer_to_binary(now_to_usec(TS)),
|
ID = jlib:integer_to_binary(now_to_usec(TS)),
|
||||||
case mnesia:dirty_write(
|
F = fun() ->
|
||||||
#archive_msg{us = {LUser, LServer},
|
mnesia:write(#archive_msg{us = {LUser, LServer},
|
||||||
id = ID,
|
id = ID,
|
||||||
timestamp = TS,
|
timestamp = TS,
|
||||||
peer = LPeer,
|
peer = LPeer,
|
||||||
bare_peer = {PUser, PServer, <<>>},
|
bare_peer = {PUser, PServer, <<>>},
|
||||||
type = Type,
|
type = Type,
|
||||||
nick = Nick,
|
nick = Nick,
|
||||||
packet = Pkt}) of
|
packet = Pkt})
|
||||||
ok ->
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{atomic, ok} ->
|
||||||
{ok, ID};
|
{ok, ID};
|
||||||
Err ->
|
{aborted, Err} ->
|
||||||
|
?ERROR_MSG("Cannot add message to MAM archive of ~s@~s: ~s",
|
||||||
|
[LUser, LServer, Err]),
|
||||||
Err
|
Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user