diff options
7 files changed, 92 insertions, 2 deletions
diff --git a/OpenSim/Framework/IAssetCache.cs b/OpenSim/Framework/IAssetCache.cs index 855b86b..8477116 100644 --- a/OpenSim/Framework/IAssetCache.cs +++ b/OpenSim/Framework/IAssetCache.cs | |||
@@ -38,6 +38,12 @@ namespace OpenSim.Framework | |||
38 | void Cache(AssetBase asset); | 38 | void Cache(AssetBase asset); |
39 | 39 | ||
40 | /// <summary> | 40 | /// <summary> |
41 | /// Cache that the specified asset wasn't found. | ||
42 | /// </summary> | ||
43 | /// <param name='id'></param> | ||
44 | /// <summary> | ||
45 | void CacheNegative(string id); | ||
46 | |||
41 | /// Get an asset by its id. | 47 | /// Get an asset by its id. |
42 | /// </summary> | 48 | /// </summary> |
43 | /// <param name='id'></param> | 49 | /// <param name='id'></param> |
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index 382b5f2..14b0280 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | |||
@@ -221,6 +221,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
221 | 221 | ||
222 | } | 222 | } |
223 | 223 | ||
224 | public void CacheNegative(string id) | ||
225 | { | ||
226 | // We don't do negative caching | ||
227 | } | ||
228 | |||
224 | /// <summary> | 229 | /// <summary> |
225 | /// Clear asset cache. | 230 | /// Clear asset cache. |
226 | /// </summary> | 231 | /// </summary> |
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index d78b082..82bc5cc 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs | |||
@@ -124,6 +124,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
124 | m_Cache.Store(asset.ID, asset); | 124 | m_Cache.Store(asset.ID, asset); |
125 | } | 125 | } |
126 | 126 | ||
127 | public void CacheNegative(string id) | ||
128 | { | ||
129 | // We don't do negative caching | ||
130 | } | ||
131 | |||
127 | public AssetBase Get(string id) | 132 | public AssetBase Get(string id) |
128 | { | 133 | { |
129 | return (AssetBase)m_Cache.Get(id); | 134 | return (AssetBase)m_Cache.Get(id); |
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index fcd4252..84e13a0 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -92,9 +92,15 @@ namespace OpenSim.Region.CoreModules.Asset | |||
92 | private ExpiringCache<string, AssetBase> m_MemoryCache; | 92 | private ExpiringCache<string, AssetBase> m_MemoryCache; |
93 | private bool m_MemoryCacheEnabled = false; | 93 | private bool m_MemoryCacheEnabled = false; |
94 | 94 | ||
95 | private ExpiringCache<string, object> m_negativeCache; | ||
96 | private bool m_negativeCacheEnabled = true; | ||
97 | private bool m_negativeCacheSliding = false; | ||
98 | |||
95 | // Expiration is expressed in hours. | 99 | // Expiration is expressed in hours. |
96 | private double m_MemoryExpiration = 0.016; | 100 | private double m_MemoryExpiration = 0.016; |
97 | private const double m_DefaultFileExpiration = 48; | 101 | private const double m_DefaultFileExpiration = 48; |
102 | // Negative cache is in seconds | ||
103 | private int m_negativeExpiration = 120; | ||
98 | private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); | 104 | private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); |
99 | private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); | 105 | private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); |
100 | 106 | ||
@@ -139,6 +145,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
139 | if (name == Name) | 145 | if (name == Name) |
140 | { | 146 | { |
141 | m_MemoryCache = new ExpiringCache<string, AssetBase>(); | 147 | m_MemoryCache = new ExpiringCache<string, AssetBase>(); |
148 | m_negativeCache = new ExpiringCache<string, object>(); | ||
142 | m_Enabled = true; | 149 | m_Enabled = true; |
143 | 150 | ||
144 | m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); | 151 | m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); |
@@ -158,6 +165,9 @@ namespace OpenSim.Region.CoreModules.Asset | |||
158 | m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration); | 165 | m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration); |
159 | m_MemoryExpiration *= 3600.0; // config in hours to seconds | 166 | m_MemoryExpiration *= 3600.0; // config in hours to seconds |
160 | 167 | ||
168 | m_negativeCacheEnabled = assetConfig.GetBoolean("NegativeCacheEnabled", m_negativeCacheEnabled); | ||
169 | m_negativeExpiration = assetConfig.GetInt("NegativeCacheTimeout", m_negativeExpiration); | ||
170 | m_negativeCacheSliding = assetConfig.GetBoolean("NegativeCacheSliding", m_negativeCacheSliding); | ||
161 | m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit); | 171 | m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit); |
162 | 172 | ||
163 | #if WAIT_ON_INPROGRESS_REQUESTS | 173 | #if WAIT_ON_INPROGRESS_REQUESTS |
@@ -355,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Asset | |||
355 | } | 365 | } |
356 | } | 366 | } |
357 | 367 | ||
368 | public void CacheNegative(string id) | ||
369 | { | ||
370 | if (m_negativeCacheEnabled) | ||
371 | { | ||
372 | if (m_negativeCacheSliding) | ||
373 | m_negativeCache.AddOrUpdate(id, null, TimeSpan.FromSeconds(m_negativeExpiration)); | ||
374 | else | ||
375 | m_negativeCache.AddOrUpdate(id, null, m_negativeExpiration); | ||
376 | } | ||
377 | } | ||
378 | |||
358 | /// <summary> | 379 | /// <summary> |
359 | /// Updates the cached file with the current time. | 380 | /// Updates the cached file with the current time. |
360 | /// </summary> | 381 | /// </summary> |
@@ -514,6 +535,10 @@ namespace OpenSim.Region.CoreModules.Asset | |||
514 | { | 535 | { |
515 | m_Requests++; | 536 | m_Requests++; |
516 | 537 | ||
538 | object dummy; | ||
539 | if (m_negativeCache.TryGetValue(id, out dummy)) | ||
540 | return null; | ||
541 | |||
517 | AssetBase asset = null; | 542 | AssetBase asset = null; |
518 | asset = GetFromWeakReference(id); | 543 | asset = GetFromWeakReference(id); |
519 | if (asset != null && m_updateFileTimeOnCacheHit) | 544 | if (asset != null && m_updateFileTimeOnCacheHit) |
@@ -622,6 +647,8 @@ namespace OpenSim.Region.CoreModules.Asset | |||
622 | 647 | ||
623 | if (m_MemoryCacheEnabled) | 648 | if (m_MemoryCacheEnabled) |
624 | m_MemoryCache = new ExpiringCache<string, AssetBase>(); | 649 | m_MemoryCache = new ExpiringCache<string, AssetBase>(); |
650 | if (m_negativeCacheEnabled) | ||
651 | m_negativeCache = new ExpiringCache<string, object>(); | ||
625 | 652 | ||
626 | lock(weakAssetReferencesLock) | 653 | lock(weakAssetReferencesLock) |
627 | weakAssetReferences = new Dictionary<string, WeakReference>(); | 654 | weakAssetReferences = new Dictionary<string, WeakReference>(); |
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 7343f4f..195bdaa 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs | |||
@@ -126,6 +126,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
126 | m_Cache.AddOrUpdate(asset.ID, asset); | 126 | m_Cache.AddOrUpdate(asset.ID, asset); |
127 | } | 127 | } |
128 | 128 | ||
129 | public void CacheNegative(string id) | ||
130 | { | ||
131 | // We don't do negative caching | ||
132 | } | ||
133 | |||
129 | public AssetBase Get(string id) | 134 | public AssetBase Get(string id) |
130 | { | 135 | { |
131 | Object asset = null; | 136 | Object asset = null; |
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index b8449d7..bdc3bef 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs | |||
@@ -260,8 +260,13 @@ namespace OpenSim.Services.Connectors | |||
260 | asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth); | 260 | asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth); |
261 | 261 | ||
262 | 262 | ||
263 | if (asset != null && m_Cache != null) | 263 | if (m_Cache != null) |
264 | m_Cache.Cache(asset); | 264 | { |
265 | if (asset != null) | ||
266 | m_Cache.Cache(asset); | ||
267 | else | ||
268 | m_Cache.CacheNegative(id); | ||
269 | } | ||
265 | } | 270 | } |
266 | return asset; | 271 | return asset; |
267 | } | 272 | } |
diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 917ea46..2b5d37e 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example | |||
@@ -24,6 +24,43 @@ | |||
24 | ; so even a small memory cache is useful | 24 | ; so even a small memory cache is useful |
25 | MemoryCacheEnabled = false | 25 | MemoryCacheEnabled = false |
26 | 26 | ||
27 | ; If a memory cache hit happens, or the asset is still in memory | ||
28 | ; due to other causes, update the timestamp on the disk file anyway. | ||
29 | ; Don't turn this on unless you share your asset cache between simulators | ||
30 | ; AND use an external process, e.g. cron job, to clean it up. | ||
31 | UpdateFileTimeOnCacheHit = false | ||
32 | |||
33 | ; Enabling this will cache negative fetches. If an asset is negative-cached | ||
34 | ; it will not be re-requested from the asset server again for a while. | ||
35 | ; Generally, this is a good thing. | ||
36 | ; | ||
37 | ; Regular expiration settings (non-sliding) mean that the asset will be | ||
38 | ; retried after the time has expired. Sliding expiration means that | ||
39 | ; the time the negative cache will keep the asset is refreshed each | ||
40 | ; time a fetch is attempted. Use sliding expiration if you have rogue | ||
41 | ; scripts hammering the asset server with requests for nonexistent | ||
42 | ; assets. | ||
43 | ; | ||
44 | ; There are two cases where negative caching may cause issues: | ||
45 | ; | ||
46 | ; 1 - If an invalid asset is repeatedly requested by a script and that asset is | ||
47 | ; subsequently created, it will not be seen until fcache clear | ||
48 | ; is used. This is a very theoretical scenario since UUID collisions | ||
49 | ; are deemed to be not occuring in practice. | ||
50 | ; This can only become an issue with sliding expiration time. | ||
51 | ; | ||
52 | ; 2 - If the asset service is clustered, an asset may not have propagated | ||
53 | ; to all cluster members when it is first attempted to fetch it. | ||
54 | ; This may theoretically occur with networked vendor systems and | ||
55 | ; would lead to an asset not found message. However, after the | ||
56 | ; expiration time has elapsed, the asset will the be fetchable. | ||
57 | ; | ||
58 | ; The defaults below are suitable for all small to medium installations | ||
59 | ; including grids. | ||
60 | NegativeCacheEnabled = true | ||
61 | NegativeCacheTimeout = 120 | ||
62 | NegativeCacheSliding = false | ||
63 | |||
27 | ; Set to false for no file cache | 64 | ; Set to false for no file cache |
28 | FileCacheEnabled = true | 65 | FileCacheEnabled = true |
29 | 66 | ||