diff options
Hopefully fixed the bug that was causing a lot of the freezing. Which was happening due to locks in the AssetCache and Texturedownload module. Where the thread from the Asset thread would be take a lock on a list in the asset cache and then try to call the Callback into the texturedownload module and hit a lock in there which was held by a ClientView thread- which at the same time would be trying to request another texture from the cache and be hitting the lock in there held by the IClientAPI. The result each thread waiting for the other one to release a lock. And as one of those was the ClientView process packet thread. No more packets from that client could be processed. For now I've made a copy of the list in AssetCache so that it can release the lock. I'm doing more work on assets (moving the client asset downloading to a module ), so will hopefully change this into a better method once I've cleaned over things up a bit.
Diffstat (limited to 'OpenSim/Framework/Communications/Cache/AssetCache.cs')
-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> |