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>
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))
{
@ -291,7 +293,7 @@ namespace OpenSim.Data.MSSQL
}
}
}
}
}
/// <summary>

View File

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

View File

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

View File

@ -326,6 +326,8 @@ namespace OpenSim.Data.SQLiteLegacy
return;
lock (ds)
{
lock (obj.Children)
{
foreach (SceneObjectPart prim in obj.Children.Values)
{
@ -333,6 +335,7 @@ namespace OpenSim.Data.SQLiteLegacy
addPrim(prim, obj.UUID, regionUUID);
}
}
}
Commit();
// 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.Permissions.CanRezObject(
part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition))
part.ParentGroup.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
return;
presence.Appearance.DetachAttachment(itemID);

View File

@ -526,7 +526,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.RootPart.CreateSelected = true;
if (!m_Scene.Permissions.CanRezObject(
group.Children.Count, remoteClient.AgentId, pos)
group.PrimCount, remoteClient.AgentId, pos)
&& !attachment)
{
// The client operates in no fail mode. It will
@ -594,7 +594,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
rootPart.Name = item.Name;
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);
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).
sceneObject.ResetIDs();
lock (sceneObject.Children)
{
foreach (SceneObjectPart part in sceneObject.Children.Values)
{
if (!ResolveUserUuid(part.CreatorID))
@ -277,6 +279,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
}
}
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.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())
{

View File

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

View File

@ -1974,7 +1974,7 @@ namespace OpenSim.Region.Framework.Scenes
if (null == group)
return null;
if (!Permissions.CanRezObject(group.Children.Count, item.OwnerID, pos))
if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos))
return null;
if (!Permissions.BypassPermissions())
@ -2051,9 +2051,12 @@ namespace OpenSim.Region.Framework.Scenes
sog.SetGroup(groupID, remoteClient);
sog.ScheduleGroupForFullUpdate();
lock (sog.Children)
{
foreach (SceneObjectPart child in sog.Children.Values)
child.Inventory.ChangeInventoryOwner(ownerID);
}
}
else
{
if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId))
@ -2062,16 +2065,18 @@ namespace OpenSim.Region.Framework.Scenes
if (sog.GroupID != groupID)
continue;
lock (sog.Children)
{
foreach (SceneObjectPart child in sog.Children.Values)
{
child.LastOwnerID = child.OwnerID;
child.Inventory.ChangeInventoryOwner(groupID);
}
}
sog.SetOwnerId(groupID);
sog.ApplyNextOwnerPermissions();
}
}
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
// can be selected as well and send property information
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)
{
@ -170,7 +175,10 @@ namespace OpenSim.Region.Framework.Scenes
break;
}
}
if (foundPrim) break;
}
if (foundPrim)
break;
}
}
}

View File

@ -1756,8 +1756,9 @@ namespace OpenSim.Region.Framework.Scenes
if (group.RootPart == null)
{
m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
group.Children == null ? 0 : group.Children.Count);
m_log.ErrorFormat(
"[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
group.Children == null ? 0 : group.PrimCount);
}
AddRestoredSceneObject(group, true, true);
@ -2064,6 +2065,8 @@ namespace OpenSim.Region.Framework.Scenes
group.RemoveScriptInstances(true);
}
lock (group.Children)
{
foreach (SceneObjectPart part in group.Children.Values)
{
if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
@ -2076,6 +2079,8 @@ namespace OpenSim.Region.Framework.Scenes
part.PhysActor = null;
}
}
}
// if (rootPart.PhysActor != null)
// {
// PhysicsScene.RemovePrim(rootPart.PhysActor);
@ -2426,15 +2431,17 @@ namespace OpenSim.Region.Framework.Scenes
// Force allocation of new LocalId
//
lock (sceneObject.Children)
{
foreach (SceneObjectPart p in sceneObject.Children.Values)
p.LocalId = 0;
}
if (sceneObject.IsAttachmentCheckFull()) // Attachment
{
sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
// 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.
AddRestoredSceneObject(sceneObject, false, false, false);
@ -2447,7 +2454,6 @@ namespace OpenSim.Region.Framework.Scenes
if (sp != null)
{
SceneObjectGroup grp = sceneObject;
m_log.DebugFormat(
@ -2459,7 +2465,6 @@ namespace OpenSim.Region.Framework.Scenes
if (AttachmentsModule != null)
AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
}
else
{

View File

@ -364,6 +364,8 @@ namespace OpenSim.Region.Framework.Scenes
// "[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)
@ -406,6 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
}
return true;
}
@ -420,11 +423,16 @@ namespace OpenSim.Region.Framework.Scenes
{
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)
{
RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count);
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,7 +1726,11 @@ 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)
{
foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
{
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
//aka ObjectFlags.JointWheel = IncludeInSearch
@ -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;

View File

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

View File

@ -601,7 +601,10 @@ namespace OpenSim.Region.Framework.Scenes
rootPart.Name = item.Name;
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);

View File

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

View File

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

View File

@ -186,10 +186,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
// Deal with new parts not revisioned that have been deleted.
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)
{

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -131,6 +131,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
DiffersFromSceneGroup = false;
// if group is not contained in scene's list
if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
{
lock (m_UnchangedEntity.Children)
{
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
}
}
// 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
@ -180,8 +183,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
/// </summary>
public bool HasChildPrim(UUID uuid)
{
lock (m_UnchangedEntity.Children)
if (m_UnchangedEntity.Children.ContainsKey(uuid))
return true;
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.
/// </summary>
public bool HasChildPrim(uint localID)
{
lock (m_UnchangedEntity.Children)
{
foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
if (part.LocalId == localID)
return true;
}
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
// had originally 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)
{
//This is the part that we use to show changes.
@ -309,6 +320,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
DiffersFromSceneGroup = true;
}
}
}
return changed;
}

View File

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

View File

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

View File

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

View File

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