Update svn properties.

0.6.6-post-fixes
Jeff Ames 2009-06-04 00:51:02 +00:00
parent 14bb372bb0
commit 007016ecd2
5 changed files with 3519 additions and 3519 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,441 +1,441 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the * * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
/// <summary> /// <summary>
/// Represent generic cache to store key/value pairs (elements) limited by time, size and count of elements. /// Represent generic cache to store key/value pairs (elements) limited by time, size and count of elements.
/// </summary> /// </summary>
/// <typeparam name="TKey"> /// <typeparam name="TKey">
/// The type of keys in the cache. /// The type of keys in the cache.
/// </typeparam> /// </typeparam>
/// <typeparam name="TValue"> /// <typeparam name="TValue">
/// The type of values in the cache. /// The type of values in the cache.
/// </typeparam> /// </typeparam>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Cache store limitations: /// Cache store limitations:
/// </para> /// </para>
/// <list type="table"> /// <list type="table">
/// <listheader> /// <listheader>
/// <term>Limitation</term> /// <term>Limitation</term>
/// <description>Description</description> /// <description>Description</description>
/// </listheader> /// </listheader>
/// <item> /// <item>
/// <term>Time</term> /// <term>Time</term>
/// <description> /// <description>
/// Element that is not accessed through <see cref="TryGetValue"/> or <see cref="Set"/> in last <see cref="ExpirationTime"/> are /// Element that is not accessed through <see cref="TryGetValue"/> or <see cref="Set"/> in last <see cref="ExpirationTime"/> are
/// removed from the cache automatically. Depending on implementation of the cache some of elements may stay longer in cache. /// removed from the cache automatically. Depending on implementation of the cache some of elements may stay longer in cache.
/// <see cref="IsTimeLimited"/> returns <see langword="true"/>, if cache is limited by time. /// <see cref="IsTimeLimited"/> returns <see langword="true"/>, if cache is limited by time.
/// </description> /// </description>
/// </item> /// </item>
/// <item> /// <item>
/// <term>Count</term> /// <term>Count</term>
/// <description> /// <description>
/// When adding an new element to cache that already have <see cref="MaxCount"/> of elements, cache will remove less recently /// When adding an new element to cache that already have <see cref="MaxCount"/> of elements, cache will remove less recently
/// used element(s) from the cache, until element fits to cache. /// used element(s) from the cache, until element fits to cache.
/// <see cref="IsCountLimited"/> returns <see langword="true"/>, if cache is limiting element count. /// <see cref="IsCountLimited"/> returns <see langword="true"/>, if cache is limiting element count.
/// </description> /// </description>
/// </item> /// </item>
/// <item> /// <item>
/// <term>Size</term> /// <term>Size</term>
/// <description> /// <description>
/// <description> /// <description>
/// When adding an new element to cache that already have <see cref="MaxSize"/> of elements, cache will remove less recently /// When adding an new element to cache that already have <see cref="MaxSize"/> of elements, cache will remove less recently
/// used element(s) from the cache, until element fits to cache. /// used element(s) from the cache, until element fits to cache.
/// <see cref="IsSizeLimited"/> returns <see langword="true"/>, if cache is limiting total size of elements. /// <see cref="IsSizeLimited"/> returns <see langword="true"/>, if cache is limiting total size of elements.
/// Normally size is bytes used by element in the cache. But it can be any other suitable unit of measure. /// Normally size is bytes used by element in the cache. But it can be any other suitable unit of measure.
/// </description> /// </description>
/// </description> /// </description>
/// </item> /// </item>
/// </list> /// </list>
/// </remarks> /// </remarks>
public interface ICnmCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> public interface ICnmCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{ {
/// <summary> /// <summary>
/// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="MaxCount"/> /// <seealso cref="MaxCount"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="IsTimeLimited"/> /// <seealso cref="IsTimeLimited"/>
int Count { get; } int Count { get; }
/// <summary> /// <summary>
/// Gets or sets elements expiration time. /// Gets or sets elements expiration time.
/// </summary> /// </summary>
/// <value> /// <value>
/// Elements expiration time. /// Elements expiration time.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ExpirationTime"/> /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ExpirationTime"/>
/// and it is not accessed through <see cref="TryGetValue"/> method or element's value is /// and it is not accessed through <see cref="TryGetValue"/> method or element's value is
/// not replaced by <see cref="Set"/> method, then it is automatically removed from the /// not replaced by <see cref="Set"/> method, then it is automatically removed from the
/// <see cref="ICnmCache{TKey,TValue}"/>. /// <see cref="ICnmCache{TKey,TValue}"/>.
/// </para> /// </para>
/// <para> /// <para>
/// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time, /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
/// because total size or count of elements stored to cache is larger than <see cref="MaxSize"/> or <see cref="MaxCount"/>. /// because total size or count of elements stored to cache is larger than <see cref="MaxSize"/> or <see cref="MaxCount"/>.
/// </para> /// </para>
/// <para> /// <para>
/// It is also possible that element stays in cache longer than <see cref="ExpirationTime"/>. /// It is also possible that element stays in cache longer than <see cref="ExpirationTime"/>.
/// </para> /// </para>
/// <para> /// <para>
/// Calling <see cref="PurgeExpired"/> try to remove all elements that are expired. /// Calling <see cref="PurgeExpired"/> try to remove all elements that are expired.
/// </para> /// </para>
/// <para> /// <para>
/// To disable time limit in cache, set <see cref="ExpirationTime"/> to <see cref="DateTime.MaxValue"/>. /// To disable time limit in cache, set <see cref="ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="IsTimeLimited"/> /// <seealso cref="IsTimeLimited"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
/// <seealso cref="Count"/> /// <seealso cref="Count"/>
/// <seealso cref="MaxCount"/> /// <seealso cref="MaxCount"/>
/// <seealso cref="MaxSize"/> /// <seealso cref="MaxSize"/>
/// <seealso cref="Size"/> /// <seealso cref="Size"/>
TimeSpan ExpirationTime { get; set; } TimeSpan ExpirationTime { get; set; }
/// <summary> /// <summary>
/// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe). /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
/// </summary> /// </summary>
/// <value> /// <value>
/// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe); /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
/// otherwise, <see langword="false"/>. /// otherwise, <see langword="false"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
/// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
/// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object. /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="SyncRoot"/> /// <seealso cref="SyncRoot"/>
/// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
bool IsSynchronized { get; } bool IsSynchronized { get; }
/// <summary> /// <summary>
/// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements. /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
/// </summary> /// </summary>
/// <value> /// <value>
/// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited; /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
/// otherwise, <see langword="false"/>. /// otherwise, <see langword="false"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="Count"/> /// <seealso cref="Count"/>
/// <seealso cref="MaxCount"/> /// <seealso cref="MaxCount"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="IsTimeLimited"/> /// <seealso cref="IsTimeLimited"/>
bool IsCountLimited { get; } bool IsCountLimited { get; }
/// <summary> /// <summary>
/// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements. /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
/// </summary> /// </summary>
/// <value> /// <value>
/// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited; /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
/// otherwise, <see langword="false"/>. /// otherwise, <see langword="false"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="MaxElementSize"/> /// <seealso cref="MaxElementSize"/>
/// <seealso cref="Size"/> /// <seealso cref="Size"/>
/// <seealso cref="MaxSize"/> /// <seealso cref="MaxSize"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="IsTimeLimited"/> /// <seealso cref="IsTimeLimited"/>
bool IsSizeLimited { get; } bool IsSizeLimited { get; }
/// <summary> /// <summary>
/// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time. /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
/// </summary> /// </summary>
/// <value> /// <value>
/// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements; /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
/// otherwise, <see langword="false"/>. /// otherwise, <see langword="false"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="Set"/> /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="Set"/>
/// or <see cref="TryGetValue"/> methods in <see cref="ExpirationTime"/> , then element is automatically removed from /// or <see cref="TryGetValue"/> methods in <see cref="ExpirationTime"/> , then element is automatically removed from
/// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
/// stay longer in cache. /// stay longer in cache.
/// </remarks> /// </remarks>
/// <seealso cref="ExpirationTime"/> /// <seealso cref="ExpirationTime"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
bool IsTimeLimited { get; } bool IsTimeLimited { get; }
/// <summary> /// <summary>
/// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements; /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
/// otherwise maximal allowed count of elements. /// otherwise maximal allowed count of elements.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
int MaxCount { get; set; } int MaxCount { get; set; }
/// <summary> /// <summary>
/// <para>Gets maximal allowed element size.</para> /// <para>Gets maximal allowed element size.</para>
/// </summary> /// </summary>
/// <value> /// <value>
/// Maximal allowed element size. /// Maximal allowed element size.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// If element's size is larger than <see cref="MaxElementSize"/>, then element is /// If element's size is larger than <see cref="MaxElementSize"/>, then element is
/// not added to the <see cref="ICnmCache{TKey,TValue}"/>. /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="Size"/> /// <seealso cref="Size"/>
/// <seealso cref="MaxSize"/> /// <seealso cref="MaxSize"/>
long MaxElementSize { get; } long MaxElementSize { get; }
/// <summary> /// <summary>
/// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure. /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
/// </para> /// </para>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception> /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception>
/// <seealso cref="MaxElementSize"/> /// <seealso cref="MaxElementSize"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="Size"/> /// <seealso cref="Size"/>
long MaxSize { get; set; } long MaxSize { get; set; }
/// <summary> /// <summary>
/// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Normally bytes, but can be any suitable unit of measure. /// Normally bytes, but can be any suitable unit of measure.
/// </para> /// </para>
/// <para> /// <para>
/// Element's size is given when element is added or replaced by <see cref="Set"/> method. /// Element's size is given when element is added or replaced by <see cref="Set"/> method.
/// </para> /// </para>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
/// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="MaxElementSize"/> /// <seealso cref="MaxElementSize"/>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="MaxSize"/> /// <seealso cref="MaxSize"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="ExpirationTime"/> /// <seealso cref="ExpirationTime"/>
long Size { get; } long Size { get; }
/// <summary> /// <summary>
/// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
/// </value> /// </value>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/> /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
/// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
/// <see cref="ICnmCache{TKey,TValue}"/>. /// <see cref="ICnmCache{TKey,TValue}"/>.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="IsSynchronized"/> /// <seealso cref="IsSynchronized"/>
/// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
object SyncRoot { get; } object SyncRoot { get; }
/// <summary> /// <summary>
/// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>. /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="Remove"/> /// <seealso cref="Remove"/>
/// <seealso cref="RemoveRange"/> /// <seealso cref="RemoveRange"/>
/// <seealso cref="TryGetValue"/> /// <seealso cref="TryGetValue"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
void Clear(); void Clear();
/// <summary> /// <summary>
/// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>. /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Element becomes expired when last access time to it has been longer time than <see cref="ExpirationTime"/>. /// Element becomes expired when last access time to it has been longer time than <see cref="ExpirationTime"/>.
/// </para> /// </para>
/// <para> /// <para>
/// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
/// may stay longer than <see cref="ExpirationTime"/> in the cache. /// may stay longer than <see cref="ExpirationTime"/> in the cache.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="IsTimeLimited"/> /// <seealso cref="IsTimeLimited"/>
/// <seealso cref="ExpirationTime"/> /// <seealso cref="ExpirationTime"/>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="Remove"/> /// <seealso cref="Remove"/>
/// <seealso cref="RemoveRange"/> /// <seealso cref="RemoveRange"/>
/// <seealso cref="TryGetValue"/> /// <seealso cref="TryGetValue"/>
/// <seealso cref="Clear"/> /// <seealso cref="Clear"/>
void PurgeExpired(); void PurgeExpired();
/// <summary> /// <summary>
/// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>. /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <param name="key"> /// <param name="key">
/// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>. /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </param> /// </param>
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="key"/> is <see langword="null"/>. /// <paramref name="key"/> is <see langword="null"/>.
/// </exception> /// </exception>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="RemoveRange"/> /// <seealso cref="RemoveRange"/>
/// <seealso cref="TryGetValue"/> /// <seealso cref="TryGetValue"/>
/// <seealso cref="Clear"/> /// <seealso cref="Clear"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
void Remove( TKey key ); void Remove( TKey key );
/// <summary> /// <summary>
/// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>. /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <param name="keys"> /// <param name="keys">
/// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>. /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </param> /// </param>
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="keys"/> is <see langword="null"/>. /// <paramref name="keys"/> is <see langword="null"/>.
/// </exception> /// </exception>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="Remove"/> /// <seealso cref="Remove"/>
/// <seealso cref="TryGetValue"/> /// <seealso cref="TryGetValue"/>
/// <seealso cref="Clear"/> /// <seealso cref="Clear"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
void RemoveRange( IEnumerable<TKey> keys ); void RemoveRange( IEnumerable<TKey> keys );
/// <summary> /// <summary>
/// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
/// <see cref="ICnmCache{TKey,TValue}"/>. /// <see cref="ICnmCache{TKey,TValue}"/>.
/// </summary> /// </summary>
/// <param name="key"> /// <param name="key">
/// The object used as the key of the element. Can't be <see langword="null"/> reference. /// The object used as the key of the element. Can't be <see langword="null"/> reference.
/// </param> /// </param>
/// <param name="value"> /// <param name="value">
/// The object used as the value of the element to add or replace. <see langword="null"/> is allowed. /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
/// </param> /// </param>
/// <param name="size"> /// <param name="size">
/// The element's size. Normally bytes, but can be any suitable unit of measure. /// The element's size. Normally bytes, but can be any suitable unit of measure.
/// </param> /// </param>
/// <returns> /// <returns>
/// <see langword="true"/> if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>; /// <see langword="true"/> if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
/// otherwise <see langword="false"/>. /// otherwise <see langword="false"/>.
/// </returns> /// </returns>
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="key"/>is <see langword="null"/>. /// <paramref name="key"/>is <see langword="null"/>.
/// </exception> /// </exception>
/// <exception cref="ArgumentOutOfRangeException"> /// <exception cref="ArgumentOutOfRangeException">
/// The element's <paramref name="size"/> is less than 0. /// The element's <paramref name="size"/> is less than 0.
/// </exception> /// </exception>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// If element's <paramref name="size"/> is larger than <see cref="MaxElementSize"/>, then element is /// If element's <paramref name="size"/> is larger than <see cref="MaxElementSize"/>, then element is
/// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
/// removed from the <see cref="ICnmCache{TKey,TValue}"/>. /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
/// </para> /// </para>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
/// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// <para> /// <para>
/// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
/// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="IsSizeLimited"/> /// <seealso cref="IsSizeLimited"/>
/// <seealso cref="IsCountLimited"/> /// <seealso cref="IsCountLimited"/>
/// <seealso cref="Remove"/> /// <seealso cref="Remove"/>
/// <seealso cref="RemoveRange"/> /// <seealso cref="RemoveRange"/>
/// <seealso cref="TryGetValue"/> /// <seealso cref="TryGetValue"/>
/// <seealso cref="Clear"/> /// <seealso cref="Clear"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
bool Set( TKey key, TValue value, long size ); bool Set( TKey key, TValue value, long size );
/// <summary> /// <summary>
/// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>. /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
/// the specified key; otherwise, <see langword="false"/>. /// the specified key; otherwise, <see langword="false"/>.
/// </returns> /// </returns>
/// <param name="key"> /// <param name="key">
/// The key whose <paramref name="value"/> to get. /// The key whose <paramref name="value"/> to get.
/// </param> /// </param>
/// <param name="value"> /// <param name="value">
/// When this method returns, the value associated with the specified <paramref name="key"/>, /// When this method returns, the value associated with the specified <paramref name="key"/>,
/// if the <paramref name="key"/> is found; otherwise, the /// if the <paramref name="key"/> is found; otherwise, the
/// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized. /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
/// </param> /// </param>
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="key"/>is <see langword="null"/>. /// <paramref name="key"/>is <see langword="null"/>.
/// </exception> /// </exception>
/// <seealso cref="Set"/> /// <seealso cref="Set"/>
/// <seealso cref="Remove"/> /// <seealso cref="Remove"/>
/// <seealso cref="RemoveRange"/> /// <seealso cref="RemoveRange"/>
/// <seealso cref="Clear"/> /// <seealso cref="Clear"/>
/// <seealso cref="PurgeExpired"/> /// <seealso cref="PurgeExpired"/>
bool TryGetValue( TKey key, out TValue value ); bool TryGetValue( TKey key, out TValue value );
} }
} }

