Improve consistency of locking for SOG.m_parts in order to avoid race conditions in linking and unlinking

This commit is contained in:
Justin Clark-Casey (justincc)
2010-08-26 00:08:53 +01:00
parent 22fd00b002
commit 8031f8ec09
23 changed files with 912 additions and 747 deletions

View File

@@ -364,45 +364,48 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
if (m_parentScene.m_clampPrimSize)
lock (sceneObject.Children)
{
foreach (SceneObjectPart part in sceneObject.Children.Values)
if (m_parentScene.m_clampPrimSize)
{
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;
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;
}
}
}
sceneObject.AttachToScene(m_parentScene);
if (sendClientUpdates)
sceneObject.ScheduleGroupForFullUpdate();
Entities.Add(sceneObject);
m_numPrim += sceneObject.Children.Count;
sceneObject.AttachToScene(m_parentScene);
if (attachToBackup)
sceneObject.AttachToBackup();
if (sendClientUpdates)
sceneObject.ScheduleGroupForFullUpdate();
Entities.Add(sceneObject);
m_numPrim += sceneObject.Children.Count;
if (attachToBackup)
sceneObject.AttachToBackup();
if (OnObjectCreate != null)
OnObjectCreate(sceneObject);
lock (m_dictionary_lock)
{
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
foreach (SceneObjectPart part in sceneObject.Children.Values)
if (OnObjectCreate != null)
OnObjectCreate(sceneObject);
lock (m_dictionary_lock)
{
SceneObjectGroupsByFullID[part.UUID] = sceneObject;
SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
foreach (SceneObjectPart part in sceneObject.Children.Values)
{
SceneObjectGroupsByFullID[part.UUID] = sceneObject;
SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
}
}
}
}
@@ -420,11 +423,16 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!resultOfObjectLinked)
{
m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count;
if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
SceneObjectGroup sog = Entities[uuid] as SceneObjectGroup;
lock (sog.Children)
{
RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count);
m_numPrim -= sog.PrimCount;
if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
{
RemovePhysicalPrim(sog.PrimCount);
}
}
}
@@ -1603,7 +1611,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (part != null)
{
if (part.ParentGroup.Children.Count != 1) // Skip single
if (part.ParentGroup.PrimCount != 1) // Skip single
{
if (part.LinkNum < 2) // Root
rootParts.Add(part);
@@ -1631,8 +1639,15 @@ namespace OpenSim.Region.Framework.Scenes
// However, editing linked parts and unlinking may be different
//
SceneObjectGroup group = root.ParentGroup;
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
int numChildren = group.Children.Count;
List<SceneObjectPart> newSet = null;
int numChildren = -1;
lock (group.Children)
{
newSet = new List<SceneObjectPart>(group.Children.Values);
numChildren = group.PrimCount;
}
// If there are prims left in a link set, but the root is
// slated for unlink, we need to do this
@@ -1711,12 +1726,17 @@ namespace OpenSim.Region.Framework.Scenes
{
if (ent is SceneObjectGroup)
{
foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children)
SceneObjectGroup sog = ent as SceneObjectGroup;
lock (sog.Children)
{
if (subent.Value.LocalId == localID)
foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
{
objid = subent.Key;
obj = subent.Value;
if (subent.Value.LocalId == localID)
{
objid = subent.Key;
obj = subent.Value;
}
}
}
}
@@ -1781,7 +1801,8 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup original = GetGroupByPrim(originalPrimID);
if (original != null)
{
if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition))
if (m_parentScene.Permissions.CanDuplicateObject(
original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
{
SceneObjectGroup copy = original.Copy(true);
copy.AbsolutePosition = copy.AbsolutePosition + offset;