Changed SceneObjectGroup to store parts with the fast and thread-safe MapAndArray collection

This commit is contained in:
John Hurliman
2010-09-16 17:30:46 -07:00
parent f5e3d5a33a
commit 860b2a502f
32 changed files with 1033 additions and 1180 deletions

View File

@@ -2051,9 +2051,7 @@ namespace OpenSim.Region.Framework.Scenes
sog.SetGroup(groupID, remoteClient);
sog.ScheduleGroupForFullUpdate();
List<SceneObjectPart> partList = null;
lock (sog.Children)
partList = new List<SceneObjectPart>(sog.Children.Values);
SceneObjectPart[] partList = sog.Parts;
foreach (SceneObjectPart child in partList)
child.Inventory.ChangeInventoryOwner(ownerID);
@@ -2066,9 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes
if (sog.GroupID != groupID)
continue;
List<SceneObjectPart> partList = null;
lock (sog.Children)
partList = new List<SceneObjectPart>(sog.Children.Values);
SceneObjectPart[] partList = sog.Parts;
foreach (SceneObjectPart child in partList)
{

View File

@@ -161,11 +161,8 @@ namespace OpenSim.Region.Framework.Scenes
bool foundPrim = false;
SceneObjectGroup sog = ent as SceneObjectGroup;
List<SceneObjectPart> partList = null;
lock (sog.Children)
partList = new List<SceneObjectPart>(sog.Children.Values);
SceneObjectPart[] partList = sog.Parts;
foreach (SceneObjectPart part in partList)
{
if (part.LocalId == primLocalID)

View File

@@ -1785,7 +1785,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_log.ErrorFormat(
"[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
group.Children == null ? 0 : group.PrimCount);
group.Parts == null ? 0 : group.PrimCount);
}
AddRestoredSceneObject(group, true, true);
@@ -2091,9 +2091,7 @@ namespace OpenSim.Region.Framework.Scenes
group.RemoveScriptInstances(true);
}
List<SceneObjectPart> partList = null;
lock (group.Children)
partList = new List<SceneObjectPart>(group.Children.Values);
SceneObjectPart[] partList = group.Parts;
foreach (SceneObjectPart part in partList)
{
@@ -2465,11 +2463,9 @@ namespace OpenSim.Region.Framework.Scenes
// Force allocation of new LocalId
//
lock (sceneObject.Children)
{
foreach (SceneObjectPart p in sceneObject.Children.Values)
p.LocalId = 0;
}
SceneObjectPart[] parts = sceneObject.Parts;
for (int i = 0; i < parts.Length; i++)
parts[i].LocalId = 0;
if (sceneObject.IsAttachmentCheckFull()) // Attachment
{

View File

@@ -348,9 +348,7 @@ namespace OpenSim.Region.Framework.Scenes
if (Entities.ContainsKey(sceneObject.UUID))
return false;
List<SceneObjectPart> children;
lock (sceneObject.Children)
children = new List<SceneObjectPart>(sceneObject.Children.Values);
SceneObjectPart[] children = sceneObject.Parts;
// Clamp child prim sizes and add child prims to the m_numPrim count
if (m_parentScene.m_clampPrimSize)
@@ -369,7 +367,7 @@ namespace OpenSim.Region.Framework.Scenes
part.Shape.Scale = scale;
}
}
m_numPrim += children.Count;
m_numPrim += children.Length;
sceneObject.AttachToScene(m_parentScene);
@@ -426,15 +424,17 @@ namespace OpenSim.Region.Framework.Scenes
lock (SceneObjectGroupsByFullID)
{
foreach (SceneObjectPart part in grp.Children.Values)
SceneObjectGroupsByFullID.Remove(part.UUID);
SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByFullID.Remove(parts[i].UUID);
SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID);
}
lock (SceneObjectGroupsByLocalID)
{
foreach (SceneObjectPart part in grp.Children.Values)
SceneObjectGroupsByLocalID.Remove(part.LocalId);
SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByLocalID.Remove(parts[i].LocalId);
SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId);
}
@@ -887,11 +887,8 @@ namespace OpenSim.Region.Framework.Scenes
if (sog != null)
{
lock (sog.Children)
{
if (sog.Children.ContainsKey(fullID))
return sog;
}
if (sog.ContainsPart(fullID))
return sog;
lock (SceneObjectGroupsByFullID)
SceneObjectGroupsByFullID.Remove(fullID);
@@ -965,7 +962,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (entity is SceneObjectGroup)
{
foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts())
foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
{
if (p.Name == name)
{
@@ -1626,14 +1623,8 @@ namespace OpenSim.Region.Framework.Scenes
//
SceneObjectGroup group = root.ParentGroup;
List<SceneObjectPart> newSet = null;
int numChildren = -1;
lock (group.Children)
{
newSet = new List<SceneObjectPart>(group.Children.Values);
numChildren = group.PrimCount;
}
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
int numChildren = newSet.Count;
// If there are prims left in a link set, but the root is
// slated for unlink, we need to do this
@@ -1711,16 +1702,13 @@ namespace OpenSim.Region.Framework.Scenes
if (ent is SceneObjectGroup)
{
SceneObjectGroup sog = ent as SceneObjectGroup;
lock (sog.Children)
foreach (SceneObjectPart part in sog.Parts)
{
foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
if (part.LocalId == localID)
{
if (subent.Value.LocalId == localID)
{
objid = subent.Key;
obj = subent.Value;
}
objid = part.UUID;
obj = part;
}
}
}
@@ -1796,8 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes
copy.SetOwnerId(AgentID);
copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
List<SceneObjectPart> partList =
new List<SceneObjectPart>(copy.Children.Values);
SceneObjectPart[] partList = copy.Parts;
if (m_parentScene.Permissions.PropagatePermissions())
{
@@ -1822,7 +1809,7 @@ namespace OpenSim.Region.Framework.Scenes
// think it's selected, so it will never send a deselect...
copy.IsSelected = false;
m_numPrim += copy.Children.Count;
m_numPrim += copy.Parts.Length;
if (rot != Quaternion.Identity)
{

View File

@@ -46,13 +46,9 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void ForceInventoryPersistence()
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.Inventory.ForceInventoryPersistence();
}
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.ForceInventoryPersistence();
}
/// <summary>
@@ -64,10 +60,9 @@ namespace OpenSim.Region.Framework.Scenes
// Don't start scripts if they're turned off in the region!
if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
}
}
@@ -80,13 +75,9 @@ namespace OpenSim.Region.Framework.Scenes
/// </param>
public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
}
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
}
/// <summary>
@@ -283,8 +274,11 @@ namespace OpenSim.Region.Framework.Scenes
PermissionMask.Transfer) | 7;
uint ownerMask = 0x7fffffff;
foreach (SceneObjectPart part in m_parts.Values)
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
ownerMask &= part.OwnerMask;
perms &= part.Inventory.MaskEffectivePermissions();
}
@@ -312,39 +306,40 @@ namespace OpenSim.Region.Framework.Scenes
public void ApplyNextOwnerPermissions()
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.ApplyNextOwnerPermissions();
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].ApplyNextOwnerPermissions();
}
public string GetStateSnapshot()
{
Dictionary<UUID, string> states = new Dictionary<UUID, string>();
foreach (SceneObjectPart part in m_parts.Values)
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates())
states[s.Key] = s.Value;
}
if (states.Count < 1)
return "";
return String.Empty;
XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
String.Empty, String.Empty);
xmldoc.AppendChild(xmlnode);
XmlElement rootElement = xmldoc.CreateElement("", "ScriptData",
"");
String.Empty);
xmldoc.AppendChild(rootElement);
XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates",
"");
String.Empty);
rootElement.AppendChild(wrapper);
@@ -424,10 +419,9 @@ namespace OpenSim.Region.Framework.Scenes
public void ResumeScripts()
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.Inventory.ResumeScripts();
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.ResumeScripts();
}
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes
// If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
// Get our own copy of the part array, and sort into the order we want to test
SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
SceneObjectPart[] partArray = targetPart.ParentGroup.Parts;
Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
{
// we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)

View File

@@ -158,16 +158,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteEndElement();
writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
lock (sceneObject.Children)
SceneObjectPart[] parts = sceneObject.Parts;
for (int i = 0; i < parts.Length; i++)
{
foreach (SceneObjectPart part in sceneObject.Children.Values)
SceneObjectPart part = parts[i];
if (part.UUID != sceneObject.RootPart.UUID)
{
if (part.UUID != sceneObject.RootPart.UUID)
{
writer.WriteStartElement(String.Empty, "Part", String.Empty);
ToOriginalXmlFormat(part, writer);
writer.WriteEndElement();
}
writer.WriteStartElement(String.Empty, "Part", String.Empty);
ToOriginalXmlFormat(part, writer);
writer.WriteEndElement();
}
}
@@ -281,15 +280,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
sceneObject.RootPart.ToXml(writer);
writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
lock (sceneObject.Children)
SceneObjectPart[] parts = sceneObject.Parts;
for (int i = 0; i < parts.Length; i++)
{
foreach (SceneObjectPart part in sceneObject.Children.Values)
{
if (part.UUID != sceneObject.RootPart.UUID)
{
part.ToXml(writer);
}
}
SceneObjectPart part = parts[i];
if (part.UUID != sceneObject.RootPart.UUID)
part.ToXml(writer);
}
writer.WriteEndElement(); // End of OtherParts

View File

@@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
SceneObjectGroup dupeSo
= scene.SceneGraph.DuplicateObject(
part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity);
Assert.That(dupeSo.Children.Count, Is.EqualTo(2));
Assert.That(dupeSo.Parts.Length, Is.EqualTo(2));
SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1);
SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2);

