From dc3cfcbe694c4f58e9abcf85d3b35d1073b25659 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 17 May 2012 23:33:26 +0100 Subject: [PATCH] Check agent limit against root agent count rather than both root and child agents From sl docs such as http://community.secondlife.com/t5/English-Knowledge-Base/Managing-Private-Regions/ta-p/700115 agent should apply to avatars only. This makes sense from a user perspective, and also from a code perspective since child agents with no physics or actions take up a fraction of root agent resources. As such, the check is now only performed in Scene.QueryAccess() - cross and teleport check this before allowing an agent to translocate. This also removes an off-by-one error that could occur in certain circumstances on teleport when a new child agent was double counted when a pre-teleport agent update was performed. This does not affect an existing bug where limits or other QueryAccess() checks are not applied to avatars logging directly into a region. --- OpenSim/Region/Framework/Scenes/Scene.cs | 47 +++++++++++++------ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 5 -- .../Region/Framework/Scenes/ScenePresence.cs | 13 ++++- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index aa27a2a0be..afec3563a9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2629,7 +2629,8 @@ namespace OpenSim.Region.Framework.Scenes if (sp == null) { m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} to scene {1} at pos {2}", client.Name, RegionInfo.RegionName, client.StartPos); + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); m_clientManager.Add(client); SubscribeToClientEvents(client); @@ -3880,8 +3881,7 @@ namespace OpenSim.Region.Framework.Scenes // XPTO: if this agent is not allowed here as root, always return false - // We have to wait until the viewer contacts this region after receiving EAC. - // That calls AddNewClient, which finally creates the ScenePresence + // TODO: This check should probably be in QueryAccess(). ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); if (nearestParcel == null) { @@ -3892,14 +3892,8 @@ namespace OpenSim.Region.Framework.Scenes return false; } - int num = m_sceneGraph.GetNumberOfScenePresences(); - - if (num >= RegionInfo.RegionSettings.AgentLimit) - { - if (!Permissions.IsAdministrator(cAgentData.AgentID)) - return false; - } - + // We have to wait until the viewer contacts this region after receiving EAC. + // That calls AddNewClient, which finally creates the ScenePresence ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) @@ -3943,14 +3937,28 @@ namespace OpenSim.Region.Framework.Scenes return false; } + /// + /// Poll until the requested ScenePresence appears or we timeout. + /// + /// The scene presence is found, else null. + /// protected virtual ScenePresence WaitGetScenePresence(UUID agentID) { int ntimes = 10; - ScenePresence childAgentUpdate = null; - while ((childAgentUpdate = GetScenePresence(agentID)) == null && (ntimes-- > 0)) + ScenePresence sp = null; + while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) Thread.Sleep(1000); - return childAgentUpdate; + if (sp == null) + m_log.WarnFormat( + "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", + agentID, RegionInfo.RegionName); +// else +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits", +// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes); + + return sp; } public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) @@ -5157,13 +5165,22 @@ namespace OpenSim.Region.Framework.Scenes // child agent creation, thereby emulating the SL behavior. public bool QueryAccess(UUID agentID, Vector3 position, out string reason) { - int num = m_sceneGraph.GetNumberOfScenePresences(); + // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. + // However, the long term fix is to make sure root agent count is always accurate. + m_sceneGraph.RecalculateStats(); + + int num = m_sceneGraph.GetRootAgentCount(); if (num >= RegionInfo.RegionSettings.AgentLimit) { if (!Permissions.IsAdministrator(agentID)) { reason = "The region is full"; + + m_log.DebugFormat( + "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", + agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); + return false; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 9819bca412..2cc9106497 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -797,11 +797,6 @@ namespace OpenSim.Region.Framework.Scenes return m_scenePresenceArray; } - public int GetNumberOfScenePresences() - { - return m_scenePresenceArray.Count; - } - /// /// Request a scene presence by UUID. Fast, indexed lookup. /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d4bbbe6253..9b157501dd 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1224,6 +1224,12 @@ namespace OpenSim.Region.Framework.Scenes Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); m_callbackURI = null; } +// else +// { +// m_log.DebugFormat( +// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", +// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); +// } ValidateAndSendAppearanceAndAgentData(); @@ -2569,7 +2575,7 @@ namespace OpenSim.Region.Framework.Scenes // If we are using the the cached appearance then send it out to everyone if (cachedappearance) { - m_log.DebugFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); + m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); // If the avatars baked textures are all in the cache, then we have a // complete appearance... send it out, if not, then we'll send it when @@ -3031,7 +3037,7 @@ namespace OpenSim.Region.Framework.Scenes public void ChildAgentDataUpdate(AgentData cAgentData) { - //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); +// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); if (!IsChildAgent) return; @@ -3171,6 +3177,9 @@ namespace OpenSim.Region.Framework.Scenes m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", +// Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity;