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

prebuild-update
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

@ -232,7 +232,9 @@ namespace OpenSim.Data.MSSQL
/// <param name="regionUUID"></param> /// <param name="regionUUID"></param>
public void StoreObject(SceneObjectGroup obj, UUID regionUUID) public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
{ {
_Log.InfoFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); lock (obj.Children)
{
_Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count);
using (SqlConnection conn = new SqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
@ -291,7 +293,7 @@ namespace OpenSim.Data.MSSQL
} }
} }
} }
}
} }
/// <summary> /// <summary>

View File

@ -135,6 +135,8 @@ namespace OpenSim.Data.MySQL
dbcon.Open(); dbcon.Open();
MySqlCommand cmd = dbcon.CreateCommand(); MySqlCommand cmd = dbcon.CreateCommand();
lock (obj.Children)
{
foreach (SceneObjectPart prim in obj.Children.Values) foreach (SceneObjectPart prim in obj.Children.Values)
{ {
cmd.Parameters.Clear(); cmd.Parameters.Clear();
@ -239,10 +241,12 @@ namespace OpenSim.Data.MySQL
ExecuteNonQuery(cmd); ExecuteNonQuery(cmd);
} }
cmd.Dispose(); cmd.Dispose();
} }
} }
} }
}
public void RemoveObject(UUID obj, UUID regionUUID) public void RemoveObject(UUID obj, UUID regionUUID)
{ {

View File

@ -359,6 +359,8 @@ namespace OpenSim.Data.SQLite
return; return;
lock (ds) lock (ds)
{
lock (obj.Children)
{ {
foreach (SceneObjectPart prim in obj.Children.Values) foreach (SceneObjectPart prim in obj.Children.Values)
{ {
@ -366,6 +368,7 @@ namespace OpenSim.Data.SQLite
addPrim(prim, obj.UUID, regionUUID); addPrim(prim, obj.UUID, regionUUID);
} }
} }
}
Commit(); Commit();
// m_log.Info("[Dump of prims]: " + ds.GetXml()); // m_log.Info("[Dump of prims]: " + ds.GetXml());

View File

@ -326,6 +326,8 @@ namespace OpenSim.Data.SQLiteLegacy
return; return;
lock (ds) lock (ds)
{
lock (obj.Children)
{ {
foreach (SceneObjectPart prim in obj.Children.Values) foreach (SceneObjectPart prim in obj.Children.Values)
{ {
@ -333,6 +335,7 @@ namespace OpenSim.Data.SQLiteLegacy
addPrim(prim, obj.UUID, regionUUID); addPrim(prim, obj.UUID, regionUUID);
} }
} }
}
Commit(); Commit();
// m_log.Info("[Dump of prims]: " + ds.GetXml()); // m_log.Info("[Dump of prims]: " + ds.GetXml());

View File

@ -406,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{ {
if (!m_scene.Permissions.CanRezObject( if (!m_scene.Permissions.CanRezObject(
part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) part.ParentGroup.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
return; return;
presence.Appearance.DetachAttachment(itemID); presence.Appearance.DetachAttachment(itemID);

View File

@ -526,7 +526,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.RootPart.CreateSelected = true; group.RootPart.CreateSelected = true;
if (!m_Scene.Permissions.CanRezObject( if (!m_Scene.Permissions.CanRezObject(
group.Children.Count, remoteClient.AgentId, pos) group.PrimCount, remoteClient.AgentId, pos)
&& !attachment) && !attachment)
{ {
// The client operates in no fail mode. It will // The client operates in no fail mode. It will
@ -594,7 +594,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
rootPart.Name = item.Name; rootPart.Name = item.Name;
rootPart.Description = item.Description; rootPart.Description = item.Description;
List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); List<SceneObjectPart> partList = null;
lock (group.Children)
partList = new List<SceneObjectPart>(group.Children.Values);
group.SetGroup(remoteClient.ActiveGroupId, remoteClient); group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)

View File

@ -243,6 +243,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// to the same scene (when this is possible). // to the same scene (when this is possible).
sceneObject.ResetIDs(); sceneObject.ResetIDs();
lock (sceneObject.Children)
{
foreach (SceneObjectPart part in sceneObject.Children.Values) foreach (SceneObjectPart part in sceneObject.Children.Values)
{ {
if (!ResolveUserUuid(part.CreatorID)) if (!ResolveUserUuid(part.CreatorID))
@ -277,6 +279,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
} }
}
if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
{ {

View File

@ -128,7 +128,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
group.SetOwnerId(remoteClient.AgentId); group.SetOwnerId(remoteClient.AgentId);
group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId); group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);
List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); List<SceneObjectPart> partList = null;
lock (group.Children)
partList = new List<SceneObjectPart>(group.Children.Values);
if (m_scene.Permissions.PropagatePermissions()) if (m_scene.Permissions.PropagatePermissions())
{ {

View File

@ -227,7 +227,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{ {
SceneObjectGroup mapdot = (SceneObjectGroup)obj; SceneObjectGroup mapdot = (SceneObjectGroup)obj;
Color mapdotspot = Color.Gray; // Default color when prim color is white Color mapdotspot = Color.Gray; // Default color when prim color is white
// Loop over prim in group // Loop over prim in group
lock (mapdot.Children)
{
foreach (SceneObjectPart part in mapdot.Children.Values) foreach (SceneObjectPart part in mapdot.Children.Values)
{ {
if (part == null) if (part == null)
@ -498,6 +501,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
//} //}
} // Object is within 256m Z of terrain } // Object is within 256m Z of terrain
} // object is at least a meter wide } // object is at least a meter wide
} // mapdot.Children lock
} // loop over group children } // loop over group children
} // entitybase is sceneobject group } // entitybase is sceneobject group
} // foreach loop over entities } // foreach loop over entities

View File

@ -1974,7 +1974,7 @@ namespace OpenSim.Region.Framework.Scenes
if (null == group) if (null == group)
return null; return null;
if (!Permissions.CanRezObject(group.Children.Count, item.OwnerID, pos)) if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos))
return null; return null;
if (!Permissions.BypassPermissions()) if (!Permissions.BypassPermissions())
@ -2051,9 +2051,12 @@ namespace OpenSim.Region.Framework.Scenes
sog.SetGroup(groupID, remoteClient); sog.SetGroup(groupID, remoteClient);
sog.ScheduleGroupForFullUpdate(); sog.ScheduleGroupForFullUpdate();
lock (sog.Children)
{
foreach (SceneObjectPart child in sog.Children.Values) foreach (SceneObjectPart child in sog.Children.Values)
child.Inventory.ChangeInventoryOwner(ownerID); child.Inventory.ChangeInventoryOwner(ownerID);
} }
}
else else
{ {
if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId))
@ -2062,16 +2065,18 @@ namespace OpenSim.Region.Framework.Scenes
if (sog.GroupID != groupID) if (sog.GroupID != groupID)
continue; continue;
lock (sog.Children)
{
foreach (SceneObjectPart child in sog.Children.Values) foreach (SceneObjectPart child in sog.Children.Values)
{ {
child.LastOwnerID = child.OwnerID; child.LastOwnerID = child.OwnerID;
child.Inventory.ChangeInventoryOwner(groupID); child.Inventory.ChangeInventoryOwner(groupID);
} }
}
sog.SetOwnerId(groupID); sog.SetOwnerId(groupID);
sog.ApplyNextOwnerPermissions(); sog.ApplyNextOwnerPermissions();
} }
} }
foreach (uint localID in localIDs) foreach (uint localID in localIDs)

