* Eliminate the need to copy asset request lists in the asset cache when an asset is received or missing

* Also eliminates a race condition
0.6.0-stable
Justin Clarke Casey 2008-09-21 18:53:58 +00:00
parent 52f0c8d15d
commit 70e8097e31
1 changed files with 22 additions and 82 deletions

View File

@ -46,7 +46,7 @@ namespace OpenSim.Framework.Communications.Cache
/// sends packetised data directly back to the client. The only point where they meet is AssetReceived() and /// sends packetised data directly back to the client. The only point where they meet is AssetReceived() and
/// AssetNotFound(), which means they do share the same asset and texture caches. /// AssetNotFound(), which means they do share the same asset and texture caches.
/// ///
/// TODO Assets in this cache are effectively immortal (they are never disposed off through old age). /// TODO: Assets in this cache are effectively immortal (they are never disposed of through old age).
/// This is not a huge problem at the moment since other memory use usually dwarfs that used by assets /// This is not a huge problem at the moment since other memory use usually dwarfs that used by assets
/// but it's something to bear in mind. /// but it's something to bear in mind.
/// </summary> /// </summary>
@ -206,24 +206,9 @@ namespace OpenSim.Framework.Communications.Cache
/// <summary> /// <summary>
/// Only get an asset if we already have it in the cache. /// Only get an asset if we already have it in the cache.
/// </summary> /// </summary>
/// <param name="assetId"></param></param> /// <param name="assetId"></param>
/// <returns></returns> /// <param name="asset"></param>
//private AssetBase GetCachedAsset(UUID assetId) /// <returns>true if the asset was in the cache, false if it was not</returns>
//{
// AssetBase asset = null;
// if (Textures.ContainsKey(assetId))
// {
// asset = Textures[assetId];
// }
// else if (Assets.ContainsKey(assetId))
// {
// asset = Assets[assetId];
// }
// return asset;
//}
private bool TryGetCachedAsset(UUID assetId, out AssetBase asset) private bool TryGetCachedAsset(UUID assetId, out AssetBase asset)
{ {
if (Textures.ContainsKey(assetId)) if (Textures.ContainsKey(assetId))
@ -451,42 +436,21 @@ namespace OpenSim.Framework.Communications.Cache
} }
// Notify requesters for this asset // Notify requesters for this asset
if (RequestLists.ContainsKey(asset.FullID)) AssetRequestsList reqList = null;
lock (RequestLists)
{
if (RequestLists.TryGetValue(asset.FullID, out reqList))
RequestLists.Remove(asset.FullID);
}
if (reqList != null)
{ {
AssetRequestsList reqList = null; foreach (NewAssetRequest req in reqList.Requests)
lock (RequestLists)
{ {
//m_log.Info("AssetCache: Lock taken on requestLists (AssetReceived #1)"); // Xantor 20080526 are we really calling all the callbacks if multiple queued for 1 request? -- Yes, checked
reqList = RequestLists[asset.FullID]; // m_log.DebugFormat("[ASSET CACHE]: Callback for asset {0}", asset.FullID);
req.Callback(asset.FullID, asset);
}
//m_log.Info("AssetCache: Lock released on requestLists (AssetReceived #1)");
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<NewAssetRequest> theseRequests = new List<NewAssetRequest>(reqList.Requests);
reqList.Requests.Clear();
lock (RequestLists)
{
// m_log.Info("AssetCache: Lock taken on requestLists (AssetReceived #2)");
RequestLists.Remove(asset.FullID);
}
//m_log.Info("AssetCache: Lock released on requestLists (AssetReceived #2)");
foreach (NewAssetRequest req in theseRequests)
{
// Xantor 20080526 are we really calling all the callbacks if multiple queued for 1 request? -- Yes, checked
// m_log.DebugFormat("[ASSET CACHE]: Callback for asset {0}", asset.FullID);
req.Callback(asset.FullID, asset);
}
} }
} }
} }
@ -509,27 +473,13 @@ namespace OpenSim.Framework.Communications.Cache
AssetRequestsList reqList = null; AssetRequestsList reqList = null;
lock (RequestLists) lock (RequestLists)
{ {
// m_log.Info("AssetCache: Lock taken on requestLists (AssetNotFound #1)"); if (RequestLists.TryGetValue(assetID, out reqList))
if (RequestLists.ContainsKey(assetID)) RequestLists.Remove(assetID);
{
reqList = RequestLists[assetID];
}
} }
// m_log.Info("AssetCache: Lock released on requestLists (AssetNotFound #1)");
if (reqList != null) if (reqList != null)
{ {
List<NewAssetRequest> theseRequests = new List<NewAssetRequest>(reqList.Requests); foreach (NewAssetRequest req in reqList.Requests)
reqList.Requests.Clear();
lock (RequestLists)
{
// m_log.Info("AssetCache: Lock taken on requestLists (AssetNotFound #2)");
RequestLists.Remove(assetID);
}
// m_log.Info("AssetCache: Lock released on requestLists (AssetNotFound #2)");
foreach (NewAssetRequest req in theseRequests)
{ {
req.Callback(assetID, null); req.Callback(assetID, null);
} }
@ -578,6 +528,7 @@ namespace OpenSim.Framework.Communications.Cache
source = 3; source = 3;
//Console.WriteLine("asset request " + requestID); //Console.WriteLine("asset request " + requestID);
} }
//check to see if asset is in local cache, if not we need to request it from asset server. //check to see if asset is in local cache, if not we need to request it from asset server.
//Console.WriteLine("asset request " + requestID); //Console.WriteLine("asset request " + requestID);
if (!Assets.ContainsKey(requestID)) if (!Assets.ContainsKey(requestID))
@ -636,6 +587,7 @@ namespace OpenSim.Framework.Communications.Cache
//no requests waiting //no requests waiting
return; return;
} }
// if less than 5, do all of them // if less than 5, do all of them
int num = Math.Min(5, AssetRequests.Count); int num = Math.Min(5, AssetRequests.Count);
@ -688,18 +640,10 @@ namespace OpenSim.Framework.Communications.Cache
//public bool AssetInCache; //public bool AssetInCache;
//public int TimeRequested; //public int TimeRequested;
public int DiscardLevel = -1; public int DiscardLevel = -1;
public AssetRequest()
{
}
} }
public class AssetInfo : AssetBase public class AssetInfo : AssetBase
{ {
public AssetInfo()
{
}
public AssetInfo(AssetBase aBase) public AssetInfo(AssetBase aBase)
{ {
Data = aBase.Data; Data = aBase.Data;
@ -712,10 +656,6 @@ namespace OpenSim.Framework.Communications.Cache
public class TextureImage : AssetBase public class TextureImage : AssetBase
{ {
public TextureImage()
{
}
public TextureImage(AssetBase aBase) public TextureImage(AssetBase aBase)
{ {
Data = aBase.Data; Data = aBase.Data;