From dd277a0d02f1aa79f4fcb5d108cbc696e90500c2 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 10 Sep 2010 12:04:12 -0700 Subject: First pass at cleaning up thread safety in EntityManager and SceneGraph --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 263 +++++++++++++------------- 1 file changed, 127 insertions(+), 136 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs') diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index dfb26b9..3d3e822 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -348,68 +348,57 @@ namespace OpenSim.Region.Framework.Scenes if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; - lock (sceneObject) - { - if (Entities.ContainsKey(sceneObject.UUID)) - { -// m_log.WarnFormat( -// "[SCENE GRAPH]: Scene object {0} {1} was already in region {2} on add request", -// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); - return false; - } - -// m_log.DebugFormat( -// "[SCENE GRAPH]: Adding object {0} {1} to region {2}", -// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); - - lock (sceneObject.Children) + if (Entities.ContainsKey(sceneObject.UUID)) + return false; + + // Clamp child prim sizes and add child prims to the m_numPrim count + lock (sceneObject.Children) + { + if (m_parentScene.m_clampPrimSize) { - if (m_parentScene.m_clampPrimSize) + foreach (SceneObjectPart part in sceneObject.Children.Values) { - foreach (SceneObjectPart part in sceneObject.Children.Values) - { - Vector3 scale = part.Shape.Scale; - - if (scale.X > m_parentScene.m_maxNonphys) - scale.X = m_parentScene.m_maxNonphys; - if (scale.Y > m_parentScene.m_maxNonphys) - scale.Y = m_parentScene.m_maxNonphys; - if (scale.Z > m_parentScene.m_maxNonphys) - scale.Z = m_parentScene.m_maxNonphys; - - part.Shape.Scale = scale; - } + Vector3 scale = part.Shape.Scale; + + if (scale.X > m_parentScene.m_maxNonphys) + scale.X = m_parentScene.m_maxNonphys; + if (scale.Y > m_parentScene.m_maxNonphys) + scale.Y = m_parentScene.m_maxNonphys; + if (scale.Z > m_parentScene.m_maxNonphys) + scale.Z = m_parentScene.m_maxNonphys; + + part.Shape.Scale = scale; } - - m_numPrim += sceneObject.Children.Count; } - - sceneObject.AttachToScene(m_parentScene); - if (sendClientUpdates) - sceneObject.ScheduleGroupForFullUpdate(); - - Entities.Add(sceneObject); + m_numPrim += sceneObject.Children.Count; + } - if (attachToBackup) - sceneObject.AttachToBackup(); + sceneObject.AttachToScene(m_parentScene); - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); - - lock (SceneObjectGroupsByFullID) - { - SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - foreach (SceneObjectPart part in sceneObject.Children.Values) - SceneObjectGroupsByFullID[part.UUID] = sceneObject; - } - - lock (SceneObjectGroupsByLocalID) - { - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; - foreach (SceneObjectPart part in sceneObject.Children.Values) - SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; - } + if (sendClientUpdates) + sceneObject.ScheduleGroupForFullUpdate(); + + Entities.Add(sceneObject); + + if (attachToBackup) + sceneObject.AttachToBackup(); + + if (OnObjectCreate != null) + OnObjectCreate(sceneObject); + + lock (SceneObjectGroupsByFullID) + { + SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) + SceneObjectGroupsByFullID[part.UUID] = sceneObject; + } + + lock (SceneObjectGroupsByLocalID) + { + SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) + SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } return true; @@ -421,42 +410,38 @@ namespace OpenSim.Region.Framework.Scenes /// true if the object was deleted, false if there was no object to delete public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) { - if (Entities.ContainsKey(uuid)) - { - SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid]; + EntityBase entity; + if (!Entities.TryGetValue(uuid, out entity) && entity is SceneObjectGroup) + return false; - if (!resultOfObjectLinked) - { - m_numPrim -= grp.PrimCount; + SceneObjectGroup grp = (SceneObjectGroup)entity; - if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) - RemovePhysicalPrim(grp.PrimCount); - } + if (!resultOfObjectLinked) + { + m_numPrim -= grp.PrimCount; - if (OnObjectRemove != null) - OnObjectRemove(Entities[uuid]); + if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) + RemovePhysicalPrim(grp.PrimCount); + } - lock (SceneObjectGroupsByFullID) - { - foreach (SceneObjectPart part in grp.Children.Values) - SceneObjectGroupsByFullID.Remove(part.UUID); - SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); - } - lock (SceneObjectGroupsByLocalID) - { - foreach (SceneObjectPart part in grp.Children.Values) - SceneObjectGroupsByLocalID.Remove(part.LocalId); - SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); - } + if (OnObjectRemove != null) + OnObjectRemove(Entities[uuid]); - Entities.Remove(uuid); - //SceneObjectGroup part; - //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) + lock (SceneObjectGroupsByFullID) + { + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByFullID.Remove(part.UUID); + SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); + } - return true; + lock (SceneObjectGroupsByLocalID) + { + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByLocalID.Remove(part.LocalId); + SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); } - return false; + return Entities.Remove(uuid); } /// @@ -468,9 +453,7 @@ namespace OpenSim.Region.Framework.Scenes protected internal void AddToUpdateList(SceneObjectGroup obj) { lock (m_updateList) - { m_updateList[obj.UUID] = obj; - } } /// @@ -480,34 +463,39 @@ namespace OpenSim.Region.Framework.Scenes { if (!Monitor.TryEnter(m_updateLock)) return; - - List updates; - - // Some updates add more updates to the updateList. - // Get the current list of updates and clear the list before iterating - lock (m_updateList) - { - updates = new List(m_updateList.Values); - m_updateList.Clear(); - } - - // Go through all updates - for (int i = 0; i < updates.Count; i++) + try { - SceneObjectGroup sog = updates[i]; + List updates; - // Don't abort the whole update if one entity happens to give us an exception. - try + // Some updates add more updates to the updateList. + // Get the current list of updates and clear the list before iterating + lock (m_updateList) { - sog.Update(); + updates = new List(m_updateList.Values); + m_updateList.Clear(); } - catch (Exception e) + + // Go through all updates + for (int i = 0; i < updates.Count; i++) { - m_log.ErrorFormat( - "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); + SceneObjectGroup sog = updates[i]; + + // Don't abort the whole update if one entity happens to give us an exception. + try + { + sog.Update(); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); + } } } - Monitor.Exit(m_updateLock); + finally + { + Monitor.Exit(m_updateLock); + } } protected internal void AddPhysicalPrim(int number) @@ -864,8 +852,9 @@ namespace OpenSim.Region.Framework.Scenes /// null if no scene object group containing that prim is found public SceneObjectGroup GetGroupByPrim(uint localID) { - if (Entities.ContainsKey(localID)) - return Entities[localID] as SceneObjectGroup; + EntityBase entity; + if (Entities.TryGetValue(localID, out entity)) + return entity as SceneObjectGroup; //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); SceneObjectGroup sog; @@ -879,23 +868,22 @@ namespace OpenSim.Region.Framework.Scenes } } - List EntityList = GetEntities(); - foreach (EntityBase ent in EntityList) + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) { //m_log.DebugFormat("Looking at entity {0}", ent.UUID); if (ent is SceneObjectGroup) { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) + sog = (SceneObjectGroup)ent; + if (sog.HasChildPrim(localID)) { - sog = (SceneObjectGroup)ent; lock (SceneObjectGroupsByLocalID) - { SceneObjectGroupsByLocalID[localID] = sog; - } return sog; } } } + return null; } @@ -921,23 +909,21 @@ namespace OpenSim.Region.Framework.Scenes } } - List EntityList = GetEntities(); - - foreach (EntityBase ent in EntityList) + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) { if (ent is SceneObjectGroup) { - if (((SceneObjectGroup)ent).HasChildPrim(fullID)) + sog = (SceneObjectGroup)ent; + if (sog.HasChildPrim(fullID)) { - sog = (SceneObjectGroup)ent; lock (SceneObjectGroupsByFullID) - { SceneObjectGroupsByFullID[fullID] = sog; - } return sog; } } } + return null; } @@ -946,7 +932,7 @@ namespace OpenSim.Region.Framework.Scenes // Primitive Ray Tracing float closestDistance = 280f; EntityIntersection result = new EntityIntersection(); - List EntityList = GetEntities(); + EntityBase[] EntityList = GetEntities(); foreach (EntityBase ent in EntityList) { if (ent is SceneObjectGroup) @@ -984,23 +970,28 @@ namespace OpenSim.Region.Framework.Scenes /// null if the part was not found protected internal SceneObjectPart GetSceneObjectPart(string name) { - List EntityList = GetEntities(); + SceneObjectPart sop = null; - // FIXME: use a dictionary here - foreach (EntityBase ent in EntityList) - { - if (ent is SceneObjectGroup) + Entities.Find( + delegate(EntityBase entity) { - foreach (SceneObjectPart p in ((SceneObjectGroup) ent).GetParts()) + if (entity is SceneObjectGroup) { - if (p.Name == name) + foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts()) { - return p; + if (p.Name == name) + { + sop = p; + return true; + } } } + + return false; } - } - return null; + ); + + return sop; } /// @@ -1021,7 +1012,7 @@ namespace OpenSim.Region.Framework.Scenes /// it /// /// - protected internal List GetEntities() + protected internal EntityBase[] GetEntities() { return Entities.GetEntities(); } @@ -1030,7 +1021,7 @@ namespace OpenSim.Region.Framework.Scenes { Dictionary topScripts = new Dictionary(); - List EntityList = GetEntities(); + EntityBase[] EntityList = GetEntities(); int limit = 0; foreach (EntityBase ent in EntityList) { @@ -1726,8 +1717,8 @@ namespace OpenSim.Region.Framework.Scenes UUID objid = UUID.Zero; SceneObjectPart obj = null; - List EntityList = GetEntities(); - foreach (EntityBase ent in EntityList) + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) { if (ent is SceneObjectGroup) { -- cgit v1.1