aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-11-05 19:36:53 +0000
committerJustin Clark-Casey (justincc)2014-11-25 23:23:11 +0000
commit06a5d6e9ef163abaadbf81c98b54c042751fae89 (patch)
tree535d0f508e2844326cacefb3f40db670fd11f5b7 /OpenSim/Region
parentAdd incoming packet async handling engine to queue some inbound udp async req... (diff)
downloadopensim-SC_OLD-06a5d6e9ef163abaadbf81c98b54c042751fae89.zip
opensim-SC_OLD-06a5d6e9ef163abaadbf81c98b54c042751fae89.tar.gz
opensim-SC_OLD-06a5d6e9ef163abaadbf81c98b54c042751fae89.tar.bz2
opensim-SC_OLD-06a5d6e9ef163abaadbf81c98b54c042751fae89.tar.xz
Introduce an IteratingUuidGatherer where each fetch from the asset service (iteration) can be controlled by the caller.
This is to enable an imminent change where incoming HG scene object fetching can assess the time taken by each request rather than being forced to perform all requests in one call. Soon, this will replace the existing UuidGatherer since it is both simpler and more flexible.
Diffstat (limited to 'OpenSim/Region')
-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)