From d9f7b8549b3cb9699eb8bd54242d31aac0f8241a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 28 Mar 2012 23:40:25 +0100 Subject: [PATCH] Simplify friends caching by only doing this for root agents - no functions require caching for child agents. This allows us to avoid unnecessary multiple calls to the friends service. All friends functions originate from the root agent and only go to other root agents in existing code. This also allows us to eliminate complex ref counting. --- OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/Linden/UDP/LLClientView.cs | 4 +- .../Avatar/Friends/FriendsModule.cs | 62 ++++++------------- .../Avatar/Friends/HGFriendsModule.cs | 6 +- .../Region/Framework/Scenes/EventManager.cs | 3 +- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../Server/IRCClientView.cs | 4 +- .../OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 9 files changed, 31 insertions(+), 55 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 3f560d0ec4..1e36b061d0 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -710,7 +710,7 @@ namespace OpenSim.Framework /// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it /// is connected). /// - ISceneAgent SceneAgent { get; } + ISceneAgent SceneAgent { get; set; } UUID SessionId { get; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cd81df5e68..98996693e0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index d1a1af0888..f3982ea8e7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -57,7 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public UUID PrincipalID; public FriendInfo[] Friends; - public int Refcount; public bool IsFriend(string friend) { @@ -255,6 +254,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnNewClient(IClientAPI client) { + if (client.SceneAgent.IsChildAgent) + return; + client.OnInstantMessage += OnInstantMessage; client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest; @@ -281,23 +283,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UUID agentID = client.AgentId; lock (m_Friends) { - UserFriendData friendsData; - if (m_Friends.TryGetValue(agentID, out friendsData)) - { - friendsData.Refcount++; - return false; - } - else - { - friendsData = new UserFriendData(); - friendsData.PrincipalID = agentID; - friendsData.Friends = GetFriendsFromService(client); - friendsData.Refcount = 1; + UserFriendData friendsData = new UserFriendData(); + friendsData.PrincipalID = agentID; + friendsData.Friends = GetFriendsFromService(client); - m_Friends[agentID] = friendsData; - return true; - } + m_Friends[agentID] = friendsData; } + + return true; } private void OnClientClosed(UUID agentID, Scene scene) @@ -307,23 +300,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { // do this for root agents closing out StatusChange(agentID, false); - } - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(agentID, out friendsData)) - { - friendsData.Refcount--; - if (friendsData.Refcount <= 0) - m_Friends.Remove(agentID); - } + lock (m_Friends) + m_Friends.Remove(agentID); } } private void OnMakeRootAgent(ScenePresence sp) { - RecacheFriends(sp.ControllingClient); + // FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event + // is on the critical path for transferring an avatar from one region to another. + CacheFriends(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) @@ -623,7 +610,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends StoreFriendships(client.AgentId, friendID); // Update the local cache. - RecacheFriends(client); + CacheFriends(client); // // Notify the friend @@ -685,7 +672,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.SendAlertMessage("Unable to terminate friendship on this sim."); // Update local cache - RecacheFriends(client); + CacheFriends(client); client.SendTerminateFriend(exfriendID); @@ -799,7 +786,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friendClient.SendInstantMessage(im); // Update the local cache - RecacheFriends(friendClient); + CacheFriends(friendClient); // we're done return true; @@ -832,7 +819,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - RecacheFriends(friendClient); + CacheFriends(friendClient); // we're done return true; } @@ -933,19 +920,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return FriendsService.GetFriends(client.AgentId); } - protected void RecacheFriends(IClientAPI client) - { - // FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event - // is on the critical path for transferring an avatar from one region to another. - UUID agentID = client.AgentId; - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(agentID, out friendsData)) - friendsData.Friends = GetFriendsFromService(client); - } - } - /// /// Are friends cached on this simulator for a particular user? /// diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index e50a84a76e..7bc30181a0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -121,7 +121,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { UUID agentID = client.AgentId; // we do this only for the root agent - if (m_Friends[agentID].Refcount == 1) + if (!client.SceneAgent.IsChildAgent) { // We need to preload the user management cache with the names // of foreign friends, just like we do with SOPs' creators @@ -426,14 +426,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); - RecacheFriends(agentClient); + CacheFriends(agentClient); } if (friendClient != null) { friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); - RecacheFriends(friendClient); + CacheFriends(friendClient); } m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7993abed72..fe3438e175 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -71,6 +71,7 @@ namespace OpenSim.Region.Framework.Scenes /// Triggered when a new client is added to the scene. /// /// + /// This is triggered for both child and root agent client connections. /// Triggered before OnClientLogin. /// public event OnNewClientDelegate OnNewClient; @@ -191,7 +192,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); /// - /// Fired when a client is removed from a scene. + /// Fired when a client is removed from a scene whether it's a child or a root agent. /// /// /// At the point of firing, the scene still contains the client's scene presence. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c887b4ed09..60fe48fe64 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2670,6 +2670,7 @@ namespace OpenSim.Region.Framework.Scenes sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } + client.SceneAgent = sp; m_LastLogin = Util.EnvironmentTickCount(); // Cache the user's name diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 5cf478ac10..43548e673f 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server private UUID m_agentID = UUID.Random(); - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } private string m_username; private string m_nick; @@ -895,7 +895,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 16ec34f62c..5ea5af74a2 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return m_ownerID; } } - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } public void Say(string message) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 455b51e595..d6e72005b5 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -327,7 +327,7 @@ namespace OpenSim.Tests.Common.Mock /// private UUID m_agentId; - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } /// /// The last caps seed url that this client was given.