From 0d73f81fb5499d698a617165fe271eb1b44e2505 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 15 May 2012 23:43:59 +0100 Subject: [PATCH] Fix issue where loading OARs could sometimes result in link numbers being reordered. This was because the parts in scene objects were sometimes not serialized in link order. This is perfectly fine since the parts still have the right link numbers, but an extra fix to adjust for this had not been done in the SerialiserModule methods that OAR loading used. Add regression test for same. Addresses http://opensimulator.org/mantis/view.php?id=5948, http://opensimulator.org/mantis/view.php?id=5749 --- .../World/Archiver/ArchiveReadRequest.cs | 4 +- .../World/Archiver/Tests/ArchiverTests.cs | 53 +++++++++++++++++++ .../Framework/Scenes/SceneObjectPart.cs | 13 ++++- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 8 +-- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index a6dbaba7d7..8af04f59f7 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization.External; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Archiver @@ -264,7 +265,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver } */ - SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); + SceneObjectGroup sceneObject = SceneObjectSerializer.FromXml2Format(serialisedSceneObject); +// SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 053c6f59d4..a19479fa3e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -291,6 +291,59 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. + /// 2 can come after 3). + /// + [Test] + public void TestLoadOarUnorderedParts() + { + TestHelpers.InMethod(); + + UUID ownerId = TestHelpers.ParseTail(0xaaaa); + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + + SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); + SceneObjectPart sop2 + = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); + SceneObjectPart sop3 + = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); + + // Add the parts so they will be written out in reverse order to the oar + sog1.AddPart(sop3); + sop3.LinkNum = 3; + sog1.AddPart(sop2); + sop2.LinkNum = 2; + + tar.WriteFile( + ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), + SceneObjectSerializer.ToXml2Format(sog1)); + + tar.Close(); + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + lock (this) + { + m_scene.EventManager.OnOarFileLoaded += LoadCompleted; + m_archiverModule.DearchiveRegion(archiveReadStream); + } + + Assert.That(m_lastErrorMessage, Is.Null); + + SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); + Assert.That(part2.LinkNum, Is.EqualTo(2)); + + SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); + Assert.That(part3.LinkNum, Is.EqualTo(3)); + } + /// /// Test loading an OpenSim Region Archive. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 611de4668e..602a3468a8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -930,7 +930,18 @@ namespace OpenSim.Region.Framework.Scenes public int LinkNum { get { return m_linkNum; } - set { m_linkNum = value; } + set + { +// if (ParentGroup != null) +// { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Setting linknum of {0}@{1} to {2} from {3}", +// Name, AbsolutePosition, value, m_linkNum); +// Util.PrintCallStack(); +// } + + m_linkNum = value; + } } public byte ClickAction diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 78f94347bd..59829d994f 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -624,7 +624,7 @@ namespace OpenSim.Tests.Common /// /// /// The prefix to be given to part names. This will be suffixed with "Part" - /// (e.g. mynamePart0 for the root part) + /// (e.g. mynamePart1 for the root part) /// /// /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" @@ -637,14 +637,14 @@ namespace OpenSim.Tests.Common SceneObjectGroup sog = new SceneObjectGroup( - CreateSceneObjectPart(string.Format("{0}Part0", partNamePrefix), new UUID(rawSogId), ownerId)); + CreateSceneObjectPart(string.Format("{0}Part1", partNamePrefix), new UUID(rawSogId), ownerId)); if (parts > 1) - for (int i = 1; i < parts; i++) + for (int i = 2; i <= parts; i++) sog.AddPart( CreateSceneObjectPart( string.Format("{0}Part{1}", partNamePrefix, i), - new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail + i)), + new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail + i - 1)), ownerId)); return sog;