diff options
-rw-r--r-- | OpenSim/Framework/Communications/Cache/AssetCache.cs | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs index d04708d..3bd8f5b 100644 --- a/OpenSim/Framework/Communications/Cache/AssetCache.cs +++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs | |||
@@ -53,29 +53,30 @@ namespace OpenSim.Framework.Communications.Cache | |||
53 | /// </summary> | 53 | /// </summary> |
54 | public class AssetCache : IAssetReceiver | 54 | public class AssetCache : IAssetReceiver |
55 | { | 55 | { |
56 | private static readonly log4net.ILog m_log | 56 | private static readonly log4net.ILog m_log |
57 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 57 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
58 | 58 | ||
59 | /// <summary> | 59 | /// <summary> |
60 | /// The cache of assets. This does not include textures. | 60 | /// The cache of assets. This does not include textures. |
61 | /// </summary> | 61 | /// </summary> |
62 | private Dictionary<LLUUID, AssetInfo> Assets; | 62 | private Dictionary<LLUUID, AssetInfo> Assets; |
63 | 63 | ||
64 | /// <summary> | 64 | /// <summary> |
65 | /// The cache of textures. | 65 | /// The cache of textures. |
66 | /// </summary> | 66 | /// </summary> |
67 | private Dictionary<LLUUID, TextureImage> Textures; | 67 | private Dictionary<LLUUID, TextureImage> Textures; |
68 | 68 | ||
69 | /// <summary> | 69 | /// |
70 | /// Assets requests which are waiting for asset server data. This includes texture requests | 70 | /// Assets requests which are waiting for asset server data. This includes texture requests |
71 | /// </summary> | 71 | /// </summary> |
72 | private Dictionary<LLUUID, AssetRequest> RequestedAssets; | 72 | private Dictionary<LLUUID, AssetRequest> RequestedAssets; |
73 | 73 | ||
74 | /// <summary> | 74 | /// <summary> |
75 | /// Asset requests with data which are ready to be sent back to requesters. This includes textures. | 75 | /// Asset requests with data which are ready to be sent back to requesters. This includes textures. |
76 | /// </summary> | 76 | /// </summary> |
77 | private List<AssetRequest> AssetRequests; | 77 | private List<AssetRequest> AssetRequests; |
78 | 78 | ||
79 | |||
79 | /// <summary> | 80 | /// <summary> |
80 | /// Until the asset request is fulfilled, each asset request is associated with a list of requesters | 81 | /// Until the asset request is fulfilled, each asset request is associated with a list of requesters |
81 | /// </summary> | 82 | /// </summary> |
@@ -150,7 +151,7 @@ namespace OpenSim.Framework.Communications.Cache | |||
150 | Assets = new Dictionary<LLUUID, AssetInfo>(); | 151 | Assets = new Dictionary<LLUUID, AssetInfo>(); |
151 | Textures = new Dictionary<LLUUID, TextureImage>(); | 152 | Textures = new Dictionary<LLUUID, TextureImage>(); |
152 | AssetRequests = new List<AssetRequest>(); | 153 | AssetRequests = new List<AssetRequest>(); |
153 | 154 | ||
154 | RequestedAssets = new Dictionary<LLUUID, AssetRequest>(); | 155 | RequestedAssets = new Dictionary<LLUUID, AssetRequest>(); |
155 | RequestLists = new Dictionary<LLUUID, AssetRequestsList>(); | 156 | RequestLists = new Dictionary<LLUUID, AssetRequestsList>(); |
156 | } | 157 | } |
@@ -242,10 +243,10 @@ namespace OpenSim.Framework.Communications.Cache | |||
242 | /// If the asset was not found this is still called with the asset UUID but with a null asset data reference</param> | 243 | /// If the asset was not found this is still called with the asset UUID but with a null asset data reference</param> |
243 | public void GetAsset(LLUUID assetId, AssetRequestCallback callback, bool isTexture) | 244 | public void GetAsset(LLUUID assetId, AssetRequestCallback callback, bool isTexture) |
244 | { | 245 | { |
245 | #if DEBUG | 246 | #if DEBUG |
246 | //m_log.DebugFormat("[ASSET CACHE]: Requesting {0} {1}", isTexture ? "texture" : "asset", assetId); | 247 | //m_log.DebugFormat("[ASSET CACHE]: Requesting {0} {1}", isTexture ? "texture" : "asset", assetId); |
247 | #endif | 248 | #endif |
248 | 249 | ||
249 | AssetBase asset; | 250 | AssetBase asset; |
250 | 251 | ||
251 | if (TryGetCachedAsset(assetId, out asset)) | 252 | if (TryGetCachedAsset(assetId, out asset)) |
@@ -253,11 +254,11 @@ namespace OpenSim.Framework.Communications.Cache | |||
253 | callback(assetId, asset); | 254 | callback(assetId, asset); |
254 | } | 255 | } |
255 | else | 256 | else |
256 | { | 257 | { |
257 | #if DEBUG | 258 | #if DEBUG |
258 | //m_log.DebugFormat("[ASSET CACHE]: Adding request for {0} {1}", isTexture ? "texture" : "asset", assetId); | 259 | //m_log.DebugFormat("[ASSET CACHE]: Adding request for {0} {1}", isTexture ? "texture" : "asset", assetId); |
259 | #endif | 260 | #endif |
260 | 261 | ||
261 | NewAssetRequest req = new NewAssetRequest(assetId, callback); | 262 | NewAssetRequest req = new NewAssetRequest(assetId, callback); |
262 | 263 | ||
263 | // Make sure we always have a request list to which to add the asset | 264 | // Make sure we always have a request list to which to add the asset |
@@ -277,7 +278,7 @@ namespace OpenSim.Framework.Communications.Cache | |||
277 | requestList.Requests.Add(req); | 278 | requestList.Requests.Add(req); |
278 | 279 | ||
279 | m_assetServer.RequestAsset(assetId, isTexture); | 280 | m_assetServer.RequestAsset(assetId, isTexture); |
280 | } | 281 | } |
281 | } | 282 | } |
282 | 283 | ||
283 | /// <summary> | 284 | /// <summary> |
@@ -322,7 +323,7 @@ namespace OpenSim.Framework.Communications.Cache | |||
322 | } | 323 | } |
323 | } while (--maxPolls > 0); | 324 | } while (--maxPolls > 0); |
324 | 325 | ||
325 | m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached", | 326 | m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached", |
326 | isTexture ? "texture" : "asset", assetID.ToString()); | 327 | isTexture ? "texture" : "asset", assetID.ToString()); |
327 | 328 | ||
328 | return null; | 329 | return null; |
@@ -390,17 +391,17 @@ namespace OpenSim.Framework.Communications.Cache | |||
390 | } | 391 | } |
391 | } | 392 | } |
392 | } | 393 | } |
393 | #if DEBUG | 394 | #if DEBUG |
394 | //m_log.DebugFormat("[ASSET CACHE]: Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result); | 395 | //m_log.DebugFormat("[ASSET CACHE]: Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result); |
395 | #endif | 396 | #endif |
396 | } | 397 | } |
397 | 398 | ||
398 | // See IAssetReceiver | 399 | // See IAssetReceiver |
399 | public void AssetReceived(AssetBase asset, bool IsTexture) | 400 | public void AssetReceived(AssetBase asset, bool IsTexture) |
400 | { | 401 | { |
401 | #if DEBUG | 402 | #if DEBUG |
402 | //m_log.DebugFormat("[ASSET CACHE]: Received {0} [{1}]", IsTexture ? "texture" : "asset", asset.FullID); | 403 | //m_log.DebugFormat("[ASSET CACHE]: Received {0} [{1}]", IsTexture ? "texture" : "asset", asset.FullID); |
403 | #endif | 404 | #endif |
404 | 405 | ||
405 | if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server | 406 | if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server |
406 | { | 407 | { |
@@ -414,9 +415,9 @@ namespace OpenSim.Framework.Communications.Cache | |||
414 | TextureImage image = new TextureImage(asset); | 415 | TextureImage image = new TextureImage(asset); |
415 | if (Textures.ContainsKey(image.FullID)) | 416 | if (Textures.ContainsKey(image.FullID)) |
416 | { | 417 | { |
417 | #if DEBUG | 418 | #if DEBUG |
418 | //m_log.DebugFormat("[ASSET CACHE]: There's already an texture {0} in memory. Skipping.", asset.FullID); | 419 | //m_log.DebugFormat("[ASSET CACHE]: There's already an texture {0} in memory. Skipping.", asset.FullID); |
419 | #endif | 420 | #endif |
420 | } | 421 | } |
421 | else | 422 | else |
422 | { | 423 | { |
@@ -433,9 +434,9 @@ namespace OpenSim.Framework.Communications.Cache | |||
433 | AssetInfo assetInf = new AssetInfo(asset); | 434 | AssetInfo assetInf = new AssetInfo(asset); |
434 | if (Assets.ContainsKey(assetInf.FullID)) | 435 | if (Assets.ContainsKey(assetInf.FullID)) |
435 | { | 436 | { |
436 | #if DEBUG | 437 | #if DEBUG |
437 | //m_log.DebugFormat("[ASSET CACHE]: There's already an asset {0} in memory. Skipping.", asset.FullID); | 438 | //m_log.DebugFormat("[ASSET CACHE]: There's already an asset {0} in memory. Skipping.", asset.FullID); |
438 | #endif | 439 | #endif |
439 | } | 440 | } |
440 | else | 441 | else |
441 | { | 442 | { |
@@ -448,9 +449,9 @@ namespace OpenSim.Framework.Communications.Cache | |||
448 | 449 | ||
449 | if (RequestedAssets.ContainsKey(assetInf.FullID)) | 450 | if (RequestedAssets.ContainsKey(assetInf.FullID)) |
450 | { | 451 | { |
451 | #if DEBUG | 452 | #if DEBUG |
452 | //m_log.DebugFormat("[ASSET CACHE]: Moving {0} from RequestedAssets to AssetRequests", asset.FullID); | 453 | //m_log.DebugFormat("[ASSET CACHE]: Moving {0} from RequestedAssets to AssetRequests", asset.FullID); |
453 | #endif | 454 | #endif |
454 | 455 | ||
455 | AssetRequest req = RequestedAssets[assetInf.FullID]; | 456 | AssetRequest req = RequestedAssets[assetInf.FullID]; |
456 | req.AssetInf = assetInf; | 457 | req.AssetInf = assetInf; |
@@ -464,17 +465,34 @@ namespace OpenSim.Framework.Communications.Cache | |||
464 | 465 | ||
465 | // Notify requesters for this asset | 466 | // Notify requesters for this asset |
466 | if (RequestLists.ContainsKey(asset.FullID)) | 467 | if (RequestLists.ContainsKey(asset.FullID)) |
467 | { | 468 | { |
469 | AssetRequestsList reqList = null; | ||
468 | lock (RequestLists) | 470 | lock (RequestLists) |
469 | { | 471 | { |
470 | AssetRequestsList reqList = RequestLists[asset.FullID]; | 472 | reqList = RequestLists[asset.FullID]; |
471 | foreach (NewAssetRequest req in reqList.Requests) | 473 | |
474 | } | ||
475 | if (reqList != null) | ||
476 | { | ||
477 | //making a copy of the list is not ideal | ||
478 | //but the old method of locking around this whole block of code was causing a multi-thread lock | ||
479 | //between this and the TextureDownloadModule | ||
480 | //while the localAsset thread running this and trying to send a texture to the callback in the | ||
481 | //texturedownloadmodule , and hitting a lock in there. While the texturedownload thread (which was holding | ||
482 | // the lock in the texturedownload module) was trying to | ||
483 | //request a new asset and hitting a lock in here on the RequestLists. | ||
484 | List<NewAssetRequest> theseRequests = new List<NewAssetRequest>(reqList.Requests); | ||
485 | reqList.Requests.Clear(); | ||
486 | |||
487 | lock (RequestLists) | ||
472 | { | 488 | { |
473 | req.Callback(asset.FullID, asset); | 489 | RequestLists.Remove(asset.FullID); |
474 | } | 490 | } |
475 | 491 | ||
476 | RequestLists.Remove(asset.FullID); | 492 | foreach (NewAssetRequest req in theseRequests) |
477 | reqList.Requests.Clear(); | 493 | { |
494 | req.Callback(asset.FullID, asset); | ||
495 | } | ||
478 | } | 496 | } |
479 | } | 497 | } |
480 | } | 498 | } |
@@ -484,7 +502,7 @@ namespace OpenSim.Framework.Communications.Cache | |||
484 | public void AssetNotFound(LLUUID assetID) | 502 | public void AssetNotFound(LLUUID assetID) |
485 | { | 503 | { |
486 | m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); | 504 | m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); |
487 | 505 | ||
488 | // Notify requesters for this asset | 506 | // Notify requesters for this asset |
489 | lock (RequestLists) | 507 | lock (RequestLists) |
490 | { | 508 | { |
@@ -495,10 +513,10 @@ namespace OpenSim.Framework.Communications.Cache | |||
495 | { | 513 | { |
496 | req.Callback(assetID, null); | 514 | req.Callback(assetID, null); |
497 | } | 515 | } |
498 | 516 | ||
499 | RequestLists.Remove(assetID); | 517 | RequestLists.Remove(assetID); |
500 | } | 518 | } |
501 | } | 519 | } |
502 | } | 520 | } |
503 | 521 | ||
504 | /// <summary> | 522 | /// <summary> |