View File

@ -161,7 +161,12 @@ namespace OpenSim.Region.Framework.Scenes
// We also need to check the children of this prim as they // We also need to check the children of this prim as they
// can be selected as well and send property information // can be selected as well and send property information
bool foundPrim = false; bool foundPrim = false;
foreach (KeyValuePair<UUID, SceneObjectPart> child in ((SceneObjectGroup) ent).Children)
SceneObjectGroup sog = ent as SceneObjectGroup;
lock (sog.Children)
{
foreach (KeyValuePair<UUID, SceneObjectPart> child in (sog.Children))
{ {
if (child.Value.LocalId == primLocalID) if (child.Value.LocalId == primLocalID)
{ {
@ -170,7 +175,10 @@ namespace OpenSim.Region.Framework.Scenes
break; break;
} }
} }
if (foundPrim) break; }
if (foundPrim)
break;
} }
} }
} }

View File

@ -1756,8 +1756,9 @@ namespace OpenSim.Region.Framework.Scenes
if (group.RootPart == null) if (group.RootPart == null)
{ {
m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", m_log.ErrorFormat(
group.Children == null ? 0 : group.Children.Count); "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
group.Children == null ? 0 : group.PrimCount);
} }
AddRestoredSceneObject(group, true, true); AddRestoredSceneObject(group, true, true);
@ -2064,6 +2065,8 @@ namespace OpenSim.Region.Framework.Scenes
group.RemoveScriptInstances(true); group.RemoveScriptInstances(true);
} }
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
{ {
if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
@ -2076,6 +2079,8 @@ namespace OpenSim.Region.Framework.Scenes
part.PhysActor = null; part.PhysActor = null;
} }
} }
}
// if (rootPart.PhysActor != null) // if (rootPart.PhysActor != null)
// { // {
// PhysicsScene.RemovePrim(rootPart.PhysActor); // PhysicsScene.RemovePrim(rootPart.PhysActor);
@ -2426,15 +2431,17 @@ namespace OpenSim.Region.Framework.Scenes
// Force allocation of new LocalId // Force allocation of new LocalId
// //
lock (sceneObject.Children)
{
foreach (SceneObjectPart p in sceneObject.Children.Values) foreach (SceneObjectPart p in sceneObject.Children.Values)
p.LocalId = 0; p.LocalId = 0;
}
if (sceneObject.IsAttachmentCheckFull()) // Attachment if (sceneObject.IsAttachmentCheckFull()) // Attachment
{ {
sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
sceneObject.RootPart.AddFlag(PrimFlags.Phantom); sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
// Don't sent a full update here because this will cause full updates to be sent twice for // Don't sent a full update here because this will cause full updates to be sent twice for
// attachments on region crossings, resulting in viewer glitches. // attachments on region crossings, resulting in viewer glitches.
AddRestoredSceneObject(sceneObject, false, false, false); AddRestoredSceneObject(sceneObject, false, false, false);
@ -2447,7 +2454,6 @@ namespace OpenSim.Region.Framework.Scenes
if (sp != null) if (sp != null)
{ {
SceneObjectGroup grp = sceneObject; SceneObjectGroup grp = sceneObject;
m_log.DebugFormat( m_log.DebugFormat(
@ -2459,7 +2465,6 @@ namespace OpenSim.Region.Framework.Scenes
if (AttachmentsModule != null) if (AttachmentsModule != null)
AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
} }
else else
{ {

View File

@ -364,6 +364,8 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENE GRAPH]: Adding object {0} {1} to region {2}", // "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
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)
@ -406,6 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
}
return true; return true;
} }
@ -420,11 +423,16 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (!resultOfObjectLinked) if (!resultOfObjectLinked)
{ {
m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; SceneObjectGroup sog = Entities[uuid] as SceneObjectGroup;
lock (sog.Children)
{
m_numPrim -= sog.PrimCount;
if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
{ {
RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count); RemovePhysicalPrim(sog.PrimCount);
}
} }
} }
@ -1603,7 +1611,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (part != null) if (part != null)
{ {
if (part.ParentGroup.Children.Count != 1) // Skip single if (part.ParentGroup.PrimCount != 1) // Skip single
{ {
if (part.LinkNum < 2) // Root if (part.LinkNum < 2) // Root
rootParts.Add(part); rootParts.Add(part);
@ -1631,8 +1639,15 @@ namespace OpenSim.Region.Framework.Scenes
// However, editing linked parts and unlinking may be different // However, editing linked parts and unlinking may be different
// //
SceneObjectGroup group = root.ParentGroup; 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 // If there are prims left in a link set, but the root is
// slated for unlink, we need to do this // slated for unlink, we need to do this
@ -1711,7 +1726,11 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (ent is SceneObjectGroup) if (ent is SceneObjectGroup)
{ {
foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children) SceneObjectGroup sog = ent as SceneObjectGroup;
lock (sog.Children)
{
foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
{ {
if (subent.Value.LocalId == localID) if (subent.Value.LocalId == localID)
{ {
@ -1721,6 +1740,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
}
//Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
//aka ObjectFlags.JointWheel = IncludeInSearch //aka ObjectFlags.JointWheel = IncludeInSearch
@ -1781,7 +1801,8 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup original = GetGroupByPrim(originalPrimID); SceneObjectGroup original = GetGroupByPrim(originalPrimID);
if (original != null) 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); SceneObjectGroup copy = original.Copy(true);
copy.AbsolutePosition = copy.AbsolutePosition + offset; copy.AbsolutePosition = copy.AbsolutePosition + offset;

View File

@ -213,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public int PrimCount public int PrimCount
{ {
get { return m_parts.Count; } get { lock (m_parts) { return m_parts.Count; } }
} }
protected Quaternion m_rotation = Quaternion.Identity; protected Quaternion m_rotation = Quaternion.Identity;
@ -237,6 +237,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <value> /// <value>
/// The parts of this scene object group. You must lock this property before using it. /// The parts of this scene object group. You must lock this property before using it.
/// If you want to know the number of children, consider using the PrimCount property instead
/// </value> /// </value>
public Dictionary<UUID, SceneObjectPart> Children public Dictionary<UUID, SceneObjectPart> Children
{ {
@ -298,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_scene.CrossPrimGroupIntoNewRegion(val, this, true); m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
} }
if (RootPart.GetStatusSandbox()) if (RootPart.GetStatusSandbox())
{ {
if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@ -308,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
return; return;
} }
} }
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
@ -558,7 +561,8 @@ namespace OpenSim.Region.Framework.Scenes
if (m_rootPart.LocalId == 0) if (m_rootPart.LocalId == 0)
m_rootPart.LocalId = m_scene.AllocateLocalId(); m_rootPart.LocalId = m_scene.AllocateLocalId();
// No need to lock here since the object isn't yet in a scene lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (Object.ReferenceEquals(part, m_rootPart)) if (Object.ReferenceEquals(part, m_rootPart))
@ -574,6 +578,7 @@ namespace OpenSim.Region.Framework.Scenes
part.ParentID = m_rootPart.LocalId; part.ParentID = m_rootPart.LocalId;
//m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
} }
}
ApplyPhysics(m_scene.m_physicalPrim); ApplyPhysics(m_scene.m_physicalPrim);
@ -670,7 +675,7 @@ namespace OpenSim.Region.Framework.Scenes
minY = 256f; minY = 256f;
minZ = 8192f; minZ = 8192f;
lock(m_parts); lock(m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
@ -995,10 +1000,13 @@ namespace OpenSim.Region.Framework.Scenes
m_rootPart.AttachedAvatar = agentID; m_rootPart.AttachedAvatar = agentID;
//Anakin Lohner bug #3839 //Anakin Lohner bug #3839
lock (m_parts)
{
foreach (SceneObjectPart p in m_parts.Values) foreach (SceneObjectPart p in m_parts.Values)
{ {
p.AttachedAvatar = agentID; p.AttachedAvatar = agentID;
} }
}
if (m_rootPart.PhysActor != null) if (m_rootPart.PhysActor != null)
{ {
@ -1065,11 +1073,15 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = detachedpos; AbsolutePosition = detachedpos;
m_rootPart.AttachedAvatar = UUID.Zero; m_rootPart.AttachedAvatar = UUID.Zero;
//Anakin Lohner bug #3839 //Anakin Lohner bug #3839
lock (m_parts)
{
foreach (SceneObjectPart p in m_parts.Values) foreach (SceneObjectPart p in m_parts.Values)
{ {
p.AttachedAvatar = UUID.Zero; p.AttachedAvatar = UUID.Zero;
} }
}
m_rootPart.SetParentLocalId(0); m_rootPart.SetParentLocalId(0);
SetAttachmentPoint((byte)0); SetAttachmentPoint((byte)0);
@ -1094,11 +1106,15 @@ namespace OpenSim.Region.Framework.Scenes
} }
m_rootPart.AttachedAvatar = UUID.Zero; m_rootPart.AttachedAvatar = UUID.Zero;
//Anakin Lohner bug #3839 //Anakin Lohner bug #3839
lock (m_parts)
{
foreach (SceneObjectPart p in m_parts.Values) foreach (SceneObjectPart p in m_parts.Values)
{ {
p.AttachedAvatar = UUID.Zero; p.AttachedAvatar = UUID.Zero;
} }
}
m_rootPart.SetParentLocalId(0); m_rootPart.SetParentLocalId(0);
//m_rootPart.SetAttachmentPoint((byte)0); //m_rootPart.SetAttachmentPoint((byte)0);
@ -1160,8 +1176,7 @@ namespace OpenSim.Region.Framework.Scenes
part.ParentID = 0; part.ParentID = 0;
part.LinkNum = 0; part.LinkNum = 0;
// No locking required since the SOG should not be in the scene yet - one can't change root parts after lock (m_parts)
// the scene object has been attached to the scene
m_parts.Add(m_rootPart.UUID, m_rootPart); m_parts.Add(m_rootPart.UUID, m_rootPart);
} }
@ -1625,7 +1640,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// /// Copy the given part as the root part of this scene object.
/// </summary> /// </summary>
/// <param name="part"></param> /// <param name="part"></param>
/// <param name="cAgentID"></param> /// <param name="cAgentID"></param>
@ -1882,11 +1897,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="cGroupID"></param> /// <param name="cGroupID"></param>
public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
{ {
SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); SceneObjectPart newPart = null;
newPart.SetParent(this);
lock (m_parts) lock (m_parts)
{ {
newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
newPart.SetParent(this);
m_parts.Add(newPart.UUID, newPart); m_parts.Add(newPart.UUID, newPart);
} }
@ -1903,8 +1919,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void ResetIDs() public void ResetIDs()
{ {
// As this is only ever called for prims which are not currently part of the scene (and hence lock (m_parts)
// not accessible by clients), there should be no need to lock {
List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
m_parts.Clear(); m_parts.Clear();
foreach (SceneObjectPart part in partsList) foreach (SceneObjectPart part in partsList)
@ -1913,6 +1929,7 @@ namespace OpenSim.Region.Framework.Scenes
m_parts.Add(part.UUID, part); m_parts.Add(part.UUID, part);
} }
} }
}
/// <summary> /// <summary>
/// ///
@ -2136,10 +2153,15 @@ namespace OpenSim.Region.Framework.Scenes
public SceneObjectPart GetChildPart(UUID primID) public SceneObjectPart GetChildPart(UUID primID)
{ {
SceneObjectPart childPart = null; SceneObjectPart childPart = null;
lock (m_parts)
{
if (m_parts.ContainsKey(primID)) if (m_parts.ContainsKey(primID))
{ {
childPart = m_parts[primID]; childPart = m_parts[primID];
} }
}
return childPart; return childPart;
} }
@ -2174,8 +2196,9 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns></returns> /// <returns></returns>
public bool HasChildPrim(UUID primID) public bool HasChildPrim(UUID primID)
{ {
if (m_parts.ContainsKey(primID)) lock (m_parts)
{ {
if (m_parts.ContainsKey(primID))
return true; return true;
} }
@ -2370,10 +2393,11 @@ namespace OpenSim.Region.Framework.Scenes
lock (m_parts) lock (m_parts)
{ {
m_parts.Remove(linkPart.UUID); m_parts.Remove(linkPart.UUID);
}
if (m_parts.Count == 1 && RootPart != null) //Single prim is left if (m_parts.Count == 1 && RootPart != null) //Single prim is left
{
RootPart.LinkNum = 0; RootPart.LinkNum = 0;
}
else else
{ {
foreach (SceneObjectPart p in m_parts.Values) foreach (SceneObjectPart p in m_parts.Values)
@ -2382,6 +2406,7 @@ namespace OpenSim.Region.Framework.Scenes
p.LinkNum--; p.LinkNum--;
} }
} }
}
linkPart.ParentID = 0; linkPart.ParentID = 0;
linkPart.LinkNum = 0; linkPart.LinkNum = 0;
@ -2761,10 +2786,12 @@ namespace OpenSim.Region.Framework.Scenes
public void UpdatePermissions(UUID AgentID, byte field, uint localID, public void UpdatePermissions(UUID AgentID, byte field, uint localID,
uint mask, byte addRemTF) uint mask, byte addRemTF)
{
lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
part.UpdatePermissions(AgentID, field, localID, mask, part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
addRemTF); }
HasGroupChanged = true; HasGroupChanged = true;
} }

