diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | 382 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | 1 |
2 files changed, 383 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..00a8143 --- /dev/null +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | |||
@@ -0,0 +1,382 @@ | |||
1 | // -------------------------------------------------------------------------------------------------------------------- | ||
2 | // <copyright company="" file="CenomeAssetCache.cs"> | ||
3 | // | ||
4 | // </copyright> | ||
5 | // <summary> | ||
6 | // | ||
7 | // </summary> | ||
8 | // | ||
9 | // -------------------------------------------------------------------------------------------------------------------- | ||
10 | using System; | ||
11 | using System.Reflection; | ||
12 | using log4net; | ||
13 | using Nini.Config; | ||
14 | using OpenSim.Framework; | ||
15 | using OpenSim.Region.Framework.Interfaces; | ||
16 | using OpenSim.Region.Framework.Scenes; | ||
17 | |||
18 | namespace OpenSim.Region.CoreModules.Asset | ||
19 | { | ||
20 | /// <summary> | ||
21 | /// Cenome memory asset cache. | ||
22 | /// </summary> | ||
23 | /// <remarks> | ||
24 | /// <para> | ||
25 | /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache". | ||
26 | /// When cache is successfully enable log should have message | ||
27 | /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)". | ||
28 | /// </para> | ||
29 | /// <para> | ||
30 | /// Cache's size is limited by two parameters: | ||
31 | /// maximal allowed size in bytes and maximal allowed asset count. When new asset | ||
32 | /// is added to cache that have achieved either size or count limitation, cache | ||
33 | /// will automatically remove less recently used assets from cache. Additionally | ||
34 | /// asset's lifetime is controlled by expiration time. | ||
35 | /// </para> | ||
36 | /// <para> | ||
37 | /// <list type="table"> | ||
38 | /// <listheader> | ||
39 | /// <term>Configuration</term> | ||
40 | /// <description>Description</description> | ||
41 | /// </listheader> | ||
42 | /// <item> | ||
43 | /// <term>MaxSize</term> | ||
44 | /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description> | ||
45 | /// </item> | ||
46 | /// <item> | ||
47 | /// <term>MaxCount</term> | ||
48 | /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description> | ||
49 | /// </item> | ||
50 | /// <item> | ||
51 | /// <term>ExpirationTime</term> | ||
52 | /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description> | ||
53 | /// </item> | ||
54 | /// </list> | ||
55 | /// </para> | ||
56 | /// </remarks> | ||
57 | /// <example> | ||
58 | /// Enabling Cenome Asset Cache: | ||
59 | /// <code> | ||
60 | /// [Modules] | ||
61 | /// AssetCaching = "CenomeMemoryAssetCache" | ||
62 | /// </code> | ||
63 | /// Setting size and expiration time limitations: | ||
64 | /// <code> | ||
65 | /// [AssetService] | ||
66 | /// ; 256 MB (default: 134217728) | ||
67 | /// MaxSize = 268435456 | ||
68 | /// ; How many assets it is possible to store cache (default: 4096) | ||
69 | /// MaxCount = 16384 | ||
70 | /// ; Expiration time - 1 hour (default: 30 minutes) | ||
71 | /// ExpirationTime = 60 | ||
72 | /// </code> | ||
73 | /// </example> | ||
74 | public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule | ||
75 | { | ||
76 | /// <summary> | ||
77 | /// Cache's default maximal asset count. | ||
78 | /// </summary> | ||
79 | /// <remarks> | ||
80 | /// <para> | ||
81 | /// Assuming that average asset size is about 32768 bytes. | ||
82 | /// </para> | ||
83 | /// </remarks> | ||
84 | public const int DefaultMaxCount = 4096; | ||
85 | |||
86 | /// <summary> | ||
87 | /// Default maximal size of the cache in bytes | ||
88 | /// </summary> | ||
89 | /// <remarks> | ||
90 | /// <para> | ||
91 | /// 128MB = 128 * 1024^2 = 134 217 728 bytes. | ||
92 | /// </para> | ||
93 | /// </remarks> | ||
94 | public const long DefaultMaxSize = 134217728; | ||
95 | |||
96 | /// <summary> | ||
97 | /// Asset's default expiration time in the cache. | ||
98 | /// </summary> | ||
99 | public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 ); | ||
100 | |||
101 | /// <summary> | ||
102 | /// Log manager instance. | ||
103 | /// </summary> | ||
104 | private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ); | ||
105 | |||
106 | /// <summary> | ||
107 | /// Cache object. | ||
108 | /// </summary> | ||
109 | private ICnmCache<string, AssetBase> m_cache; | ||
110 | |||
111 | /// <summary> | ||
112 | /// Count of cache commands | ||
113 | /// </summary> | ||
114 | private int m_cachedCount; | ||
115 | |||
116 | /// <summary> | ||
117 | /// How many gets before dumping statistics | ||
118 | /// </summary> | ||
119 | /// <remarks> | ||
120 | /// If 0 or less, then disabled. | ||
121 | /// </remarks> | ||
122 | private int m_debugEpoch; | ||
123 | |||
124 | /// <summary> | ||
125 | /// Is Cenome asset cache enabled. | ||
126 | /// </summary> | ||
127 | private bool m_enabled; | ||
128 | |||
129 | /// <summary> | ||
130 | /// Count of get requests | ||
131 | /// </summary> | ||
132 | private int m_getCount; | ||
133 | |||
134 | /// <summary> | ||
135 | /// How many hits | ||
136 | /// </summary> | ||
137 | private int m_hitCount; | ||
138 | |||
139 | /// <summary> | ||
140 | /// Initialize asset cache module with default parameters. | ||
141 | /// </summary> | ||
142 | public void Initialize() | ||
143 | { | ||
144 | Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime ); | ||
145 | } | ||
146 | |||
147 | /// <summary> | ||
148 | /// Initialize asset cache module, with custom parameters. | ||
149 | /// </summary> | ||
150 | /// <param name="maximalSize"> | ||
151 | /// Cache's maximal size in bytes. | ||
152 | /// </param> | ||
153 | /// <param name="maximalCount"> | ||
154 | /// Cache's maximal count of assets. | ||
155 | /// </param> | ||
156 | /// <param name="expirationTime"> | ||
157 | /// Asset's expiration time. | ||
158 | /// </param> | ||
159 | public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime ) | ||
160 | { | ||
161 | if( maximalSize <= 0 || maximalCount <= 0 ) | ||
162 | { | ||
163 | Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." ); | ||
164 | m_enabled = false; | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | if( expirationTime <= TimeSpan.Zero ) | ||
169 | { | ||
170 | // Disable expiration time | ||
171 | expirationTime = TimeSpan.MaxValue; | ||
172 | } | ||
173 | |||
174 | // Create cache and add synchronization wrapper over it | ||
175 | m_cache = | ||
176 | CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>( | ||
177 | maximalSize, maximalCount, expirationTime ) ); | ||
178 | m_enabled = true; | ||
179 | Log.InfoFormat( | ||
180 | "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})", | ||
181 | maximalSize, | ||
182 | maximalCount, | ||
183 | expirationTime ); | ||
184 | } | ||
185 | |||
186 | #region IImprovedAssetCache Members | ||
187 | |||
188 | /// <summary> | ||
189 | /// Cache asset. | ||
190 | /// </summary> | ||
191 | /// <param name="asset"> | ||
192 | /// The asset that is being cached. | ||
193 | /// </param> | ||
194 | public void Cache( AssetBase asset ) | ||
195 | { | ||
196 | long size = asset.Data != null ? asset.Data.Length : 1; | ||
197 | m_cache.Set( asset.ID, asset, size ); | ||
198 | m_cachedCount++; | ||
199 | } | ||
200 | |||
201 | /// <summary> | ||
202 | /// Clear asset cache. | ||
203 | /// </summary> | ||
204 | public void Clear() | ||
205 | { | ||
206 | m_cache.Clear(); | ||
207 | } | ||
208 | |||
209 | /// <summary> | ||
210 | /// Expire (remove) asset stored to cache. | ||
211 | /// </summary> | ||
212 | /// <param name="id"> | ||
213 | /// The expired asset's id. | ||
214 | /// </param> | ||
215 | public void Expire( string id ) | ||
216 | { | ||
217 | m_cache.Remove( id ); | ||
218 | } | ||
219 | |||
220 | /// <summary> | ||
221 | /// Get asset stored | ||
222 | /// </summary> | ||
223 | /// <param name="id"> | ||
224 | /// The asset's id. | ||
225 | /// </param> | ||
226 | /// <returns> | ||
227 | /// Asset if it is found from cache; otherwise <see langword="null"/>. | ||
228 | /// </returns> | ||
229 | /// <remarks> | ||
230 | /// <para> | ||
231 | /// Caller should always check that is return value <see langword="null"/>. | ||
232 | /// Cache doesn't guarantee in any situation that asset is stored to it. | ||
233 | /// </para> | ||
234 | /// </remarks> | ||
235 | public AssetBase Get( string id ) | ||
236 | { | ||
237 | m_getCount++; | ||
238 | AssetBase assetBase; | ||
239 | if( m_cache.TryGetValue( id, out assetBase ) ) | ||
240 | m_hitCount++; | ||
241 | |||
242 | if( m_getCount == m_debugEpoch ) | ||
243 | { | ||
244 | Log.InfoFormat( | ||
245 | "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes", | ||
246 | m_cachedCount, | ||
247 | m_getCount, | ||
248 | ((double) m_hitCount / m_getCount) * 100.0, | ||
249 | m_cache.Size, | ||
250 | m_cache.Size / m_cache.Count ); | ||
251 | m_getCount = 0; | ||
252 | m_hitCount = 0; | ||
253 | m_cachedCount = 0; | ||
254 | } | ||
255 | |||
256 | return assetBase; | ||
257 | } | ||
258 | |||
259 | #endregion | ||
260 | |||
261 | #region ISharedRegionModule Members | ||
262 | |||
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 | IConfig moduleConfig = source.Configs[ "Modules" ]; | ||
305 | if( moduleConfig == null ) | ||
306 | return; | ||
307 | |||
308 | string 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 | long maxSize = DefaultMaxSize; | ||
316 | int maxCount = DefaultMaxCount; | ||
317 | TimeSpan expirationTime = DefaultExpirationTime; | ||
318 | |||
319 | IConfig 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 | |||
380 | #endregion | ||
381 | } | ||
382 | } | ||
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 393f340..9969ebe 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | |||
@@ -19,6 +19,7 @@ | |||
19 | <RegionModule id="HGAssetBroker" type="OpenSim.Region.CoreModules.ServiceConnectors.Asset.HGAssetBroker" /> | 19 | <RegionModule id="HGAssetBroker" type="OpenSim.Region.CoreModules.ServiceConnectors.Asset.HGAssetBroker" /> |
20 | <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" /> | 20 | <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" /> |
21 | <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" /> | 21 | <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" /> |
22 | <RegionModule id="CenomeMemoryAssetCache" type="OpenSim.Region.CoreModules.Asset.CenomeMemoryAssetCache"/> | ||
22 | <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" /> | 23 | <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" /> |
23 | <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" /> | 24 | <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" /> |
24 | </Extension> | 25 | </Extension> |