refactor: Split file cache manipulation code into separate methods, as has already been done for the memory cache
parent
46f5893d55
commit
5dc785bbf2
|
@ -226,7 +226,6 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
if (m_AssetService == null)
|
if (m_AssetService == null)
|
||||||
{
|
{
|
||||||
m_AssetService = scene.RequestModuleInterface<IAssetService>();
|
m_AssetService = scene.RequestModuleInterface<IAssetService>();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,8 +249,57 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
private void UpdateMemoryCache(string key, AssetBase asset)
|
private void UpdateMemoryCache(string key, AssetBase asset)
|
||||||
{
|
{
|
||||||
if (m_MemoryCacheEnabled)
|
m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
|
||||||
m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
|
}
|
||||||
|
|
||||||
|
private void UpdateFileCache(string key, AssetBase asset)
|
||||||
|
{
|
||||||
|
string filename = GetFileName(asset.ID);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// If the file is already cached, don't cache it, just touch it so access time is updated
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
File.SetLastAccessTime(filename, DateTime.Now);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Once we start writing, make sure we flag that we're writing
|
||||||
|
// that object to the cache so that we don't try to write the
|
||||||
|
// same file multiple times.
|
||||||
|
lock (m_CurrentlyWriting)
|
||||||
|
{
|
||||||
|
#if WAIT_ON_INPROGRESS_REQUESTS
|
||||||
|
if (m_CurrentlyWriting.ContainsKey(filename))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (m_CurrentlyWriting.Contains(filename))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_CurrentlyWriting.Add(filename);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.FireAndForget(
|
||||||
|
delegate { WriteFileCache(filename, asset); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LogException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cache(AssetBase asset)
|
public void Cache(AssetBase asset)
|
||||||
|
@ -259,57 +307,100 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
// TODO: Spawn this off to some seperate thread to do the actual writing
|
// TODO: Spawn this off to some seperate thread to do the actual writing
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
|
//m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
|
||||||
|
|
||||||
UpdateMemoryCache(asset.ID, asset);
|
if (m_MemoryCacheEnabled)
|
||||||
|
UpdateMemoryCache(asset.ID, asset);
|
||||||
|
|
||||||
string filename = GetFileName(asset.ID);
|
UpdateFileCache(asset.ID, asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get an asset from the in-memory cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private AssetBase GetFromMemoryCache(string id)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
|
||||||
|
if (m_MemoryCache.TryGetValue(id, out asset))
|
||||||
|
m_MemoryHits++;
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get an asset from the file cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private AssetBase GetFromFileCache(string id)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
|
||||||
|
string filename = GetFileName(id);
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
FileStream stream = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// If the file is already cached, don't cache it, just touch it so access time is updated
|
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
if (File.Exists(filename))
|
BinaryFormatter bformatter = new BinaryFormatter();
|
||||||
{
|
|
||||||
File.SetLastAccessTime(filename, DateTime.Now);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Once we start writing, make sure we flag that we're writing
|
asset = (AssetBase)bformatter.Deserialize(stream);
|
||||||
// that object to the cache so that we don't try to write the
|
|
||||||
// same file multiple times.
|
|
||||||
lock (m_CurrentlyWriting)
|
|
||||||
{
|
|
||||||
#if WAIT_ON_INPROGRESS_REQUESTS
|
|
||||||
if (m_CurrentlyWriting.ContainsKey(filename))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
UpdateMemoryCache(id, asset);
|
||||||
if (m_CurrentlyWriting.Contains(filename))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_CurrentlyWriting.Add(filename);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
m_DiskHits++;
|
||||||
|
}
|
||||||
|
catch (System.Runtime.Serialization.SerializationException e)
|
||||||
|
{
|
||||||
|
LogException(e);
|
||||||
|
|
||||||
Util.FireAndForget(
|
// If there was a problem deserializing the asset, the asset may
|
||||||
delegate { WriteFileCache(filename, asset); });
|
// either be corrupted OR was serialized under an old format
|
||||||
}
|
// {different version of AssetBase} -- we should attempt to
|
||||||
|
// delete it and re-cache
|
||||||
|
File.Delete(filename);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LogException(e);
|
LogException(e);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if WAIT_ON_INPROGRESS_REQUESTS
|
||||||
|
// Check if we're already downloading this asset. If so, try to wait for it to
|
||||||
|
// download.
|
||||||
|
if (m_WaitOnInprogressTimeout > 0)
|
||||||
|
{
|
||||||
|
m_RequestsForInprogress++;
|
||||||
|
|
||||||
|
ManualResetEvent waitEvent;
|
||||||
|
if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
|
||||||
|
{
|
||||||
|
waitEvent.WaitOne(m_WaitOnInprogressTimeout);
|
||||||
|
return Get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Track how often we have the problem that an asset is requested while
|
||||||
|
// it is still being downloaded by a previous request.
|
||||||
|
if (m_CurrentlyWriting.Contains(filename))
|
||||||
|
{
|
||||||
|
m_RequestsForInprogress++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssetBase Get(string id)
|
public AssetBase Get(string id)
|
||||||
|
@ -318,72 +409,10 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
AssetBase asset = null;
|
AssetBase asset = null;
|
||||||
|
|
||||||
if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset))
|
if (m_MemoryCacheEnabled)
|
||||||
{
|
asset = GetFromMemoryCache(id);
|
||||||
m_MemoryHits++;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
asset = GetFromFileCache(id);
|
||||||
string filename = GetFileName(id);
|
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
|
||||||
FileStream stream = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
BinaryFormatter bformatter = new BinaryFormatter();
|
|
||||||
|
|
||||||
asset = (AssetBase)bformatter.Deserialize(stream);
|
|
||||||
|
|
||||||
UpdateMemoryCache(id, asset);
|
|
||||||
|
|
||||||
m_DiskHits++;
|
|
||||||
}
|
|
||||||
catch (System.Runtime.Serialization.SerializationException e)
|
|
||||||
{
|
|
||||||
LogException(e);
|
|
||||||
|
|
||||||
// If there was a problem deserializing the asset, the asset may
|
|
||||||
// either be corrupted OR was serialized under an old format
|
|
||||||
// {different version of AssetBase} -- we should attempt to
|
|
||||||
// delete it and re-cache
|
|
||||||
File.Delete(filename);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LogException(e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (stream != null)
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if WAIT_ON_INPROGRESS_REQUESTS
|
|
||||||
// Check if we're already downloading this asset. If so, try to wait for it to
|
|
||||||
// download.
|
|
||||||
if (m_WaitOnInprogressTimeout > 0)
|
|
||||||
{
|
|
||||||
m_RequestsForInprogress++;
|
|
||||||
|
|
||||||
ManualResetEvent waitEvent;
|
|
||||||
if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
|
|
||||||
{
|
|
||||||
waitEvent.WaitOne(m_WaitOnInprogressTimeout);
|
|
||||||
return Get(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Track how often we have the problem that an asset is requested while
|
|
||||||
// it is still being downloaded by a previous request.
|
|
||||||
if (m_CurrentlyWriting.Contains(filename))
|
|
||||||
{
|
|
||||||
m_RequestsForInprogress++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
|
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
|
||||||
{
|
{
|
||||||
|
@ -474,9 +503,9 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
/// removes empty tier directories.
|
/// removes empty tier directories.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dir"></param>
|
/// <param name="dir"></param>
|
||||||
|
/// <param name="purgeLine"></param>
|
||||||
private void CleanExpiredFiles(string dir, DateTime purgeLine)
|
private void CleanExpiredFiles(string dir, DateTime purgeLine)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach (string file in Directory.GetFiles(dir))
|
foreach (string file in Directory.GetFiles(dir))
|
||||||
{
|
{
|
||||||
if (File.GetLastAccessTime(file) < purgeLine)
|
if (File.GetLastAccessTime(file) < purgeLine)
|
||||||
|
|
Loading…
Reference in New Issue