View File

@ -601,7 +601,10 @@ namespace OpenSim.Region.Framework.Scenes
rootPart.Name = item.Name; rootPart.Name = item.Name;
rootPart.Description = item.Description; rootPart.Description = item.Description;
List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); List<SceneObjectPart> partList = null;
lock (group.Children)
partList = new List<SceneObjectPart>(group.Children.Values);
group.SetGroup(m_part.GroupID, null); group.SetGroup(m_part.GroupID, null);

View File

@ -121,6 +121,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
continue; continue;
temp = (SceneObjectGroup) currObj; temp = (SceneObjectGroup) currObj;
lock (temp.Children)
{
if (m_CMEntityHash.ContainsKey(temp.UUID)) if (m_CMEntityHash.ContainsKey(temp.UUID))
{ {
foreach (SceneObjectPart part in temp.Children.Values) foreach (SceneObjectPart part in temp.Children.Values)
@ -133,6 +135,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
missingList.Add(part); missingList.Add(part);
} }
} }
}
return missingList; return missingList;
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -167,10 +167,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
{ {
// Deal with new parts not revisioned that have been deleted. // Deal with new parts not revisioned that have been deleted.
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
} }
}
/// <summary> /// <summary>
/// Retrieves the latest revision of a region in xml form, /// Retrieves the latest revision of a region in xml form,
@ -207,8 +210,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
{ {
temp = SceneObjectSerializer.FromXml2Format(xml); temp = SceneObjectSerializer.FromXml2Format(xml);
temp.SetScene(scene); temp.SetScene(scene);
lock (temp.Children)
{
foreach (SceneObjectPart part in temp.Children.Values) foreach (SceneObjectPart part in temp.Children.Values)
part.RegionHandle = scene.RegionInfo.RegionHandle; part.RegionHandle = scene.RegionInfo.RegionHandle;
}
ReplacementList.Add(temp.UUID, (EntityBase)temp); ReplacementList.Add(temp.UUID, (EntityBase)temp);
} }
catch (Exception e) catch (Exception e)
@ -338,6 +346,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
System.Collections.ArrayList auraList = new System.Collections.ArrayList(); System.Collections.ArrayList auraList = new System.Collections.ArrayList();
if (group == null) if (group == null)
return null; return null;
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
{ {
if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
@ -347,6 +358,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
} }
} }
}
return auraList; return auraList;
} }

