When an uncached asset is requested multiple times concurrently, only load it once

Signed-off-by: root <root@grid00001.t-data.com>
bulletsim
Oren Hurvitz 2011-07-18 12:32:32 +03:00 committed by root
parent 56830bfe07
commit 71ef4a8fb3
1 changed files with 48 additions and 8 deletions

View File

@ -48,6 +48,13 @@ namespace OpenSim.Services.Connectors
private string m_ServerURI = String.Empty;
private IImprovedAssetCache m_Cache = null;
private delegate void AssetRetrievedEx(AssetBase asset);
// Keeps track of concurrent requests for the same asset, so that it's only loaded once.
// Maps: Asset ID -> Handlers which will be called when the asset has been loaded
private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
public AssetServicesConnector()
{
}
@ -178,23 +185,56 @@ namespace OpenSim.Services.Connectors
if (asset == null)
{
bool result = false;
lock (m_AssetHandlers)
{
AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
AsynchronousRestObjectRequester.
MakeRequest<int, AssetBase>("GET", uri, 0,
AssetRetrievedEx handlers;
if (m_AssetHandlers.TryGetValue(id, out handlers))
{
// Someone else is already loading this asset. It will notify our handler when done.
handlers += handlerEx;
return true;
}
// Load the asset ourselves
handlers += handlerEx;
m_AssetHandlers.Add(id, handlers);
}
bool success = false;
try
{
AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
delegate(AssetBase a)
{
if (m_Cache != null)
m_Cache.Cache(a);
handler(id, sender, a);
result = true;
AssetRetrievedEx handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
handlers.Invoke(a);
});
return result;
success = true;
}
finally
{
if (!success)
{
lock (m_AssetHandlers)
{
m_AssetHandlers.Remove(id);
}
}
}
}
else
{
//Util.FireAndForget(delegate { handler(id, sender, asset); });
handler(id, sender, asset);
}