From a0d80140f2d0ad6dd63970a3a3d5c0da8320ae75 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 00:42:06 +0100 Subject: [PATCH] Make all the objects in a coalescence reappears after being loaded from an IAR. This still doesn't work proprerly since some required textures/contained item assets might be missing. From pure code inspection, it looks like the uuid gatherer may get most asset uuids because the scene object serializer naively pulls non-root parts from all contained scene objects into one mega-object. However, root part uuids may well still be missing, and there may be other odd artifacts from this bug. It appears that storing the size of the coalescence and the offsets is redundant, since one can work out this information from the position data already in the scene object groups. --- .../Archiver/InventoryArchiveReadRequest.cs | 28 ++++++++--- .../Tests/InventoryArchiveTestCase.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 43 ++++++++++------- .../Asset/LocalAssetServiceConnector.cs | 2 + .../CoalescedSceneObjectsSerializer.cs | 47 ++++++++++++++++--- OpenSim/Services/AssetService/AssetService.cs | 10 +++- OpenSim/Services/Interfaces/IAssetService.cs | 5 ++ OpenSim/Tests/Common/Mock/MockAssetService.cs | 22 +++++++-- OpenSim/Tests/Common/Setup/AssetHelpers.cs | 7 +++ .../Tests/Common/Setup/SceneSetupHelpers.cs | 7 ++- 10 files changed, 134 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 01170aaf65..f3d2f26cfe 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -471,16 +471,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (m_creatorIdForAssetId.ContainsKey(assetId)) { string xmlData = Utils.BytesToString(data); - SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - foreach (SceneObjectPart sop in sog.Parts) + List sceneObjects = new List(); + + CoalescedSceneObjects coa = null; + if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) { - if (sop.CreatorData == null || sop.CreatorData == "") - { - sop.CreatorID = m_creatorIdForAssetId[assetId]; - } +// m_log.DebugFormat( +// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); + + sceneObjects.AddRange(coa.Objects); + } + else + { + sceneObjects.Add(SceneObjectSerializer.FromOriginalXmlFormat(xmlData)); } - data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)); + foreach (SceneObjectGroup sog in sceneObjects) + foreach (SceneObjectPart sop in sog.Parts) + if (sop.CreatorData == null || sop.CreatorData == "") + sop.CreatorID = m_creatorIdForAssetId[assetId]; + + if (coa != null) + data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa)); + else + data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sceneObjects[0])); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index f2d050c16a..e2316f0bdd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests InventoryItemBase coaItem = new InventoryItemBase(); coaItem.Name = m_coaItemName; coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); - coaItem.AssetID = asset1.FullID; + coaItem.AssetID = coaAsset.FullID; coaItem.GroupID = UUID.Random(); coaItem.CreatorIdAsUuid = m_uaLL1.PrincipalID; coaItem.Owner = m_uaLL1.PrincipalID; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 0c4e364765..f747c899de 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -62,9 +62,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); m_archiverModule = new InventoryArchiverModule(); - m_scene = SceneSetupHelpers.SetupScene("Inventory"); + m_scene = SceneSetupHelpers.SetupScene("asset inventory"); SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); } + + [Test] + public void TestLoadCoalesecedItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); + + InventoryItemBase coaItem + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); + + Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); + + string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); + + CoalescedSceneObjects coa; + bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); + + Assert.That(readResult, Is.True); + + // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around + } /// /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive @@ -257,22 +281,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); } - - [Test] - public void TestLoadCoalesecedItem() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); - m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); - - InventoryItemBase coaItem - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); - - Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); - - // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 1b3419d12f..51d1d599c5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -195,6 +195,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public byte[] GetData(string id) { +// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); + AssetBase asset = m_Cache.Get(id); if (asset != null) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index a0e120a9ac..babcb54ae9 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -55,11 +55,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// public static string ToXml(CoalescedSceneObjects coa) - { - // TODO: Should probably return an empty xml serialization rather than a blank string - if (!coa.HasObjects) - return ""; - + { using (StringWriter sw = new StringWriter()) { using (XmlTextWriter writer = new XmlTextWriter(sw)) @@ -105,10 +101,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization string output = sw.ToString(); -// m_log.Debug(output); +// Console.WriteLine(output); return output; } } + + public static bool TryFromXml(string xml, out CoalescedSceneObjects coa) + { +// m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml); + + coa = null; + + using (StringReader sr = new StringReader(xml)) + { + using (XmlTextReader reader = new XmlTextReader(sr)) + { + reader.Read(); + if (reader.Name != "CoalescedObject") + { +// m_log.DebugFormat( +// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", +// reader.Name); + + return false; + } + + coa = new CoalescedSceneObjects(UUID.Zero); + reader.Read(); + + while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") + { + if (reader.Name == "SceneObjectGroup") + { + string soXml = reader.ReadOuterXml(); + coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); + } + } + + reader.ReadEndElement(); // CoalescedObject + } + } + + return true; + } } } \ No newline at end of file diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index a81af4355a..e1f90b6e18 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -89,6 +89,8 @@ namespace OpenSim.Services.AssetService public virtual AssetBase Get(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -107,6 +109,8 @@ namespace OpenSim.Services.AssetService public virtual AssetMetadata GetMetadata(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset metadata for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -121,6 +125,8 @@ namespace OpenSim.Services.AssetService public virtual byte[] GetData(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset data for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -150,7 +156,9 @@ namespace OpenSim.Services.AssetService public virtual string Store(AssetBase asset) { - //m_log.DebugFormat("[ASSET SERVICE]: Store asset {0} {1}", asset.Name, asset.ID); +// m_log.DebugFormat( +// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); + m_Database.StoreAsset(asset); return asset.ID; diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 3be6815728..1ac1cec358 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -48,6 +48,11 @@ namespace OpenSim.Services.Interfaces /// AssetMetadata GetMetadata(string id); + /// + /// Get an asset's data, ignoring the metadata. + /// + /// + /// null if there is no such asset byte[] GetData(string id); /// diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index 4118308bed..9d7c5e29e6 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -54,13 +54,19 @@ namespace OpenSim.Tests.Common.Mock public AssetBase Get(string id) { - m_log.DebugFormat("[MOCK ASSET SERVICE]: Getting asset with id {0}", id); +// m_log.DebugFormat("[MOCK ASSET SERVICE]: Getting asset with id {0}", id); AssetBase asset; if (Assets.ContainsKey(id)) + { asset = Assets[id]; +// m_log.DebugFormat( +// "[MOCK ASSET SERVICE]: Got asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); + } else - asset = null; + { + asset = null; + } return asset; } @@ -77,7 +83,14 @@ namespace OpenSim.Tests.Common.Mock public byte[] GetData(string id) { - throw new System.NotImplementedException(); +// m_log.DebugFormat("[MOCK ASSET SERVICE]: Requesting data for asset {0}", id); + + AssetBase asset = Get(id); + + if (asset == null) + return null; + else + return asset.Data; } public bool Get(string id, object sender, AssetRetrieved handler) @@ -89,7 +102,8 @@ namespace OpenSim.Tests.Common.Mock public string Store(AssetBase asset) { - m_log.DebugFormat("[MOCK ASSET SERVICE]: Storing asset {0}", asset.ID); +// m_log.DebugFormat( +// "[MOCK ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); Assets[asset.ID] = asset; diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index 971c6bcf36..d572249997 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -30,6 +30,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Services.Interfaces; namespace OpenSim.Tests.Common { @@ -118,5 +119,11 @@ namespace OpenSim.Tests.Common asset.Data = data; return asset; } + + public static string ReadAssetAsString(IAssetService assetService, UUID uuid) + { + byte[] assetData = assetService.GetData(uuid.ToString()); + return Encoding.ASCII.GetString(assetData); + } } } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index eb08b62f19..837f4e235f 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -168,14 +168,17 @@ namespace OpenSim.Tests.Common.Setup { LocalAssetServicesConnector assetService = new LocalAssetServicesConnector(); IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("AssetService"); + config.AddConfig("Modules"); config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); + + config.AddConfig("AssetService"); if (real) config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); else config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockAssetService"); + config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + assetService.Initialise(config); assetService.AddRegion(testScene); assetService.RegionLoaded(testScene);