View File

@@ -81,12 +81,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since
// it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed.
Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link.");
Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained children after delink.");
Assert.That(grp1.Children.Count == 2);
Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained children after delink.");
Assert.That(grp1.Parts.Length == 2);
if (debugtest)
{
m_log.Debug("parts: " + grp1.Children.Count);
m_log.Debug("parts: " + grp1.Parts.Length);
m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset);
m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset);
@@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
if (debugtest)
m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset);
Assert.That(grp1.Children.Count, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero");
}
@@ -177,22 +177,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests
grp3.LinkToGroup(grp4);
// At this point we should have 4 parts total in two groups.
Assert.That(grp1.Children.Count == 2, "Group1 children count should be 2");
Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2");
Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link.");
Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained parts after delink.");
Assert.That(grp3.Children.Count == 2, "Group3 children count should be 2");
Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained parts after delink.");
Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2");
Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link.");
Assert.That(grp4.Children.Count, Is.EqualTo(0), "Group 4 still contained parts after delink.");
Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink.");
if (debugtest)
{
m_log.Debug("--------After Link-------");
m_log.Debug("Group1: parts:" + grp1.Children.Count);
m_log.Debug("Group1: parts:" + grp1.Parts.Length);
m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset);
m_log.Debug("Group3: parts:"+grp3.Children.Count);
m_log.Debug("Group3: parts:" + grp3.Parts.Length);
m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation);
m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset);
m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset);
@@ -240,12 +240,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
if (debugtest)
{
m_log.Debug("--------After De-Link-------");
m_log.Debug("Group1: parts:" + grp1.Children.Count);
m_log.Debug("Group1: parts:" + grp1.Parts.Length);
m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation);
m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset);
m_log.Debug("Group3: parts:" + grp3.Children.Count);
m_log.Debug("Group3: parts:" + grp3.Parts.Length);
m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation);
m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset);
m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset);
@@ -295,9 +295,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
Assert.That(storedObjects.Count, Is.EqualTo(1));
Assert.That(storedObjects[0].Children.Count, Is.EqualTo(2));
Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid));
Assert.That(storedObjects[0].Children.ContainsKey(linkPartUuid));
Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2));
Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
Assert.That(storedObjects[0].ContainsPart(linkPartUuid));
}
/// <summary>
@@ -338,8 +338,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
Assert.That(storedObjects.Count, Is.EqualTo(1));
Assert.That(storedObjects[0].Children.Count, Is.EqualTo(1));
Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid));
Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(1));
Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
}
}
}

View File

@@ -121,8 +121,11 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
foreach (SceneObjectPart part in sceneObject.GetParts())
SceneObjectPart[] parts = sceneObject.Parts;
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
// m_log.DebugFormat(
// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);