From 7e72afcb3e9d5467ad4dd2e6ba5d1e0632d77877 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 3 Dec 2010 00:08:58 +0000 Subject: [PATCH] Only force prim persistence before delete if the prim is the result of an unpersisted delink This considerably improves delete performance for objects with large linksets --- OpenSim/Region/Framework/Scenes/Scene.cs | 11 +++++++---- .../Region/Framework/Scenes/SceneObjectGroup.cs | 15 +++++++++++++-- .../Scenes/Tests/SceneObjectLinkingTests.cs | 8 ++++++-- bin/OpenSim.exe.config | 2 ++ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 90223b134f..66c6924bcc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1997,7 +1997,7 @@ namespace OpenSim.Region.Framework.Scenes /// Object Id /// Suppress broadcasting changes to other clients. public void DeleteSceneObject(SceneObjectGroup group, bool silent) - { + { // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); //SceneObjectPart rootPart = group.GetChildPart(group.UUID); @@ -2038,7 +2038,7 @@ namespace OpenSim.Region.Framework.Scenes group.DeleteGroupFromScene(silent); -// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); +// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); } /// @@ -2057,9 +2057,12 @@ namespace OpenSim.Region.Framework.Scenes // Force a database update so that the scene object group ID is accurate. It's possible that the // group has recently been delinked from another group but that this change has not been persisted // to the DB. - ForceSceneObjectBackup(so); + // This is an expensive thing to do so only do it if absolutely necessary. + if (so.HasGroupChangedDueToDelink) + ForceSceneObjectBackup(so); + so.DetachFromBackup(); - SimulationDataService.RemoveObject(so.UUID, m_regInfo.RegionID); + SimulationDataService.RemoveObject(so.UUID, m_regInfo.RegionID); } // We need to keep track of this state in case this group is still queued for further backup. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 4ec530e1de..f17fb28f8d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -119,10 +119,19 @@ namespace OpenSim.Region.Framework.Scenes timeFirstChanged = DateTime.Now.Ticks; } m_hasGroupChanged = value; + +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: HasGroupChanged set to {0} for {1} {2}", m_hasGroupChanged, Name, LocalId); } get { return m_hasGroupChanged; } } + + /// + /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since + /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. + /// + public bool HasGroupChangedDueToDelink { get; private set; } private bool isTimeToPersist() { @@ -1330,6 +1339,7 @@ namespace OpenSim.Region.Framework.Scenes backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; HasGroupChanged = false; + HasGroupChangedDueToDelink = false; m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); @@ -2208,8 +2218,9 @@ namespace OpenSim.Region.Framework.Scenes linkPart.Rezzed = RootPart.Rezzed; - //HasGroupChanged = true; - //ScheduleGroupForFullUpdate(); + // When we delete a group, we currently have to force persist to the database if the object id has changed + // (since delete works by deleting all rows which have a given object id) + objectGroup.HasGroupChangedDueToDelink = true; return objectGroup; } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index f57cf98b37..b84298f2fa 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -121,13 +121,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests "Not exactly sure what this is asserting..."); // Delink part 2 - grp1.DelinkFromGroup(part2.LocalId); + SceneObjectGroup grp3 = grp1.DelinkFromGroup(part2.LocalId); if (debugtest) m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset); 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"); + Assert.That(grp3.HasGroupChangedDueToDelink, Is.True); } [Test] @@ -325,7 +326,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectGroup sog = new SceneObjectGroup(rootPart); sog.AddPart(linkPart); - scene.AddNewSceneObject(sog, true); + scene.AddNewSceneObject(sog, true); // In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked // scene backup thread. @@ -333,7 +334,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests // These changes should occur immediately without waiting for a backup pass SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); + + Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.True); scene.DeleteSceneObject(groupToDelete, false); + Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.False); List storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 3c7adf5419..eece04092f 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -13,6 +13,8 @@ + +