View File

@ -186,10 +186,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
// Deal with new parts not revisioned that have been deleted. // Deal with new parts not revisioned that have been deleted.
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
} }
}
public void SendMetaEntitiesToNewClient(IClientAPI client) public void SendMetaEntitiesToNewClient(IClientAPI client)
{ {

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -131,6 +131,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
DiffersFromSceneGroup = false; DiffersFromSceneGroup = false;
// if group is not contained in scene's list // if group is not contained in scene's list
if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
{
lock (m_UnchangedEntity.Children)
{ {
foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
{ {
@ -157,6 +159,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
} }
// 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, // a deleted part has no where to point a beam particle system,
// if a metapart had a particle system (maybe it represented a moved part) remove it // if a metapart had a particle system (maybe it represented a moved part) remove it
@ -180,8 +183,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
/// </summary> /// </summary>
public bool HasChildPrim(UUID uuid) public bool HasChildPrim(UUID uuid)
{ {
lock (m_UnchangedEntity.Children)
if (m_UnchangedEntity.Children.ContainsKey(uuid)) if (m_UnchangedEntity.Children.ContainsKey(uuid))
return true; return true;
return false; return false;
} }
@ -189,10 +194,14 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
/// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId.
/// </summary> /// </summary>
public bool HasChildPrim(uint localID) public bool HasChildPrim(uint localID)
{
lock (m_UnchangedEntity.Children)
{ {
foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
if (part.LocalId == localID) if (part.LocalId == localID)
return true; return true;
}
return false; return false;
} }
@ -228,6 +237,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
// Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
// had originally saved. // had originally saved.
// m_Entity will NOT necessarily be the same entity as the user had saved. // m_Entity will NOT necessarily be the same entity as the user had saved.
lock (m_UnchangedEntity.Children)
{
foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
{ {
//This is the part that we use to show changes. //This is the part that we use to show changes.
@ -309,6 +320,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
DiffersFromSceneGroup = true; DiffersFromSceneGroup = true;
} }
} }
}
return changed; return changed;
} }

View File

@ -150,6 +150,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
{ {
//make new uuids //make new uuids
Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>(); Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>();
lock (m_Entity.Children)
{
foreach (SceneObjectPart part in m_Entity.Children.Values) foreach (SceneObjectPart part in m_Entity.Children.Values)
{ {
part.ResetIDs(part.LinkNum); part.ResetIDs(part.LinkNum);
@ -160,6 +163,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
m_Entity.RootPart.PhysActor = null; m_Entity.RootPart.PhysActor = null;
m_Entity.Children = parts; m_Entity.Children = parts;
} }
}
#endregion Protected Methods #endregion Protected Methods
@ -173,14 +177,19 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
//This deletes the group without removing from any databases. //This deletes the group without removing from any databases.
//This is important because we are not IN any database. //This is important because we are not IN any database.
//m_Entity.FakeDeleteGroup(); //m_Entity.FakeDeleteGroup();
lock (m_Entity.Children)
{
foreach (SceneObjectPart part in m_Entity.Children.Values) foreach (SceneObjectPart part in m_Entity.Children.Values)
client.SendKillObject(m_Entity.RegionHandle, part.LocalId); client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
} }
}
/// <summary> /// <summary>
/// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server.
/// </summary> /// </summary>
public virtual void HideFromAll() public virtual void HideFromAll()
{
lock (m_Entity.Children)
{ {
foreach (SceneObjectPart part in m_Entity.Children.Values) foreach (SceneObjectPart part in m_Entity.Children.Values)
{ {
@ -190,6 +199,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
); );
} }
} }
}
public void SendFullUpdate(IClientAPI client) public void SendFullUpdate(IClientAPI client)
{ {

View File

@ -185,15 +185,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
get get
{ {
SceneObjectPart my = GetSOP(); SceneObjectPart my = GetSOP();
IObject[] rets = null;
lock (my.ParentGroup.Children)
{
int total = my.ParentGroup.Children.Count; int total = my.ParentGroup.Children.Count;
IObject[] rets = new IObject[total]; rets = new IObject[total];
int i = 0; int i = 0;
foreach (KeyValuePair<UUID, SceneObjectPart> pair in my.ParentGroup.Children) foreach (KeyValuePair<UUID, SceneObjectPart> pair in my.ParentGroup.Children)
{ {
rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security); rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security);
} }
}
return rets; return rets;
} }

