diff options
author | Justin Clark-Casey (justincc) | 2012-10-20 01:26:04 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-10-20 01:26:04 +0100 |
commit | cd3762ca9f97052a6fe91a3eca491407cc6f039e (patch) | |
tree | e9561d7b955e5f6153c79082879380493b96670c /OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups | |
parent | Fix build break from commit e469879 (diff) | |
download | opensim-SC_OLD-cd3762ca9f97052a6fe91a3eca491407cc6f039e.zip opensim-SC_OLD-cd3762ca9f97052a6fe91a3eca491407cc6f039e.tar.gz opensim-SC_OLD-cd3762ca9f97052a6fe91a3eca491407cc6f039e.tar.bz2 opensim-SC_OLD-cd3762ca9f97052a6fe91a3eca491407cc6f039e.tar.xz |
Add experimental [Groups] MessageOnlineUsersOnly option for Flotsam XmlRpc groups.
This retrieves and caches information from the PresenceService to only send messages to online users.
This is reported to much improve performance for large groups where most users are offline.
Cache is 20 seconds to balance requests against users not receiving messages until cache updates.
This is an alternative to an approach where login/logout notification is sent directly from simulator to groups service.
However, I'm not convinced that this PresenceService approach is actually better. Needs more thought.
Diffstat (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups')
-rw-r--r-- | OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 10b83e6..55bb7dc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Linq; | ||
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using log4net; | 32 | using log4net; |
32 | using Mono.Addins; | 33 | using Mono.Addins; |
@@ -36,6 +37,8 @@ using OpenMetaverse.StructuredData; | |||
36 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
37 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
38 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Services.Interfaces; | ||
41 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; | ||
39 | 42 | ||
40 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | 43 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups |
41 | { | 44 | { |
@@ -45,6 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 49 | ||
47 | private List<Scene> m_sceneList = new List<Scene>(); | 50 | private List<Scene> m_sceneList = new List<Scene>(); |
51 | private IPresenceService m_presenceService; | ||
48 | 52 | ||
49 | private IMessageTransferModule m_msgTransferModule = null; | 53 | private IMessageTransferModule m_msgTransferModule = null; |
50 | 54 | ||
@@ -54,6 +58,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
54 | private bool m_groupMessagingEnabled = false; | 58 | private bool m_groupMessagingEnabled = false; |
55 | private bool m_debugEnabled = true; | 59 | private bool m_debugEnabled = true; |
56 | 60 | ||
61 | /// <summary> | ||
62 | /// If enabled, module only tries to send group IMs to online users by querying cached presence information. | ||
63 | /// </summary> | ||
64 | private bool m_messageOnlineAgentsOnly; | ||
65 | |||
66 | /// <summary> | ||
67 | /// Cache for online users. | ||
68 | /// </summary> | ||
69 | /// <remarks> | ||
70 | /// Group ID is key, presence information for online members is value. | ||
71 | /// Will only be non-null if m_messageOnlineAgentsOnly = true | ||
72 | /// We cache here so that group messages don't constantly have to re-request the online user list to avoid | ||
73 | /// attempted expensive sending of messages to offline users. | ||
74 | /// The tradeoff is that a user that comes online will not receive messages consistently from all other users | ||
75 | /// until caches have updated. | ||
76 | /// Therefore, we set the cache expiry to just 20 seconds. | ||
77 | /// </remarks> | ||
78 | private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache; | ||
79 | |||
80 | private int m_usersOnlineCacheExpirySeconds = 20; | ||
81 | |||
57 | #region IRegionModuleBase Members | 82 | #region IRegionModuleBase Members |
58 | 83 | ||
59 | public void Initialise(IConfigSource config) | 84 | public void Initialise(IConfigSource config) |
@@ -83,10 +108,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
83 | return; | 108 | return; |
84 | } | 109 | } |
85 | 110 | ||
111 | m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); | ||
112 | |||
113 | if (m_messageOnlineAgentsOnly) | ||
114 | m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>(); | ||
115 | |||
86 | m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); | 116 | m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); |
87 | } | 117 | } |
88 | 118 | ||
89 | m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); | 119 | m_log.InfoFormat( |
120 | "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", | ||
121 | m_messageOnlineAgentsOnly, m_debugEnabled); | ||
90 | } | 122 | } |
91 | 123 | ||
92 | public void AddRegion(Scene scene) | 124 | public void AddRegion(Scene scene) |
@@ -126,6 +158,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
126 | return; | 158 | return; |
127 | } | 159 | } |
128 | 160 | ||
161 | if (m_presenceService == null) | ||
162 | m_presenceService = scene.PresenceService; | ||
129 | 163 | ||
130 | m_sceneList.Add(scene); | 164 | m_sceneList.Add(scene); |
131 | 165 | ||
@@ -207,12 +241,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
207 | public void SendMessageToGroup(GridInstantMessage im, UUID groupID) | 241 | public void SendMessageToGroup(GridInstantMessage im, UUID groupID) |
208 | { | 242 | { |
209 | List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); | 243 | List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); |
210 | 244 | ||
211 | if (m_debugEnabled) | 245 | if (m_messageOnlineAgentsOnly) |
212 | m_log.DebugFormat( | 246 | { |
213 | "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", | 247 | string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray(); |
214 | groupID, groupMembers.Count); | 248 | |
215 | 249 | // We cache in order not to overwhlem the presence service on large grids with many groups. This does | |
250 | // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. | ||
251 | // (assuming this is the same across all grid simulators). | ||
252 | PresenceInfo[] onlineAgents; | ||
253 | if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) | ||
254 | { | ||
255 | onlineAgents = m_presenceService.GetAgents(t1); | ||
256 | m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); | ||
257 | } | ||
258 | |||
259 | HashSet<string> onlineAgentsUuidSet = new HashSet<string>(); | ||
260 | Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); | ||
261 | |||
262 | int allMembersCount = groupMembers.Count; | ||
263 | groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); | ||
264 | |||
265 | // if (m_debugEnabled) | ||
266 | m_log.DebugFormat( | ||
267 | "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", | ||
268 | groupID, allMembersCount, groupMembers.Count()); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | if (m_debugEnabled) | ||
273 | m_log.DebugFormat( | ||
274 | "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", | ||
275 | groupID, groupMembers.Count); | ||
276 | } | ||
277 | |||
216 | foreach (GroupMembersData member in groupMembers) | 278 | foreach (GroupMembersData member in groupMembers) |
217 | { | 279 | { |
218 | if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) | 280 | if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) |