aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2008-11-28 16:06:39 +0000
committerAlexey Shchepin <alexey@process-one.net>2008-11-28 16:06:39 +0000
commit964cb84864729e669b6276bb76d55aadaa943b4b (patch)
treeee2dbc43853c57111149732e57fbea1662f05db0
parent* src/ejabberdctl.template: Fix detection of ejabberdctl.cfg path (diff)
* src/mod_muc/mod_muc_room.erl: Clean user activity after timeout
(EJAB-804) SVN Revision: 1688
-rw-r--r--ChangeLog5
-rw-r--r--src/mod_muc/mod_muc_room.erl153
2 files changed, 111 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index 538b29dc5..41c44f958 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl
index edd5912ea..0e13b21fc 100644
--- a/src/mod_muc/mod_muc_room.erl
+++ b/src/mod_muc/mod_muc_room.erl
@@ -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} ->