From 8031f8ec09df4f654c86a9c7bc498664f7b9d9dc Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 26 Aug 2010 00:08:53 +0100
Subject: Improve consistency of locking for SOG.m_parts in order to avoid race
conditions in linking and unlinking
---
.../ContentManagementSystem/CMEntityCollection.cs | 19 ++-
.../ContentManagementSystem/CMModel.cs | 35 +++--
.../ContentManagementSystem/CMView.cs | 9 +-
.../ContentManagementEntity.cs | 173 +++++++++++----------
.../ContentManagementSystem/MetaEntity.cs | 38 +++--
.../Scripting/Minimodule/SOPObject.cs | 19 ++-
6 files changed, 170 insertions(+), 123 deletions(-)
(limited to 'OpenSim/Region/OptionalModules')
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
index 56656fc..de1e01c 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
@@ -121,16 +121,19 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
continue;
temp = (SceneObjectGroup) currObj;
- if (m_CMEntityHash.ContainsKey(temp.UUID))
+ lock (temp.Children)
{
- foreach (SceneObjectPart part in temp.Children.Values)
- if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
+ if (m_CMEntityHash.ContainsKey(temp.UUID))
+ {
+ foreach (SceneObjectPart part in temp.Children.Values)
+ if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
+ missingList.Add(part);
+ }
+ else //Entire group is missing from revision. (and is a new part in region)
+ {
+ foreach (SceneObjectPart part in temp.Children.Values)
missingList.Add(part);
- }
- else //Entire group is missing from revision. (and is a new part in region)
- {
- foreach (SceneObjectPart part in temp.Children.Values)
- missingList.Add(part);
+ }
}
}
return missingList;
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
index 0dc78c0..e5fcb54 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -167,9 +167,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
{
// Deal with new parts not revisioned that have been deleted.
- foreach (SceneObjectPart part in group.Children.Values)
- if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
- m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
+ lock (group.Children)
+ {
+ foreach (SceneObjectPart part in group.Children.Values)
+ if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
+ m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
+ }
}
///
@@ -207,8 +210,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
{
temp = SceneObjectSerializer.FromXml2Format(xml);
temp.SetScene(scene);
- foreach (SceneObjectPart part in temp.Children.Values)
- part.RegionHandle = scene.RegionInfo.RegionHandle;
+
+ lock (temp.Children)
+ {
+ foreach (SceneObjectPart part in temp.Children.Values)
+ part.RegionHandle = scene.RegionInfo.RegionHandle;
+ }
+
ReplacementList.Add(temp.UUID, (EntityBase)temp);
}
catch (Exception e)
@@ -338,15 +346,20 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
System.Collections.ArrayList auraList = new System.Collections.ArrayList();
if (group == null)
return null;
- foreach (SceneObjectPart part in group.Children.Values)
+
+ lock (group.Children)
{
- if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
+ foreach (SceneObjectPart part in group.Children.Values)
{
- ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
- ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
- auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
+ if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
+ {
+ ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
+ ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
+ auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
+ }
}
}
+
return auraList;
}
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
index 46fbd39..f75f40a 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
@@ -186,9 +186,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
// Deal with new parts not revisioned that have been deleted.
- foreach (SceneObjectPart part in group.Children.Values)
- if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
- ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
+ lock (group.Children)
+ {
+ foreach (SceneObjectPart part in group.Children.Values)
+ if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
+ ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
+ }
}
public void SendMetaEntitiesToNewClient(IClientAPI client)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
index ada6701..2730eee 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -132,30 +132,33 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
// if group is not contained in scene's list
if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
{
- foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
+ lock (m_UnchangedEntity.Children)
{
- // if scene list no longer contains this part, display translucent part and mark with red aura
- if (!ContainsKey(sceneEntityList, part.UUID))
+ foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
{
- // if already displaying a red aura over part, make sure its red
- if (m_AuraEntities.ContainsKey(part.UUID))
- {
- m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
- }
- else
+ // if scene list no longer contains this part, display translucent part and mark with red aura
+ if (!ContainsKey(sceneEntityList, part.UUID))
{
- AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
- part.GetWorldPosition(),
- MetaEntity.TRANSLUCENT,
- new Vector3(254,0,0),
- part.Scale
- );
- m_AuraEntities.Add(part.UUID, auraGroup);
+ // if already displaying a red aura over part, make sure its red
+ if (m_AuraEntities.ContainsKey(part.UUID))
+ {
+ m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
+ }
+ else
+ {
+ AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
+ part.GetWorldPosition(),
+ MetaEntity.TRANSLUCENT,
+ new Vector3(254,0,0),
+ part.Scale
+ );
+ m_AuraEntities.Add(part.UUID, auraGroup);
+ }
+ SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
+ SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
}
- SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
- SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
+ // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
}
- // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
}
// a deleted part has no where to point a beam particle system,
@@ -180,8 +183,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
///
public bool HasChildPrim(UUID uuid)
{
- if (m_UnchangedEntity.Children.ContainsKey(uuid))
- return true;
+ lock (m_UnchangedEntity.Children)
+ if (m_UnchangedEntity.Children.ContainsKey(uuid))
+ return true;
+
return false;
}
@@ -190,9 +195,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
///
public bool HasChildPrim(uint localID)
{
- foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
- if (part.LocalId == localID)
- return true;
+ lock (m_UnchangedEntity.Children)
+ {
+ foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
+ if (part.LocalId == localID)
+ return true;
+ }
+
return false;
}
@@ -228,37 +237,72 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
// Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
// had originally saved.
// m_Entity will NOT necessarily be the same entity as the user had saved.
- foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
+ lock (m_UnchangedEntity.Children)
{
- //This is the part that we use to show changes.
- metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
- if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
+ foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
{
- sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
- differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
- if (differences != Diff.NONE)
- metaEntityPart.Text = "CHANGE: " + differences.ToString();
- if (differences != 0)
+ //This is the part that we use to show changes.
+ metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
+ if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
{
- // Root Part that has been modified
- if ((differences&Diff.POSITION) > 0)
+ sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
+ differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
+ if (differences != Diff.NONE)
+ metaEntityPart.Text = "CHANGE: " + differences.ToString();
+ if (differences != 0)
+ {
+ // Root Part that has been modified
+ if ((differences&Diff.POSITION) > 0)
+ {
+ // If the position of any part has changed, make sure the RootPart of the
+ // meta entity is pointing with a beam particle system
+ if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
+ {
+ m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
+ m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
+ }
+ BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
+ m_UnchangedEntity.RootPart.GetWorldPosition(),
+ MetaEntity.TRANSLUCENT,
+ sceneEntityPart,
+ new Vector3(0,0,254)
+ );
+ m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
+ }
+
+ if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
+ {
+ m_AuraEntities[UnchangedPart.UUID].HideFromAll();
+ m_AuraEntities.Remove(UnchangedPart.UUID);
+ }
+ AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
+ UnchangedPart.GetWorldPosition(),
+ MetaEntity.TRANSLUCENT,
+ new Vector3(0,0,254),
+ UnchangedPart.Scale
+ );
+ m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
+ SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
+
+ DiffersFromSceneGroup = true;
+ }
+ else // no differences between scene part and meta part
{
- // If the position of any part has changed, make sure the RootPart of the
- // meta entity is pointing with a beam particle system
if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
{
m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
}
- BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
- m_UnchangedEntity.RootPart.GetWorldPosition(),
- MetaEntity.TRANSLUCENT,
- sceneEntityPart,
- new Vector3(0,0,254)
- );
- m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
+ if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
+ {
+ m_AuraEntities[UnchangedPart.UUID].HideFromAll();
+ m_AuraEntities.Remove(UnchangedPart.UUID);
+ }
+ SetPartTransparency(metaEntityPart, MetaEntity.NONE);
}
-
+ }
+ else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
+ {
if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
{
m_AuraEntities[UnchangedPart.UUID].HideFromAll();
@@ -267,48 +311,17 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
UnchangedPart.GetWorldPosition(),
MetaEntity.TRANSLUCENT,
- new Vector3(0,0,254),
+ new Vector3(254,0,0),
UnchangedPart.Scale
);
m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
-
+
DiffersFromSceneGroup = true;
}
- else // no differences between scene part and meta part
- {
- if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
- {
- m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
- m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
- }
- if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
- {
- m_AuraEntities[UnchangedPart.UUID].HideFromAll();
- m_AuraEntities.Remove(UnchangedPart.UUID);
- }
- SetPartTransparency(metaEntityPart, MetaEntity.NONE);
- }
- }
- else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
- {
- if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
- {
- m_AuraEntities[UnchangedPart.UUID].HideFromAll();
- m_AuraEntities.Remove(UnchangedPart.UUID);
- }
- AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
- UnchangedPart.GetWorldPosition(),
- MetaEntity.TRANSLUCENT,
- new Vector3(254,0,0),
- UnchangedPart.Scale
- );
- m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
- SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
-
- DiffersFromSceneGroup = true;
}
}
+
return changed;
}
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index 841ee00..796f437 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -150,15 +150,19 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
{
//make new uuids
Dictionary parts = new Dictionary();
- foreach (SceneObjectPart part in m_Entity.Children.Values)
+
+ lock (m_Entity.Children)
{
- part.ResetIDs(part.LinkNum);
- parts.Add(part.UUID, part);
+ foreach (SceneObjectPart part in m_Entity.Children.Values)
+ {
+ part.ResetIDs(part.LinkNum);
+ parts.Add(part.UUID, part);
+ }
+
+ //finalize
+ m_Entity.RootPart.PhysActor = null;
+ m_Entity.Children = parts;
}
-
- //finalize
- m_Entity.RootPart.PhysActor = null;
- m_Entity.Children = parts;
}
#endregion Protected Methods
@@ -173,8 +177,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
//This deletes the group without removing from any databases.
//This is important because we are not IN any database.
//m_Entity.FakeDeleteGroup();
- foreach (SceneObjectPart part in m_Entity.Children.Values)
- client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
+ lock (m_Entity.Children)
+ {
+ foreach (SceneObjectPart part in m_Entity.Children.Values)
+ client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
+ }
}
///
@@ -182,12 +189,15 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
///
public virtual void HideFromAll()
{
- foreach (SceneObjectPart part in m_Entity.Children.Values)
+ lock (m_Entity.Children)
{
- m_Entity.Scene.ForEachClient(
- delegate(IClientAPI controller)
- { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
- );
+ foreach (SceneObjectPart part in m_Entity.Children.Values)
+ {
+ m_Entity.Scene.ForEachClient(
+ delegate(IClientAPI controller)
+ { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
+ );
+ }
}
}
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 96cccb7..34171b0 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -185,14 +185,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
get
{
SceneObjectPart my = GetSOP();
- int total = my.ParentGroup.Children.Count;
-
- IObject[] rets = new IObject[total];
-
- int i = 0;
- foreach (KeyValuePair pair in my.ParentGroup.Children)
+ IObject[] rets = null;
+
+ lock (my.ParentGroup.Children)
{
- rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security);
+ int total = my.ParentGroup.Children.Count;
+
+ rets = new IObject[total];
+
+ int i = 0;
+ foreach (KeyValuePair pair in my.ParentGroup.Children)
+ {
+ rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security);
+ }
}
return rets;
--
cgit v1.1