View File

@ -1,98 +1,98 @@
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// <copyright company="" file="PrimeNumberHelper.cs"> // <copyright company="" file="PrimeNumberHelper.cs">
// //
// </copyright> // </copyright>
// <summary> // <summary>
// //
// </summary> // </summary>
// //
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
using System; using System;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
/// <summary> /// <summary>
/// Utility class that is used to find small prime numbers and test is number prime number. /// Utility class that is used to find small prime numbers and test is number prime number.
/// </summary> /// </summary>
public static class PrimeNumberHelper public static class PrimeNumberHelper
{ {
/// <summary> /// <summary>
/// Precalculated prime numbers. /// Precalculated prime numbers.
/// </summary> /// </summary>
private static readonly int[] Primes = new int[] private static readonly int[] Primes = new int[]
{ {
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239,
293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333,
2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431,
90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449,
389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559,
5999471, 7199369 5999471, 7199369
}; };
/// <summary> /// <summary>
/// Get prime number that is equal or larger than <see cref="min"/>. /// Get prime number that is equal or larger than <see cref="min"/>.
/// </summary> /// </summary>
/// <param name="min"> /// <param name="min">
/// Minimal returned prime number. /// Minimal returned prime number.
/// </param> /// </param>
/// <returns> /// <returns>
/// Primer number that is equal or larger than <see cref="min"/>. If <see cref="min"/> is too large, return -1. /// Primer number that is equal or larger than <see cref="min"/>. If <see cref="min"/> is too large, return -1.
/// </returns> /// </returns>
public static int GetPrime( int min ) public static int GetPrime( int min )
{ {
if( min <= 2 ) if( min <= 2 )
return 2; return 2;
if( Primes[ Primes.Length - 1 ] < min ) if( Primes[ Primes.Length - 1 ] < min )
{ {
for( int i = min | 1 ; i < 0x7FFFFFFF ; i += 2 ) for( int i = min | 1 ; i < 0x7FFFFFFF ; i += 2 )
{ {
if( IsPrime( i ) ) if( IsPrime( i ) )
return i; return i;
} }
return -1; return -1;
} }
for( int i = Primes.Length - 2 ; i >= 0 ; i-- ) for( int i = Primes.Length - 2 ; i >= 0 ; i-- )
{ {
if( min == Primes[ i ] ) if( min == Primes[ i ] )
return min; return min;
if( min > Primes[ i ] ) if( min > Primes[ i ] )
return Primes[ i + 1 ]; return Primes[ i + 1 ];
} }
return 2; return 2;
} }
/// <summary> /// <summary>
/// Just basic Sieve of Eratosthenes prime number test. /// Just basic Sieve of Eratosthenes prime number test.
/// </summary> /// </summary>
/// <param name="candinate"> /// <param name="candinate">
/// Number that is tested. /// Number that is tested.
/// </param> /// </param>
/// <returns> /// <returns>
/// true, if <see cref="candinate"/> is prime number; otherwise false. /// true, if <see cref="candinate"/> is prime number; otherwise false.
/// </returns> /// </returns>
public static bool IsPrime( int candinate ) public static bool IsPrime( int candinate )
{ {
if( (candinate & 1) == 0 ) if( (candinate & 1) == 0 )
// Even number - only prime if 2 // Even number - only prime if 2
return candinate == 2; return candinate == 2;
int upperBound = (int) Math.Sqrt( candinate ); int upperBound = (int) Math.Sqrt( candinate );
for( int i = 3 ; i < upperBound ; i += 2 ) for( int i = 3 ; i < upperBound ; i += 2 )
{ {
if( candinate % i == 0 ) if( candinate % i == 0 )
return false; return false;
} }
return true; return true;
} }
} }
} }

