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