aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs8
3 files changed, 41 insertions, 17 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index d16b73b..08a2301 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1757,6 +1757,7 @@ namespace OpenSim.Region.Framework.Scenes
1757 { 1757 {
1758 if (group != null) 1758 if (group != null)
1759 { 1759 {
1760 group.HasGroupChanged = true;
1760 group.ProcessBackup(SimulationDataService, true); 1761 group.ProcessBackup(SimulationDataService, true);
1761 } 1762 }
1762 } 1763 }
@@ -2345,13 +2346,12 @@ namespace OpenSim.Region.Framework.Scenes
2345 { 2346 {
2346 if (!softDelete) 2347 if (!softDelete)
2347 { 2348 {
2348 // Force a database update so that the scene object group ID is accurate. It's possible that the 2349 // If the group contains prims whose SceneGroupID is incorrect then force a
2349 // group has recently been delinked from another group but that this change has not been persisted 2350 // database update, because RemoveObject() works by searching on the SceneGroupID.
2350 // to the DB.
2351 // This is an expensive thing to do so only do it if absolutely necessary. 2351 // This is an expensive thing to do so only do it if absolutely necessary.
2352 if (so.HasGroupChangedDueToDelink) 2352 if (so.GroupContainsForeignPrims)
2353 ForceSceneObjectBackup(so); 2353 ForceSceneObjectBackup(so);
2354 2354
2355 so.DetachFromBackup(); 2355 so.DetachFromBackup();
2356 SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); 2356 SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID);
2357 } 2357 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6f26176..a78a0cb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -150,12 +150,27 @@ namespace OpenSim.Region.Framework.Scenes
150 150
151 get { return m_hasGroupChanged; } 151 get { return m_hasGroupChanged; }
152 } 152 }
153
154 private bool m_groupContainsForeignPrims = false;
153 155
154 /// <summary> 156 /// <summary>
155 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 157 /// Whether the group contains prims that came from a different group. This happens when
156 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 158 /// linking or delinking groups. The implication is that until the group is persisted,
159 /// the prims in the database still use the old SceneGroupID. That's a problem if the group
160 /// is deleted, because we delete groups by searching for prims by their SceneGroupID.
157 /// </summary> 161 /// </summary>
158 public bool HasGroupChangedDueToDelink { get; private set; } 162 public bool GroupContainsForeignPrims
163 {
164 private set
165 {
166 m_groupContainsForeignPrims = value;
167 if (m_groupContainsForeignPrims)
168 HasGroupChanged = true;
169 }
170
171 get { return m_groupContainsForeignPrims; }
172 }
173
159 174
160 private bool isTimeToPersist() 175 private bool isTimeToPersist()
161 { 176 {
@@ -1624,7 +1639,7 @@ namespace OpenSim.Region.Framework.Scenes
1624 backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; 1639 backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity;
1625 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; 1640 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
1626 HasGroupChanged = false; 1641 HasGroupChanged = false;
1627 HasGroupChangedDueToDelink = false; 1642 GroupContainsForeignPrims = false;
1628 1643
1629 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 1644 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
1630 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 1645 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
@@ -2388,6 +2403,8 @@ namespace OpenSim.Region.Framework.Scenes
2388 // If linking prims with different permissions, fix them 2403 // If linking prims with different permissions, fix them
2389 AdjustChildPrimPermissions(); 2404 AdjustChildPrimPermissions();
2390 2405
2406 GroupContainsForeignPrims = true;
2407
2391 AttachToBackup(); 2408 AttachToBackup();
2392 2409
2393 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the 2410 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
@@ -2531,9 +2548,16 @@ namespace OpenSim.Region.Framework.Scenes
2531 2548
2532 linkPart.Rezzed = RootPart.Rezzed; 2549 linkPart.Rezzed = RootPart.Rezzed;
2533 2550
2534 // When we delete a group, we currently have to force persist to the database if the object id has changed 2551 // We must persist the delinked group to the database immediately, for safety. The problem
2535 // (since delete works by deleting all rows which have a given object id) 2552 // is that although in memory the new group has a new SceneGroupID, in the database it
2536 objectGroup.HasGroupChangedDueToDelink = true; 2553 // still has the parent group's SceneGroupID (until the next backup). This means that if the
2554 // parent group is deleted then the delinked group will also be deleted from the database.
2555 // This problem will disappear if the region remains alive long enough for another backup,
2556 // since at that time the delinked group's new SceneGroupID will be written to the database.
2557 // But if the region crashes before that then the prims will be permanently gone, and this must
2558 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case
2559 // because the delinked group doesn't know when the source group is deleted.)
2560 m_scene.ForceSceneObjectBackup(objectGroup);
2537 2561
2538 return objectGroup; 2562 return objectGroup;
2539 } 2563 }
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 9378e20..fa8277c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
143 143
144 Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink."); 144 Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
145 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); 145 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero");
146 Assert.That(grp3.HasGroupChangedDueToDelink, Is.True); 146 Assert.That(grp3.GroupContainsForeignPrims, Is.True);
147 } 147 }
148 148
149 [Test] 149 [Test]
@@ -349,10 +349,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
349 349
350 // These changes should occur immediately without waiting for a backup pass 350 // These changes should occur immediately without waiting for a backup pass
351 SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); 351 SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false);
352 352
353 Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.True); 353 Assert.That(groupToDelete.GroupContainsForeignPrims, Is.True);
354 scene.DeleteSceneObject(groupToDelete, false); 354 scene.DeleteSceneObject(groupToDelete, false);
355 Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.False); 355 Assert.That(groupToDelete.GroupContainsForeignPrims, Is.False);
356 356
357 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 357 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
358 358