diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | 19 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 607 |
2 files changed, 579 insertions, 47 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 522de79..be409bb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -571,9 +571,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
571 | "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", | 571 | "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", |
572 | so.Name, so.AttachedAvatar, url); | 572 | so.Name, so.AttachedAvatar, url); |
573 | 573 | ||
574 | Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); | 574 | IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url); |
575 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url); | 575 | uuidGatherer.RecordAssetUuids(so); |
576 | uuidGatherer.GatherAssetUuids(so, ids); | 576 | |
577 | // XXX: We will shortly use this iterating mechanism to check if a fetch is taking too long | ||
578 | // but just for now we will simply fetch everything. If this was permanent could use | ||
579 | // GatherAll() | ||
580 | while (uuidGatherer.GatherNext()) | ||
581 | m_log.DebugFormat( | ||
582 | "[HG ENTITY TRANSFER]: Gathered attachment {0} for HG user {1} with asset server {2}", | ||
583 | so.Name, so.OwnerID, url); | ||
584 | |||
585 | IDictionary<UUID, sbyte> ids = uuidGatherer.GetGatheredUuids(); | ||
586 | |||
587 | m_log.DebugFormat( | ||
588 | "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset server {3}", | ||
589 | ids.Count, so.Name, so.OwnerID, url); | ||
577 | 590 | ||
578 | foreach (KeyValuePair<UUID, sbyte> kvp in ids) | 591 | foreach (KeyValuePair<UUID, sbyte> kvp in ids) |
579 | uuidGatherer.FetchAsset(kvp.Key); | 592 | uuidGatherer.FetchAsset(kvp.Key); |
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 20ff5b5..9c4e4c0 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |||
@@ -57,17 +57,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
57 | 57 | ||
58 | protected IAssetService m_assetService; | 58 | protected IAssetService m_assetService; |
59 | 59 | ||
60 | // /// <summary> | 60 | // /// <summary> |
61 | // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate | 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. | 62 | // /// asset was found by the asset service. |
63 | // /// </summary> | 63 | // /// </summary> |
64 | // private AssetBase m_requestedObjectAsset; | 64 | // private AssetBase m_requestedObjectAsset; |
65 | // | 65 | // |
66 | // /// <summary> | 66 | // /// <summary> |
67 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. | 67 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. |
68 | // /// </summary> | 68 | // /// </summary> |
69 | // private bool m_waitingForObjectAsset; | 69 | // private bool m_waitingForObjectAsset; |
70 | 70 | ||
71 | public UuidGatherer(IAssetService assetService) | 71 | public UuidGatherer(IAssetService assetService) |
72 | { | 72 | { |
73 | m_assetService = assetService; | 73 | m_assetService = assetService; |
@@ -133,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
133 | throw; | 133 | throw; |
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | /// <summary> | 137 | /// <summary> |
138 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | 138 | /// Gather all the asset uuids associated with the asset referenced by a given uuid |
139 | /// </summary> | 139 | /// </summary> |
@@ -154,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
154 | try | 154 | try |
155 | { | 155 | { |
156 | assetUuids[assetUuid] = assetType; | 156 | assetUuids[assetUuid] = assetType; |
157 | 157 | ||
158 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | 158 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) |
159 | { | 159 | { |
160 | GetWearableAssetUuids(assetUuid, assetUuids); | 160 | GetWearableAssetUuids(assetUuid, assetUuids); |
@@ -204,16 +204,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
204 | /// </param> | 204 | /// </param> |
205 | public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids) | 205 | public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids) |
206 | { | 206 | { |
207 | // m_log.DebugFormat( | 207 | // m_log.DebugFormat( |
208 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); | 208 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); |
209 | 209 | ||
210 | SceneObjectPart[] parts = sceneObject.Parts; | 210 | SceneObjectPart[] parts = sceneObject.Parts; |
211 | for (int i = 0; i < parts.Length; i++) | 211 | for (int i = 0; i < parts.Length; i++) |
212 | { | 212 | { |
213 | SceneObjectPart part = parts[i]; | 213 | SceneObjectPart part = parts[i]; |
214 | 214 | ||
215 | // m_log.DebugFormat( | 215 | // m_log.DebugFormat( |
216 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); | 216 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); |
217 | 217 | ||
218 | try | 218 | try |
219 | { | 219 | { |
@@ -234,7 +234,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
234 | } | 234 | } |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | // If the prim is a sculpt then preserve this information too | 238 | // If the prim is a sculpt then preserve this information too |
239 | if (part.Shape.SculptTexture != UUID.Zero) | 239 | if (part.Shape.SculptTexture != UUID.Zero) |
240 | assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; | 240 | assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; |
@@ -262,13 +262,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
262 | } | 262 | } |
263 | 263 | ||
264 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); | 264 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); |
265 | 265 | ||
266 | // Now analyze this prim's inventory items to preserve all the uuids that they reference | 266 | // Now analyze this prim's inventory items to preserve all the uuids that they reference |
267 | foreach (TaskInventoryItem tii in taskDictionary.Values) | 267 | foreach (TaskInventoryItem tii in taskDictionary.Values) |
268 | { | 268 | { |
269 | // m_log.DebugFormat( | 269 | // m_log.DebugFormat( |
270 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", | 270 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", |
271 | // tii.Name, tii.Type, part.Name, part.UUID); | 271 | // tii.Name, tii.Type, part.Name, part.UUID); |
272 | 272 | ||
273 | if (!assetUuids.ContainsKey(tii.AssetID)) | 273 | if (!assetUuids.ContainsKey(tii.AssetID)) |
274 | GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids); | 274 | GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids); |
@@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
278 | // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and | 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 | 279 | // inventory transfer. There needs to be a way for a module to register a method without assuming a |
280 | // Scene.EventManager is present. | 280 | // Scene.EventManager is present. |
281 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); | 281 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); |
282 | 282 | ||
283 | 283 | ||
284 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs | 284 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs |
@@ -375,7 +375,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
375 | } | 375 | } |
376 | } | 376 | } |
377 | } | 377 | } |
378 | 378 | ||
379 | /// <summary> | 379 | /// <summary> |
380 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | 380 | /// Get an asset synchronously, potentially using an asynchronous callback. If the |
381 | /// asynchronous callback is used, we will wait for it to complete. | 381 | /// asynchronous callback is used, we will wait for it to complete. |
@@ -388,25 +388,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
388 | 388 | ||
389 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it | 389 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it |
390 | // to complete anyway! | 390 | // to complete anyway! |
391 | // m_waitingForObjectAsset = true; | 391 | // m_waitingForObjectAsset = true; |
392 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); | 392 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); |
393 | // | 393 | // |
394 | // // The asset cache callback can either | 394 | // // The asset cache callback can either |
395 | // // | 395 | // // |
396 | // // 1. Complete on the same thread (if the asset is already in the cache) or | 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). | 397 | // // 2. Come in via a different thread (if we need to go fetch it). |
398 | // // | 398 | // // |
399 | // // The code below handles both these alternatives. | 399 | // // The code below handles both these alternatives. |
400 | // lock (this) | 400 | // lock (this) |
401 | // { | 401 | // { |
402 | // if (m_waitingForObjectAsset) | 402 | // if (m_waitingForObjectAsset) |
403 | // { | 403 | // { |
404 | // Monitor.Wait(this); | 404 | // Monitor.Wait(this); |
405 | // m_waitingForObjectAsset = false; | 405 | // m_waitingForObjectAsset = false; |
406 | // } | 406 | // } |
407 | // } | 407 | // } |
408 | // | 408 | // |
409 | // return m_requestedObjectAsset; | 409 | // return m_requestedObjectAsset; |
410 | } | 410 | } |
411 | 411 | ||
412 | /// <summary> | 412 | /// <summary> |
@@ -416,7 +416,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
416 | /// <param name="assetUuids">Dictionary in which to record the references</param> | 416 | /// <param name="assetUuids">Dictionary in which to record the references</param> |
417 | private void GetTextEmbeddedAssetUuids(UUID textAssetUuid, IDictionary<UUID, sbyte> assetUuids) | 417 | private void GetTextEmbeddedAssetUuids(UUID textAssetUuid, IDictionary<UUID, sbyte> assetUuids) |
418 | { | 418 | { |
419 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | 419 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); |
420 | 420 | ||
421 | AssetBase textAsset = GetAsset(textAssetUuid); | 421 | AssetBase textAsset = GetAsset(textAssetUuid); |
422 | 422 | ||
@@ -630,7 +630,526 @@ namespace OpenSim.Region.Framework.Scenes | |||
630 | 630 | ||
631 | public AssetBase FetchAsset(UUID assetID) | 631 | public AssetBase FetchAsset(UUID assetID) |
632 | { | 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 | public class IteratingUuidGatherer | ||
652 | { | ||
653 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
654 | |||
655 | /// <summary> | ||
656 | /// Is gathering complete? | ||
657 | /// </summary> | ||
658 | public bool GatheringComplete { get { return m_assetUuidsToInspect.Count <= 0; } } | ||
659 | |||
660 | protected IAssetService m_assetService; | ||
661 | |||
662 | protected IDictionary<UUID, sbyte> m_gatheredAssetUuids; | ||
663 | |||
664 | protected Queue<UUID> m_assetUuidsToInspect; | ||
665 | |||
666 | public IteratingUuidGatherer(IAssetService assetService) | ||
667 | { | ||
668 | m_assetService = assetService; | ||
669 | m_gatheredAssetUuids = new Dictionary<UUID, sbyte>(); | ||
670 | |||
671 | // FIXME: Not efficient for searching, can improve. | ||
672 | m_assetUuidsToInspect = new Queue<UUID>(); | ||
673 | } | ||
674 | |||
675 | public IDictionary<UUID, sbyte> GetGatheredUuids() | ||
676 | { | ||
677 | return new Dictionary<UUID, sbyte>(m_gatheredAssetUuids); | ||
678 | } | ||
679 | |||
680 | public bool AddAssetUuidToInspect(UUID uuid) | ||
681 | { | ||
682 | if (m_assetUuidsToInspect.Contains(uuid)) | ||
683 | return false; | ||
684 | |||
685 | m_assetUuidsToInspect.Enqueue(uuid); | ||
686 | |||
687 | return true; | ||
688 | } | ||
689 | |||
690 | /// <summary> | ||
691 | /// Gathers the next set of assets returned by the next uuid to get from the asset service. | ||
692 | /// </summary> | ||
693 | /// <returns>false if gathering is already complete, true otherwise</returns> | ||
694 | public bool GatherNext() | ||
695 | { | ||
696 | if (GatheringComplete) | ||
697 | return false; | ||
698 | |||
699 | GetAssetUuids(m_assetUuidsToInspect.Dequeue()); | ||
700 | |||
701 | return true; | ||
702 | } | ||
703 | |||
704 | /// <summary> | ||
705 | /// Gathers all remaining asset UUIDS no matter how many calls are required to the asset service. | ||
706 | /// </summary> | ||
707 | /// <returns>false if gathering is already complete, true otherwise</returns> | ||
708 | public bool GatherAll() | ||
709 | { | ||
710 | if (GatheringComplete) | ||
711 | return false; | ||
712 | |||
713 | while (GatherNext()); | ||
714 | |||
715 | return true; | ||
716 | } | ||
717 | |||
718 | /// <summary> | ||
719 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | ||
720 | /// </summary> | ||
721 | /// <remarks> | ||
722 | /// This includes both those directly associated with | ||
723 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
724 | /// within this object). | ||
725 | /// This method assumes that the asset type associated with this asset in persistent storage is correct (which | ||
726 | /// should always be the case). So with this method we always need to retrieve asset data even if the asset | ||
727 | /// is of a type which is known not to reference any other assets | ||
728 | /// </remarks> | ||
729 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> | ||
730 | private void GetAssetUuids(UUID assetUuid) | ||
731 | { | ||
732 | // avoid infinite loops | ||
733 | if (m_gatheredAssetUuids.ContainsKey(assetUuid)) | ||
734 | return; | ||
633 | 735 | ||
736 | try | ||
737 | { | ||
738 | AssetBase assetBase = GetAsset(assetUuid); | ||
739 | |||
740 | if (null != assetBase) | ||
741 | { | ||
742 | sbyte assetType = assetBase.Type; | ||
743 | m_gatheredAssetUuids[assetUuid] = assetType; | ||
744 | |||
745 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | ||
746 | { | ||
747 | RecordWearableAssetUuids(assetBase); | ||
748 | } | ||
749 | else if ((sbyte)AssetType.Gesture == assetType) | ||
750 | { | ||
751 | RecordGestureAssetUuids(assetBase); | ||
752 | } | ||
753 | else if ((sbyte)AssetType.Notecard == assetType) | ||
754 | { | ||
755 | RecordTextEmbeddedAssetUuids(assetBase); | ||
756 | } | ||
757 | else if ((sbyte)AssetType.LSLText == assetType) | ||
758 | { | ||
759 | RecordTextEmbeddedAssetUuids(assetBase); | ||
760 | } | ||
761 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
762 | { | ||
763 | RecordMaterialAssetUuids(assetBase); | ||
764 | } | ||
765 | else if ((sbyte)AssetType.Object == assetType) | ||
766 | { | ||
767 | RecordSceneObjectAssetUuids(assetBase); | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | catch (Exception) | ||
772 | { | ||
773 | m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); | ||
774 | throw; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | private void RecordAssetUuids(UUID assetUuid, sbyte assetType) | ||
779 | { | ||
780 | // Here, we want to collect uuids which require further asset fetches but mark the others as gathered | ||
781 | try | ||
782 | { | ||
783 | m_gatheredAssetUuids[assetUuid] = assetType; | ||
784 | |||
785 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | ||
786 | { | ||
787 | AddAssetUuidToInspect(assetUuid); | ||
788 | } | ||
789 | else if ((sbyte)AssetType.Gesture == assetType) | ||
790 | { | ||
791 | AddAssetUuidToInspect(assetUuid); | ||
792 | } | ||
793 | else if ((sbyte)AssetType.Notecard == assetType) | ||
794 | { | ||
795 | AddAssetUuidToInspect(assetUuid); | ||
796 | } | ||
797 | else if ((sbyte)AssetType.LSLText == assetType) | ||
798 | { | ||
799 | AddAssetUuidToInspect(assetUuid); | ||
800 | } | ||
801 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
802 | { | ||
803 | AddAssetUuidToInspect(assetUuid); | ||
804 | } | ||
805 | else if ((sbyte)AssetType.Object == assetType) | ||
806 | { | ||
807 | AddAssetUuidToInspect(assetUuid); | ||
808 | } | ||
809 | } | ||
810 | catch (Exception) | ||
811 | { | ||
812 | m_log.ErrorFormat( | ||
813 | "[ITERATABLE UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", | ||
814 | assetUuid, assetType); | ||
815 | throw; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | /// <summary> | ||
820 | /// Gather all the asset uuids associated with a given object. | ||
821 | /// </summary> | ||
822 | /// <remarks> | ||
823 | /// This includes both those directly associated with | ||
824 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
825 | /// within this object). | ||
826 | /// </remarks> | ||
827 | /// <param name="sceneObject">The scene object for which to gather assets</param> | ||
828 | public void RecordAssetUuids(SceneObjectGroup sceneObject) | ||
829 | { | ||
830 | // m_log.DebugFormat( | ||
831 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); | ||
832 | |||
833 | SceneObjectPart[] parts = sceneObject.Parts; | ||
834 | for (int i = 0; i < parts.Length; i++) | ||
835 | { | ||
836 | SceneObjectPart part = parts[i]; | ||
837 | |||
838 | // m_log.DebugFormat( | ||
839 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); | ||
840 | |||
841 | try | ||
842 | { | ||
843 | Primitive.TextureEntry textureEntry = part.Shape.Textures; | ||
844 | if (textureEntry != null) | ||
845 | { | ||
846 | // Get the prim's default texture. This will be used for faces which don't have their own texture | ||
847 | if (textureEntry.DefaultTexture != null) | ||
848 | RecordTextureEntryAssetUuids(textureEntry.DefaultTexture); | ||
849 | |||
850 | if (textureEntry.FaceTextures != null) | ||
851 | { | ||
852 | // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) | ||
853 | foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) | ||
854 | { | ||
855 | if (texture != null) | ||
856 | RecordTextureEntryAssetUuids(texture); | ||
857 | } | ||
858 | } | ||
859 | } | ||
860 | |||
861 | // If the prim is a sculpt then preserve this information too | ||
862 | if (part.Shape.SculptTexture != UUID.Zero) | ||
863 | m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; | ||
864 | |||
865 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) | ||
866 | m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; | ||
867 | |||
868 | if (part.CollisionSound != UUID.Zero) | ||
869 | m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; | ||
870 | |||
871 | if (part.ParticleSystem.Length > 0) | ||
872 | { | ||
873 | try | ||
874 | { | ||
875 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); | ||
876 | if (ps.Texture != UUID.Zero) | ||
877 | m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture; | ||
878 | } | ||
879 | catch (Exception) | ||
880 | { | ||
881 | m_log.WarnFormat( | ||
882 | "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", | ||
883 | part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); | ||
884 | } | ||
885 | } | ||
886 | |||
887 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); | ||
888 | |||
889 | // Now analyze this prim's inventory items to preserve all the uuids that they reference | ||
890 | foreach (TaskInventoryItem tii in taskDictionary.Values) | ||
891 | { | ||
892 | // m_log.DebugFormat( | ||
893 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", | ||
894 | // tii.Name, tii.Type, part.Name, part.UUID); | ||
895 | |||
896 | if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID)) | ||
897 | RecordAssetUuids(tii.AssetID, (sbyte)tii.Type); | ||
898 | } | ||
899 | |||
900 | // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed | ||
901 | // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and | ||
902 | // inventory transfer. There needs to be a way for a module to register a method without assuming a | ||
903 | // Scene.EventManager is present. | ||
904 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); | ||
905 | |||
906 | |||
907 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs | ||
908 | RecordMaterialsUuids(part); | ||
909 | } | ||
910 | catch (Exception e) | ||
911 | { | ||
912 | m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); | ||
913 | m_log.DebugFormat( | ||
914 | "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", | ||
915 | part.Shape.TextureEntry.Length); | ||
916 | } | ||
917 | } | ||
918 | } | ||
919 | |||
920 | /// <summary> | ||
921 | /// Collect all the asset uuids found in one face of a Texture Entry. | ||
922 | /// </summary> | ||
923 | private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) | ||
924 | { | ||
925 | m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture; | ||
926 | |||
927 | if (texture.MaterialID != UUID.Zero) | ||
928 | AddAssetUuidToInspect(texture.MaterialID); | ||
929 | } | ||
930 | |||
931 | /// <summary> | ||
932 | /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps | ||
933 | /// stored in legacy format in part.DynAttrs | ||
934 | /// </summary> | ||
935 | /// <param name="part"></param> | ||
936 | public void RecordMaterialsUuids(SceneObjectPart part) | ||
937 | { | ||
938 | // scan thru the dynAttrs map of this part for any textures used as materials | ||
939 | OSD osdMaterials = null; | ||
940 | |||
941 | lock (part.DynAttrs) | ||
942 | { | ||
943 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) | ||
944 | { | ||
945 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); | ||
946 | |||
947 | if (materialsStore == null) | ||
948 | return; | ||
949 | |||
950 | materialsStore.TryGetValue("Materials", out osdMaterials); | ||
951 | } | ||
952 | |||
953 | if (osdMaterials != null) | ||
954 | { | ||
955 | //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd)); | ||
956 | |||
957 | if (osdMaterials is OSDArray) | ||
958 | { | ||
959 | OSDArray matsArr = osdMaterials as OSDArray; | ||
960 | foreach (OSDMap matMap in matsArr) | ||
961 | { | ||
962 | try | ||
963 | { | ||
964 | if (matMap.ContainsKey("Material")) | ||
965 | { | ||
966 | OSDMap mat = matMap["Material"] as OSDMap; | ||
967 | if (mat.ContainsKey("NormMap")) | ||
968 | { | ||
969 | UUID normalMapId = mat["NormMap"].AsUUID(); | ||
970 | if (normalMapId != UUID.Zero) | ||
971 | { | ||
972 | m_gatheredAssetUuids[normalMapId] = (sbyte)AssetType.Texture; | ||
973 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); | ||
974 | } | ||
975 | } | ||
976 | if (mat.ContainsKey("SpecMap")) | ||
977 | { | ||
978 | UUID specularMapId = mat["SpecMap"].AsUUID(); | ||
979 | if (specularMapId != UUID.Zero) | ||
980 | { | ||
981 | m_gatheredAssetUuids[specularMapId] = (sbyte)AssetType.Texture; | ||
982 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); | ||
983 | } | ||
984 | } | ||
985 | } | ||
986 | |||
987 | } | ||
988 | catch (Exception e) | ||
989 | { | ||
990 | m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message); | ||
991 | } | ||
992 | } | ||
993 | } | ||
994 | } | ||
995 | } | ||
996 | } | ||
997 | |||
998 | /// <summary> | ||
999 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | ||
1000 | /// asynchronous callback is used, we will wait for it to complete. | ||
1001 | /// </summary> | ||
1002 | /// <param name="uuid"></param> | ||
1003 | /// <returns></returns> | ||
1004 | protected virtual AssetBase GetAsset(UUID uuid) | ||
1005 | { | ||
1006 | return m_assetService.Get(uuid.ToString()); | ||
1007 | } | ||
1008 | |||
1009 | /// <summary> | ||
1010 | /// Record the asset uuids embedded within the given text (e.g. a script). | ||
1011 | /// </summary> | ||
1012 | /// <param name="textAsset"></param> | ||
1013 | private void RecordTextEmbeddedAssetUuids(AssetBase textAsset) | ||
1014 | { | ||
1015 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | ||
1016 | |||
1017 | string script = Utils.BytesToString(textAsset.Data); | ||
1018 | // m_log.DebugFormat("[ARCHIVER]: Script {0}", script); | ||
1019 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(script); | ||
1020 | // m_log.DebugFormat("[ARCHIVER]: Found {0} matches in text", uuidMatches.Count); | ||
1021 | |||
1022 | foreach (Match uuidMatch in uuidMatches) | ||
1023 | { | ||
1024 | UUID uuid = new UUID(uuidMatch.Value); | ||
1025 | // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); | ||
1026 | |||
1027 | AddAssetUuidToInspect(uuid); | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | /// <summary> | ||
1032 | /// Record the uuids referenced by the given wearable asset | ||
1033 | /// </summary> | ||
1034 | /// <param name="assetBase"></param> | ||
1035 | private void RecordWearableAssetUuids(AssetBase assetBase) | ||
1036 | { | ||
1037 | //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); | ||
1038 | AssetWearable wearableAsset = new AssetBodypart(assetBase.FullID, assetBase.Data); | ||
1039 | wearableAsset.Decode(); | ||
1040 | |||
1041 | //m_log.DebugFormat( | ||
1042 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); | ||
1043 | |||
1044 | foreach (UUID uuid in wearableAsset.Textures.Values) | ||
1045 | m_gatheredAssetUuids[uuid] = (sbyte)AssetType.Texture; | ||
1046 | } | ||
1047 | |||
1048 | /// <summary> | ||
1049 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with | ||
1050 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
1051 | /// within this object). | ||
1052 | /// </summary> | ||
1053 | /// <param name="sceneObjectAsset"></param> | ||
1054 | private void RecordSceneObjectAssetUuids(AssetBase sceneObjectAsset) | ||
1055 | { | ||
1056 | string xml = Utils.BytesToString(sceneObjectAsset.Data); | ||
1057 | |||
1058 | CoalescedSceneObjects coa; | ||
1059 | if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) | ||
1060 | { | ||
1061 | foreach (SceneObjectGroup sog in coa.Objects) | ||
1062 | RecordAssetUuids(sog); | ||
1063 | } | ||
1064 | else | ||
1065 | { | ||
1066 | SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); | ||
1067 | |||
1068 | if (null != sog) | ||
1069 | RecordAssetUuids(sog); | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | /// <summary> | ||
1074 | /// Get the asset uuid associated with a gesture | ||
1075 | /// </summary> | ||
1076 | /// <param name="gestureAsset"></param> | ||
1077 | private void RecordGestureAssetUuids(AssetBase gestureAsset) | ||
1078 | { | ||
1079 | using (MemoryStream ms = new MemoryStream(gestureAsset.Data)) | ||
1080 | using (StreamReader sr = new StreamReader(ms)) | ||
1081 | { | ||
1082 | sr.ReadLine(); // Unknown (Version?) | ||
1083 | sr.ReadLine(); // Unknown | ||
1084 | sr.ReadLine(); // Unknown | ||
1085 | sr.ReadLine(); // Name | ||
1086 | sr.ReadLine(); // Comment ? | ||
1087 | int count = Convert.ToInt32(sr.ReadLine()); // Item count | ||
1088 | |||
1089 | for (int i = 0 ; i < count ; i++) | ||
1090 | { | ||
1091 | string type = sr.ReadLine(); | ||
1092 | if (type == null) | ||
1093 | break; | ||
1094 | string name = sr.ReadLine(); | ||
1095 | if (name == null) | ||
1096 | break; | ||
1097 | string id = sr.ReadLine(); | ||
1098 | if (id == null) | ||
1099 | break; | ||
1100 | string unknown = sr.ReadLine(); | ||
1101 | if (unknown == null) | ||
1102 | break; | ||
1103 | |||
1104 | // If it can be parsed as a UUID, it is an asset ID | ||
1105 | UUID uuid; | ||
1106 | if (UUID.TryParse(id, out uuid)) | ||
1107 | m_gatheredAssetUuids[uuid] = (sbyte)AssetType.Animation; // the asset is either an Animation or a Sound, but this distinction isn't important | ||
1108 | } | ||
1109 | } | ||
1110 | } | ||
1111 | |||
1112 | /// <summary> | ||
1113 | /// Get the asset uuid's referenced in a material. | ||
1114 | /// </summary> | ||
1115 | private void RecordMaterialAssetUuids(AssetBase materialAsset) | ||
1116 | { | ||
1117 | OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); | ||
1118 | |||
1119 | UUID normMap = mat["NormMap"].AsUUID(); | ||
1120 | if (normMap != UUID.Zero) | ||
1121 | m_gatheredAssetUuids[normMap] = (sbyte)AssetType.Texture; | ||
1122 | |||
1123 | UUID specMap = mat["SpecMap"].AsUUID(); | ||
1124 | if (specMap != UUID.Zero) | ||
1125 | m_gatheredAssetUuids[specMap] = (sbyte)AssetType.Texture; | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | public class IteratingHGUuidGatherer : IteratingUuidGatherer | ||
1130 | { | ||
1131 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
1132 | |||
1133 | protected string m_assetServerURL; | ||
1134 | |||
1135 | public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL) | ||
1136 | : base(assetService) | ||
1137 | { | ||
1138 | m_assetServerURL = assetServerURL; | ||
1139 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) | ||
1140 | m_assetServerURL = m_assetServerURL + "/"; | ||
1141 | } | ||
1142 | |||
1143 | protected override AssetBase GetAsset(UUID uuid) | ||
1144 | { | ||
1145 | if (string.Empty == m_assetServerURL) | ||
1146 | return base.GetAsset(uuid); | ||
1147 | else | ||
1148 | return FetchAsset(uuid); | ||
1149 | } | ||
1150 | |||
1151 | public AssetBase FetchAsset(UUID assetID) | ||
1152 | { | ||
634 | // Test if it's already here | 1153 | // Test if it's already here |
635 | AssetBase asset = m_assetService.Get(assetID.ToString()); | 1154 | AssetBase asset = m_assetService.Get(assetID.ToString()); |
636 | if (asset == null) | 1155 | if (asset == null) |