When linking two groups, and then deleting the combined group: delete *all* of the combined group's prims, including those that came from the second subgroup
This fixes http://opensimulator.org/mantis/view.php?id=61750.8.0.3
parent
b0cb0ec02f
commit
62b3bdf0fc
|
@ -1757,6 +1757,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
if (group != null)
|
if (group != null)
|
||||||
{
|
{
|
||||||
|
group.HasGroupChanged = true;
|
||||||
group.ProcessBackup(SimulationDataService, true);
|
group.ProcessBackup(SimulationDataService, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2345,11 +2346,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
if (!softDelete)
|
if (!softDelete)
|
||||||
{
|
{
|
||||||
// Force a database update so that the scene object group ID is accurate. It's possible that the
|
// If the group contains prims whose SceneGroupID is incorrect then force a
|
||||||
// group has recently been delinked from another group but that this change has not been persisted
|
// database update, because RemoveObject() works by searching on the SceneGroupID.
|
||||||
// to the DB.
|
|
||||||
// This is an expensive thing to do so only do it if absolutely necessary.
|
// This is an expensive thing to do so only do it if absolutely necessary.
|
||||||
if (so.HasGroupChangedDueToDelink)
|
if (so.GroupContainsForeignPrims)
|
||||||
ForceSceneObjectBackup(so);
|
ForceSceneObjectBackup(so);
|
||||||
|
|
||||||
so.DetachFromBackup();
|
so.DetachFromBackup();
|
||||||
|
|
|
@ -151,11 +151,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
get { return m_hasGroupChanged; }
|
get { return m_hasGroupChanged; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool m_groupContainsForeignPrims = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
|
/// Whether the group contains prims that came from a different group. This happens when
|
||||||
/// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
|
/// linking or delinking groups. The implication is that until the group is persisted,
|
||||||
|
/// the prims in the database still use the old SceneGroupID. That's a problem if the group
|
||||||
|
/// is deleted, because we delete groups by searching for prims by their SceneGroupID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasGroupChangedDueToDelink { get; private set; }
|
public bool GroupContainsForeignPrims
|
||||||
|
{
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
m_groupContainsForeignPrims = value;
|
||||||
|
if (m_groupContainsForeignPrims)
|
||||||
|
HasGroupChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get { return m_groupContainsForeignPrims; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool isTimeToPersist()
|
private bool isTimeToPersist()
|
||||||
{
|
{
|
||||||
|
@ -1624,7 +1639,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity;
|
backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity;
|
||||||
backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
|
backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
|
||||||
HasGroupChanged = false;
|
HasGroupChanged = false;
|
||||||
HasGroupChangedDueToDelink = false;
|
GroupContainsForeignPrims = false;
|
||||||
|
|
||||||
m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
|
m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
|
||||||
datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
|
datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
|
||||||
|
@ -2388,6 +2403,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// If linking prims with different permissions, fix them
|
// If linking prims with different permissions, fix them
|
||||||
AdjustChildPrimPermissions();
|
AdjustChildPrimPermissions();
|
||||||
|
|
||||||
|
GroupContainsForeignPrims = true;
|
||||||
|
|
||||||
AttachToBackup();
|
AttachToBackup();
|
||||||
|
|
||||||
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
// 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
|
||||||
|
|
||||||
linkPart.Rezzed = RootPart.Rezzed;
|
linkPart.Rezzed = RootPart.Rezzed;
|
||||||
|
|
||||||
// When we delete a group, we currently have to force persist to the database if the object id has changed
|
// We must persist the delinked group to the database immediately, for safety. The problem
|
||||||
// (since delete works by deleting all rows which have a given object id)
|
// is that although in memory the new group has a new SceneGroupID, in the database it
|
||||||
objectGroup.HasGroupChangedDueToDelink = true;
|
// still has the parent group's SceneGroupID (until the next backup). This means that if the
|
||||||
|
// parent group is deleted then the delinked group will also be deleted from the database.
|
||||||
|
// This problem will disappear if the region remains alive long enough for another backup,
|
||||||
|
// since at that time the delinked group's new SceneGroupID will be written to the database.
|
||||||
|
// But if the region crashes before that then the prims will be permanently gone, and this must
|
||||||
|
// not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case
|
||||||
|
// because the delinked group doesn't know when the source group is deleted.)
|
||||||
|
m_scene.ForceSceneObjectBackup(objectGroup);
|
||||||
|
|
||||||
return objectGroup;
|
return objectGroup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
Assert.That(grp1.Parts.Length, 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");
|
Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero");
|
||||||
Assert.That(grp3.HasGroupChangedDueToDelink, Is.True);
|
Assert.That(grp3.GroupContainsForeignPrims, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -350,9 +350,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
// These changes should occur immediately without waiting for a backup pass
|
// These changes should occur immediately without waiting for a backup pass
|
||||||
SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false);
|
SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false);
|
||||||
|
|
||||||
Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.True);
|
Assert.That(groupToDelete.GroupContainsForeignPrims, Is.True);
|
||||||
scene.DeleteSceneObject(groupToDelete, false);
|
scene.DeleteSceneObject(groupToDelete, false);
|
||||||
Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.False);
|
Assert.That(groupToDelete.GroupContainsForeignPrims, Is.False);
|
||||||
|
|
||||||
List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
|
List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue