First pass at cleaning up thread safety in EntityManager and SceneGraph

This commit is contained in:
John Hurliman
2010-09-10 12:04:12 -07:00
parent 9609faa8eb
commit dd277a0d02
25 changed files with 252 additions and 395 deletions

View File

@@ -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))
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)
{
// 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 (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
/// <returns>true if the object was deleted, false if there was no object to delete</returns>
public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
{
if (Entities.ContainsKey(uuid))
EntityBase entity;
if (!Entities.TryGetValue(uuid, out entity) && entity is SceneObjectGroup)
return false;
SceneObjectGroup grp = (SceneObjectGroup)entity;
if (!resultOfObjectLinked)
{
SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid];
m_numPrim -= grp.PrimCount;
if (!resultOfObjectLinked)
{
m_numPrim -= grp.PrimCount;
if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
RemovePhysicalPrim(grp.PrimCount);
}
if (OnObjectRemove != null)
OnObjectRemove(Entities[uuid]);
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);
}
Entities.Remove(uuid);
//SceneObjectGroup part;
//((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
return true;
if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
RemovePhysicalPrim(grp.PrimCount);
}
return false;
if (OnObjectRemove != null)
OnObjectRemove(Entities[uuid]);
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);
}
return Entities.Remove(uuid);
}
/// <summary>
@@ -468,9 +453,7 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void AddToUpdateList(SceneObjectGroup obj)
{
lock (m_updateList)
{
m_updateList[obj.UUID] = obj;
}
}
/// <summary>
@@ -480,34 +463,39 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!Monitor.TryEnter(m_updateLock))
return;
List<SceneObjectGroup> updates;
// Some updates add more updates to the updateList.
// Get the current list of updates and clear the list before iterating
lock (m_updateList)
try
{
updates = new List<SceneObjectGroup>(m_updateList.Values);
m_updateList.Clear();
}
List<SceneObjectGroup> updates;
// Go through all updates
for (int i = 0; i < updates.Count; i++)
{
SceneObjectGroup sog = updates[i];
// 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<SceneObjectGroup>(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
/// <returns>null if no scene object group containing that prim is found</returns>
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<EntityBase> 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<EntityBase> 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<EntityBase> EntityList = GetEntities();
EntityBase[] EntityList = GetEntities();
foreach (EntityBase ent in EntityList)
{
if (ent is SceneObjectGroup)
@@ -984,23 +970,28 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>null if the part was not found</returns>
protected internal SceneObjectPart GetSceneObjectPart(string name)
{
List<EntityBase> 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;
}
/// <summary>
@@ -1021,7 +1012,7 @@ namespace OpenSim.Region.Framework.Scenes
/// it
/// </summary>
/// <returns></returns>
protected internal List<EntityBase> GetEntities()
protected internal EntityBase[] GetEntities()
{
return Entities.GetEntities();
}
@@ -1030,7 +1021,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
List<EntityBase> 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<EntityBase> EntityList = GetEntities();
foreach (EntityBase ent in EntityList)
EntityBase[] entityList = GetEntities();
foreach (EntityBase ent in entityList)
{
if (ent is SceneObjectGroup)
{