aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
diff options
context:
space:
mode:
authorDahlia Trimble2009-06-02 22:42:47 +0000
committerDahlia Trimble2009-06-02 22:42:47 +0000
commitb38be1a7fdf71a7d3c6d6f761590827b1f45483c (patch)
tree2be409eb714dfd93d78e50d8b0def07b8e9758e1 /OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
parentThank you kindly, MattSetzer, for a patch that solves a Mantis: (diff)
downloadopensim-SC_OLD-b38be1a7fdf71a7d3c6d6f761590827b1f45483c.zip
opensim-SC_OLD-b38be1a7fdf71a7d3c6d6f761590827b1f45483c.tar.gz
opensim-SC_OLD-b38be1a7fdf71a7d3c6d6f761590827b1f45483c.tar.bz2
opensim-SC_OLD-b38be1a7fdf71a7d3c6d6f761590827b1f45483c.tar.xz
Thank you Imaze Rhiano for a patch that implements Cenome Memory Asset Cache (Mantis #3759)
See the files: bin/config-include/GridCommon.ini.example and bin/config-include/StandaloneCommon.ini.example to configure and enable this caching method.
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs')
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs381
1 files changed, 381 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
new file mode 100644
index 0000000..4a34ca0
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -0,0 +1,381 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using log4net;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35
36namespace OpenSim.Region.CoreModules.Asset
37{
38 /// <summary>
39 /// Cenome memory asset cache.
40 /// </summary>
41 /// <remarks>
42 /// <para>
43 /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache".
44 /// When cache is successfully enable log should have message
45 /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)".
46 /// </para>
47 /// <para>
48 /// Cache's size is limited by two parameters:
49 /// maximal allowed size in bytes and maximal allowed asset count. When new asset
50 /// is added to cache that have achieved either size or count limitation, cache
51 /// will automatically remove less recently used assets from cache. Additionally
52 /// asset's lifetime is controlled by expiration time.
53 /// </para>
54 /// <para>
55 /// <list type="table">
56 /// <listheader>
57 /// <term>Configuration</term>
58 /// <description>Description</description>
59 /// </listheader>
60 /// <item>
61 /// <term>MaxSize</term>
62 /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description>
63 /// </item>
64 /// <item>
65 /// <term>MaxCount</term>
66 /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description>
67 /// </item>
68 /// <item>
69 /// <term>ExpirationTime</term>
70 /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description>
71 /// </item>
72 /// </list>
73 /// </para>
74 /// </remarks>
75 /// <example>
76 /// Enabling Cenome Asset Cache:
77 /// <code>
78 /// [Modules]
79 /// AssetCaching = "CenomeMemoryAssetCache"
80 /// </code>
81 /// Setting size and expiration time limitations:
82 /// <code>
83 /// [AssetService]
84 /// ; 256 MB (default: 134217728)
85 /// MaxSize = 268435456
86 /// ; How many assets it is possible to store cache (default: 4096)
87 /// MaxCount = 16384
88 /// ; Expiration time - 1 hour (default: 30 minutes)
89 /// ExpirationTime = 60
90 /// </code>
91 /// </example>
92 public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule
93 {
94 /// <summary>
95 /// Cache's default maximal asset count.
96 /// </summary>
97 /// <remarks>
98 /// <para>
99 /// Assuming that average asset size is about 32768 bytes.
100 /// </para>
101 /// </remarks>
102 public const int DefaultMaxCount = 4096;
103
104 /// <summary>
105 /// Default maximal size of the cache in bytes
106 /// </summary>
107 /// <remarks>
108 /// <para>
109 /// 128MB = 128 * 1024^2 = 134 217 728 bytes.
110 /// </para>
111 /// </remarks>
112 public const long DefaultMaxSize = 134217728;
113
114 /// <summary>
115 /// Asset's default expiration time in the cache.
116 /// </summary>
117 public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 );
118
119 /// <summary>
120 /// Log manager instance.
121 /// </summary>
122 private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
123
124 /// <summary>
125 /// Cache object.
126 /// </summary>
127 private ICnmCache<string, AssetBase> m_cache;
128
129 /// <summary>
130 /// Is Cenome asset cache enabled.
131 /// </summary>
132 private bool m_enabled;
133
134 /// <summary>
135 /// Count of get requests
136 /// </summary>
137 private int m_getCount;
138
139 /// <summary>
140 /// How many hits
141 /// </summary>
142 private int m_hitCount;
143
144 /// <summary>
145 /// Count of cache commands
146 /// </summary>
147 private int m_cachedCount;
148
149 /// <summary>
150 /// How many gets before dumping statistics
151 /// </summary>
152 /// <remarks>
153 /// If 0 or less, then disabled.
154 /// </remarks>
155 private int m_debugEpoch = 0;
156
157 /// <summary>
158 /// Initialize asset cache module with default parameters.
159 /// </summary>
160 public void Initialize()
161 {
162 Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime );
163 }
164
165 /// <summary>
166 /// Initialize asset cache module, with custom parameters.
167 /// </summary>
168 /// <param name="maximalSize">
169 /// Cache's maximal size in bytes.
170 /// </param>
171 /// <param name="maximalCount">
172 /// Cache's maximal count of assets.
173 /// </param>
174 /// <param name="expirationTime">
175 /// Asset's expiration time.
176 /// </param>
177 public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime )
178 {
179 if( maximalSize <= 0 || maximalCount <= 0 || expirationTime <= TimeSpan.Zero )
180 {
181 Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." );
182 m_enabled = false;
183 return;
184 }
185
186 // Create cache and add synchronization wrapper over it
187 m_cache =
188 CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>(
189 maximalSize, maximalCount, expirationTime ) );
190 m_enabled = true;
191 Log.InfoFormat("[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})", maximalSize, maximalCount, expirationTime );
192 }
193
194 #region IImprovedAssetCache Members
195 /// <summary>
196 /// Cache asset.
197 /// </summary>
198 /// <param name="asset">
199 /// The asset that is being cached.
200 /// </param>
201 public void Cache( AssetBase asset )
202 {
203 long size = asset.Data != null ? asset.Data.Length : 1;
204 m_cache.Set( asset.ID, asset, size );
205 m_cachedCount++;
206 }
207
208 /// <summary>
209 /// Clear asset cache.
210 /// </summary>
211 public void Clear()
212 {
213 m_cache.Clear();
214 }
215
216 /// <summary>
217 /// Expire (remove) asset stored to cache.
218 /// </summary>
219 /// <param name="id">
220 /// The expired asset's id.
221 /// </param>
222 public void Expire( string id )
223 {
224 m_cache.Remove( id );
225 }
226
227 /// <summary>
228 /// Get asset stored
229 /// </summary>
230 /// <param name="id">
231 /// The asset's id.
232 /// </param>
233 /// <returns>
234 /// Asset if it is found from cache; otherwise <see langword="null"/>.
235 /// </returns>
236 /// <remarks>
237 /// <para>
238 /// Caller should always check that is return value <see langword="null"/>.
239 /// Cache doesn't guarantee in any situation that asset is stored to it.
240 /// </para>
241 /// </remarks>
242 public AssetBase Get( string id )
243 {
244 m_getCount++;
245 AssetBase assetBase;
246 if( m_cache.TryGetValue( id, out assetBase ) )
247 m_hitCount++;
248
249 if( m_getCount == m_debugEpoch )
250 {
251 Log.InfoFormat( "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes",
252 m_cachedCount, m_getCount, ( (double) m_hitCount / m_getCount ) * 100.0, m_cache.Size, m_cache.Size / m_cache.Count );
253 m_getCount = 0;
254 m_hitCount = 0;
255 m_cachedCount = 0;
256 }
257
258 return assetBase;
259 }
260 #endregion
261
262 #region ISharedRegionModule Members
263 /// <summary>
264 /// Gets region module's name.
265 /// </summary>
266 public string Name
267 {
268 get { return "CenomeMemoryAssetCache"; }
269 }
270
271 /// <summary>
272 /// New region is being added to server.
273 /// </summary>
274 /// <param name="scene">
275 /// Region's scene.
276 /// </param>
277 public void AddRegion( Scene scene )
278 {
279 if( m_enabled )
280 scene.RegisterModuleInterface<IImprovedAssetCache>( this );
281 }
282
283 /// <summary>
284 /// Close region module.
285 /// </summary>
286 public void Close()
287 {
288 m_enabled = false;
289 m_cache.Clear();
290 m_cache = null;
291 }
292
293 /// <summary>
294 /// Initialize region module.
295 /// </summary>
296 /// <param name="source">
297 /// Configuration source.
298 /// </param>
299 public void Initialise( IConfigSource source )
300 {
301 m_cache = null;
302 m_enabled = false;
303
304 var moduleConfig = source.Configs[ "Modules" ];
305 if( moduleConfig == null )
306 return;
307
308 var name = moduleConfig.GetString( "AssetCaching" );
309 Log.DebugFormat( "[XXX] name = {0} (this module's name: {1}", name, Name );
310
311 if( name != Name )
312 return;
313
314 // This module is used
315 var maxSize = DefaultMaxSize;
316 var maxCount = DefaultMaxCount;
317 var expirationTime = DefaultExpirationTime;
318
319 var assetConfig = source.Configs[ "AssetCache" ];
320 if( assetConfig != null )
321 {
322 // Get optional configurations
323 maxSize = assetConfig.GetLong( "MaxSize", DefaultMaxSize );
324 maxCount = assetConfig.GetInt( "MaxCount", DefaultMaxCount );
325 expirationTime =
326 TimeSpan.FromMinutes( assetConfig.GetInt( "ExpirationTime", (int) DefaultExpirationTime.TotalMinutes ) );
327
328 // Debugging purposes only
329 m_debugEpoch = assetConfig.GetInt( "DebugEpoch", 0 );
330 }
331
332 Initialize( maxSize, maxCount, expirationTime );
333 }
334
335 /// <summary>
336 /// Initialization post handling.
337 /// </summary>
338 /// <remarks>
339 /// <para>
340 /// Modules can use this to initialize connection with other modules.
341 /// </para>
342 /// </remarks>
343 public void PostInitialise()
344 {
345 }
346
347 /// <summary>
348 /// Region has been loaded.
349 /// </summary>
350 /// <param name="scene">
351 /// Region's scene.
352 /// </param>
353 /// <remarks>
354 /// <para>
355 /// This is needed for all module types. Modules will register
356 /// Interfaces with scene in AddScene, and will also need a means
357 /// to access interfaces registered by other modules. Without
358 /// this extra method, a module attempting to use another modules'
359 /// interface would be successful only depending on load order,
360 /// which can't be depended upon, or modules would need to resort
361 /// to ugly kludges to attempt to request interfaces when needed
362 /// and unnecessary caching logic repeated in all modules.
363 /// The extra function stub is just that much cleaner.
364 /// </para>
365 /// </remarks>
366 public void RegionLoaded( Scene scene )
367 {
368 }
369
370 /// <summary>
371 /// Region is being removed.
372 /// </summary>
373 /// <param name="scene">
374 /// Region scene that is being removed.
375 /// </param>
376 public void RemoveRegion( Scene scene )
377 {
378 }
379 #endregion
380 }
381}