diff options
author | Justin Clark-Casey (justincc) | 2011-11-15 15:57:53 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2011-11-15 15:57:53 +0000 |
commit | 50803dfe2ca8818f438d740e788762e1faf1078c (patch) | |
tree | 17b06e2666f45748399539994d41d4c400f2e09f | |
parent | refactor: Don't create a new UUID for passing uuids to client - UUIDs are str... (diff) | |
download | opensim-SC_OLD-50803dfe2ca8818f438d740e788762e1faf1078c.zip opensim-SC_OLD-50803dfe2ca8818f438d740e788762e1faf1078c.tar.gz opensim-SC_OLD-50803dfe2ca8818f438d740e788762e1faf1078c.tar.bz2 opensim-SC_OLD-50803dfe2ca8818f438d740e788762e1faf1078c.tar.xz |
For clients that are entering a simulator from initial login, stop executing FriendsModule.FetchFriendslist() asychronously.
Executing this asynchronously allows a race condition where subsequent friends fetches hit a cache that FetchFriendsList() had not yet populated.
Changing this to synchronous may improve issues where a user does not see friends as online even though they are.
I don't believe synchronous is a problem here, but if it is, then a more complicated signalling mechanism is required. Locking the cache isn't sufficient.
3 files changed, 34 insertions, 11 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 76d84ec..f84033b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | |||
@@ -79,9 +79,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
79 | protected IFriendsService m_FriendsService = null; | 79 | protected IFriendsService m_FriendsService = null; |
80 | protected FriendsSimConnector m_FriendsSimConnector; | 80 | protected FriendsSimConnector m_FriendsSimConnector; |
81 | 81 | ||
82 | protected Dictionary<UUID, UserFriendData> m_Friends = | 82 | /// <summary> |
83 | new Dictionary<UUID, UserFriendData>(); | 83 | /// Cache friends lists for users. |
84 | /// </summary> | ||
85 | /// <remarks> | ||
86 | /// This is a complex and error-prone thing to do. At the moment, we assume that the efficiency gained in | ||
87 | /// permissions checks outweighs the disadvantages of that complexity. | ||
88 | /// </remarks> | ||
89 | protected Dictionary<UUID, UserFriendData> m_Friends = new Dictionary<UUID, UserFriendData>(); | ||
84 | 90 | ||
91 | /// <summary> | ||
92 | /// Maintain a record of viewers that need to be sent notifications for friends that are online. This only | ||
93 | /// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism. | ||
94 | /// </summary> | ||
85 | protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>(); | 95 | protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>(); |
86 | 96 | ||
87 | protected IPresenceService PresenceService | 97 | protected IPresenceService PresenceService |
@@ -189,6 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
189 | { | 199 | { |
190 | if (!m_Enabled) | 200 | if (!m_Enabled) |
191 | return; | 201 | return; |
202 | |||
192 | m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); | 203 | m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); |
193 | 204 | ||
194 | m_Scenes.Add(scene); | 205 | m_Scenes.Add(scene); |
@@ -244,12 +255,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
244 | client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); | 255 | client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); |
245 | client.OnGrantUserRights += OnGrantUserRights; | 256 | client.OnGrantUserRights += OnGrantUserRights; |
246 | 257 | ||
247 | Util.FireAndForget(delegate { FetchFriendslist(client); }); | 258 | // Do not do this asynchronously. If we do, then subsequent code can outrace FetchFriendsList() and |
259 | // return misleading results from the still empty friends cache. | ||
260 | // If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls | ||
261 | // to GetFriends() will wait until FetchFriendslist() completes. Locks are insufficient. | ||
262 | FetchFriendslist(client); | ||
248 | } | 263 | } |
249 | 264 | ||
250 | /// Fetch the friends list or increment the refcount for the existing | 265 | |
251 | /// friends list | 266 | /// <summary> |
267 | /// Fetch the friends list or increment the refcount for the existing | ||
268 | /// friends list. | ||
269 | /// </summary> | ||
270 | /// <param name="client"> | ||
271 | /// </param> | ||
272 | /// <returns> | ||
252 | /// Returns true if the list was fetched, false if it wasn't | 273 | /// Returns true if the list was fetched, false if it wasn't |
274 | /// </returns> | ||
253 | protected virtual bool FetchFriendslist(IClientAPI client) | 275 | protected virtual bool FetchFriendslist(IClientAPI client) |
254 | { | 276 | { |
255 | UUID agentID = client.AgentId; | 277 | UUID agentID = client.AgentId; |
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 3b661ed..f416f06 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | |||
@@ -479,8 +479,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
479 | } | 479 | } |
480 | 480 | ||
481 | protected bool IsFriendWithPerms(UUID user,UUID objectOwner) | 481 | protected bool IsFriendWithPerms(UUID user,UUID objectOwner) |
482 | { | 482 | { |
483 | |||
484 | if (user == UUID.Zero) | 483 | if (user == UUID.Zero) |
485 | return false; | 484 | return false; |
486 | 485 | ||
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 96da2c3..bf9ad65 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -73,8 +73,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
73 | /// </summary> | 73 | /// </summary> |
74 | public event OnNewClientDelegate OnNewClient; | 74 | public event OnNewClientDelegate OnNewClient; |
75 | 75 | ||
76 | public delegate void OnClientLoginDelegate(IClientAPI client); | 76 | /// <summary> |
77 | public event OnClientLoginDelegate OnClientLogin; | 77 | /// Fired if the client entering this sim is doing so as a new login |
78 | /// </summary> | ||
79 | public event Action<IClientAPI> OnClientLogin; | ||
78 | 80 | ||
79 | public delegate void OnNewPresenceDelegate(ScenePresence presence); | 81 | public delegate void OnNewPresenceDelegate(ScenePresence presence); |
80 | 82 | ||
@@ -651,10 +653,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
651 | 653 | ||
652 | public void TriggerOnClientLogin(IClientAPI client) | 654 | public void TriggerOnClientLogin(IClientAPI client) |
653 | { | 655 | { |
654 | OnClientLoginDelegate handlerClientLogin = OnClientLogin; | 656 | Action<IClientAPI> handlerClientLogin = OnClientLogin; |
655 | if (handlerClientLogin != null) | 657 | if (handlerClientLogin != null) |
656 | { | 658 | { |
657 | foreach (OnClientLoginDelegate d in handlerClientLogin.GetInvocationList()) | 659 | foreach (Action<IClientAPI> d in handlerClientLogin.GetInvocationList()) |
658 | { | 660 | { |
659 | try | 661 | try |
660 | { | 662 | { |