* src/mod_muc/mod_muc_room.erl: Clean user activity after timeout

(EJAB-804)

SVN Revision: 1688
This commit is contained in:
Alexey Shchepin 2008-11-28 16:06:39 +00:00
parent 78b90e9300
commit 964cb84864
2 changed files with 111 additions and 47 deletions

View File

@ -1,3 +1,8 @@
2008-11-28 Alexey Shchepin <alexey@process-one.net>
* src/mod_muc/mod_muc_room.erl: Clean user activity after timeout
(EJAB-804)
2008-11-26 Badlop <badlop@process-one.net>
* src/ejabberdctl.template: Fix detection of ejabberdctl.cfg path

View File

@ -103,7 +103,7 @@
subject = "",
subject_author = "",
just_created = false,
activity = ?DICT:new(),
activity = treap:empty(),
room_shaper,
room_queue = queue:new()}).
@ -243,13 +243,12 @@ normal_state({route, From, "",
message_time = Now,
message_shaper = MessageShaper},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity),
store_user_activity(
From, NewActivity, StateData),
StateData2 =
StateData1#state{
room_shaper = RoomShaper},
process_groupchat_message(From, Packet, StateData1);
process_groupchat_message(From, Packet, StateData2);
true ->
StateData1 =
if
@ -270,13 +269,12 @@ normal_state({route, From, "",
{message, From},
StateData#state.room_queue),
StateData2 =
StateData1#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity),
store_user_activity(
From, NewActivity, StateData1),
StateData3 =
StateData2#state{
room_queue = RoomQueue},
{next_state, normal_state, StateData2}
{next_state, normal_state, StateData3}
end;
true ->
MessageInterval =
@ -290,11 +288,8 @@ normal_state({route, From, "",
message = Packet,
message_shaper = MessageShaper},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity)},
store_user_activity(
From, NewActivity, StateData),
{next_state, normal_state, StateData1}
end;
"error" ->
@ -436,12 +431,7 @@ normal_state({route, From, Nick,
(Now >= Activity#activity.presence_time + MinPresenceInterval) and
(Activity#activity.presence == undefined) ->
NewActivity = Activity#activity{presence_time = Now},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity)},
StateData1 = store_user_activity(From, NewActivity, StateData),
process_presence(From, Nick, Packet, StateData1);
true ->
if
@ -454,12 +444,7 @@ normal_state({route, From, Nick,
ok
end,
NewActivity = Activity#activity{presence = {Nick, Packet}},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity)},
StateData1 = store_user_activity(From, NewActivity, StateData),
{next_state, normal_state, StateData1}
end;
@ -737,27 +722,25 @@ handle_info(process_room_queue, normal_state = StateName, StateData) ->
Packet = Activity#activity.message,
NewActivity = Activity#activity{message = undefined},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity),
store_user_activity(
From, NewActivity, StateData),
StateData2 =
StateData1#state{
room_queue = RoomQueue},
StateData2 = prepare_room_queue(StateData1),
process_groupchat_message(From, Packet, StateData2);
StateData3 = prepare_room_queue(StateData2),
process_groupchat_message(From, Packet, StateData3);
{{value, {presence, From}}, RoomQueue} ->
Activity = get_user_activity(From, StateData),
{Nick, Packet} = Activity#activity.presence,
NewActivity = Activity#activity{presence = undefined},
StateData1 =
StateData#state{
activity = ?DICT:store(
jlib:jid_tolower(From),
NewActivity,
StateData#state.activity),
store_user_activity(
From, NewActivity, StateData),
StateData2 =
StateData1#state{
room_queue = RoomQueue},
StateData2 = prepare_room_queue(StateData1),
process_presence(From, Nick, Packet, StateData2);
StateData3 = prepare_room_queue(StateData2),
process_presence(From, Nick, Packet, StateData3);
{empty, _} ->
{next_state, StateName, StateData}
end;
@ -1284,9 +1267,9 @@ get_max_users_admin_threshold(StateData) ->
mod_muc, max_users_admin_threshold, 5).
get_user_activity(JID, StateData) ->
case ?DICT:find(jlib:jid_tolower(JID),
StateData#state.activity) of
{ok, A} -> A;
case treap:lookup(jlib:jid_tolower(JID),
StateData#state.activity) of
{ok, _P, A} -> A;
error ->
MessageShaper =
shaper:new(gen_mod:get_module_opt(
@ -1300,6 +1283,82 @@ get_user_activity(JID, StateData) ->
presence_shaper = PresenceShaper}
end.
store_user_activity(JID, UserActivity, StateData) ->
MinMessageInterval =
gen_mod:get_module_opt(
StateData#state.server_host,
mod_muc, min_message_interval, 0),
MinPresenceInterval =
gen_mod:get_module_opt(
StateData#state.server_host,
mod_muc, min_presence_interval, 0),
Key = jlib:jid_tolower(JID),
Now = now_to_usec(now()),
Activity1 = clean_treap(StateData#state.activity, {1, -Now}),
Activity =
case treap:lookup(Key, Activity1) of
{ok, _P, _A} ->
treap:delete(Key, Activity1);
error ->
Activity1
end,
StateData1 =
case (MinMessageInterval == 0) andalso
(MinPresenceInterval == 0) andalso
(UserActivity#activity.message_shaper == none) andalso
(UserActivity#activity.presence_shaper == none) andalso
(UserActivity#activity.message == undefined) andalso
(UserActivity#activity.presence == undefined) of
true ->
StateData#state{activity = Activity};
false ->
case (UserActivity#activity.message == undefined) andalso
(UserActivity#activity.presence == undefined) of
true ->
{_, MessageShaperInterval} =
shaper:update(UserActivity#activity.message_shaper,
100000),
{_, PresenceShaperInterval} =
shaper:update(UserActivity#activity.presence_shaper,
100000),
Delay = lists:max([MessageShaperInterval,
PresenceShaperInterval,
MinMessageInterval * 1000,
MinPresenceInterval * 1000]) * 1000,
Priority = {1, -(Now + Delay)},
StateData#state{
activity = treap:insert(
Key,
Priority,
UserActivity,
Activity)};
false ->
Priority = {0, 0},
StateData#state{
activity = treap:insert(
Key,
Priority,
UserActivity,
Activity)}
end
end,
StateData1.
clean_treap(Treap, CleanPriority) ->
case treap:is_empty(Treap) of
true ->
Treap;
false ->
{_Key, Priority, _Value} = treap:get_root(Treap),
if
Priority > CleanPriority ->
clean_treap(treap:delete_root(Treap), CleanPriority);
true ->
Treap
end
end.
prepare_room_queue(StateData) ->
case queue:out(StateData#state.room_queue) of
{{value, {message, From}}, _RoomQueue} ->