diff options
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 12 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 38 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs | 8 |
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 | ||