Add negative caching to flotsam cache. Prevents scripts from hammering the asset server
parent
ec4c258794
commit
07b48fd58c
|
@ -38,6 +38,12 @@ namespace OpenSim.Framework
|
||||||
void Cache(AssetBase asset);
|
void Cache(AssetBase asset);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Cache that the specified asset wasn't found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='id'></param>
|
||||||
|
/// <summary>
|
||||||
|
void CacheNegative(string id);
|
||||||
|
|
||||||
/// Get an asset by its id.
|
/// Get an asset by its id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name='id'></param>
|
/// <param name='id'></param>
|
||||||
|
|
|
@ -221,6 +221,11 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheNegative(string id)
|
||||||
|
{
|
||||||
|
// We don't do negative caching
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clear asset cache.
|
/// Clear asset cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -124,6 +124,11 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
m_Cache.Store(asset.ID, asset);
|
m_Cache.Store(asset.ID, asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheNegative(string id)
|
||||||
|
{
|
||||||
|
// We don't do negative caching
|
||||||
|
}
|
||||||
|
|
||||||
public AssetBase Get(string id)
|
public AssetBase Get(string id)
|
||||||
{
|
{
|
||||||
return (AssetBase)m_Cache.Get(id);
|
return (AssetBase)m_Cache.Get(id);
|
||||||
|
|
|
@ -92,9 +92,15 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
private ExpiringCache<string, AssetBase> m_MemoryCache;
|
private ExpiringCache<string, AssetBase> m_MemoryCache;
|
||||||
private bool m_MemoryCacheEnabled = false;
|
private bool m_MemoryCacheEnabled = false;
|
||||||
|
|
||||||
|
private ExpiringCache<string, object> m_negativeCache;
|
||||||
|
private bool m_negativeCacheEnabled = true;
|
||||||
|
private bool m_negativeCacheSliding = false;
|
||||||
|
|
||||||
// Expiration is expressed in hours.
|
// Expiration is expressed in hours.
|
||||||
private double m_MemoryExpiration = 0.016;
|
private double m_MemoryExpiration = 0.016;
|
||||||
private const double m_DefaultFileExpiration = 48;
|
private const double m_DefaultFileExpiration = 48;
|
||||||
|
// Negative cache is in seconds
|
||||||
|
private int m_negativeExpiration = 120;
|
||||||
private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
|
private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
|
||||||
private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0);
|
private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0);
|
||||||
|
|
||||||
|
@ -139,6 +145,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
{
|
{
|
||||||
m_MemoryCache = new ExpiringCache<string, AssetBase>();
|
m_MemoryCache = new ExpiringCache<string, AssetBase>();
|
||||||
|
m_negativeCache = new ExpiringCache<string, object>();
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name);
|
||||||
|
@ -158,6 +165,9 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration);
|
m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration);
|
||||||
m_MemoryExpiration *= 3600.0; // config in hours to seconds
|
m_MemoryExpiration *= 3600.0; // config in hours to seconds
|
||||||
|
|
||||||
|
m_negativeCacheEnabled = assetConfig.GetBoolean("NegativeCacheEnabled", m_negativeCacheEnabled);
|
||||||
|
m_negativeExpiration = assetConfig.GetInt("NegativeCacheTimeout", m_negativeExpiration);
|
||||||
|
m_negativeCacheSliding = assetConfig.GetBoolean("NegativeCacheSliding", m_negativeCacheSliding);
|
||||||
m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit);
|
m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit);
|
||||||
|
|
||||||
#if WAIT_ON_INPROGRESS_REQUESTS
|
#if WAIT_ON_INPROGRESS_REQUESTS
|
||||||
|
@ -355,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheNegative(string id)
|
||||||
|
{
|
||||||
|
if (m_negativeCacheEnabled)
|
||||||
|
{
|
||||||
|
if (m_negativeCacheSliding)
|
||||||
|
m_negativeCache.AddOrUpdate(id, null, TimeSpan.FromSeconds(m_negativeExpiration));
|
||||||
|
else
|
||||||
|
m_negativeCache.AddOrUpdate(id, null, m_negativeExpiration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the cached file with the current time.
|
/// Updates the cached file with the current time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -514,6 +535,10 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
{
|
{
|
||||||
m_Requests++;
|
m_Requests++;
|
||||||
|
|
||||||
|
object dummy;
|
||||||
|
if (m_negativeCache.TryGetValue(id, out dummy))
|
||||||
|
return null;
|
||||||
|
|
||||||
AssetBase asset = null;
|
AssetBase asset = null;
|
||||||
asset = GetFromWeakReference(id);
|
asset = GetFromWeakReference(id);
|
||||||
if (asset != null && m_updateFileTimeOnCacheHit)
|
if (asset != null && m_updateFileTimeOnCacheHit)
|
||||||
|
@ -622,6 +647,8 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
|
|
||||||
if (m_MemoryCacheEnabled)
|
if (m_MemoryCacheEnabled)
|
||||||
m_MemoryCache = new ExpiringCache<string, AssetBase>();
|
m_MemoryCache = new ExpiringCache<string, AssetBase>();
|
||||||
|
if (m_negativeCacheEnabled)
|
||||||
|
m_negativeCache = new ExpiringCache<string, object>();
|
||||||
|
|
||||||
lock(weakAssetReferencesLock)
|
lock(weakAssetReferencesLock)
|
||||||
weakAssetReferences = new Dictionary<string, WeakReference>();
|
weakAssetReferences = new Dictionary<string, WeakReference>();
|
||||||
|
|
|
@ -126,6 +126,11 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
m_Cache.AddOrUpdate(asset.ID, asset);
|
m_Cache.AddOrUpdate(asset.ID, asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheNegative(string id)
|
||||||
|
{
|
||||||
|
// We don't do negative caching
|
||||||
|
}
|
||||||
|
|
||||||
public AssetBase Get(string id)
|
public AssetBase Get(string id)
|
||||||
{
|
{
|
||||||
Object asset = null;
|
Object asset = null;
|
||||||
|
|
|
@ -260,8 +260,13 @@ namespace OpenSim.Services.Connectors
|
||||||
asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth);
|
asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth);
|
||||||
|
|
||||||
|
|
||||||
if (asset != null && m_Cache != null)
|
if (m_Cache != null)
|
||||||
m_Cache.Cache(asset);
|
{
|
||||||
|
if (asset != null)
|
||||||
|
m_Cache.Cache(asset);
|
||||||
|
else
|
||||||
|
m_Cache.CacheNegative(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,43 @@
|
||||||
; so even a small memory cache is useful
|
; so even a small memory cache is useful
|
||||||
MemoryCacheEnabled = false
|
MemoryCacheEnabled = false
|
||||||
|
|
||||||
|
; If a memory cache hit happens, or the asset is still in memory
|
||||||
|
; due to other causes, update the timestamp on the disk file anyway.
|
||||||
|
; Don't turn this on unless you share your asset cache between simulators
|
||||||
|
; AND use an external process, e.g. cron job, to clean it up.
|
||||||
|
UpdateFileTimeOnCacheHit = false
|
||||||
|
|
||||||
|
; Enabling this will cache negative fetches. If an asset is negative-cached
|
||||||
|
; it will not be re-requested from the asset server again for a while.
|
||||||
|
; Generally, this is a good thing.
|
||||||
|
;
|
||||||
|
; Regular expiration settings (non-sliding) mean that the asset will be
|
||||||
|
; retried after the time has expired. Sliding expiration means that
|
||||||
|
; the time the negative cache will keep the asset is refreshed each
|
||||||
|
; time a fetch is attempted. Use sliding expiration if you have rogue
|
||||||
|
; scripts hammering the asset server with requests for nonexistent
|
||||||
|
; assets.
|
||||||
|
;
|
||||||
|
; There are two cases where negative caching may cause issues:
|
||||||
|
;
|
||||||
|
; 1 - If an invalid asset is repeatedly requested by a script and that asset is
|
||||||
|
; subsequently created, it will not be seen until fcache clear
|
||||||
|
; is used. This is a very theoretical scenario since UUID collisions
|
||||||
|
; are deemed to be not occuring in practice.
|
||||||
|
; This can only become an issue with sliding expiration time.
|
||||||
|
;
|
||||||
|
; 2 - If the asset service is clustered, an asset may not have propagated
|
||||||
|
; to all cluster members when it is first attempted to fetch it.
|
||||||
|
; This may theoretically occur with networked vendor systems and
|
||||||
|
; would lead to an asset not found message. However, after the
|
||||||
|
; expiration time has elapsed, the asset will the be fetchable.
|
||||||
|
;
|
||||||
|
; The defaults below are suitable for all small to medium installations
|
||||||
|
; including grids.
|
||||||
|
NegativeCacheEnabled = true
|
||||||
|
NegativeCacheTimeout = 120
|
||||||
|
NegativeCacheSliding = false
|
||||||
|
|
||||||
; Set to false for no file cache
|
; Set to false for no file cache
|
||||||
FileCacheEnabled = true
|
FileCacheEnabled = true
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue