diff options
author | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
commit | 134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch) | |
tree | 216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |
parent | More changing to production grid. Double oops. (diff) | |
download | opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2 opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz |
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 604 |
1 files changed, 400 insertions, 204 deletions
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index e238d01..9ec4e1d 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |||
@@ -34,9 +34,11 @@ using System.Threading; | |||
34 | using log4net; | 34 | using log4net; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenMetaverse.Assets; | 36 | using OpenMetaverse.Assets; |
37 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
38 | using OpenSim.Region.Framework.Scenes.Serialization; | 39 | using OpenSim.Region.Framework.Scenes.Serialization; |
39 | using OpenSim.Services.Interfaces; | 40 | using OpenSim.Services.Interfaces; |
41 | using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType; | ||
40 | 42 | ||
41 | namespace OpenSim.Region.Framework.Scenes | 43 | namespace OpenSim.Region.Framework.Scenes |
42 | { | 44 | { |
@@ -53,75 +55,81 @@ namespace OpenSim.Region.Framework.Scenes | |||
53 | { | 55 | { |
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 56 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
55 | 57 | ||
58 | /// <summary> | ||
59 | /// Is gathering complete? | ||
60 | /// </summary> | ||
61 | public bool Complete { get { return m_assetUuidsToInspect.Count <= 0; } } | ||
62 | |||
63 | /// <summary> | ||
64 | /// The dictionary of UUIDs gathered so far. If Complete == true then this is all the reachable UUIDs. | ||
65 | /// </summary> | ||
66 | /// <value>The gathered uuids.</value> | ||
67 | public IDictionary<UUID, sbyte> GatheredUuids { get; private set; } | ||
68 | |||
69 | /// <summary> | ||
70 | /// Gets the next UUID to inspect. | ||
71 | /// </summary> | ||
72 | /// <value>If there is no next UUID then returns null</value> | ||
73 | public UUID? NextUuidToInspect | ||
74 | { | ||
75 | get | ||
76 | { | ||
77 | if (Complete) | ||
78 | return null; | ||
79 | else | ||
80 | return m_assetUuidsToInspect.Peek(); | ||
81 | } | ||
82 | } | ||
83 | |||
56 | protected IAssetService m_assetService; | 84 | protected IAssetService m_assetService; |
57 | 85 | ||
58 | // /// <summary> | 86 | protected Queue<UUID> m_assetUuidsToInspect; |
59 | // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate | 87 | |
60 | // /// asset was found by the asset service. | 88 | /// <summary> |
61 | // /// </summary> | 89 | /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. |
62 | // private AssetBase m_requestedObjectAsset; | 90 | /// </summary> |
63 | // | 91 | /// <remarks>In this case the collection of gathered assets will start out blank.</remarks> |
64 | // /// <summary> | 92 | /// <param name="assetService"> |
65 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. | 93 | /// Asset service. |
66 | // /// </summary> | 94 | /// </param> |
67 | // private bool m_waitingForObjectAsset; | 95 | public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>()) {} |
68 | 96 | ||
69 | public UuidGatherer(IAssetService assetService) | 97 | /// <summary> |
98 | /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. | ||
99 | /// </summary> | ||
100 | /// <param name="assetService"> | ||
101 | /// Asset service. | ||
102 | /// </param> | ||
103 | /// <param name="collector"> | ||
104 | /// Gathered UUIDs will be collected in this dictinaory. | ||
105 | /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. | ||
106 | /// </param> | ||
107 | public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) | ||
70 | { | 108 | { |
71 | m_assetService = assetService; | 109 | m_assetService = assetService; |
110 | GatheredUuids = collector; | ||
111 | |||
112 | // FIXME: Not efficient for searching, can improve. | ||
113 | m_assetUuidsToInspect = new Queue<UUID>(); | ||
72 | } | 114 | } |
73 | 115 | ||
74 | /// <summary> | 116 | /// <summary> |
75 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | 117 | /// Adds the asset uuid for inspection during the gathering process. |
76 | /// </summary> | 118 | /// </summary> |
77 | /// <remarks> | 119 | /// <returns><c>true</c>, if for inspection was added, <c>false</c> otherwise.</returns> |
78 | /// This includes both those directly associated with | 120 | /// <param name="uuid">UUID.</param> |
79 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | 121 | public bool AddForInspection(UUID uuid) |
80 | /// within this object). | ||
81 | /// </remarks> | ||
82 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> | ||
83 | /// <param name="assetType">The type of the asset for the uuid given</param> | ||
84 | /// <param name="assetUuids">The assets gathered</param> | ||
85 | public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) | ||
86 | { | 122 | { |
87 | // avoid infinite loops | 123 | if (m_assetUuidsToInspect.Contains(uuid)) |
88 | if (assetUuids.ContainsKey(assetUuid)) | 124 | return false; |
89 | return; | ||
90 | 125 | ||
91 | try | 126 | // m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); |
92 | { | 127 | |
93 | assetUuids[assetUuid] = assetType; | 128 | m_assetUuidsToInspect.Enqueue(uuid); |
94 | |||
95 | if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) | ||
96 | { | ||
97 | GetWearableAssetUuids(assetUuid, assetUuids); | ||
98 | } | ||
99 | else if (AssetType.Gesture == assetType) | ||
100 | { | ||
101 | GetGestureAssetUuids(assetUuid, assetUuids); | ||
102 | } | ||
103 | else if (AssetType.Notecard == assetType) | ||
104 | { | ||
105 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); | ||
106 | } | ||
107 | else if (AssetType.LSLText == assetType) | ||
108 | { | ||
109 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); | ||
110 | } | ||
111 | else if (AssetType.Object == assetType) | ||
112 | { | ||
113 | GetSceneObjectAssetUuids(assetUuid, assetUuids); | ||
114 | } | ||
115 | } | ||
116 | catch (Exception) | ||
117 | { | ||
118 | m_log.ErrorFormat( | ||
119 | "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", | ||
120 | assetUuid, assetType); | ||
121 | throw; | ||
122 | } | ||
123 | } | ||
124 | 129 | ||
130 | return true; | ||
131 | } | ||
132 | |||
125 | /// <summary> | 133 | /// <summary> |
126 | /// Gather all the asset uuids associated with a given object. | 134 | /// Gather all the asset uuids associated with a given object. |
127 | /// </summary> | 135 | /// </summary> |
@@ -131,19 +139,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
131 | /// within this object). | 139 | /// within this object). |
132 | /// </remarks> | 140 | /// </remarks> |
133 | /// <param name="sceneObject">The scene object for which to gather assets</param> | 141 | /// <param name="sceneObject">The scene object for which to gather assets</param> |
134 | /// <param name="assetUuids">The assets gathered</param> | 142 | public void AddForInspection(SceneObjectGroup sceneObject) |
135 | public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) | ||
136 | { | 143 | { |
137 | // m_log.DebugFormat( | 144 | // m_log.DebugFormat( |
138 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); | 145 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); |
139 | 146 | ||
140 | SceneObjectPart[] parts = sceneObject.Parts; | 147 | SceneObjectPart[] parts = sceneObject.Parts; |
141 | for (int i = 0; i < parts.Length; i++) | 148 | for (int i = 0; i < parts.Length; i++) |
142 | { | 149 | { |
143 | SceneObjectPart part = parts[i]; | 150 | SceneObjectPart part = parts[i]; |
144 | 151 | ||
145 | // m_log.DebugFormat( | 152 | // m_log.DebugFormat( |
146 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); | 153 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); |
147 | 154 | ||
148 | try | 155 | try |
149 | { | 156 | { |
@@ -152,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
152 | { | 159 | { |
153 | // Get the prim's default texture. This will be used for faces which don't have their own texture | 160 | // Get the prim's default texture. This will be used for faces which don't have their own texture |
154 | if (textureEntry.DefaultTexture != null) | 161 | if (textureEntry.DefaultTexture != null) |
155 | assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; | 162 | RecordTextureEntryAssetUuids(textureEntry.DefaultTexture); |
156 | 163 | ||
157 | if (textureEntry.FaceTextures != null) | 164 | if (textureEntry.FaceTextures != null) |
158 | { | 165 | { |
@@ -160,27 +167,59 @@ namespace OpenSim.Region.Framework.Scenes | |||
160 | foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) | 167 | foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) |
161 | { | 168 | { |
162 | if (texture != null) | 169 | if (texture != null) |
163 | assetUuids[texture.TextureID] = AssetType.Texture; | 170 | RecordTextureEntryAssetUuids(texture); |
164 | } | 171 | } |
165 | } | 172 | } |
166 | } | 173 | } |
167 | 174 | ||
168 | // If the prim is a sculpt then preserve this information too | 175 | // If the prim is a sculpt then preserve this information too |
169 | if (part.Shape.SculptTexture != UUID.Zero) | 176 | if (part.Shape.SculptTexture != UUID.Zero) |
170 | assetUuids[part.Shape.SculptTexture] = AssetType.Texture; | 177 | GatheredUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; |
171 | 178 | ||
179 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) | ||
180 | GatheredUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; | ||
181 | |||
182 | if (part.CollisionSound != UUID.Zero) | ||
183 | GatheredUuids[part.CollisionSound] = (sbyte)AssetType.Sound; | ||
184 | |||
185 | if (part.ParticleSystem.Length > 0) | ||
186 | { | ||
187 | try | ||
188 | { | ||
189 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); | ||
190 | if (ps.Texture != UUID.Zero) | ||
191 | GatheredUuids[ps.Texture] = (sbyte)AssetType.Texture; | ||
192 | } | ||
193 | catch (Exception) | ||
194 | { | ||
195 | m_log.WarnFormat( | ||
196 | "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", | ||
197 | part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); | ||
198 | } | ||
199 | } | ||
200 | |||
172 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); | 201 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); |
173 | 202 | ||
174 | // Now analyze this prim's inventory items to preserve all the uuids that they reference | 203 | // Now analyze this prim's inventory items to preserve all the uuids that they reference |
175 | foreach (TaskInventoryItem tii in taskDictionary.Values) | 204 | foreach (TaskInventoryItem tii in taskDictionary.Values) |
176 | { | 205 | { |
177 | // m_log.DebugFormat( | 206 | // m_log.DebugFormat( |
178 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", | 207 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", |
179 | // tii.Name, tii.Type, part.Name, part.UUID); | 208 | // tii.Name, tii.Type, part.Name, part.UUID); |
180 | 209 | ||
181 | if (!assetUuids.ContainsKey(tii.AssetID)) | 210 | if (!GatheredUuids.ContainsKey(tii.AssetID)) |
182 | GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); | 211 | AddForInspection(tii.AssetID, (sbyte)tii.Type); |
183 | } | 212 | } |
213 | |||
214 | // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed | ||
215 | // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and | ||
216 | // inventory transfer. There needs to be a way for a module to register a method without assuming a | ||
217 | // Scene.EventManager is present. | ||
218 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); | ||
219 | |||
220 | |||
221 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs | ||
222 | RecordMaterialsUuids(part); | ||
184 | } | 223 | } |
185 | catch (Exception e) | 224 | catch (Exception e) |
186 | { | 225 | { |
@@ -191,179 +230,334 @@ namespace OpenSim.Region.Framework.Scenes | |||
191 | } | 230 | } |
192 | } | 231 | } |
193 | } | 232 | } |
194 | |||
195 | // /// <summary> | ||
196 | // /// The callback made when we request the asset for an object from the asset service. | ||
197 | // /// </summary> | ||
198 | // private void AssetReceived(string id, Object sender, AssetBase asset) | ||
199 | // { | ||
200 | // lock (this) | ||
201 | // { | ||
202 | // m_requestedObjectAsset = asset; | ||
203 | // m_waitingForObjectAsset = false; | ||
204 | // Monitor.Pulse(this); | ||
205 | // } | ||
206 | // } | ||
207 | 233 | ||
208 | /// <summary> | 234 | /// <summary> |
209 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | 235 | /// Gathers the next set of assets returned by the next uuid to get from the asset service. |
210 | /// asynchronous callback is used, we will wait for it to complete. | ||
211 | /// </summary> | 236 | /// </summary> |
212 | /// <param name="uuid"></param> | 237 | /// <returns>false if gathering is already complete, true otherwise</returns> |
213 | /// <returns></returns> | 238 | public bool GatherNext() |
214 | protected virtual AssetBase GetAsset(UUID uuid) | ||
215 | { | 239 | { |
216 | return m_assetService.Get(uuid.ToString()); | 240 | if (Complete) |
241 | return false; | ||
242 | |||
243 | UUID nextToInspect = m_assetUuidsToInspect.Dequeue(); | ||
244 | |||
245 | // m_log.DebugFormat("[UUID GATHERER]: Inspecting asset {0}", nextToInspect); | ||
246 | |||
247 | GetAssetUuids(nextToInspect); | ||
217 | 248 | ||
218 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it | 249 | return true; |
219 | // to complete anyway! | ||
220 | // m_waitingForObjectAsset = true; | ||
221 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); | ||
222 | // | ||
223 | // // The asset cache callback can either | ||
224 | // // | ||
225 | // // 1. Complete on the same thread (if the asset is already in the cache) or | ||
226 | // // 2. Come in via a different thread (if we need to go fetch it). | ||
227 | // // | ||
228 | // // The code below handles both these alternatives. | ||
229 | // lock (this) | ||
230 | // { | ||
231 | // if (m_waitingForObjectAsset) | ||
232 | // { | ||
233 | // Monitor.Wait(this); | ||
234 | // m_waitingForObjectAsset = false; | ||
235 | // } | ||
236 | // } | ||
237 | // | ||
238 | // return m_requestedObjectAsset; | ||
239 | } | 250 | } |
240 | 251 | ||
241 | /// <summary> | 252 | /// <summary> |
242 | /// Record the asset uuids embedded within the given script. | 253 | /// Gathers all remaining asset UUIDS no matter how many calls are required to the asset service. |
243 | /// </summary> | 254 | /// </summary> |
244 | /// <param name="scriptUuid"></param> | 255 | /// <returns>false if gathering is already complete, true otherwise</returns> |
245 | /// <param name="assetUuids">Dictionary in which to record the references</param> | 256 | public bool GatherAll() |
246 | private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) | ||
247 | { | 257 | { |
248 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | 258 | if (Complete) |
259 | return false; | ||
249 | 260 | ||
250 | AssetBase embeddingAsset = GetAsset(embeddingAssetId); | 261 | while (GatherNext()); |
251 | 262 | ||
252 | if (null != embeddingAsset) | 263 | return true; |
253 | { | 264 | } |
254 | string script = Utils.BytesToString(embeddingAsset.Data); | ||
255 | // m_log.DebugFormat("[ARCHIVER]: Script {0}", script); | ||
256 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(script); | ||
257 | // m_log.DebugFormat("[ARCHIVER]: Found {0} matches in text", uuidMatches.Count); | ||
258 | 265 | ||
259 | foreach (Match uuidMatch in uuidMatches) | 266 | /// <summary> |
267 | /// Gather all the asset uuids associated with the asset referenced by a given uuid | ||
268 | /// </summary> | ||
269 | /// <remarks> | ||
270 | /// This includes both those directly associated with | ||
271 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | ||
272 | /// within this object). | ||
273 | /// This method assumes that the asset type associated with this asset in persistent storage is correct (which | ||
274 | /// should always be the case). So with this method we always need to retrieve asset data even if the asset | ||
275 | /// is of a type which is known not to reference any other assets | ||
276 | /// </remarks> | ||
277 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> | ||
278 | private void GetAssetUuids(UUID assetUuid) | ||
279 | { | ||
280 | // avoid infinite loops | ||
281 | if (GatheredUuids.ContainsKey(assetUuid)) | ||
282 | return; | ||
283 | |||
284 | try | ||
285 | { | ||
286 | AssetBase assetBase = GetAsset(assetUuid); | ||
287 | |||
288 | if (null != assetBase) | ||
260 | { | 289 | { |
261 | UUID uuid = new UUID(uuidMatch.Value); | 290 | sbyte assetType = assetBase.Type; |
262 | // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); | 291 | GatheredUuids[assetUuid] = assetType; |
292 | |||
293 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) | ||
294 | { | ||
295 | RecordWearableAssetUuids(assetBase); | ||
296 | } | ||
297 | else if ((sbyte)AssetType.Gesture == assetType) | ||
298 | { | ||
299 | RecordGestureAssetUuids(assetBase); | ||
300 | } | ||
301 | else if ((sbyte)AssetType.Notecard == assetType) | ||
302 | { | ||
303 | RecordTextEmbeddedAssetUuids(assetBase); | ||
304 | } | ||
305 | else if ((sbyte)AssetType.LSLText == assetType) | ||
306 | { | ||
307 | RecordTextEmbeddedAssetUuids(assetBase); | ||
308 | } | ||
309 | else if ((sbyte)OpenSimAssetType.Material == assetType) | ||
310 | { | ||
311 | RecordMaterialAssetUuids(assetBase); | ||
312 | } | ||
313 | else if ((sbyte)AssetType.Object == assetType) | ||
314 | { | ||
315 | RecordSceneObjectAssetUuids(assetBase); | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | catch (Exception) | ||
320 | { | ||
321 | m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); | ||
322 | throw; | ||
323 | } | ||
324 | } | ||
263 | 325 | ||
264 | // Assume AssetIDs embedded are textures. | 326 | private void AddForInspection(UUID assetUuid, sbyte assetType) |
265 | assetUuids[uuid] = AssetType.Texture; | 327 | { |
328 | // Here, we want to collect uuids which require further asset fetches but mark the others as gathered | ||
329 | try | ||
330 | { | ||
331 | if ((sbyte)AssetType.Bodypart == assetType | ||
332 | || (sbyte)AssetType.Clothing == assetType | ||
333 | || (sbyte)AssetType.Gesture == assetType | ||
334 | || (sbyte)AssetType.Notecard == assetType | ||
335 | || (sbyte)AssetType.LSLText == assetType | ||
336 | || (sbyte)OpenSimAssetType.Material == assetType | ||
337 | || (sbyte)AssetType.Object == assetType) | ||
338 | { | ||
339 | AddForInspection(assetUuid); | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | GatheredUuids[assetUuid] = assetType; | ||
266 | } | 344 | } |
267 | } | 345 | } |
346 | catch (Exception) | ||
347 | { | ||
348 | m_log.ErrorFormat( | ||
349 | "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", | ||
350 | assetUuid, assetType); | ||
351 | throw; | ||
352 | } | ||
268 | } | 353 | } |
269 | 354 | ||
270 | /// <summary> | 355 | /// <summary> |
271 | /// Record the uuids referenced by the given wearable asset | 356 | /// Collect all the asset uuids found in one face of a Texture Entry. |
272 | /// </summary> | 357 | /// </summary> |
273 | /// <param name="wearableAssetUuid"></param> | 358 | private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) |
274 | /// <param name="assetUuids">Dictionary in which to record the references</param> | ||
275 | private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) | ||
276 | { | 359 | { |
277 | AssetBase assetBase = GetAsset(wearableAssetUuid); | 360 | GatheredUuids[texture.TextureID] = (sbyte)AssetType.Texture; |
278 | 361 | ||
279 | if (null != assetBase) | 362 | if (texture.MaterialID != UUID.Zero) |
363 | AddForInspection(texture.MaterialID); | ||
364 | } | ||
365 | |||
366 | /// <summary> | ||
367 | /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps | ||
368 | /// stored in legacy format in part.DynAttrs | ||
369 | /// </summary> | ||
370 | /// <param name="part"></param> | ||
371 | private void RecordMaterialsUuids(SceneObjectPart part) | ||
372 | { | ||
373 | // scan thru the dynAttrs map of this part for any textures used as materials | ||
374 | OSD osdMaterials = null; | ||
375 | |||
376 | lock (part.DynAttrs) | ||
280 | { | 377 | { |
281 | //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); | 378 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) |
282 | AssetWearable wearableAsset = new AssetBodypart(wearableAssetUuid, assetBase.Data); | ||
283 | wearableAsset.Decode(); | ||
284 | |||
285 | //m_log.DebugFormat( | ||
286 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); | ||
287 | |||
288 | foreach (UUID uuid in wearableAsset.Textures.Values) | ||
289 | { | 379 | { |
290 | assetUuids[uuid] = AssetType.Texture; | 380 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); |
381 | |||
382 | if (materialsStore == null) | ||
383 | return; | ||
384 | |||
385 | materialsStore.TryGetValue("Materials", out osdMaterials); | ||
386 | } | ||
387 | |||
388 | if (osdMaterials != null) | ||
389 | { | ||
390 | //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd)); | ||
391 | |||
392 | if (osdMaterials is OSDArray) | ||
393 | { | ||
394 | OSDArray matsArr = osdMaterials as OSDArray; | ||
395 | foreach (OSDMap matMap in matsArr) | ||
396 | { | ||
397 | try | ||
398 | { | ||
399 | if (matMap.ContainsKey("Material")) | ||
400 | { | ||
401 | OSDMap mat = matMap["Material"] as OSDMap; | ||
402 | if (mat.ContainsKey("NormMap")) | ||
403 | { | ||
404 | UUID normalMapId = mat["NormMap"].AsUUID(); | ||
405 | if (normalMapId != UUID.Zero) | ||
406 | { | ||
407 | GatheredUuids[normalMapId] = (sbyte)AssetType.Texture; | ||
408 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); | ||
409 | } | ||
410 | } | ||
411 | if (mat.ContainsKey("SpecMap")) | ||
412 | { | ||
413 | UUID specularMapId = mat["SpecMap"].AsUUID(); | ||
414 | if (specularMapId != UUID.Zero) | ||
415 | { | ||
416 | GatheredUuids[specularMapId] = (sbyte)AssetType.Texture; | ||
417 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | } | ||
423 | catch (Exception e) | ||
424 | { | ||
425 | m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message); | ||
426 | } | ||
427 | } | ||
428 | } | ||
291 | } | 429 | } |
292 | } | 430 | } |
293 | } | 431 | } |
294 | 432 | ||
295 | /// <summary> | 433 | /// <summary> |
434 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | ||
435 | /// asynchronous callback is used, we will wait for it to complete. | ||
436 | /// </summary> | ||
437 | /// <param name="uuid"></param> | ||
438 | /// <returns></returns> | ||
439 | protected virtual AssetBase GetAsset(UUID uuid) | ||
440 | { | ||
441 | return m_assetService.Get(uuid.ToString()); | ||
442 | } | ||
443 | |||
444 | /// <summary> | ||
445 | /// Record the asset uuids embedded within the given text (e.g. a script). | ||
446 | /// </summary> | ||
447 | /// <param name="textAsset"></param> | ||
448 | private void RecordTextEmbeddedAssetUuids(AssetBase textAsset) | ||
449 | { | ||
450 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); | ||
451 | |||
452 | string text = Utils.BytesToString(textAsset.Data); | ||
453 | // m_log.DebugFormat("[UUID GATHERER]: Text {0}", text); | ||
454 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(text); | ||
455 | // m_log.DebugFormat("[UUID GATHERER]: Found {0} matches in text", uuidMatches.Count); | ||
456 | |||
457 | foreach (Match uuidMatch in uuidMatches) | ||
458 | { | ||
459 | UUID uuid = new UUID(uuidMatch.Value); | ||
460 | // m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid); | ||
461 | |||
462 | AddForInspection(uuid); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | /// <summary> | ||
467 | /// Record the uuids referenced by the given wearable asset | ||
468 | /// </summary> | ||
469 | /// <param name="assetBase"></param> | ||
470 | private void RecordWearableAssetUuids(AssetBase assetBase) | ||
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 | GatheredUuids[uuid] = (sbyte)AssetType.Texture; | ||
481 | } | ||
482 | |||
483 | /// <summary> | ||
296 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with | 484 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with |
297 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained | 485 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained |
298 | /// within this object). | 486 | /// within this object). |
299 | /// </summary> | 487 | /// </summary> |
300 | /// <param name="sceneObject"></param> | 488 | /// <param name="sceneObjectAsset"></param> |
301 | /// <param name="assetUuids"></param> | 489 | private void RecordSceneObjectAssetUuids(AssetBase sceneObjectAsset) |
302 | private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) | ||
303 | { | 490 | { |
304 | AssetBase objectAsset = GetAsset(sceneObjectUuid); | 491 | string xml = Utils.BytesToString(sceneObjectAsset.Data); |
305 | 492 | ||
306 | if (null != objectAsset) | 493 | CoalescedSceneObjects coa; |
494 | if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) | ||
307 | { | 495 | { |
308 | string xml = Utils.BytesToString(objectAsset.Data); | 496 | foreach (SceneObjectGroup sog in coa.Objects) |
309 | 497 | AddForInspection(sog); | |
310 | CoalescedSceneObjects coa; | 498 | } |
311 | if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) | 499 | else |
312 | { | 500 | { |
313 | foreach (SceneObjectGroup sog in coa.Objects) | 501 | SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); |
314 | GatherAssetUuids(sog, assetUuids); | 502 | |
315 | } | 503 | if (null != sog) |
316 | else | 504 | AddForInspection(sog); |
505 | } | ||
506 | } | ||
507 | |||
508 | /// <summary> | ||
509 | /// Get the asset uuid associated with a gesture | ||
510 | /// </summary> | ||
511 | /// <param name="gestureAsset"></param> | ||
512 | private void RecordGestureAssetUuids(AssetBase gestureAsset) | ||
513 | { | ||
514 | using (MemoryStream ms = new MemoryStream(gestureAsset.Data)) | ||
515 | using (StreamReader sr = new StreamReader(ms)) | ||
516 | { | ||
517 | sr.ReadLine(); // Unknown (Version?) | ||
518 | sr.ReadLine(); // Unknown | ||
519 | sr.ReadLine(); // Unknown | ||
520 | sr.ReadLine(); // Name | ||
521 | sr.ReadLine(); // Comment ? | ||
522 | int count = Convert.ToInt32(sr.ReadLine()); // Item count | ||
523 | |||
524 | for (int i = 0 ; i < count ; i++) | ||
317 | { | 525 | { |
318 | SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); | 526 | string type = sr.ReadLine(); |
319 | 527 | if (type == null) | |
320 | if (null != sog) | 528 | break; |
321 | GatherAssetUuids(sog, assetUuids); | 529 | string name = sr.ReadLine(); |
530 | if (name == null) | ||
531 | break; | ||
532 | string id = sr.ReadLine(); | ||
533 | if (id == null) | ||
534 | break; | ||
535 | string unknown = sr.ReadLine(); | ||
536 | if (unknown == null) | ||
537 | break; | ||
538 | |||
539 | // If it can be parsed as a UUID, it is an asset ID | ||
540 | UUID uuid; | ||
541 | if (UUID.TryParse(id, out uuid)) | ||
542 | GatheredUuids[uuid] = (sbyte)AssetType.Animation; // the asset is either an Animation or a Sound, but this distinction isn't important | ||
322 | } | 543 | } |
323 | } | 544 | } |
324 | } | 545 | } |
325 | 546 | ||
326 | /// <summary> | 547 | /// <summary> |
327 | /// Get the asset uuid associated with a gesture | 548 | /// Get the asset uuid's referenced in a material. |
328 | /// </summary> | 549 | /// </summary> |
329 | /// <param name="gestureUuid"></param> | 550 | private void RecordMaterialAssetUuids(AssetBase materialAsset) |
330 | /// <param name="assetUuids"></param> | ||
331 | private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) | ||
332 | { | 551 | { |
333 | AssetBase assetBase = GetAsset(gestureUuid); | 552 | OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); |
334 | if (null == assetBase) | ||
335 | return; | ||
336 | |||
337 | MemoryStream ms = new MemoryStream(assetBase.Data); | ||
338 | StreamReader sr = new StreamReader(ms); | ||
339 | 553 | ||
340 | sr.ReadLine(); // Unknown (Version?) | 554 | UUID normMap = mat["NormMap"].AsUUID(); |
341 | sr.ReadLine(); // Unknown | 555 | if (normMap != UUID.Zero) |
342 | sr.ReadLine(); // Unknown | 556 | GatheredUuids[normMap] = (sbyte)AssetType.Texture; |
343 | sr.ReadLine(); // Name | ||
344 | sr.ReadLine(); // Comment ? | ||
345 | int count = Convert.ToInt32(sr.ReadLine()); // Item count | ||
346 | 557 | ||
347 | for (int i = 0 ; i < count ; i++) | 558 | UUID specMap = mat["SpecMap"].AsUUID(); |
348 | { | 559 | if (specMap != UUID.Zero) |
349 | string type = sr.ReadLine(); | 560 | GatheredUuids[specMap] = (sbyte)AssetType.Texture; |
350 | if (type == null) | ||
351 | break; | ||
352 | string name = sr.ReadLine(); | ||
353 | if (name == null) | ||
354 | break; | ||
355 | string id = sr.ReadLine(); | ||
356 | if (id == null) | ||
357 | break; | ||
358 | string unknown = sr.ReadLine(); | ||
359 | if (unknown == null) | ||
360 | break; | ||
361 | |||
362 | // If it can be parsed as a UUID, it is an asset ID | ||
363 | UUID uuid; | ||
364 | if (UUID.TryParse(id, out uuid)) | ||
365 | assetUuids[uuid] = AssetType.Animation; | ||
366 | } | ||
367 | } | 561 | } |
368 | } | 562 | } |
369 | 563 | ||
@@ -374,7 +568,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
374 | protected string m_assetServerURL; | 568 | protected string m_assetServerURL; |
375 | 569 | ||
376 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) | 570 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) |
377 | : base(assetService) | 571 | : this(assetService, assetServerURL, new Dictionary<UUID, sbyte>()) {} |
572 | |||
573 | public HGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary<UUID, sbyte> collector) | ||
574 | : base(assetService, collector) | ||
378 | { | 575 | { |
379 | m_assetServerURL = assetServerURL; | 576 | m_assetServerURL = assetServerURL; |
380 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) | 577 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) |
@@ -391,7 +588,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
391 | 588 | ||
392 | public AssetBase FetchAsset(UUID assetID) | 589 | public AssetBase FetchAsset(UUID assetID) |
393 | { | 590 | { |
394 | |||
395 | // Test if it's already here | 591 | // Test if it's already here |
396 | AssetBase asset = m_assetService.Get(assetID.ToString()); | 592 | AssetBase asset = m_assetService.Get(assetID.ToString()); |
397 | if (asset == null) | 593 | if (asset == null) |