]> granicus.if.org Git - ejabberd/commitdiff
* src/mod_muc/mod_muc_room.erl: Clean user activity after timeout
authorAlexey Shchepin <alexey@process-one.net>
Fri, 28 Nov 2008 16:06:39 +0000 (16:06 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Fri, 28 Nov 2008 16:06:39 +0000 (16:06 +0000)
(EJAB-804)

SVN Revision: 1688

ChangeLog
src/mod_muc/mod_muc_room.erl

index 538b29dc573b3bf8dd4f1f5525c80524a9a4c706..41c44f958b4449f3c592ef72d4e87e38e048d75f 100644 (file)
--- 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
index edd5912ea9cf407d52cc6535536e9a4097497df0..0e13b21fcf665808d4a97b3580402e6dd7558618 100644 (file)
                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} ->