View File

@ -235,7 +235,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
case ScriptBaseClass.LINK_SET: case ScriptBaseClass.LINK_SET:
if (m_host.ParentGroup != null) if (m_host.ParentGroup != null)
{
lock (m_host.ParentGroup.Children)
return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
}
return ret; return ret;
case ScriptBaseClass.LINK_ROOT: case ScriptBaseClass.LINK_ROOT:
@ -250,7 +253,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_OTHERS:
if (m_host.ParentGroup == null) if (m_host.ParentGroup == null)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
lock (m_host.ParentGroup.Children)
ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
if (ret.Contains(m_host)) if (ret.Contains(m_host))
ret.Remove(m_host); ret.Remove(m_host);
return ret; return ret;
@ -258,7 +264,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_ALL_CHILDREN:
if (m_host.ParentGroup == null) if (m_host.ParentGroup == null)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
lock (m_host.ParentGroup.Children)
ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
if (ret.Contains(m_host.ParentGroup.RootPart)) if (ret.Contains(m_host.ParentGroup.RootPart))
ret.Remove(m_host.ParentGroup.RootPart); ret.Remove(m_host.ParentGroup.RootPart);
return ret; return ret;
@ -1178,6 +1187,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (group == null) if (group == null)
return; return;
bool allow = true; bool allow = true;
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
{ {
if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
@ -1186,6 +1198,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
} }
} }
}
if (!allow) if (!allow)
return; return;
@ -3492,7 +3505,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (m_host.ParentGroup.Children.Count > 1) if (m_host.ParentGroup.PrimCount > 1)
{ {
return m_host.LinkNum; return m_host.LinkNum;
} }
@ -3604,6 +3617,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_OTHERS:
case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_ALL_CHILDREN:
case ScriptBaseClass.LINK_THIS: case ScriptBaseClass.LINK_THIS:
lock (parentPrim.Children)
{
foreach (SceneObjectPart part in parentPrim.Children.Values) foreach (SceneObjectPart part in parentPrim.Children.Values)
{ {
if (part.UUID != m_host.UUID) if (part.UUID != m_host.UUID)
@ -3613,6 +3628,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
break; break;
}
default: default:
childPrim = parentPrim.GetLinkNumPart(linknum); childPrim = parentPrim.GetLinkNumPart(linknum);
if (childPrim.UUID == m_host.UUID) if (childPrim.UUID == m_host.UUID)
@ -3623,6 +3639,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (linknum == ScriptBaseClass.LINK_ROOT) if (linknum == ScriptBaseClass.LINK_ROOT)
{ {
// Restructuring Multiple Prims. // Restructuring Multiple Prims.
lock (parentPrim.Children)
{
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
parts.Remove(parentPrim.RootPart); parts.Remove(parentPrim.RootPart);
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
@ -3646,6 +3664,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
newRoot.ParentGroup.ScheduleGroupForFullUpdate(); newRoot.ParentGroup.ScheduleGroupForFullUpdate();
} }
} }
}
else else
{ {
if (childPrim == null) if (childPrim == null)
@ -3665,6 +3684,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (parentPrim.RootPart.AttachmentPoint != 0) if (parentPrim.RootPart.AttachmentPoint != 0)
return; // Fail silently if attached return; // Fail silently if attached
lock (parentPrim.Children)
{
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
parts.Remove(parentPrim.RootPart); parts.Remove(parentPrim.RootPart);
@ -3676,6 +3697,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.HasGroupChanged = true; parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate(); parentPrim.ScheduleGroupForFullUpdate();
} }
}
public LSL_String llGetLinkKey(int linknum) public LSL_String llGetLinkKey(int linknum)
{ {
@ -4200,7 +4222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
partItemID = item.ItemID; partItemID = item.ItemID;
int linkNumber = m_host.LinkNum; int linkNumber = m_host.LinkNum;
if (m_host.ParentGroup.Children.Count == 1) if (m_host.ParentGroup.PrimCount == 1)
linkNumber = 0; linkNumber = 0;
object[] resobj = new object[] object[] resobj = new object[]

View File

@ -209,6 +209,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
else else
Type = 0x02; // Passive Type = 0x02; // Passive
lock (part.ParentGroup.Children)
{
foreach (SceneObjectPart p in part.ParentGroup.Children.Values) foreach (SceneObjectPart p in part.ParentGroup.Children.Values)
{ {
if (p.Inventory.ContainsScripts()) if (p.Inventory.ContainsScripts())
@ -217,6 +219,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
break; break;
} }
} }
}
Position = new LSL_Types.Vector3(part.AbsolutePosition.X, Position = new LSL_Types.Vector3(part.AbsolutePosition.X,
part.AbsolutePosition.Y, part.AbsolutePosition.Y,