diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs
index d04708dc0f..3bd8f5b58b 100644
--- a/OpenSim/Framework/Communications/Cache/AssetCache.cs
+++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs
@@ -53,29 +53,30 @@ namespace OpenSim.Framework.Communications.Cache
///
public class AssetCache : IAssetReceiver
{
- private static readonly log4net.ILog m_log
+ private static readonly log4net.ILog m_log
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
///
/// The cache of assets. This does not include textures.
///
private Dictionary Assets;
-
+
///
/// The cache of textures.
///
private Dictionary Textures;
- ///
+ ///
/// Assets requests which are waiting for asset server data. This includes texture requests
///
private Dictionary RequestedAssets;
-
+
///
/// Asset requests with data which are ready to be sent back to requesters. This includes textures.
///
private List AssetRequests;
+
///
/// Until the asset request is fulfilled, each asset request is associated with a list of requesters
///
@@ -150,7 +151,7 @@ namespace OpenSim.Framework.Communications.Cache
Assets = new Dictionary();
Textures = new Dictionary();
AssetRequests = new List();
-
+
RequestedAssets = new Dictionary();
RequestLists = new Dictionary();
}
@@ -242,10 +243,10 @@ namespace OpenSim.Framework.Communications.Cache
/// If the asset was not found this is still called with the asset UUID but with a null asset data reference
public void GetAsset(LLUUID assetId, AssetRequestCallback callback, bool isTexture)
{
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Requesting {0} {1}", isTexture ? "texture" : "asset", assetId);
- #endif
-
+#endif
+
AssetBase asset;
if (TryGetCachedAsset(assetId, out asset))
@@ -253,11 +254,11 @@ namespace OpenSim.Framework.Communications.Cache
callback(assetId, asset);
}
else
- {
- #if DEBUG
+ {
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Adding request for {0} {1}", isTexture ? "texture" : "asset", assetId);
- #endif
-
+#endif
+
NewAssetRequest req = new NewAssetRequest(assetId, callback);
// Make sure we always have a request list to which to add the asset
@@ -277,7 +278,7 @@ namespace OpenSim.Framework.Communications.Cache
requestList.Requests.Add(req);
m_assetServer.RequestAsset(assetId, isTexture);
- }
+ }
}
///
@@ -322,7 +323,7 @@ namespace OpenSim.Framework.Communications.Cache
}
} while (--maxPolls > 0);
- m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached",
+ m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached",
isTexture ? "texture" : "asset", assetID.ToString());
return null;
@@ -390,17 +391,17 @@ namespace OpenSim.Framework.Communications.Cache
}
}
}
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result);
- #endif
+#endif
}
// See IAssetReceiver
public void AssetReceived(AssetBase asset, bool IsTexture)
{
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Received {0} [{1}]", IsTexture ? "texture" : "asset", asset.FullID);
- #endif
+#endif
if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server
{
@@ -414,9 +415,9 @@ namespace OpenSim.Framework.Communications.Cache
TextureImage image = new TextureImage(asset);
if (Textures.ContainsKey(image.FullID))
{
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: There's already an texture {0} in memory. Skipping.", asset.FullID);
- #endif
+#endif
}
else
{
@@ -433,9 +434,9 @@ namespace OpenSim.Framework.Communications.Cache
AssetInfo assetInf = new AssetInfo(asset);
if (Assets.ContainsKey(assetInf.FullID))
{
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: There's already an asset {0} in memory. Skipping.", asset.FullID);
- #endif
+#endif
}
else
{
@@ -448,9 +449,9 @@ namespace OpenSim.Framework.Communications.Cache
if (RequestedAssets.ContainsKey(assetInf.FullID))
{
- #if DEBUG
+#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Moving {0} from RequestedAssets to AssetRequests", asset.FullID);
- #endif
+#endif
AssetRequest req = RequestedAssets[assetInf.FullID];
req.AssetInf = assetInf;
@@ -464,17 +465,34 @@ namespace OpenSim.Framework.Communications.Cache
// Notify requesters for this asset
if (RequestLists.ContainsKey(asset.FullID))
- {
+ {
+ AssetRequestsList reqList = null;
lock (RequestLists)
{
- AssetRequestsList reqList = RequestLists[asset.FullID];
- foreach (NewAssetRequest req in reqList.Requests)
+ reqList = RequestLists[asset.FullID];
+
+ }
+ if (reqList != null)
+ {
+ //making a copy of the list is not ideal
+ //but the old method of locking around this whole block of code was causing a multi-thread lock
+ //between this and the TextureDownloadModule
+ //while the localAsset thread running this and trying to send a texture to the callback in the
+ //texturedownloadmodule , and hitting a lock in there. While the texturedownload thread (which was holding
+ // the lock in the texturedownload module) was trying to
+ //request a new asset and hitting a lock in here on the RequestLists.
+ List theseRequests = new List(reqList.Requests);
+ reqList.Requests.Clear();
+
+ lock (RequestLists)
+ {
+ RequestLists.Remove(asset.FullID);
+ }
+
+ foreach (NewAssetRequest req in theseRequests)
{
req.Callback(asset.FullID, asset);
}
-
- RequestLists.Remove(asset.FullID);
- reqList.Requests.Clear();
}
}
}
@@ -484,7 +502,7 @@ namespace OpenSim.Framework.Communications.Cache
public void AssetNotFound(LLUUID assetID)
{
m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID);
-
+
// Notify requesters for this asset
lock (RequestLists)
{
@@ -495,10 +513,10 @@ namespace OpenSim.Framework.Communications.Cache
{
req.Callback(assetID, null);
}
-
+
RequestLists.Remove(assetID);
}
- }
+ }
}
///