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