aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs607
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)