aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJohn Hurliman2010-09-09 14:45:10 -0700
committerJohn Hurliman2010-09-09 14:45:10 -0700
commit8415b988063234ab7686b873520708891bca50a6 (patch)
tree136312e2ceca296731dbedf6109528497a53ebe1
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-8415b988063234ab7686b873520708891bca50a6.zip
opensim-SC_OLD-8415b988063234ab7686b873520708891bca50a6.tar.gz
opensim-SC_OLD-8415b988063234ab7686b873520708891bca50a6.tar.bz2
opensim-SC_OLD-8415b988063234ab7686b873520708891bca50a6.tar.xz
Over a dozen thread safety fixes in FriendsModule
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs330
1 files changed, 163 insertions, 167 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 1c1ba2d..4e4eee9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
54 public UUID PrincipalID; 54 public UUID PrincipalID;
55 public FriendInfo[] Friends; 55 public FriendInfo[] Friends;
56 public int Refcount; 56 public int Refcount;
57 public UUID RegionID;
58 57
59 public bool IsFriend(string friend) 58 public bool IsFriend(string friend)
60 { 59 {
@@ -67,7 +66,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
67 return false; 66 return false;
68 } 67 }
69 } 68 }
70 69
70 private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 72
73 protected List<Scene> m_Scenes = new List<Scene>(); 73 protected List<Scene> m_Scenes = new List<Scene>();
@@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
79 protected Dictionary<UUID, UserFriendData> m_Friends = 79 protected Dictionary<UUID, UserFriendData> m_Friends =
80 new Dictionary<UUID, UserFriendData>(); 80 new Dictionary<UUID, UserFriendData>();
81 81
82 protected List<UUID> m_NeedsListOfFriends = new List<UUID>(); 82 protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>();
83 83
84 protected IPresenceService PresenceService 84 protected IPresenceService PresenceService
85 { 85 {
@@ -146,7 +146,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
146 // Instantiate the request handler 146 // Instantiate the request handler
147 IHttpServer server = MainServer.GetHttpServer((uint)mPort); 147 IHttpServer server = MainServer.GetHttpServer((uint)mPort);
148 server.AddStreamHandler(new FriendsRequestHandler(this)); 148 server.AddStreamHandler(new FriendsRequestHandler(this));
149
150 } 149 }
151 150
152 if (m_FriendsService == null) 151 if (m_FriendsService == null)
@@ -173,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
173 scene.EventManager.OnNewClient += OnNewClient; 172 scene.EventManager.OnNewClient += OnNewClient;
174 scene.EventManager.OnClientClosed += OnClientClosed; 173 scene.EventManager.OnClientClosed += OnClientClosed;
175 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; 174 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
176 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
177 scene.EventManager.OnClientLogin += OnClientLogin; 175 scene.EventManager.OnClientLogin += OnClientLogin;
178 } 176 }
179 177
@@ -198,16 +196,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
198 196
199 public uint GetFriendPerms(UUID principalID, UUID friendID) 197 public uint GetFriendPerms(UUID principalID, UUID friendID)
200 { 198 {
201 if (!m_Friends.ContainsKey(principalID)) 199 FriendInfo[] friends = GetFriends(principalID);
202 return 0; 200 foreach (FriendInfo fi in friends)
203
204 UserFriendData data = m_Friends[principalID];
205
206 foreach (FriendInfo fi in data.Friends)
207 { 201 {
208 if (fi.Friend == friendID.ToString()) 202 if (fi.Friend == friendID.ToString())
209 return (uint)fi.TheirFlags; 203 return (uint)fi.TheirFlags;
210 } 204 }
205
211 return 0; 206 return 0;
212 } 207 }
213 208
@@ -217,73 +212,59 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
217 client.OnApproveFriendRequest += OnApproveFriendRequest; 212 client.OnApproveFriendRequest += OnApproveFriendRequest;
218 client.OnDenyFriendRequest += OnDenyFriendRequest; 213 client.OnDenyFriendRequest += OnDenyFriendRequest;
219 client.OnTerminateFriendship += OnTerminateFriendship; 214 client.OnTerminateFriendship += OnTerminateFriendship;
220
221 client.OnGrantUserRights += OnGrantUserRights; 215 client.OnGrantUserRights += OnGrantUserRights;
222 216
223 lock (m_Friends) 217 // Asynchronously fetch the friends list or increment the refcount for the existing
224 { 218 // friends list
225 if (m_Friends.ContainsKey(client.AgentId)) 219 Util.FireAndForget(
220 delegate(object o)
226 { 221 {
227 m_Friends[client.AgentId].Refcount++; 222 lock (m_Friends)
228 return; 223 {
229 } 224 UserFriendData friendsData;
230 225 if (m_Friends.TryGetValue(client.AgentId, out friendsData))
231 UserFriendData newFriends = new UserFriendData(); 226 {
232 227 friendsData.Refcount++;
233 newFriends.PrincipalID = client.AgentId; 228 }
234 newFriends.Friends = m_FriendsService.GetFriends(client.AgentId); 229 else
235 newFriends.Refcount = 1; 230 {
236 newFriends.RegionID = UUID.Zero; 231 friendsData = new UserFriendData();
232 friendsData.PrincipalID = client.AgentId;
233 friendsData.Friends = FriendsService.GetFriends(client.AgentId);
234 friendsData.Refcount = 1;
237 235
238 m_Friends.Add(client.AgentId, newFriends); 236 m_Friends[client.AgentId] = friendsData;
239 } 237 }
240 238 }
239 }
240 );
241 } 241 }
242 242
243 private void OnClientClosed(UUID agentID, Scene scene) 243 private void OnClientClosed(UUID agentID, Scene scene)
244 { 244 {
245 ScenePresence sp = scene.GetScenePresence(agentID); 245 ScenePresence sp = scene.GetScenePresence(agentID);
246 if (sp != null && !sp.IsChildAgent) 246 if (sp != null && !sp.IsChildAgent)
247 {
247 // do this for root agents closing out 248 // do this for root agents closing out
248 StatusChange(agentID, false); 249 StatusChange(agentID, false);
250 }
249 251
250 lock (m_Friends) 252 lock (m_Friends)
251 if (m_Friends.ContainsKey(agentID)) 253 {
254 UserFriendData friendsData;
255 if (m_Friends.TryGetValue(agentID, out friendsData))
252 { 256 {
253 if (m_Friends[agentID].Refcount == 1) 257 friendsData.Refcount--;
258 if (friendsData.Refcount <= 0)
254 m_Friends.Remove(agentID); 259 m_Friends.Remove(agentID);
255 else
256 m_Friends[agentID].Refcount--;
257 } 260 }
258 }
259
260 private void OnMakeRootAgent(ScenePresence sp)
261 {
262 UUID agentID = sp.ControllingClient.AgentId;
263
264 if (m_Friends.ContainsKey(agentID))
265 {
266 // This is probably an overkill, but just
267 // to make sure we have the latest and greatest
268 // friends list -- always pull OnMakeRoot
269 m_Friends[agentID].Friends =
270 m_FriendsService.GetFriends(agentID);
271
272 m_Friends[agentID].RegionID =
273 sp.ControllingClient.Scene.RegionInfo.RegionID;
274 } 261 }
275 } 262 }
276 263
277 264 private void OnMakeRootAgent(ScenePresence sp)
278 private void OnMakeChildAgent(ScenePresence sp)
279 { 265 {
280 UUID agentID = sp.ControllingClient.AgentId; 266 UUID agentID = sp.ControllingClient.AgentId;
281 267 UpdateFriendsCache(agentID);
282 if (m_Friends.ContainsKey(agentID))
283 {
284 if (m_Friends[agentID].RegionID == sp.ControllingClient.Scene.RegionInfo.RegionID)
285 m_Friends[agentID].RegionID = UUID.Zero;
286 }
287 } 268 }
288 269
289 private void OnClientLogin(IClientAPI client) 270 private void OnClientLogin(IClientAPI client)
@@ -295,72 +276,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
295 276
296 // Register that we need to send the list of online friends to this user 277 // Register that we need to send the list of online friends to this user
297 lock (m_NeedsListOfFriends) 278 lock (m_NeedsListOfFriends)
298 if (!m_NeedsListOfFriends.Contains(agentID)) 279 m_NeedsListOfFriends.Add(agentID);
299 {
300 m_NeedsListOfFriends.Add(agentID);
301 }
302 } 280 }
303 281
304 public void SendFriendsOnlineIfNeeded(IClientAPI client) 282 public void SendFriendsOnlineIfNeeded(IClientAPI client)
305 { 283 {
306 UUID agentID = client.AgentId; 284 UUID agentID = client.AgentId;
307 if (m_NeedsListOfFriends.Contains(agentID)) 285
286 // Check if the online friends list is needed
287 lock (m_NeedsListOfFriends)
308 { 288 {
309 if (!m_Friends.ContainsKey(agentID)) 289 if (!m_NeedsListOfFriends.Remove(agentID))
310 {
311 m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID);
312 return; 290 return;
313 } 291 }
314
315 //
316 // Send the friends online
317 //
318 List<UUID> online = GetOnlineFriends(agentID);
319 if (online.Count > 0)
320 {
321 m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
322 client.SendAgentOnline(online.ToArray());
323 }
324
325 //
326 // Send outstanding friendship offers
327 //
328 if (m_Friends.ContainsKey(agentID))
329 {
330 List<string> outstanding = new List<string>();
331 292
332 foreach (FriendInfo fi in m_Friends[agentID].Friends) 293 // Send the friends online
333 if (fi.TheirFlags == -1) 294 List<UUID> online = GetOnlineFriends(agentID);
334 outstanding.Add(fi.Friend); 295 if (online.Count > 0)
296 {
297 m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
298 client.SendAgentOnline(online.ToArray());
299 }
335 300
336 GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, "", agentID, (byte)InstantMessageDialog.FriendshipOffered, "Will you be my friend?", true, Vector3.Zero); 301 // Send outstanding friendship offers
337 foreach (string fid in outstanding) 302 List<string> outstanding = new List<string>();
338 { 303 FriendInfo[] friends = GetFriends(agentID);
339 try 304 foreach (FriendInfo fi in friends)
340 { 305 {
341 im.fromAgentID = new Guid(fid); 306 if (fi.TheirFlags == -1)
342 } 307 outstanding.Add(fi.Friend);
343 catch 308 }
344 {
345 continue;
346 }
347 309
348 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, new UUID(im.fromAgentID)); 310 GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered,
349 im.fromAgentName = account.FirstName + " " + account.LastName; 311 "Will you be my friend?", true, Vector3.Zero);
350 312
351 PresenceInfo presence = PresenceService.GetAgent(new UUID(im.fromAgentID)); 313 foreach (string fid in outstanding)
352 if (presence != null) 314 {
353 im.offline = 0; 315 UUID fromAgentID;
316 if (!UUID.TryParse(fid, out fromAgentID))
317 continue;
354 318
355 im.imSessionID = im.fromAgentID; 319 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
320 PresenceInfo presence = PresenceService.GetAgent(fromAgentID);
356 321
357 // Finally 322 im.fromAgentID = fromAgentID.Guid;
358 LocalFriendshipOffered(agentID, im); 323 im.fromAgentName = account.FirstName + " " + account.LastName;
359 } 324 im.offline = (byte)((presence == null) ? 1 : 0);
360 } 325 im.imSessionID = im.fromAgentID;
361 326
362 lock (m_NeedsListOfFriends) 327 // Finally
363 m_NeedsListOfFriends.Remove(agentID); 328 LocalFriendshipOffered(agentID, im);
364 } 329 }
365 } 330 }
366 331
@@ -369,44 +334,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
369 List<string> friendList = new List<string>(); 334 List<string> friendList = new List<string>();
370 List<UUID> online = new List<UUID>(); 335 List<UUID> online = new List<UUID>();
371 336
372 foreach (FriendInfo fi in m_Friends[userID].Friends) 337 FriendInfo[] friends = GetFriends(userID);
338 foreach (FriendInfo fi in friends)
373 { 339 {
374 if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1)) 340 if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1))
375 friendList.Add(fi.Friend); 341 friendList.Add(fi.Friend);
376 } 342 }
377 343
378 if (friendList.Count == 0) 344 if (friendList.Count > 0)
379 // no friends whatsoever 345 {
380 return online; 346 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
381 347 foreach (PresenceInfo pi in presence)
382 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); 348 {
383 349 UUID presenceID;
384 foreach (PresenceInfo pi in presence) 350 if (UUID.TryParse(pi.UserID, out presenceID))
385 online.Add(new UUID(pi.UserID)); 351 online.Add(presenceID);
386 //m_log.DebugFormat("[XXX] {0} friend online {1}", userID, pi.UserID); 352 }
353 }
387 354
388 return online; 355 return online;
389 } 356 }
390 357
391 // 358 /// <summary>
392 // Find the client for a ID 359 /// Find the client for a ID
393 // 360 /// </summary>
394 public IClientAPI LocateClientObject(UUID agentID) 361 public IClientAPI LocateClientObject(UUID agentID)
395 { 362 {
396 Scene scene = GetClientScene(agentID); 363 Scene scene = GetClientScene(agentID);
397 if (scene == null) 364 if (scene != null)
398 return null; 365 {
399 366 ScenePresence presence = scene.GetScenePresence(agentID);
400 ScenePresence presence = scene.GetScenePresence(agentID); 367 if (presence != null)
401 if (presence == null) 368 return presence.ControllingClient;
402 return null; 369 }
403 370
404 return presence.ControllingClient; 371 return null;
405 } 372 }
406 373
407 // 374 /// <summary>
408 // Find the scene for an agent 375 /// Find the scene for an agent
409 // 376 /// </summary>
410 private Scene GetClientScene(UUID agentId) 377 private Scene GetClientScene(UUID agentId)
411 { 378 {
412 lock (m_Scenes) 379 lock (m_Scenes)
@@ -414,13 +381,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
414 foreach (Scene scene in m_Scenes) 381 foreach (Scene scene in m_Scenes)
415 { 382 {
416 ScenePresence presence = scene.GetScenePresence(agentId); 383 ScenePresence presence = scene.GetScenePresence(agentId);
417 if (presence != null) 384 if (presence != null && !presence.IsChildAgent)
418 { 385 return scene;
419 if (!presence.IsChildAgent)
420 return scene;
421 }
422 } 386 }
423 } 387 }
388
424 return null; 389 return null;
425 } 390 }
426 391
@@ -431,35 +396,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
431 /// <param name="online"></param> 396 /// <param name="online"></param>
432 private void StatusChange(UUID agentID, bool online) 397 private void StatusChange(UUID agentID, bool online)
433 { 398 {
434 //m_log.DebugFormat("[FRIENDS]: StatusChange {0}", online); 399 FriendInfo[] friends = GetFriends(agentID);
435 if (m_Friends.ContainsKey(agentID)) 400 if (friends.Length > 0)
436 { 401 {
437 //m_log.DebugFormat("[FRIENDS]: # of friends: {0}", m_Friends[agentID].Friends.Length);
438 List<FriendInfo> friendList = new List<FriendInfo>(); 402 List<FriendInfo> friendList = new List<FriendInfo>();
439 foreach (FriendInfo fi in m_Friends[agentID].Friends) 403 foreach (FriendInfo fi in friends)
440 { 404 {
441 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) 405 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1))
442 friendList.Add(fi); 406 friendList.Add(fi);
443 } 407 }
444 408
445 Util.FireAndForget(delegate 409 Util.FireAndForget(
446 { 410 delegate
447 foreach (FriendInfo fi in friendList)
448 { 411 {
449 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); 412 foreach (FriendInfo fi in friendList)
450 // Notify about this user status 413 {
451 StatusNotify(fi, agentID, online); 414 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID);
415 // Notify about this user status
416 StatusNotify(fi, agentID, online);
417 }
452 } 418 }
453 }); 419 );
454 } 420 }
455 else
456 m_log.WarnFormat("[FRIENDS]: {0} not found in cache", agentID);
457 } 421 }
458 422
459 private void StatusNotify(FriendInfo friend, UUID userID, bool online) 423 private void StatusNotify(FriendInfo friend, UUID userID, bool online)
460 { 424 {
461 UUID friendID = UUID.Zero; 425 UUID friendID;
462
463 if (UUID.TryParse(friend.Friend, out friendID)) 426 if (UUID.TryParse(friend.Friend, out friendID))
464 { 427 {
465 // Try local 428 // Try local
@@ -476,12 +439,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
476 } 439 }
477 } 440 }
478 else 441 else
442 {
479 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 443 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
444 }
480 } 445 }
481 446
482 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 447 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
483 { 448 {
484 if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered) 449 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
485 { 450 {
486 // we got a friendship offer 451 // we got a friendship offer
487 UUID principalID = new UUID(im.fromAgentID); 452 UUID principalID = new UUID(im.fromAgentID);
@@ -527,9 +492,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
527 492
528 FriendsService.StoreFriend(agentID, friendID.ToString(), 1); 493 FriendsService.StoreFriend(agentID, friendID.ToString(), 1);
529 FriendsService.StoreFriend(friendID, agentID.ToString(), 1); 494 FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
530 // update the local cache
531 m_Friends[agentID].Friends = FriendsService.GetFriends(agentID);
532 495
496 // Update the local cache
497 UpdateFriendsCache(agentID);
533 498
534 // 499 //
535 // Notify the friend 500 // Notify the friend
@@ -584,7 +549,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
584 FriendsService.Delete(exfriendID, agentID.ToString()); 549 FriendsService.Delete(exfriendID, agentID.ToString());
585 550
586 // Update local cache 551 // Update local cache
587 m_Friends[agentID].Friends = FriendsService.GetFriends(agentID); 552 UpdateFriendsCache(agentID);
588 553
589 client.SendTerminateFriend(exfriendID); 554 client.SendTerminateFriend(exfriendID);
590 555
@@ -606,16 +571,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
606 571
607 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) 572 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
608 { 573 {
609 if (!m_Friends.ContainsKey(remoteClient.AgentId)) 574 FriendInfo[] friends = GetFriends(remoteClient.AgentId);
575 if (friends.Length == 0)
610 return; 576 return;
611 577
612 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); 578 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
613 // Let's find the friend in this user's friend list 579 // Let's find the friend in this user's friend list
614 UserFriendData fd = m_Friends[remoteClient.AgentId];
615 FriendInfo friend = null; 580 FriendInfo friend = null;
616 foreach (FriendInfo fi in fd.Friends) 581 foreach (FriendInfo fi in friends)
582 {
617 if (fi.Friend == target.ToString()) 583 if (fi.Friend == target.ToString())
618 friend = fi; 584 friend = fi;
585 }
619 586
620 if (friend != null) // Found it 587 if (friend != null) // Found it
621 { 588 {
@@ -672,8 +639,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
672 GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID, 639 GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID,
673 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero); 640 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero);
674 friendClient.SendInstantMessage(im); 641 friendClient.SendInstantMessage(im);
675 // update the local cache 642
676 m_Friends[friendID].Friends = FriendsService.GetFriends(friendID); 643 // Update the local cache
644 UpdateFriendsCache(friendID);
645
677 // we're done 646 // we're done
678 return true; 647 return true;
679 } 648 }
@@ -687,7 +656,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
687 if (friendClient != null) 656 if (friendClient != null)
688 { 657 {
689 // the prospective friend in this sim as root agent 658 // the prospective friend in this sim as root agent
690
691 GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID, 659 GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID,
692 (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, userID.ToString(), false, Vector3.Zero); 660 (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, userID.ToString(), false, Vector3.Zero);
693 friendClient.SendInstantMessage(im); 661 friendClient.SendInstantMessage(im);
@@ -706,7 +674,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
706 // the friend in this sim as root agent 674 // the friend in this sim as root agent
707 friendClient.SendTerminateFriend(exfriendID); 675 friendClient.SendTerminateFriend(exfriendID);
708 // update local cache 676 // update local cache
709 m_Friends[exfriendID].Friends = FriendsService.GetFriends(exfriendID); 677 UpdateFriendsCache(exfriendID);
710 // we're done 678 // we're done
711 return true; 679 return true;
712 } 680 }
@@ -735,11 +703,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
735 703
736 } 704 }
737 705
738 // update local cache 706 // Update local cache
739 //m_Friends[friendID].Friends = m_FriendsService.GetFriends(friendID); 707 lock (m_Friends)
740 foreach (FriendInfo finfo in m_Friends[friendID].Friends) 708 {
741 if (finfo.Friend == userID.ToString()) 709 FriendInfo[] friends = GetFriends(friendID);
742 finfo.TheirFlags = rights; 710 foreach (FriendInfo finfo in friends)
711 {
712 if (finfo.Friend == userID.ToString())
713 finfo.TheirFlags = rights;
714 }
715 }
743 716
744 return true; 717 return true;
745 } 718 }
@@ -765,7 +738,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
765 738
766 return false; 739 return false;
767 } 740 }
741
768 #endregion 742 #endregion
769 743
744 private FriendInfo[] GetFriends(UUID agentID)
745 {
746 UserFriendData friendsData;
747
748 lock (m_Friends)
749 {
750 if (m_Friends.TryGetValue(agentID, out friendsData))
751 return friendsData.Friends;
752 }
753
754 return EMPTY_FRIENDS;
755 }
756
757 private void UpdateFriendsCache(UUID agentID)
758 {
759 lock (m_Friends)
760 {
761 UserFriendData friendsData;
762 if (m_Friends.TryGetValue(agentID, out friendsData))
763 friendsData.Friends = FriendsService.GetFriends(agentID);
764 }
765 }
770 } 766 }
771} 767}