subject = "",
subject_author = "",
just_created = false,
- activity = ?DICT:new(),
+ activity = treap:empty(),
room_shaper,
room_queue = queue:new()}).
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
{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 =
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" ->
(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
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;
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;
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(
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} ->