From f9945bf87f93d9e676801af77c4a7fdaf3999ef4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 11 Aug 2008 23:20:14 +0000 Subject: [PATCH] Patch #9163 - Refactor initial packet sending out of InnerScene into ScenePresence. Pace prim delivery to about 200 updates/s max. Break a long-held lock that caused the notorious MapBlockQuery XMLRPC timeout on agent login. Eliminate 60 second timeout at "Waiting for region handshake". Fix region crossing/teleport response. Fix appearance in primmy regions. --- .../Region/Environment/Scenes/InnerScene.cs | 37 ----- OpenSim/Region/Environment/Scenes/Scene.cs | 9 - .../Environment/Scenes/ScenePresence.cs | 157 +++++++++--------- 3 files changed, 74 insertions(+), 129 deletions(-) diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs index 8b395a2a7d..c4e4919a37 100644 --- a/OpenSim/Region/Environment/Scenes/InnerScene.cs +++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs @@ -954,43 +954,6 @@ namespace OpenSim.Region.Environment.Scenes return LLUUID.Zero; } - protected internal void SendAllSceneObjectsToClient(ScenePresence presence) - { - List EntityList = GetEntities(); - - foreach (EntityBase ent in EntityList) - { - if (ent is SceneObjectGroup) - { - // Only send child agents stuff in their draw distance. - // This will need to be done for every agent once we figure out - // what we're going to use to store prim that agents already got - // the initial update for and what we'll use to limit the - // space we check for new objects on movement. - - if (presence.IsChildAgent && m_parentScene.m_seeIntoRegionFromNeighbor) - { - LLVector3 oLoc = ((SceneObjectGroup)ent).AbsolutePosition; - float distResult = (float)Util.GetDistanceTo(presence.AbsolutePosition, oLoc); - - //m_log.Info("[DISTANCE]: " + distResult.ToString()); - - if (distResult < presence.DrawDistance) - { - // Send Only if we don't already know about it. - // KnownPrim also makes the prim known when called. - if (!presence.KnownPrim(((SceneObjectGroup)ent).UUID)) - ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); - } - } - else - { - ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); - } - } - } - } - protected internal void ForEachClient(Action action) { lock (ScenePresences) diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 33b2f6fc0b..f39a0e63a1 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -3498,15 +3498,6 @@ namespace OpenSim.Region.Environment.Scenes m_innerScene.RemovePhysicalPrim(num); } - /// - /// - /// - /// - public void SendAllSceneObjectsToClient(ScenePresence presence) - { - m_innerScene.SendAllSceneObjectsToClient(presence); - } - //The idea is to have a group of method that return a list of avatars meeting some requirement // ie it could be all m_scenePresences within a certain range of the calling prim/avatar. diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index e37b26b875..1fcda038e6 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -128,7 +128,6 @@ namespace OpenSim.Region.Environment.Scenes // Agent moves with a PID controller causing a force to be exerted. private bool m_newForce = false; private bool m_newCoarseLocations = true; - private bool m_gotAllObjectsInScene = false; private float m_health = 100f; private LLVector3 m_lastVelocity = LLVector3.Zero; @@ -161,8 +160,6 @@ namespace OpenSim.Region.Environment.Scenes private LLVector3 m_autoPilotTarget = LLVector3.Zero; private bool m_sitAtAutoTarget = false; - private List m_knownPrimUUID = new List(); - // Agent's Draw distance. protected float m_DrawDistance = 0f; @@ -193,6 +190,8 @@ namespace OpenSim.Region.Environment.Scenes private LLVector3 posLastSignificantMove = new LLVector3(); private UpdateQueue m_partsUpdateQueue = new UpdateQueue(); + private Queue m_pendingObjects = null; + private Dictionary m_updateTimes = new Dictionary(); #region Properties @@ -212,16 +211,6 @@ namespace OpenSim.Region.Environment.Scenes get { return m_movementflag; } } - public bool KnownPrim(LLUUID primID) - { - if (m_knownPrimUUID.Contains(primID)) - { - return true; - } - m_knownPrimUUID.Add(primID); - return false; - } - public bool Updated { set { m_updateflag = value; } @@ -508,72 +497,93 @@ namespace OpenSim.Region.Environment.Scenes //} m_perfMonMS = System.Environment.TickCount; - if (!m_gotAllObjectsInScene) + if (m_pendingObjects == null) { if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor) { - m_scene.SendAllSceneObjectsToClient(this); - m_gotAllObjectsInScene = true; + m_pendingObjects = new Queue(); + + foreach (EntityBase e in m_scene.Entities.Values) + if(e is SceneObjectGroup) + m_pendingObjects.Enqueue((SceneObjectGroup)e); } } - if (m_partsUpdateQueue.Count > 0) + while(m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 60) { - bool runUpdate = true; - int updateCount = 0; - while (runUpdate) - { - SceneObjectPart part = m_partsUpdateQueue.Dequeue(); - if (m_updateTimes.ContainsKey(part.UUID)) - { - ScenePartUpdate update = m_updateTimes[part.UUID]; + SceneObjectGroup g = m_pendingObjects.Dequeue(); - // We deal with the possibility that two updates occur at the same unix time - // at the update point itself. - if (update.LastFullUpdateTime < part.TimeStampFull) - { + // This is where we should check for draw distance + // do culling and stuff. Problem with that is that until + // we recheck in movement, that won't work right. + // So it's not implemented now. + // + + // Don't even queue if we have seent this one + // + if (!m_updateTimes.ContainsKey(g.UUID)) + g.ScheduleFullUpdateToAvatar(this); + } + + int updateCount = 0; + + while (m_partsUpdateQueue.Count > 0) + { + SceneObjectPart part = m_partsUpdateQueue.Dequeue(); + if (m_updateTimes.ContainsKey(part.UUID)) + { + ScenePartUpdate update = m_updateTimes[part.UUID]; + + // We deal with the possibility that two updates occur at + // the same unix time at the update point itself. + + if (update.LastFullUpdateTime < part.TimeStampFull) + { // m_log.DebugFormat( // "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampFull); - part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); + part.SendFullUpdate(ControllingClient, + GenerateClientFlags(part.UUID)); - // We'll update to the part's timestamp rather than the current time to - // avoid the race condition whereby the next tick occurs while we are - // doing this update. If this happened, then subsequent updates which occurred - // on the same tick or the next tick of the last update would be ignored. - update.LastFullUpdateTime = part.TimeStampFull; + // We'll update to the part's timestamp rather than + // the current time to avoid the race condition + // whereby the next tick occurs while we are doing + // this update. If this happened, then subsequent + // updates which occurred on the same tick or the + // next tick of the last update would be ignored. - updateCount++; - } - else if (update.LastTerseUpdateTime <= part.TimeStampTerse) - { + update.LastFullUpdateTime = part.TimeStampFull; + + updateCount++; + } + else if (update.LastTerseUpdateTime <= part.TimeStampTerse) + { // m_log.DebugFormat( // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampTerse); - part.SendTerseUpdate(ControllingClient); + part.SendTerseUpdate(ControllingClient); - update.LastTerseUpdateTime = part.TimeStampTerse; - updateCount++; - } - } - else - { - //never been sent to client before so do full update - part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); - ScenePartUpdate update = new ScenePartUpdate(); - update.FullID = part.UUID; - update.LastFullUpdateTime = part.TimeStampFull; - m_updateTimes.Add(part.UUID, update); + update.LastTerseUpdateTime = part.TimeStampTerse; updateCount++; } - - if (m_partsUpdateQueue.Count < 1 || updateCount > 60) - { - runUpdate = false; - } } + else + { + //never been sent to client before so do full update + + part.SendFullUpdate(ControllingClient, + GenerateClientFlags(part.UUID)); + ScenePartUpdate update = new ScenePartUpdate(); + update.FullID = part.UUID; + update.LastFullUpdateTime = part.TimeStampFull; + m_updateTimes.Add(part.UUID, update); + updateCount++; + } + + if (updateCount > 60) + break; } m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); @@ -631,15 +641,13 @@ namespace OpenSim.Region.Environment.Scenes m_scene.SwapRootAgentCount(false); m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid); m_scene.AddCapsHandler(m_uuid); - //if (!m_gotAllObjectsInScene) - //{ - m_scene.SendAllSceneObjectsToClient(this); + + // On the next prim update, all objects will be sent + // + m_pendingObjects = null; m_scene.EventManager.TriggerOnMakeRootAgent(this); m_scene.CommsManager.UserService.UpdateUserCurrentRegion(UUID, m_scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionHandle); - - //m_gotAllObjectsInScene = true; - //} } /// @@ -776,7 +784,6 @@ namespace OpenSim.Region.Environment.Scenes { m_isChildAgent = false; - //this.m_scene.SendAllSceneObjectsToClient(this.ControllingClient); MakeRootAgent(AbsolutePosition, false); } } @@ -2043,7 +2050,8 @@ namespace OpenSim.Region.Environment.Scenes // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. if (m_scene.m_seeIntoRegionFromNeighbor) - m_scene.SendAllSceneObjectsToClient(this); + m_pendingObjects = null; + //cAgentData.AVHeight; //cAgentData.regionHandle; //m_velocity = cAgentData.Velocity; @@ -2248,10 +2256,6 @@ namespace OpenSim.Region.Environment.Scenes m_attachments.Clear(); } } - lock (m_knownPrimUUID) - { - m_knownPrimUUID.Clear(); - } lock (m_knownChildRegions) { m_knownChildRegions.Clear(); @@ -2398,7 +2402,6 @@ namespace OpenSim.Region.Environment.Scenes m_newForce = (bool)info.GetValue("m_newForce", typeof(bool)); //m_newAvatar = (bool)info.GetValue("m_newAvatar", typeof(bool)); m_newCoarseLocations = (bool)info.GetValue("m_newCoarseLocations", typeof(bool)); - m_gotAllObjectsInScene = (bool)info.GetValue("m_gotAllObjectsInScene", typeof(bool)); m_avHeight = (float)info.GetValue("m_avHeight", typeof(float)); crossingFromRegion = (ulong)info.GetValue("crossingFromRegion", typeof(ulong)); @@ -2503,13 +2506,6 @@ namespace OpenSim.Region.Environment.Scenes m_state = (byte)info.GetValue("m_state", typeof(byte)); - List knownPrimUUID_work = (List)info.GetValue("m_knownPrimUUID", typeof(List)); - - foreach (Guid id in knownPrimUUID_work) - { - m_knownPrimUUID.Add(new LLUUID(id)); - } - //System.Console.WriteLine("ScenePresence Deserialize END"); } @@ -2551,7 +2547,7 @@ namespace OpenSim.Region.Environment.Scenes info.AddValue("m_newForce", m_newForce); //info.AddValue("m_newAvatar", m_newAvatar); info.AddValue("m_newCoarseLocations", m_newCoarseLocations); - info.AddValue("m_gotAllObjectsInScene", m_gotAllObjectsInScene); + info.AddValue("m_gotAllObjectsInScene", false); info.AddValue("m_avHeight", m_avHeight); // info.AddValue("m_regionInfo", m_regionInfo); @@ -2650,11 +2646,6 @@ namespace OpenSim.Region.Environment.Scenes List knownPrimUUID_work = new List(); - foreach (LLUUID id in m_knownPrimUUID) - { - knownPrimUUID_work.Add(id.UUID); - } - info.AddValue("m_knownPrimUUID", knownPrimUUID_work); }