View File

@ -1,382 +1,382 @@
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// <copyright company="" file="CenomeAssetCache.cs"> // <copyright company="" file="CenomeAssetCache.cs">
// //
// </copyright> // </copyright>
// <summary> // <summary>
// //
// </summary> // </summary>
// //
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
using System; using System;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Asset namespace OpenSim.Region.CoreModules.Asset
{ {
/// <summary> /// <summary>
/// Cenome memory asset cache. /// Cenome memory asset cache.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache". /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache".
/// When cache is successfully enable log should have message /// When cache is successfully enable log should have message
/// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)". /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)".
/// </para> /// </para>
/// <para> /// <para>
/// Cache's size is limited by two parameters: /// Cache's size is limited by two parameters:
/// maximal allowed size in bytes and maximal allowed asset count. When new asset /// maximal allowed size in bytes and maximal allowed asset count. When new asset
/// is added to cache that have achieved either size or count limitation, cache /// is added to cache that have achieved either size or count limitation, cache
/// will automatically remove less recently used assets from cache. Additionally /// will automatically remove less recently used assets from cache. Additionally
/// asset's lifetime is controlled by expiration time. /// asset's lifetime is controlled by expiration time.
/// </para> /// </para>
/// <para> /// <para>
/// <list type="table"> /// <list type="table">
/// <listheader> /// <listheader>
/// <term>Configuration</term> /// <term>Configuration</term>
/// <description>Description</description> /// <description>Description</description>
/// </listheader> /// </listheader>
/// <item> /// <item>
/// <term>MaxSize</term> /// <term>MaxSize</term>
/// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description> /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description>
/// </item> /// </item>
/// <item> /// <item>
/// <term>MaxCount</term> /// <term>MaxCount</term>
/// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description> /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description>
/// </item> /// </item>
/// <item> /// <item>
/// <term>ExpirationTime</term> /// <term>ExpirationTime</term>
/// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description> /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description>
/// </item> /// </item>
/// </list> /// </list>
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <example> /// <example>
/// Enabling Cenome Asset Cache: /// Enabling Cenome Asset Cache:
/// <code> /// <code>
/// [Modules] /// [Modules]
/// AssetCaching = "CenomeMemoryAssetCache" /// AssetCaching = "CenomeMemoryAssetCache"
/// </code> /// </code>
/// Setting size and expiration time limitations: /// Setting size and expiration time limitations:
/// <code> /// <code>
/// [AssetService] /// [AssetService]
/// ; 256 MB (default: 134217728) /// ; 256 MB (default: 134217728)
/// MaxSize = 268435456 /// MaxSize = 268435456
/// ; How many assets it is possible to store cache (default: 4096) /// ; How many assets it is possible to store cache (default: 4096)
/// MaxCount = 16384 /// MaxCount = 16384
/// ; Expiration time - 1 hour (default: 30 minutes) /// ; Expiration time - 1 hour (default: 30 minutes)
/// ExpirationTime = 60 /// ExpirationTime = 60
/// </code> /// </code>
/// </example> /// </example>
public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule
{ {
/// <summary> /// <summary>
/// Cache's default maximal asset count. /// Cache's default maximal asset count.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Assuming that average asset size is about 32768 bytes. /// Assuming that average asset size is about 32768 bytes.
/// </para> /// </para>
/// </remarks> /// </remarks>
public const int DefaultMaxCount = 4096; public const int DefaultMaxCount = 4096;
/// <summary> /// <summary>
/// Default maximal size of the cache in bytes /// Default maximal size of the cache in bytes
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// 128MB = 128 * 1024^2 = 134 217 728 bytes. /// 128MB = 128 * 1024^2 = 134 217 728 bytes.
/// </para> /// </para>
/// </remarks> /// </remarks>
public const long DefaultMaxSize = 134217728; public const long DefaultMaxSize = 134217728;
/// <summary> /// <summary>
/// Asset's default expiration time in the cache. /// Asset's default expiration time in the cache.
/// </summary> /// </summary>
public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 ); public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 );
/// <summary> /// <summary>
/// Log manager instance. /// Log manager instance.
/// </summary> /// </summary>
private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ); private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
/// <summary> /// <summary>
/// Cache object. /// Cache object.
/// </summary> /// </summary>
private ICnmCache<string, AssetBase> m_cache; private ICnmCache<string, AssetBase> m_cache;
/// <summary> /// <summary>
/// Count of cache commands /// Count of cache commands
/// </summary> /// </summary>
private int m_cachedCount; private int m_cachedCount;
/// <summary> /// <summary>
/// How many gets before dumping statistics /// How many gets before dumping statistics
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// If 0 or less, then disabled. /// If 0 or less, then disabled.
/// </remarks> /// </remarks>
private int m_debugEpoch; private int m_debugEpoch;
/// <summary> /// <summary>
/// Is Cenome asset cache enabled. /// Is Cenome asset cache enabled.
/// </summary> /// </summary>
private bool m_enabled; private bool m_enabled;
/// <summary> /// <summary>
/// Count of get requests /// Count of get requests
/// </summary> /// </summary>
private int m_getCount; private int m_getCount;
/// <summary> /// <summary>
/// How many hits /// How many hits
/// </summary> /// </summary>
private int m_hitCount; private int m_hitCount;
/// <summary> /// <summary>
/// Initialize asset cache module with default parameters. /// Initialize asset cache module with default parameters.
/// </summary> /// </summary>
public void Initialize() public void Initialize()
{ {
Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime ); Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime );
} }
/// <summary> /// <summary>
/// Initialize asset cache module, with custom parameters. /// Initialize asset cache module, with custom parameters.
/// </summary> /// </summary>
/// <param name="maximalSize"> /// <param name="maximalSize">
/// Cache's maximal size in bytes. /// Cache's maximal size in bytes.
/// </param> /// </param>
/// <param name="maximalCount"> /// <param name="maximalCount">
/// Cache's maximal count of assets. /// Cache's maximal count of assets.
/// </param> /// </param>
/// <param name="expirationTime"> /// <param name="expirationTime">
/// Asset's expiration time. /// Asset's expiration time.
/// </param> /// </param>
public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime ) public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime )
{ {
if( maximalSize <= 0 || maximalCount <= 0 ) if( maximalSize <= 0 || maximalCount <= 0 )
{ {
Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." ); Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." );
m_enabled = false; m_enabled = false;
return; return;
} }
if( expirationTime <= TimeSpan.Zero ) if( expirationTime <= TimeSpan.Zero )
{ {
// Disable expiration time // Disable expiration time
expirationTime = TimeSpan.MaxValue; expirationTime = TimeSpan.MaxValue;
} }
// Create cache and add synchronization wrapper over it // Create cache and add synchronization wrapper over it
m_cache = m_cache =
CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>( CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>(
maximalSize, maximalCount, expirationTime ) ); maximalSize, maximalCount, expirationTime ) );
m_enabled = true; m_enabled = true;
Log.InfoFormat( Log.InfoFormat(
"[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})", "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})",
maximalSize, maximalSize,
maximalCount, maximalCount,
expirationTime ); expirationTime );
} }
#region IImprovedAssetCache Members #region IImprovedAssetCache Members
/// <summary> /// <summary>
/// Cache asset. /// Cache asset.
/// </summary> /// </summary>
/// <param name="asset"> /// <param name="asset">
/// The asset that is being cached. /// The asset that is being cached.
/// </param> /// </param>
public void Cache( AssetBase asset ) public void Cache( AssetBase asset )
{ {
long size = asset.Data != null ? asset.Data.Length : 1; long size = asset.Data != null ? asset.Data.Length : 1;
m_cache.Set( asset.ID, asset, size ); m_cache.Set( asset.ID, asset, size );
m_cachedCount++; m_cachedCount++;
} }
/// <summary> /// <summary>
/// Clear asset cache. /// Clear asset cache.
/// </summary> /// </summary>
public void Clear() public void Clear()
{ {
m_cache.Clear(); m_cache.Clear();
} }
/// <summary> /// <summary>
/// Expire (remove) asset stored to cache. /// Expire (remove) asset stored to cache.
/// </summary> /// </summary>
/// <param name="id"> /// <param name="id">
/// The expired asset's id. /// The expired asset's id.
/// </param> /// </param>
public void Expire( string id ) public void Expire( string id )
{ {
m_cache.Remove( id ); m_cache.Remove( id );
} }
/// <summary> /// <summary>
/// Get asset stored /// Get asset stored
/// </summary> /// </summary>
/// <param name="id"> /// <param name="id">
/// The asset's id. /// The asset's id.
/// </param> /// </param>
/// <returns> /// <returns>
/// Asset if it is found from cache; otherwise <see langword="null"/>. /// Asset if it is found from cache; otherwise <see langword="null"/>.
/// </returns> /// </returns>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Caller should always check that is return value <see langword="null"/>. /// Caller should always check that is return value <see langword="null"/>.
/// Cache doesn't guarantee in any situation that asset is stored to it. /// Cache doesn't guarantee in any situation that asset is stored to it.
/// </para> /// </para>
/// </remarks> /// </remarks>
public AssetBase Get( string id ) public AssetBase Get( string id )
{ {
m_getCount++; m_getCount++;
AssetBase assetBase; AssetBase assetBase;
if( m_cache.TryGetValue( id, out assetBase ) ) if( m_cache.TryGetValue( id, out assetBase ) )
m_hitCount++; m_hitCount++;
if( m_getCount == m_debugEpoch ) if( m_getCount == m_debugEpoch )
{ {
Log.InfoFormat( Log.InfoFormat(
"[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes", "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes",
m_cachedCount, m_cachedCount,
m_getCount, m_getCount,
((double) m_hitCount / m_getCount) * 100.0, ((double) m_hitCount / m_getCount) * 100.0,
m_cache.Size, m_cache.Size,
m_cache.Size / m_cache.Count ); m_cache.Size / m_cache.Count );
m_getCount = 0; m_getCount = 0;
m_hitCount = 0; m_hitCount = 0;
m_cachedCount = 0; m_cachedCount = 0;
} }
return assetBase; return assetBase;
} }
#endregion #endregion
#region ISharedRegionModule Members #region ISharedRegionModule Members
/// <summary> /// <summary>
/// Gets region module's name. /// Gets region module's name.
/// </summary> /// </summary>
public string Name public string Name
{ {
get { return "CenomeMemoryAssetCache"; } get { return "CenomeMemoryAssetCache"; }
} }
/// <summary> /// <summary>
/// New region is being added to server. /// New region is being added to server.
/// </summary> /// </summary>
/// <param name="scene"> /// <param name="scene">
/// Region's scene. /// Region's scene.
/// </param> /// </param>
public void AddRegion( Scene scene ) public void AddRegion( Scene scene )
{ {
if( m_enabled ) if( m_enabled )
scene.RegisterModuleInterface<IImprovedAssetCache>( this ); scene.RegisterModuleInterface<IImprovedAssetCache>( this );
} }
/// <summary> /// <summary>
/// Close region module. /// Close region module.
/// </summary> /// </summary>
public void Close() public void Close()
{ {
m_enabled = false; m_enabled = false;
m_cache.Clear(); m_cache.Clear();
m_cache = null; m_cache = null;
} }
/// <summary> /// <summary>
/// Initialize region module. /// Initialize region module.
/// </summary> /// </summary>
/// <param name="source"> /// <param name="source">
/// Configuration source. /// Configuration source.
/// </param> /// </param>
public void Initialise( IConfigSource source ) public void Initialise( IConfigSource source )
{ {
m_cache = null; m_cache = null;
m_enabled = false; m_enabled = false;
IConfig moduleConfig = source.Configs[ "Modules" ]; IConfig moduleConfig = source.Configs[ "Modules" ];
if( moduleConfig == null ) if( moduleConfig == null )
return; return;
string name = moduleConfig.GetString( "AssetCaching" ); string name = moduleConfig.GetString( "AssetCaching" );
Log.DebugFormat( "[XXX] name = {0} (this module's name: {1}", name, Name ); Log.DebugFormat( "[XXX] name = {0} (this module's name: {1}", name, Name );
if( name != Name ) if( name != Name )
return; return;
// This module is used // This module is used
long maxSize = DefaultMaxSize; long maxSize = DefaultMaxSize;
int maxCount = DefaultMaxCount; int maxCount = DefaultMaxCount;
TimeSpan expirationTime = DefaultExpirationTime; TimeSpan expirationTime = DefaultExpirationTime;
IConfig assetConfig = source.Configs[ "AssetCache" ]; IConfig assetConfig = source.Configs[ "AssetCache" ];
if( assetConfig != null ) if( assetConfig != null )
{ {
// Get optional configurations // Get optional configurations
maxSize = assetConfig.GetLong( "MaxSize", DefaultMaxSize ); maxSize = assetConfig.GetLong( "MaxSize", DefaultMaxSize );
maxCount = assetConfig.GetInt( "MaxCount", DefaultMaxCount ); maxCount = assetConfig.GetInt( "MaxCount", DefaultMaxCount );
expirationTime = expirationTime =
TimeSpan.FromMinutes( assetConfig.GetInt( "ExpirationTime", (int) DefaultExpirationTime.TotalMinutes ) ); TimeSpan.FromMinutes( assetConfig.GetInt( "ExpirationTime", (int) DefaultExpirationTime.TotalMinutes ) );
// Debugging purposes only // Debugging purposes only
m_debugEpoch = assetConfig.GetInt( "DebugEpoch", 0 ); m_debugEpoch = assetConfig.GetInt( "DebugEpoch", 0 );
} }
Initialize( maxSize, maxCount, expirationTime ); Initialize( maxSize, maxCount, expirationTime );
} }
/// <summary> /// <summary>
/// Initialization post handling. /// Initialization post handling.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// Modules can use this to initialize connection with other modules. /// Modules can use this to initialize connection with other modules.
/// </para> /// </para>
/// </remarks> /// </remarks>
public void PostInitialise() public void PostInitialise()
{ {
} }
/// <summary> /// <summary>
/// Region has been loaded. /// Region has been loaded.
/// </summary> /// </summary>
/// <param name="scene"> /// <param name="scene">
/// Region's scene. /// Region's scene.
/// </param> /// </param>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// This is needed for all module types. Modules will register /// This is needed for all module types. Modules will register
/// Interfaces with scene in AddScene, and will also need a means /// Interfaces with scene in AddScene, and will also need a means
/// to access interfaces registered by other modules. Without /// to access interfaces registered by other modules. Without
/// this extra method, a module attempting to use another modules' /// this extra method, a module attempting to use another modules'
/// interface would be successful only depending on load order, /// interface would be successful only depending on load order,
/// which can't be depended upon, or modules would need to resort /// which can't be depended upon, or modules would need to resort
/// to ugly kludges to attempt to request interfaces when needed /// to ugly kludges to attempt to request interfaces when needed
/// and unnecessary caching logic repeated in all modules. /// and unnecessary caching logic repeated in all modules.
/// The extra function stub is just that much cleaner. /// The extra function stub is just that much cleaner.
/// </para> /// </para>
/// </remarks> /// </remarks>
public void RegionLoaded( Scene scene ) public void RegionLoaded( Scene scene )
{ {
} }
/// <summary> /// <summary>
/// Region is being removed. /// Region is being removed.
/// </summary> /// </summary>
/// <param name="scene"> /// <param name="scene">
/// Region scene that is being removed. /// Region scene that is being removed.
/// </param> /// </param>
public void RemoveRegion( Scene scene ) public void RemoveRegion( Scene scene )
{ {
} }
#endregion #endregion
} }
} }