diff options
Diffstat (limited to '')
8 files changed, 112 insertions, 713 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 59b30a9..7d9c9a9 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -776,7 +776,6 @@ namespace OpenSim.Region.CoreModules.Asset | |||
776 | { | 776 | { |
777 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); | 777 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); |
778 | 778 | ||
779 | Dictionary<UUID, sbyte> assetIdsToCheck = new Dictionary<UUID, sbyte>(); | ||
780 | Dictionary<UUID, bool> assetsFound = new Dictionary<UUID, bool>(); | 779 | Dictionary<UUID, bool> assetsFound = new Dictionary<UUID, bool>(); |
781 | 780 | ||
782 | foreach (Scene s in m_Scenes) | 781 | foreach (Scene s in m_Scenes) |
@@ -784,10 +783,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
784 | StampRegionStatusFile(s.RegionInfo.RegionID); | 783 | StampRegionStatusFile(s.RegionInfo.RegionID); |
785 | 784 | ||
786 | s.ForEachSOG(delegate(SceneObjectGroup e) | 785 | s.ForEachSOG(delegate(SceneObjectGroup e) |
787 | { | 786 | { |
788 | gatherer.GatherAssetUuids(e, assetIdsToCheck); | 787 | gatherer.AddForInspection(e); |
788 | gatherer.GatherAll(); | ||
789 | 789 | ||
790 | foreach (UUID assetID in assetIdsToCheck.Keys) | 790 | foreach (UUID assetID in gatherer.GatheredUuids.Keys) |
791 | { | 791 | { |
792 | if (!assetsFound.ContainsKey(assetID)) | 792 | if (!assetsFound.ContainsKey(assetID)) |
793 | { | 793 | { |
@@ -800,7 +800,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
800 | else if (storeUncached) | 800 | else if (storeUncached) |
801 | { | 801 | { |
802 | AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); | 802 | AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); |
803 | if (cachedAsset == null && assetIdsToCheck[assetID] != (sbyte)AssetType.Unknown) | 803 | if (cachedAsset == null && gatherer.GatheredUuids[assetID] != (sbyte)AssetType.Unknown) |
804 | assetsFound[assetID] = false; | 804 | assetsFound[assetID] = false; |
805 | else | 805 | else |
806 | assetsFound[assetID] = true; | 806 | assetsFound[assetID] = true; |
@@ -810,11 +810,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
810 | { | 810 | { |
811 | m_log.DebugFormat( | 811 | m_log.DebugFormat( |
812 | "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", | 812 | "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", |
813 | assetID, assetIdsToCheck[assetID], e.Name, e.AbsolutePosition, s.Name); | 813 | assetID, gatherer.GatheredUuids[assetID], e.Name, e.AbsolutePosition, s.Name); |
814 | } | 814 | } |
815 | } | 815 | } |
816 | 816 | ||
817 | assetIdsToCheck.Clear(); | 817 | gatherer.GatheredUuids.Clear(); |
818 | }); | 818 | }); |
819 | } | 819 | } |
820 | 820 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 6dab227..42a4c7a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -94,11 +94,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
94 | protected UUID m_id; | 94 | protected UUID m_id; |
95 | 95 | ||
96 | /// <value> | 96 | /// <value> |
97 | /// Used to collect the uuids of the assets that we need to save into the archive | ||
98 | /// </value> | ||
99 | protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>(); | ||
100 | |||
101 | /// <value> | ||
102 | /// Used to collect the uuids of the users that we need to save into the archive | 97 | /// Used to collect the uuids of the users that we need to save into the archive |
103 | /// </value> | 98 | /// </value> |
104 | protected Dictionary<UUID, int> m_userUuids = new Dictionary<UUID, int>(); | 99 | protected Dictionary<UUID, int> m_userUuids = new Dictionary<UUID, int>(); |
@@ -225,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
225 | 220 | ||
226 | // Don't chase down link asset items as they actually point to their target item IDs rather than an asset | 221 | // Don't chase down link asset items as they actually point to their target item IDs rather than an asset |
227 | if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) | 222 | if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) |
228 | m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids); | 223 | m_assetGatherer.AddForInspection(inventoryItem.AssetID); |
229 | } | 224 | } |
230 | 225 | ||
231 | /// <summary> | 226 | /// <summary> |
@@ -422,12 +417,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
422 | 417 | ||
423 | if (SaveAssets) | 418 | if (SaveAssets) |
424 | { | 419 | { |
425 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); | 420 | m_assetGatherer.GatherAll(); |
421 | |||
422 | m_log.DebugFormat( | ||
423 | "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); | ||
426 | 424 | ||
427 | AssetsRequest ar | 425 | AssetsRequest ar |
428 | = new AssetsRequest( | 426 | = new AssetsRequest( |
429 | new AssetsArchiver(m_archiveWriter), | 427 | new AssetsArchiver(m_archiveWriter), |
430 | m_assetUuids, m_scene.AssetService, | 428 | m_assetGatherer.GatheredUuids, m_scene.AssetService, |
431 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | 429 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, |
432 | options, ReceivedAllAssets); | 430 | options, ReceivedAllAssets); |
433 | 431 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 2ddb599..fceda80 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -605,8 +605,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
605 | // so.Name, so.AttachedAvatar, url); | 605 | // so.Name, so.AttachedAvatar, url); |
606 | 606 | ||
607 | IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); | 607 | IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); |
608 | IteratingHGUuidGatherer uuidGatherer | 608 | HGUuidGatherer uuidGatherer |
609 | = new IteratingHGUuidGatherer(Scene.AssetService, url, ids); | 609 | = new HGUuidGatherer(Scene.AssetService, url, ids); |
610 | uuidGatherer.AddForInspection(so); | 610 | uuidGatherer.AddForInspection(so); |
611 | 611 | ||
612 | while (!uuidGatherer.Complete) | 612 | while (!uuidGatherer.Complete) |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 2ac1517..6343a81 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -412,12 +412,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
412 | 412 | ||
413 | // The act of gathering UUIDs downloads some assets from the remote server | 413 | // The act of gathering UUIDs downloads some assets from the remote server |
414 | // but not all... | 414 | // but not all... |
415 | Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); | ||
416 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | 415 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); |
417 | uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids); | 416 | uuidGatherer.AddForInspection(assetID); |
418 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); | 417 | uuidGatherer.GatherAll(); |
418 | |||
419 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", uuidGatherer.GatheredUuids.Count); | ||
419 | bool success = true; | 420 | bool success = true; |
420 | foreach (UUID uuid in ids.Keys) | 421 | foreach (UUID uuid in uuidGatherer.GatheredUuids.Keys) |
421 | if (FetchAsset(userAssetURL, uuid) == null) | 422 | if (FetchAsset(userAssetURL, uuid) == null) |
422 | success = false; | 423 | success = false; |
423 | 424 | ||
@@ -428,7 +429,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
428 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); | 429 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); |
429 | } | 430 | } |
430 | 431 | ||
431 | |||
432 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) | 432 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) |
433 | { | 433 | { |
434 | m_log.DebugFormat("[HG ASSET MAPPER]: Starting to send asset {0} with children to asset server {1}", assetID, userAssetURL); | 434 | m_log.DebugFormat("[HG ASSET MAPPER]: Starting to send asset {0} with children to asset server {1}", assetID, userAssetURL); |
@@ -442,9 +442,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
442 | return; | 442 | return; |
443 | } | 443 | } |
444 | 444 | ||
445 | Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); | ||
446 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | 445 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); |
447 | uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids); | 446 | uuidGatherer.AddForInspection(asset.FullID); |
448 | 447 | ||
449 | // Check which assets already exist in the destination server | 448 | // Check which assets already exist in the destination server |
450 | 449 | ||
@@ -452,16 +451,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
452 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 451 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
453 | url = url + "/"; | 452 | url = url + "/"; |
454 | 453 | ||
455 | string[] remoteAssetIDs = new string[ids.Count]; | 454 | string[] remoteAssetIDs = new string[uuidGatherer.GatheredUuids.Count]; |
456 | int i = 0; | 455 | int i = 0; |
457 | foreach (UUID id in ids.Keys) | 456 | foreach (UUID id in uuidGatherer.GatheredUuids.Keys) |
458 | remoteAssetIDs[i++] = url + id.ToString(); | 457 | remoteAssetIDs[i++] = url + id.ToString(); |
459 | 458 | ||
460 | bool[] exist = m_scene.AssetService.AssetsExist(remoteAssetIDs); | 459 | bool[] exist = m_scene.AssetService.AssetsExist(remoteAssetIDs); |
461 | 460 | ||
462 | var existSet = new HashSet<string>(); | 461 | var existSet = new HashSet<string>(); |
463 | i = 0; | 462 | i = 0; |
464 | foreach (UUID id in ids.Keys) | 463 | foreach (UUID id in uuidGatherer.GatheredUuids.Keys) |
465 | { | 464 | { |
466 | if (exist[i]) | 465 | if (exist[i]) |
467 | existSet.Add(id.ToString()); | 466 | existSet.Add(id.ToString()); |
@@ -472,7 +471,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
472 | 471 | ||
473 | bool success = true; | 472 | bool success = true; |
474 | 473 | ||
475 | foreach (UUID uuid in ids.Keys) | 474 | foreach (UUID uuid in uuidGatherer.GatheredUuids.Keys) |
476 | { | 475 | { |
477 | if (!existSet.Contains(uuid.ToString())) | 476 | if (!existSet.Contains(uuid.ToString())) |
478 | { | 477 | { |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index b7d7c26..d67bdce 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs | |||
@@ -219,7 +219,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
219 | 219 | ||
220 | private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids) | 220 | private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids) |
221 | { | 221 | { |
222 | m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); | 222 | m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name); |
223 | 223 | ||
224 | EntityBase[] entities = scene.GetEntities(); | 224 | EntityBase[] entities = scene.GetEntities(); |
225 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | 225 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
@@ -253,13 +253,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
253 | 253 | ||
254 | if (SaveAssets) | 254 | if (SaveAssets) |
255 | { | 255 | { |
256 | UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); | 256 | UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids); |
257 | int prevAssets = assetUuids.Count; | 257 | int prevAssets = assetUuids.Count; |
258 | 258 | ||
259 | foreach (SceneObjectGroup sceneObject in sceneObjects) | 259 | foreach (SceneObjectGroup sceneObject in sceneObjects) |
260 | { | 260 | assetGatherer.AddForInspection(sceneObject); |
261 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | 261 | |
262 | } | 262 | assetGatherer.GatherAll(); |
263 | 263 | ||
264 | m_log.DebugFormat( | 264 | m_log.DebugFormat( |
265 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | 265 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs index a12b170..1fe0e79 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs | |||
@@ -61,11 +61,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
61 | = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); | 61 | = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); |
62 | m_assetService.Store(corruptAsset); | 62 | m_assetService.Store(corruptAsset); |
63 | 63 | ||
64 | IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>(); | 64 | m_uuidGatherer.AddForInspection(corruptAssetUuid); |
65 | m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids); | 65 | m_uuidGatherer.GatherAll(); |
66 | 66 | ||
67 | // We count the uuid as gathered even if the asset itself is corrupt. | 67 | // We count the uuid as gathered even if the asset itself is corrupt. |
68 | Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); | 68 | Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(1)); |
69 | } | 69 | } |
70 | 70 | ||
71 | /// <summary> | 71 | /// <summary> |
@@ -77,38 +77,42 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
77 | TestHelpers.InMethod(); | 77 | TestHelpers.InMethod(); |
78 | 78 | ||
79 | UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); | 79 | UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); |
80 | IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>(); | ||
81 | |||
82 | m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids); | ||
83 | 80 | ||
84 | // We count the uuid as gathered even if the asset itself is missing. | 81 | m_uuidGatherer.AddForInspection(missingAssetUuid); |
85 | Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); | 82 | m_uuidGatherer.GatherAll(); |
83 | |||
84 | Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(0)); | ||
86 | } | 85 | } |
87 | 86 | ||
88 | [Test] | 87 | [Test] |
89 | public void TestNotecardAsset() | 88 | public void TestNotecardAsset() |
90 | { | 89 | { |
91 | TestHelpers.InMethod(); | 90 | TestHelpers.InMethod(); |
92 | // log4net.Config.XmlConfigurator.Configure(); | 91 | TestHelpers.EnableLogging(); |
93 | 92 | ||
94 | UUID ownerId = TestHelpers.ParseTail(0x10); | 93 | UUID ownerId = TestHelpers.ParseTail(0x10); |
95 | UUID soAssetId = TestHelpers.ParseTail(0x20); | 94 | UUID embeddedId = TestHelpers.ParseTail(0x20); |
95 | UUID missingEmbeddedId = TestHelpers.ParseTail(0x21); | ||
96 | UUID ncAssetId = TestHelpers.ParseTail(0x30); | 96 | UUID ncAssetId = TestHelpers.ParseTail(0x30); |
97 | 97 | ||
98 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId); | 98 | AssetBase ncAsset |
99 | AssetBase soAsset = AssetHelpers.CreateAsset(soAssetId, so); | 99 | = AssetHelpers.CreateNotecardAsset( |
100 | m_assetService.Store(soAsset); | 100 | ncAssetId, string.Format("Hello{0}World{1}", embeddedId, missingEmbeddedId)); |
101 | |||
102 | AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); | ||
103 | m_assetService.Store(ncAsset); | 101 | m_assetService.Store(ncAsset); |
104 | 102 | ||
105 | IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>(); | 103 | AssetBase embeddedAsset = AssetHelpers.CreateNotecardAsset(embeddedId, "We'll meet again."); |
106 | m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids); | 104 | m_assetService.Store(embeddedAsset); |
107 | 105 | ||
108 | // We count the uuid as gathered even if the asset itself is corrupt. | 106 | m_uuidGatherer.AddForInspection(ncAssetId); |
109 | Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); | 107 | m_uuidGatherer.GatherAll(); |
110 | Assert.That(foundAssetUuids.ContainsKey(ncAssetId)); | 108 | |
111 | Assert.That(foundAssetUuids.ContainsKey(soAssetId)); | 109 | // foreach (UUID key in m_uuidGatherer.GatheredUuids.Keys) |
110 | // System.Console.WriteLine("key : {0}", key); | ||
111 | |||
112 | Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(3)); | ||
113 | Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(ncAssetId)); | ||
114 | Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(embeddedId)); | ||
115 | Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(missingEmbeddedId)); | ||
112 | } | 116 | } |
113 | } | 117 | } |
114 | } | 118 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2c5353f..28653c6 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |||
@@ -55,616 +55,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
55 | { | 55 | { |
56 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 56 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
57 | 57 | ||
58 | protected IAssetService m_assetService; | ||
59 | |||
60 | // /// <summary> | ||
61 | // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate | ||
62 | // /// asset was found by the asset service. | ||
63 | // /// </summary> | ||
64 | // private AssetBase m_requestedObjectAsset; | ||
65 | // | ||
66 | // /// <summary> | ||
67 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. | ||
68 | // /// </summary> | ||
69 | // private bool m_waitingForObjectAsset; | ||
70 | |||
71 | public UuidGatherer(IAssetService assetService) | ||
72 | { | ||
73 | m_assetService = assetService; | ||
74 | } | ||
75 | |||
76 | /// <summary> | ||
77 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | ||
78 | /// </summary> | ||
79 | /// <remarks> | ||
80 | /// This includes both those directly associated with | ||
81 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
82 | /// within this object). | ||
83 | /// This method assumes that the asset type associated with this asset in persistent storage is correct (which | ||
84 | /// should always be the case). So with this method we always need to retrieve asset data even if the asset | ||
85 | /// is of a type which is known not to reference any other assets | ||
86 | /// </remarks> | ||
87 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> | ||
88 | /// <param name="assetUuids">The assets gathered</param> | ||
89 | public void GatherAssetUuids(UUID assetUuid, IDictionary<UUID, sbyte> assetUuids) | ||
90 | { | ||
91 | // avoid infinite loops | ||
92 | if (assetUuids.ContainsKey(assetUuid)) | ||
93 | return; | ||
94 | |||
95 | try | ||
96 | { | ||
97 | AssetBase assetBase = GetAsset(assetUuid); | ||
98 | |||
99 | if (null != assetBase) | ||
100 | { | ||
101 | sbyte assetType = assetBase.Type; | ||
102 | assetUuids[assetUuid] = assetType; | ||
103 | |||
104 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | ||
105 | { | ||
106 | GetWearableAssetUuids(assetBase, assetUuids); | ||
107 | } | ||
108 | else if ((sbyte)AssetType.Gesture == assetType) | ||
109 | { | ||
110 | GetGestureAssetUuids(assetBase, assetUuids); | ||
111 | } | ||
112 | else if ((sbyte)AssetType.Notecard == assetType) | ||
113 | { | ||
114 | GetTextEmbeddedAssetUuids(assetBase, assetUuids); | ||
115 | } | ||
116 | else if ((sbyte)AssetType.LSLText == assetType) | ||
117 | { | ||
118 | GetTextEmbeddedAssetUuids(assetBase, assetUuids); | ||
119 | } | ||
120 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
121 | { | ||
122 | GetMaterialAssetUuids(assetBase, assetUuids); | ||
123 | } | ||
124 | else if ((sbyte)AssetType.Object == assetType) | ||
125 | { | ||
126 | GetSceneObjectAssetUuids(assetBase, assetUuids); | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | catch (Exception) | ||
131 | { | ||
132 | m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); | ||
133 | throw; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | ||
139 | /// </summary> | ||
140 | /// <remarks> | ||
141 | /// This includes both those directly associated with | ||
142 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
143 | /// within this object). | ||
144 | /// </remarks> | ||
145 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> | ||
146 | /// <param name="assetType">The type of the asset for the uuid given</param> | ||
147 | /// <param name="assetUuids">The assets gathered</param> | ||
148 | public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids) | ||
149 | { | ||
150 | // avoid infinite loops | ||
151 | if (assetUuids.ContainsKey(assetUuid)) | ||
152 | return; | ||
153 | |||
154 | try | ||
155 | { | ||
156 | assetUuids[assetUuid] = assetType; | ||
157 | |||
158 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | ||
159 | { | ||
160 | GetWearableAssetUuids(assetUuid, assetUuids); | ||
161 | } | ||
162 | else if ((sbyte)AssetType.Gesture == assetType) | ||
163 | { | ||
164 | GetGestureAssetUuids(assetUuid, assetUuids); | ||
165 | } | ||
166 | else if ((sbyte)AssetType.Notecard == assetType) | ||
167 | { | ||
168 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); | ||
169 | } | ||
170 | else if ((sbyte)AssetType.LSLText == assetType) | ||
171 | { | ||
172 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); | ||
173 | } | ||
174 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
175 | { | ||
176 | GetMaterialAssetUuids(assetUuid, assetUuids); | ||
177 | } | ||
178 | else if ((sbyte)AssetType.Object == assetType) | ||
179 | { | ||
180 | GetSceneObjectAssetUuids(assetUuid, assetUuids); | ||
181 | } | ||
182 | } | ||
183 | catch (Exception) | ||
184 | { | ||
185 | m_log.ErrorFormat( | ||
186 | "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", | ||
187 | assetUuid, assetType); | ||
188 | throw; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | /// <summary> | ||
193 | /// Gather all the asset uuids associated with a given object. | ||
194 | /// </summary> | ||
195 | /// <remarks> | ||
196 | /// This includes both those directly associated with | ||
197 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
198 | /// within this object). | ||
199 | /// </remarks> | ||
200 | /// <param name="sceneObject">The scene object for which to gather assets</param> | ||
201 | /// <param name="assetUuids"> | ||
202 | /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. | ||
203 | /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. | ||
204 | /// </param> | ||
205 | public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids) | ||
206 | { | ||
207 | // m_log.DebugFormat( | ||
208 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); | ||
209 | |||
210 | SceneObjectPart[] parts = sceneObject.Parts; | ||
211 | for (int i = 0; i < parts.Length; i++) | ||
212 | { | ||
213 | SceneObjectPart part = parts[i]; | ||
214 | |||
215 | // m_log.DebugFormat( | ||
216 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); | ||
217 | |||
218 | try | ||
219 | { | ||
220 | Primitive.TextureEntry textureEntry = part.Shape.Textures; | ||
221 | if (textureEntry != null) | ||
222 | { | ||
223 | // Get the prim's default texture. This will be used for faces which don't have their own texture | ||
224 | if (textureEntry.DefaultTexture != null) | ||
225 | GatherTextureEntryAssets(textureEntry.DefaultTexture, assetUuids); | ||
226 | |||
227 | if (textureEntry.FaceTextures != null) | ||
228 | { | ||
229 | // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) | ||
230 | foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) | ||
231 | { | ||
232 | if (texture != null) | ||
233 | GatherTextureEntryAssets(texture, assetUuids); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | // If the prim is a sculpt then preserve this information too | ||
239 | if (part.Shape.SculptTexture != UUID.Zero) | ||
240 | assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; | ||
241 | |||
242 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) | ||
243 | assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; | ||
244 | |||
245 | if (part.CollisionSound != UUID.Zero) | ||
246 | assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; | ||
247 | |||
248 | if (part.ParticleSystem.Length > 0) | ||
249 | { | ||
250 | try | ||
251 | { | ||
252 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); | ||
253 | if (ps.Texture != UUID.Zero) | ||
254 | assetUuids[ps.Texture] = (sbyte)AssetType.Texture; | ||
255 | } | ||
256 | catch (Exception) | ||
257 | { | ||
258 | m_log.WarnFormat( | ||
259 | "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", | ||
260 | part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); | ||
265 | |||
266 | // Now analyze this prim's inventory items to preserve all the uuids that they reference | ||
267 | foreach (TaskInventoryItem tii in taskDictionary.Values) | ||
268 | { | ||
269 | // m_log.DebugFormat( | ||
270 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", | ||
271 | // tii.Name, tii.Type, part.Name, part.UUID); | ||
272 | |||
273 | if (!assetUuids.ContainsKey(tii.AssetID)) | ||
274 | GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids); | ||
275 | } | ||
276 | |||
277 | // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed | ||
278 | // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and | ||
279 | // inventory transfer. There needs to be a way for a module to register a method without assuming a | ||
280 | // Scene.EventManager is present. | ||
281 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); | ||
282 | |||
283 | |||
284 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs | ||
285 | GatherMaterialsUuids(part, assetUuids); | ||
286 | } | ||
287 | catch (Exception e) | ||
288 | { | ||
289 | m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); | ||
290 | m_log.DebugFormat( | ||
291 | "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", | ||
292 | part.Shape.TextureEntry.Length); | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /// <summary> | ||
298 | /// Gather all the asset uuids found in one face of a Texture Entry. | ||
299 | /// </summary> | ||
300 | private void GatherTextureEntryAssets(Primitive.TextureEntryFace texture, IDictionary<UUID, sbyte> assetUuids) | ||
301 | { | ||
302 | assetUuids[texture.TextureID] = (sbyte)AssetType.Texture; | ||
303 | |||
304 | if (texture.MaterialID != UUID.Zero) | ||
305 | { | ||
306 | GatherAssetUuids(texture.MaterialID, (sbyte)OpenSimAssetType.Material, assetUuids); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /// <summary> | ||
311 | /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps | ||
312 | /// stored in legacy format in part.DynAttrs | ||
313 | /// </summary> | ||
314 | /// <param name="part"></param> | ||
315 | /// <param name="assetUuids"></param> | ||
316 | //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids) | ||
317 | public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids) | ||
318 | { | ||
319 | // scan thru the dynAttrs map of this part for any textures used as materials | ||
320 | OSD osdMaterials = null; | ||
321 | |||
322 | lock (part.DynAttrs) | ||
323 | { | ||
324 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) | ||
325 | { | ||
326 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); | ||
327 | |||
328 | if (materialsStore == null) | ||
329 | return; | ||
330 | |||
331 | materialsStore.TryGetValue("Materials", out osdMaterials); | ||
332 | } | ||
333 | |||
334 | if (osdMaterials != null) | ||
335 | { | ||
336 | //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd)); | ||
337 | |||
338 | if (osdMaterials is OSDArray) | ||
339 | { | ||
340 | OSDArray matsArr = osdMaterials as OSDArray; | ||
341 | foreach (OSDMap matMap in matsArr) | ||
342 | { | ||
343 | try | ||
344 | { | ||
345 | if (matMap.ContainsKey("Material")) | ||
346 | { | ||
347 | OSDMap mat = matMap["Material"] as OSDMap; | ||
348 | if (mat.ContainsKey("NormMap")) | ||
349 | { | ||
350 | UUID normalMapId = mat["NormMap"].AsUUID(); | ||
351 | if (normalMapId != UUID.Zero) | ||
352 | { | ||
353 | assetUuids[normalMapId] = (sbyte)AssetType.Texture; | ||
354 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); | ||
355 | } | ||
356 | } | ||
357 | if (mat.ContainsKey("SpecMap")) | ||
358 | { | ||
359 | UUID specularMapId = mat["SpecMap"].AsUUID(); | ||
360 | if (specularMapId != UUID.Zero) | ||
361 | { | ||
362 | assetUuids[specularMapId] = (sbyte)AssetType.Texture; | ||
363 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | } | ||
369 | catch (Exception e) | ||
370 | { | ||
371 | m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message); | ||
372 | } | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | |||
379 | /// <summary> | ||
380 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | ||
381 | /// asynchronous callback is used, we will wait for it to complete. | ||
382 | /// </summary> | ||
383 | /// <param name="uuid"></param> | ||
384 | /// <returns></returns> | ||
385 | protected virtual AssetBase GetAsset(UUID uuid) | ||
386 | { | ||
387 | return m_assetService.Get(uuid.ToString()); | ||
388 | |||
389 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it | ||
390 | // to complete anyway! | ||
391 | // m_waitingForObjectAsset = true; | ||
392 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); | ||
393 | // | ||
394 | // // The asset cache callback can either | ||
395 | // // | ||
396 | // // 1. Complete on the same thread (if the asset is already in the cache) or | ||
397 | // // 2. Come in via a different thread (if we need to go fetch it). | ||
398 | // // | ||
399 | // // The code below handles both these alternatives. | ||
400 | // lock (this) | ||
401 | // { | ||
402 | // if (m_waitingForObjectAsset) | ||
403 | // { | ||
404 | // Monitor.Wait(this); | ||
405 | // m_waitingForObjectAsset = false; | ||
406 | // } | ||
407 | // } | ||
408 | // | ||
409 | // return m_requestedObjectAsset; | ||
410 | } | ||
411 | |||
412 | /// <summary> | ||
413 | /// Record the asset uuids embedded within the given text (e.g. a script). | ||
414 | /// </summary> | ||
415 | /// <param name="textAssetUuid"></param> | ||
416 | /// <param name="assetUuids">Dictionary in which to record the references</param> | ||
417 | private void GetTextEmbeddedAssetUuids(UUID textAssetUuid, IDictionary<UUID, sbyte> assetUuids) | ||
418 | { | ||
419 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | ||
420 | |||
421 | AssetBase textAsset = GetAsset(textAssetUuid); | ||
422 | |||
423 | if (null != textAsset) | ||
424 | GetTextEmbeddedAssetUuids(textAsset, assetUuids); | ||
425 | } | ||
426 | |||
427 | /// <summary> | 58 | /// <summary> |
428 | /// Record the asset uuids embedded within the given text (e.g. a script). | 59 | /// Is gathering complete? |
429 | /// </summary> | ||
430 | /// <param name="textAsset"></param> | ||
431 | /// <param name="assetUuids">Dictionary in which to record the references</param> | ||
432 | private void GetTextEmbeddedAssetUuids(AssetBase textAsset, IDictionary<UUID, sbyte> assetUuids) | ||
433 | { | ||
434 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | ||
435 | |||
436 | string script = Utils.BytesToString(textAsset.Data); | ||
437 | // m_log.DebugFormat("[ARCHIVER]: Script {0}", script); | ||
438 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(script); | ||
439 | // m_log.DebugFormat("[ARCHIVER]: Found {0} matches in text", uuidMatches.Count); | ||
440 | |||
441 | foreach (Match uuidMatch in uuidMatches) | ||
442 | { | ||
443 | UUID uuid = new UUID(uuidMatch.Value); | ||
444 | // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); | ||
445 | |||
446 | // Embedded asset references (if not false positives) could be for many types of asset, so we will | ||
447 | // label these as unknown. | ||
448 | assetUuids[uuid] = (sbyte)AssetType.Unknown; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | /// <summary> | ||
453 | /// Record the uuids referenced by the given wearable asset | ||
454 | /// </summary> | ||
455 | /// <param name="wearableAssetUuid"></param> | ||
456 | /// <param name="assetUuids">Dictionary in which to record the references</param> | ||
457 | private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids) | ||
458 | { | ||
459 | AssetBase assetBase = GetAsset(wearableAssetUuid); | ||
460 | |||
461 | if (null != assetBase) | ||
462 | GetWearableAssetUuids(assetBase, assetUuids); | ||
463 | } | ||
464 | |||
465 | /// <summary> | ||
466 | /// Record the uuids referenced by the given wearable asset | ||
467 | /// </summary> | ||
468 | /// <param name="assetBase"></param> | ||
469 | /// <param name="assetUuids">Dictionary in which to record the references</param> | ||
470 | private void GetWearableAssetUuids(AssetBase assetBase, IDictionary<UUID, sbyte> assetUuids) | ||
471 | { | ||
472 | //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); | ||
473 | AssetWearable wearableAsset = new AssetBodypart(assetBase.FullID, assetBase.Data); | ||
474 | wearableAsset.Decode(); | ||
475 | |||
476 | //m_log.DebugFormat( | ||
477 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); | ||
478 | |||
479 | foreach (UUID uuid in wearableAsset.Textures.Values) | ||
480 | { | ||
481 | assetUuids[uuid] = (sbyte)AssetType.Texture; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /// <summary> | ||
486 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with | ||
487 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
488 | /// within this object). | ||
489 | /// </summary> | ||
490 | /// <param name="sceneObject"></param> | ||
491 | /// <param name="assetUuids"></param> | ||
492 | private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids) | ||
493 | { | ||
494 | AssetBase sceneObjectAsset = GetAsset(sceneObjectUuid); | ||
495 | |||
496 | if (null != sceneObjectAsset) | ||
497 | GetSceneObjectAssetUuids(sceneObjectAsset, assetUuids); | ||
498 | } | ||
499 | |||
500 | /// <summary> | ||
501 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with | ||
502 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
503 | /// within this object). | ||
504 | /// </summary> | ||
505 | /// <param name="sceneObjectAsset"></param> | ||
506 | /// <param name="assetUuids"></param> | ||
507 | private void GetSceneObjectAssetUuids(AssetBase sceneObjectAsset, IDictionary<UUID, sbyte> assetUuids) | ||
508 | { | ||
509 | string xml = Utils.BytesToString(sceneObjectAsset.Data); | ||
510 | |||
511 | CoalescedSceneObjects coa; | ||
512 | if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) | ||
513 | { | ||
514 | foreach (SceneObjectGroup sog in coa.Objects) | ||
515 | GatherAssetUuids(sog, assetUuids); | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); | ||
520 | |||
521 | if (null != sog) | ||
522 | GatherAssetUuids(sog, assetUuids); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | /// <summary> | ||
527 | /// Get the asset uuid associated with a gesture | ||
528 | /// </summary> | ||
529 | /// <param name="gestureUuid"></param> | ||
530 | /// <param name="assetUuids"></param> | ||
531 | private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids) | ||
532 | { | ||
533 | AssetBase gestureAsset = GetAsset(gestureUuid); | ||
534 | if (null == gestureAsset) | ||
535 | return; | ||
536 | |||
537 | GetGestureAssetUuids(gestureAsset, assetUuids); | ||
538 | } | ||
539 | |||
540 | /// <summary> | ||
541 | /// Get the asset uuid associated with a gesture | ||
542 | /// </summary> | ||
543 | /// <param name="gestureAsset"></param> | ||
544 | /// <param name="assetUuids"></param> | ||
545 | private void GetGestureAssetUuids(AssetBase gestureAsset, IDictionary<UUID, sbyte> assetUuids) | ||
546 | { | ||
547 | using (MemoryStream ms = new MemoryStream(gestureAsset.Data)) | ||
548 | using (StreamReader sr = new StreamReader(ms)) | ||
549 | { | ||
550 | sr.ReadLine(); // Unknown (Version?) | ||
551 | sr.ReadLine(); // Unknown | ||
552 | sr.ReadLine(); // Unknown | ||
553 | sr.ReadLine(); // Name | ||
554 | sr.ReadLine(); // Comment ? | ||
555 | int count = Convert.ToInt32(sr.ReadLine()); // Item count | ||
556 | |||
557 | for (int i = 0 ; i < count ; i++) | ||
558 | { | ||
559 | string type = sr.ReadLine(); | ||
560 | if (type == null) | ||
561 | break; | ||
562 | string name = sr.ReadLine(); | ||
563 | if (name == null) | ||
564 | break; | ||
565 | string id = sr.ReadLine(); | ||
566 | if (id == null) | ||
567 | break; | ||
568 | string unknown = sr.ReadLine(); | ||
569 | if (unknown == null) | ||
570 | break; | ||
571 | |||
572 | // If it can be parsed as a UUID, it is an asset ID | ||
573 | UUID uuid; | ||
574 | if (UUID.TryParse(id, out uuid)) | ||
575 | assetUuids[uuid] = (sbyte)AssetType.Animation; // the asset is either an Animation or a Sound, but this distinction isn't important | ||
576 | } | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /// <summary> | ||
581 | /// Get the asset uuid's referenced in a material. | ||
582 | /// </summary> | ||
583 | private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids) | ||
584 | { | ||
585 | AssetBase assetBase = GetAsset(materialUuid); | ||
586 | if (null == assetBase) | ||
587 | return; | ||
588 | |||
589 | GetMaterialAssetUuids(assetBase, assetUuids); | ||
590 | } | ||
591 | |||
592 | /// <summary> | ||
593 | /// Get the asset uuid's referenced in a material. | ||
594 | /// </summary> | 60 | /// </summary> |
595 | private void GetMaterialAssetUuids(AssetBase materialAsset, IDictionary<UUID, sbyte> assetUuids) | 61 | public bool Complete { get { return m_assetUuidsToInspect.Count <= 0; } } |
596 | { | ||
597 | OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); | ||
598 | |||
599 | UUID normMap = mat["NormMap"].AsUUID(); | ||
600 | if (normMap != UUID.Zero) | ||
601 | assetUuids[normMap] = (sbyte)AssetType.Texture; | ||
602 | |||
603 | UUID specMap = mat["SpecMap"].AsUUID(); | ||
604 | if (specMap != UUID.Zero) | ||
605 | assetUuids[specMap] = (sbyte)AssetType.Texture; | ||
606 | } | ||
607 | } | ||
608 | |||
609 | public class HGUuidGatherer : UuidGatherer | ||
610 | { | ||
611 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
612 | |||
613 | protected string m_assetServerURL; | ||
614 | |||
615 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) | ||
616 | : base(assetService) | ||
617 | { | ||
618 | m_assetServerURL = assetServerURL; | ||
619 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) | ||
620 | m_assetServerURL = m_assetServerURL + "/"; | ||
621 | } | ||
622 | |||
623 | protected override AssetBase GetAsset(UUID uuid) | ||
624 | { | ||
625 | if (string.Empty == m_assetServerURL) | ||
626 | return base.GetAsset(uuid); | ||
627 | else | ||
628 | return FetchAsset(uuid); | ||
629 | } | ||
630 | |||
631 | public AssetBase FetchAsset(UUID assetID) | ||
632 | { | ||
633 | // Test if it's already here | ||
634 | AssetBase asset = m_assetService.Get(assetID.ToString()); | ||
635 | if (asset == null) | ||
636 | { | ||
637 | // It's not, so fetch it from abroad | ||
638 | asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); | ||
639 | if (asset != null) | ||
640 | m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); | ||
641 | else | ||
642 | m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); | ||
643 | } | ||
644 | //else | ||
645 | // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); | ||
646 | |||
647 | return asset; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | /// <summary> | ||
652 | /// Gather uuids for a given entity. | ||
653 | /// </summary> | ||
654 | /// <remarks> | ||
655 | /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts | ||
656 | /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets | ||
657 | /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be | ||
658 | /// retrieved to work out which assets it references). | ||
659 | /// </remarks> | ||
660 | public class IteratingUuidGatherer | ||
661 | { | ||
662 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
663 | 62 | ||
664 | /// <summary> | 63 | /// <summary> |
665 | /// Is gathering complete? | 64 | /// The dictionary of UUIDs gathered so far. If Complete == true then this is all the reachable UUIDs. |
666 | /// </summary> | 65 | /// </summary> |
667 | public bool Complete { get { return m_assetUuidsToInspect.Count <= 0; } } | 66 | /// <value>The gathered uuids.</value> |
67 | public IDictionary<UUID, sbyte> GatheredUuids { get; private set; } | ||
668 | 68 | ||
669 | /// <summary> | 69 | /// <summary> |
670 | /// Gets the next UUID to inspect. | 70 | /// Gets the next UUID to inspect. |
@@ -683,13 +83,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
683 | 83 | ||
684 | protected IAssetService m_assetService; | 84 | protected IAssetService m_assetService; |
685 | 85 | ||
686 | protected IDictionary<UUID, sbyte> m_gatheredAssetUuids; | ||
687 | |||
688 | protected Queue<UUID> m_assetUuidsToInspect; | 86 | protected Queue<UUID> m_assetUuidsToInspect; |
689 | 87 | ||
690 | /// <summary> | 88 | /// <summary> |
691 | /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. | 89 | /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. |
692 | /// </summary> | 90 | /// </summary> |
91 | /// <remarks>In this case the collection of gathered assets will start out blank.</remarks> | ||
92 | /// <param name="assetService"> | ||
93 | /// Asset service. | ||
94 | /// </param> | ||
95 | public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>()) {} | ||
96 | |||
97 | /// <summary> | ||
98 | /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. | ||
99 | /// </summary> | ||
693 | /// <param name="assetService"> | 100 | /// <param name="assetService"> |
694 | /// Asset service. | 101 | /// Asset service. |
695 | /// </param> | 102 | /// </param> |
@@ -697,10 +104,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
697 | /// Gathered UUIDs will be collected in this dictinaory. | 104 | /// Gathered UUIDs will be collected in this dictinaory. |
698 | /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. | 105 | /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. |
699 | /// </param> | 106 | /// </param> |
700 | public IteratingUuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) | 107 | public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) |
701 | { | 108 | { |
702 | m_assetService = assetService; | 109 | m_assetService = assetService; |
703 | m_gatheredAssetUuids = collector; | 110 | GatheredUuids = collector; |
704 | 111 | ||
705 | // FIXME: Not efficient for searching, can improve. | 112 | // FIXME: Not efficient for searching, can improve. |
706 | m_assetUuidsToInspect = new Queue<UUID>(); | 113 | m_assetUuidsToInspect = new Queue<UUID>(); |
@@ -765,13 +172,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
765 | 172 | ||
766 | // If the prim is a sculpt then preserve this information too | 173 | // If the prim is a sculpt then preserve this information too |
767 | if (part.Shape.SculptTexture != UUID.Zero) | 174 | if (part.Shape.SculptTexture != UUID.Zero) |
768 | m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; | 175 | GatheredUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; |
769 | 176 | ||
770 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) | 177 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) |
771 | m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; | 178 | GatheredUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; |
772 | 179 | ||
773 | if (part.CollisionSound != UUID.Zero) | 180 | if (part.CollisionSound != UUID.Zero) |
774 | m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; | 181 | GatheredUuids[part.CollisionSound] = (sbyte)AssetType.Sound; |
775 | 182 | ||
776 | if (part.ParticleSystem.Length > 0) | 183 | if (part.ParticleSystem.Length > 0) |
777 | { | 184 | { |
@@ -779,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
779 | { | 186 | { |
780 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); | 187 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); |
781 | if (ps.Texture != UUID.Zero) | 188 | if (ps.Texture != UUID.Zero) |
782 | m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture; | 189 | GatheredUuids[ps.Texture] = (sbyte)AssetType.Texture; |
783 | } | 190 | } |
784 | catch (Exception) | 191 | catch (Exception) |
785 | { | 192 | { |
@@ -798,7 +205,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
798 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", | 205 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", |
799 | // tii.Name, tii.Type, part.Name, part.UUID); | 206 | // tii.Name, tii.Type, part.Name, part.UUID); |
800 | 207 | ||
801 | if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID)) | 208 | if (!GatheredUuids.ContainsKey(tii.AssetID)) |
802 | AddForInspection(tii.AssetID, (sbyte)tii.Type); | 209 | AddForInspection(tii.AssetID, (sbyte)tii.Type); |
803 | } | 210 | } |
804 | 211 | ||
@@ -865,7 +272,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
865 | private void GetAssetUuids(UUID assetUuid) | 272 | private void GetAssetUuids(UUID assetUuid) |
866 | { | 273 | { |
867 | // avoid infinite loops | 274 | // avoid infinite loops |
868 | if (m_gatheredAssetUuids.ContainsKey(assetUuid)) | 275 | if (GatheredUuids.ContainsKey(assetUuid)) |
869 | return; | 276 | return; |
870 | 277 | ||
871 | try | 278 | try |
@@ -875,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
875 | if (null != assetBase) | 282 | if (null != assetBase) |
876 | { | 283 | { |
877 | sbyte assetType = assetBase.Type; | 284 | sbyte assetType = assetBase.Type; |
878 | m_gatheredAssetUuids[assetUuid] = assetType; | 285 | GatheredUuids[assetUuid] = assetType; |
879 | 286 | ||
880 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | 287 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) |
881 | { | 288 | { |
@@ -915,29 +322,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
915 | // Here, we want to collect uuids which require further asset fetches but mark the others as gathered | 322 | // Here, we want to collect uuids which require further asset fetches but mark the others as gathered |
916 | try | 323 | try |
917 | { | 324 | { |
918 | m_gatheredAssetUuids[assetUuid] = assetType; | 325 | GatheredUuids[assetUuid] = assetType; |
919 | 326 | ||
920 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | 327 | if ((sbyte)AssetType.Bodypart == assetType |
921 | { | 328 | || (sbyte)AssetType.Clothing == assetType |
922 | AddForInspection(assetUuid); | 329 | || (sbyte)AssetType.Gesture == assetType |
923 | } | 330 | || (sbyte)AssetType.Notecard == assetType |
924 | else if ((sbyte)AssetType.Gesture == assetType) | 331 | || (sbyte)AssetType.LSLText == assetType |
925 | { | 332 | || (sbyte)OpenSimAssetType.Material == assetType |
926 | AddForInspection(assetUuid); | 333 | || (sbyte)AssetType.Object == assetType) |
927 | } | ||
928 | else if ((sbyte)AssetType.Notecard == assetType) | ||
929 | { | ||
930 | AddForInspection(assetUuid); | ||
931 | } | ||
932 | else if ((sbyte)AssetType.LSLText == assetType) | ||
933 | { | ||
934 | AddForInspection(assetUuid); | ||
935 | } | ||
936 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
937 | { | ||
938 | AddForInspection(assetUuid); | ||
939 | } | ||
940 | else if ((sbyte)AssetType.Object == assetType) | ||
941 | { | 334 | { |
942 | AddForInspection(assetUuid); | 335 | AddForInspection(assetUuid); |
943 | } | 336 | } |
@@ -956,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
956 | /// </summary> | 349 | /// </summary> |
957 | private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) | 350 | private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) |
958 | { | 351 | { |
959 | m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture; | 352 | GatheredUuids[texture.TextureID] = (sbyte)AssetType.Texture; |
960 | 353 | ||
961 | if (texture.MaterialID != UUID.Zero) | 354 | if (texture.MaterialID != UUID.Zero) |
962 | AddForInspection(texture.MaterialID); | 355 | AddForInspection(texture.MaterialID); |
@@ -1003,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1003 | UUID normalMapId = mat["NormMap"].AsUUID(); | 396 | UUID normalMapId = mat["NormMap"].AsUUID(); |
1004 | if (normalMapId != UUID.Zero) | 397 | if (normalMapId != UUID.Zero) |
1005 | { | 398 | { |
1006 | m_gatheredAssetUuids[normalMapId] = (sbyte)AssetType.Texture; | 399 | GatheredUuids[normalMapId] = (sbyte)AssetType.Texture; |
1007 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); | 400 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); |
1008 | } | 401 | } |
1009 | } | 402 | } |
@@ -1012,7 +405,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1012 | UUID specularMapId = mat["SpecMap"].AsUUID(); | 405 | UUID specularMapId = mat["SpecMap"].AsUUID(); |
1013 | if (specularMapId != UUID.Zero) | 406 | if (specularMapId != UUID.Zero) |
1014 | { | 407 | { |
1015 | m_gatheredAssetUuids[specularMapId] = (sbyte)AssetType.Texture; | 408 | GatheredUuids[specularMapId] = (sbyte)AssetType.Texture; |
1016 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); | 409 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); |
1017 | } | 410 | } |
1018 | } | 411 | } |
@@ -1048,17 +441,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1048 | { | 441 | { |
1049 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | 442 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); |
1050 | 443 | ||
1051 | string script = Utils.BytesToString(textAsset.Data); | 444 | string text = Utils.BytesToString(textAsset.Data); |
1052 | // m_log.DebugFormat("[ARCHIVER]: Script {0}", script); | 445 | // m_log.DebugFormat("[UUID GATHERER]: Text {0}", text); |
1053 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(script); | 446 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(text); |
1054 | // m_log.DebugFormat("[ARCHIVER]: Found {0} matches in text", uuidMatches.Count); | 447 | // m_log.DebugFormat("[UUID GATHERER]: Found {0} matches in text", uuidMatches.Count); |
1055 | 448 | ||
1056 | foreach (Match uuidMatch in uuidMatches) | 449 | foreach (Match uuidMatch in uuidMatches) |
1057 | { | 450 | { |
1058 | UUID uuid = new UUID(uuidMatch.Value); | 451 | UUID uuid = new UUID(uuidMatch.Value); |
1059 | // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); | 452 | // m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid); |
1060 | 453 | ||
1061 | AddForInspection(uuid); | 454 | GatheredUuids[uuid] = (sbyte)AssetType.Unknown; |
1062 | } | 455 | } |
1063 | } | 456 | } |
1064 | 457 | ||
@@ -1076,7 +469,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1076 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); | 469 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); |
1077 | 470 | ||
1078 | foreach (UUID uuid in wearableAsset.Textures.Values) | 471 | foreach (UUID uuid in wearableAsset.Textures.Values) |
1079 | m_gatheredAssetUuids[uuid] = (sbyte)AssetType.Texture; | 472 | GatheredUuids[uuid] = (sbyte)AssetType.Texture; |
1080 | } | 473 | } |
1081 | 474 | ||
1082 | /// <summary> | 475 | /// <summary> |
@@ -1138,7 +531,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1138 | // If it can be parsed as a UUID, it is an asset ID | 531 | // If it can be parsed as a UUID, it is an asset ID |
1139 | UUID uuid; | 532 | UUID uuid; |
1140 | if (UUID.TryParse(id, out uuid)) | 533 | if (UUID.TryParse(id, out uuid)) |
1141 | m_gatheredAssetUuids[uuid] = (sbyte)AssetType.Animation; // the asset is either an Animation or a Sound, but this distinction isn't important | 534 | GatheredUuids[uuid] = (sbyte)AssetType.Animation; // the asset is either an Animation or a Sound, but this distinction isn't important |
1142 | } | 535 | } |
1143 | } | 536 | } |
1144 | } | 537 | } |
@@ -1152,21 +545,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1152 | 545 | ||
1153 | UUID normMap = mat["NormMap"].AsUUID(); | 546 | UUID normMap = mat["NormMap"].AsUUID(); |
1154 | if (normMap != UUID.Zero) | 547 | if (normMap != UUID.Zero) |
1155 | m_gatheredAssetUuids[normMap] = (sbyte)AssetType.Texture; | 548 | GatheredUuids[normMap] = (sbyte)AssetType.Texture; |
1156 | 549 | ||
1157 | UUID specMap = mat["SpecMap"].AsUUID(); | 550 | UUID specMap = mat["SpecMap"].AsUUID(); |
1158 | if (specMap != UUID.Zero) | 551 | if (specMap != UUID.Zero) |
1159 | m_gatheredAssetUuids[specMap] = (sbyte)AssetType.Texture; | 552 | GatheredUuids[specMap] = (sbyte)AssetType.Texture; |
1160 | } | 553 | } |
1161 | } | 554 | } |
1162 | 555 | ||
1163 | public class IteratingHGUuidGatherer : IteratingUuidGatherer | 556 | public class HGUuidGatherer : UuidGatherer |
1164 | { | 557 | { |
1165 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 558 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
1166 | 559 | ||
1167 | protected string m_assetServerURL; | 560 | protected string m_assetServerURL; |
1168 | 561 | ||
1169 | public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary<UUID, sbyte> collector) | 562 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) |
563 | : this(assetService, assetServerURL, new Dictionary<UUID, sbyte>()) {} | ||
564 | |||
565 | public HGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary<UUID, sbyte> collector) | ||
1170 | : base(assetService, collector) | 566 | : base(assetService, collector) |
1171 | { | 567 | { |
1172 | m_assetServerURL = assetServerURL; | 568 | m_assetServerURL = assetServerURL; |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index f67f613..2f9bb1e 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs | |||
@@ -426,10 +426,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance | |||
426 | cdl.AddRow("Assets", ""); | 426 | cdl.AddRow("Assets", ""); |
427 | sb.Append(cdl.ToString()); | 427 | sb.Append(cdl.ToString()); |
428 | 428 | ||
429 | Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>(); | 429 | uuidGatherer.AddForInspection(wi.AssetID); |
430 | uuidGatherer.GatherAssetUuids(wi.AssetID, assetUuids); | 430 | uuidGatherer.GatherAll(); |
431 | string[] assetStrings | 431 | string[] assetStrings |
432 | = Array.ConvertAll<UUID, string>(assetUuids.Keys.ToArray(), u => u.ToString()); | 432 | = Array.ConvertAll<UUID, string>(uuidGatherer.GatheredUuids.Keys.ToArray(), u => u.ToString()); |
433 | 433 | ||
434 | bool[] existChecks = scene.AssetService.AssetsExist(assetStrings); | 434 | bool[] existChecks = scene.AssetService.AssetsExist(assetStrings); |
435 | 435 | ||
@@ -440,7 +440,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance | |||
440 | cdt.AddColumn("Found", 5); | 440 | cdt.AddColumn("Found", 5); |
441 | 441 | ||
442 | for (int k = 0; k < existChecks.Length; k++) | 442 | for (int k = 0; k < existChecks.Length; k++) |
443 | cdt.AddRow((AssetType)assetUuids[new UUID(assetStrings[k])], assetStrings[k], existChecks[k] ? "yes" : "no"); | 443 | cdt.AddRow( |
444 | (AssetType)uuidGatherer.GatheredUuids[new UUID(assetStrings[k])], | ||
445 | assetStrings[k], existChecks[k] ? "yes" : "no"); | ||
444 | 446 | ||
445 | sb.Append(cdt.ToString()); | 447 | sb.Append(cdt.ToString()); |
446 | sb.Append("\n"); | 448 | sb.Append("\n"); |