From: Kevin W. <kev...@us...> - 2005-04-04 04:27:47
|
Update of /cvsroot/nhibernate/NHibernateContrib/src/NHibernate.Caches/SysCache In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28543 Added Files: SysCache.cs syscache.nunit SysCacheFixture.cs SysCacheProvider.cs SysCacheProviderFixture.cs Log Message: migrating cache implementations to new folder --- NEW FILE: SysCacheFixture.cs --- #region License // // SysCache - A cache provider for NHibernate using System.Web.Caching.Cache. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // CLOVER:OFF // #endregion using System; using System.Collections; using NHibernate.Cache; using NUnit.Framework; namespace NHibernate.Caches.SysCache.Tests { [TestFixture] public class SysCacheFixture { private SysCacheProvider provider; private Hashtable props; [TestFixtureSetUp] public void FixtureSetup() { log4net.Config.DOMConfigurator.Configure(); props = new Hashtable(); props.Add( "relativeExpiration", 120 ); props.Add( "priority", 4 ); provider = new SysCacheProvider(); } [Test] public void TestPut() { string key = "key1"; string value = "value"; ICache cache = provider.BuildCache( "nunit", props ); Assert.IsNotNull( cache, "no cache returned" ); Assert.IsNull( cache.Get( key ), "cache returned an item we didn't add !?!" ); cache.Put( key, value ); object item = cache.Get( key ); Assert.IsNotNull( item ); Assert.AreEqual( value, item, "didn't return the item we added" ); } [Test] public void TestRemove() { string key = "key1"; string value = "value"; ICache cache = provider.BuildCache( "nunit", props ); Assert.IsNotNull( cache, "no cache returned" ); // add the item cache.Put( key, value ); // make sure it's there object item = cache.Get( key ); Assert.IsNotNull( item, "item just added is not there" ); // remove it cache.Remove( key ); // make sure it's not there item = cache.Get( key ); Assert.IsNull( item, "item still exists in cache" ); } [Test] public void TestClear() { string key = "key1"; string value = "value"; ICache cache = provider.BuildCache( "nunit", props ); Assert.IsNotNull( cache, "no cache returned" ); // add the item cache.Put( key, value ); // make sure it's there object item = cache.Get( key ); Assert.IsNotNull( item, "couldn't find item in cache" ); // clear the cache cache.Clear(); // make sure we don't get an item item = cache.Get( key ); Assert.IsNull( item, "item still exists in cache" ); } [Test] public void TestDefaultConstructor() { ICache cache = new SysCache(); Assert.IsNotNull( cache ); } [Test] public void TestNoPropertiesConstructor() { ICache cache = new SysCache( "nunit" ); Assert.IsNotNull( cache ); } [Test] [ExpectedException( typeof( IndexOutOfRangeException ) )] public void TestPriorityOutOfRange() { Hashtable h = new Hashtable(); h.Add( "priority", 7 ); new SysCache( "nunit", h ); } [Test] [ExpectedException( typeof( NotSupportedException ) )] public void TestDoubleException() { Hashtable h = new Hashtable(); h.Add( "staticExpiration", DateTime.Now ); h.Add( "relativeExpiration", 300 ); new SysCache( "nunit", h ); } [Test] [ExpectedException( typeof( ArgumentOutOfRangeException ) )] public void TestHistoricStaticExpiration() { Hashtable h = new Hashtable(); h.Add( "staticExpiration", DateTime.Parse( "1/1/1980") ); new SysCache( "nunit", h ); } [Test] [ExpectedException( typeof( ArgumentException ) )] public void TestBadStaticExpiration() { Hashtable h = new Hashtable(); h.Add( "staticExpiration", "foobar" ); new SysCache( "nunit", h ); } [Test] [ExpectedException( typeof( ArgumentException ) )] public void TestBadRelativeExpiration() { Hashtable h = new Hashtable(); h.Add( "relativeExpiration", "foobar" ); new SysCache( "nunit", h ); } [Test] public void TestEmptyProperties() { ICache cache = new SysCache( "nunit", new Hashtable() ); Assert.IsNotNull( cache ); } [Test] [ExpectedException( typeof( ArgumentNullException ) )] public void TestNullKeyPut() { ICache cache = new SysCache(); cache.Put( null, null ); } [Test] [ExpectedException( typeof( ArgumentNullException ) )] public void TestNullValuePut() { ICache cache = new SysCache(); cache.Put( "nunit", null ); } [Test] public void TestNullKeyGet() { ICache cache = new SysCache(); cache.Put( "nunit", "value" ); object item = cache.Get( null ); Assert.IsNull( item ); } [Test] [ExpectedException( typeof( ArgumentNullException ) )] public void TestNullKeyRemove() { ICache cache = new SysCache(); cache.Remove( null ); } [Test] public void TestRegions() { string key = "key"; ICache cache1 = provider.BuildCache( "nunit1", props ); ICache cache2 = provider.BuildCache( "nunit2", props ); string s1 = "test1"; string s2 = "test2"; cache1.Put( key, s1 ); cache2.Put( key, s2 ); object get1 = cache1.Get( key ); object get2 = cache2.Get( key ); Assert.IsFalse( get1 == get2 ); } } } --- NEW FILE: SysCache.cs --- #region License // // SysCache - A cache provider for NHibernate using System.Web.Caching.Cache. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #endregion using System; using System.Collections; using System.Web; using AspCache = System.Web.Caching; // clash with new NHibernate namespace below using log4net; using NHibernate.Cache; namespace NHibernate.Caches.SysCache { /// <summary> /// Pluggable cache implementation using the System.Web.Caching classes /// </summary> public class SysCache : ICache { private static readonly ILog log = LogManager.GetLogger( typeof( SysCache ) ); private string _region; private AspCache.Cache _cache; private DateTime _absExpiration; private TimeSpan _slidingExpiration; private AspCache.CacheItemPriority _priority; private Hashtable _map; private static readonly TimeSpan _defaultRelativeExpiration = TimeSpan.FromSeconds( 300 ); private static readonly string _cacheKeyPrefix = "NHibernate-Cache:"; /// <summary> /// default constructor /// </summary> public SysCache() : this( null, null ) { } /// <summary> /// constructor with no properties /// </summary> /// <param name="region"></param> public SysCache( string region ) : this( region, null ) { } /// <summary> /// full constructor /// </summary> /// <param name="region"></param> /// <param name="properties">cache configuration properties</param> /// <remarks> /// There are three (3) configurable parameters: /// <ul> /// <li>staticExpiration = a specific DateTime to expire each item on</li> /// <li>relativeExpiration = number of seconds to wait before expiring each item</li> /// <li>priority = a numeric cost of expiring each item, where 1 is a low cost, 5 is the highest, and 3 is normal. Only values 1 through 5 are valid.</li> /// </ul> /// staticExpiration and relativeExpiration are exclusive - you can only specify one or the other, not both. /// All parameters are optional. The defaults are a relativeExpiration of 300 seconds and the default priority of 3. /// </remarks> /// <exception cref="IndexOutOfRangeException">The "priority" property is not between 1 and 5</exception> /// <exception cref="NotSupportedException">"staticExpiration" and "relativeExpiration" properties were both specified.</exception> /// <exception cref="ArgumentOutOfRangeException">The "staticExpiration" property is not in the future.</exception> /// <exception cref="ArgumentException">The "relativeExpiration" property could not be parsed.</exception> public SysCache( string region, IDictionary properties ) { _region = region; _map = new Hashtable(); _cache = HttpRuntime.Cache; Configure( properties ); } private void Configure( IDictionary props ) { if( props == null ) { if( log.IsDebugEnabled ) { log.Debug( "configuring cache with default values" ); } _absExpiration = AspCache.Cache.NoAbsoluteExpiration; _slidingExpiration = _defaultRelativeExpiration; _priority = AspCache.CacheItemPriority.Default; } else { if( props["priority"] != null ) { int priority = Convert.ToInt32( props["priority"] ); if( priority < 1 || priority > 5 ) { if( log.IsWarnEnabled ) { log.Warn( "priority value out of range: " + priority.ToString() ); } throw new IndexOutOfRangeException( "priority must be between 1 and 5" ); } _priority = (AspCache.CacheItemPriority)priority; if( log.IsDebugEnabled ) { log.Debug( "new priority: " + _priority.ToString() ); } } else { _priority = AspCache.CacheItemPriority.Default; } if( props["relativeExpiration"] == null && props["staticExpiration"] == null ) { if( log.IsDebugEnabled ) { log.Debug( "no expiration values given, using defaults" ); } _absExpiration = AspCache.Cache.NoAbsoluteExpiration; _slidingExpiration = _defaultRelativeExpiration; return; } if( props["relativeExpiration"] != null && props["staticExpiration"] != null ) { if( log.IsWarnEnabled ) { log.Warn( "both expiration types specified" ); } throw new NotSupportedException( "staticExpiration and relativeExpiration are exclusive - specify one or the other, not both." ); } if( props["relativeExpiration"] == null && props["staticExpiration"] != null ) { DateTime exp; if( props["staticExpiration"] is DateTime ) { exp = (DateTime)props["staticExpiration"]; } else { try { exp = DateTime.Parse( props["staticExpiration"].ToString() ); } catch( Exception ex ) { if( log.IsWarnEnabled ) { log.Warn( "could not parse static expiration" ); } throw new ArgumentException( "could not parse as DateTime", "staticExpiration", ex ); } } if( exp > DateTime.Now ) { _absExpiration = exp; if( log.IsDebugEnabled ) { log.Debug( "new static expiration value: " + _absExpiration.ToString() ); } } else { if( log.IsWarnEnabled ) { log.Warn( "static expiration not a future time or date" ); } throw new ArgumentOutOfRangeException( "staticExpiration", exp.ToString(), "staticExpiration must be in the future" ); } _slidingExpiration = _defaultRelativeExpiration; } else { _absExpiration = AspCache.Cache.NoAbsoluteExpiration; try { int seconds = Convert.ToInt32( props["relativeExpiration"] ); _slidingExpiration = TimeSpan.FromSeconds( seconds ); if( log.IsDebugEnabled ) { log.Debug( "new relative expiration value: " + seconds.ToString() ); } } catch( Exception ex ) { if( log.IsWarnEnabled ) { log.Warn( "error parsing relative expiration value" ); } throw new ArgumentException( "could not parse relativeException as a number of seconds", "relativeException", ex ); } } } } private string GetCacheKey( object key ) { return String.Concat( _cacheKeyPrefix, _region, ":", key.ToString() ); } /// <summary></summary> /// <param name="key"></param> /// <returns></returns> public object Get( object key ) { if( key == null ) { return null; } string cacheKey = GetCacheKey( key ); if( log.IsDebugEnabled ) { log.Debug( String.Format( "Fetching object '{0}' from the cache.", cacheKey ) ); } return _cache.Get( cacheKey ); } /// <summary></summary> /// <param name="key"></param> /// <param name="value"></param> public void Put( object key, object value ) { if( key == null ) { throw new ArgumentNullException( "key", "null key not allowed" ); } if( value == null ) { throw new ArgumentNullException( "value", "null value not allowed" ); } string cacheKey = GetCacheKey( key ); if( _cache[ cacheKey ] != null ) { if( log.IsDebugEnabled ) { log.Debug( String.Format("updating value of key '{0}' to '{1}'.", cacheKey, value.ToString() ) ); } _cache[ cacheKey ] = value; } else { if( log.IsDebugEnabled ) { log.Debug( String.Format("adding new data: key={0}&value={1}", cacheKey, value.ToString() ) ); } _map.Add( cacheKey, value ); _cache.Add( cacheKey, value, null, _absExpiration, _slidingExpiration, _priority, new AspCache.CacheItemRemovedCallback( this.CacheItemRemoved ) ); } } /// <summary> /// make sure the Hashtable is in sync with the cache by using the callback. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="reason"></param> public void CacheItemRemoved( string key, object value, AspCache.CacheItemRemovedReason reason ) { _map.Remove( key ); } /// <summary></summary> /// <param name="key"></param> public void Remove( object key ) { if( key == null ) { throw new ArgumentNullException( "key" ); } string cacheKey = GetCacheKey( key ); if( log.IsDebugEnabled ) { log.Debug( "removing item with key: " + cacheKey ); } _map.Remove( cacheKey ); // possibly not needed now that callbacks are used _cache.Remove( cacheKey ); } /// <summary></summary> public void Clear() { ArrayList keys = new ArrayList( _map.Keys ); foreach( object key in keys ) { _cache.Remove( key.ToString() ); } _map.Clear(); } /// <summary></summary> public void Destroy() { Clear(); } /// <summary></summary> public string Region { set { _region = value; } } } } --- NEW FILE: SysCacheProviderFixture.cs --- #region License // // SysCache - A cache provider for NHibernate using System.Web.Caching.Cache. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // CLOVER:OFF // #endregion using System; using System.Collections; using NHibernate.Cache; using NUnit.Framework; namespace NHibernate.Caches.SysCache.Tests { [TestFixture] public class SysCacheProviderFixture { private ICacheProvider provider; private Hashtable props; [TestFixtureSetUp] public void FixtureSetup() { log4net.Config.DOMConfigurator.Configure(); props = new Hashtable(); props.Add( "staticExpiration", DateTime.Parse( "1/1/3000" ) ); props.Add( "priority", 2 ); } [SetUp] public void Setup() { provider = new SysCacheProvider(); } [Test] public void TestBuildCacheNullNull() { ICache cache = provider.BuildCache( null, null ); Assert.IsNotNull( cache, "no cache returned" ); } [Test] public void TestBuildCacheStringNull() { ICache cache = provider.BuildCache( "a_region", null ); Assert.IsNotNull( cache, "no cache returned" ); } [Test] public void TestBuildCacheStringICollection() { ICache cache = provider.BuildCache( "another_region", props ); Assert.IsNotNull( cache, "no cache returned" ); } [Test] public void TestNextTimestamp() { long ts = provider.NextTimestamp(); Assert.IsNotNull( ts, "no timestamp returned" ); } } } --- NEW FILE: SysCacheProvider.cs --- #region License // // SysCache - A cache provider for NHibernate using System.Web.Caching.Cache. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #endregion using System; using System.Collections; using System.Text; using log4net; using NHibernate.Cache; namespace NHibernate.Caches.SysCache { /// <summary> /// Cache provider using the System.Web.Caching classes /// </summary> public class SysCacheProvider : ICacheProvider { private static readonly ILog log = LogManager.GetLogger( typeof( SysCacheProvider ) ); /// <summary> /// build a new SysCache /// </summary> /// <param name="regionName"></param> /// <param name="properties"></param> /// <returns></returns> [CLSCompliant(false)] public ICache BuildCache( string regionName, IDictionary properties ) { if( regionName == null ) { regionName = ""; } if( properties == null ) { properties = new Hashtable(); } if( log.IsDebugEnabled ) { StringBuilder sb = new StringBuilder(); foreach( DictionaryEntry de in properties ) { sb.Append( "name=" ); sb.Append( de.Key.ToString() ); sb.Append( "&value=" ); sb.Append( de.Value.ToString() ); sb.Append( ";" ); } log.Debug( "building cache with region: " + regionName + ", properties: " + sb.ToString() ); } return new SysCache( regionName, properties ); } /// <summary></summary> /// <returns></returns> public long NextTimestamp() { return Timestamper.Next(); } } } --- NEW FILE: syscache.nunit --- <NUnitProject> <Settings activeconfig="Debug"/> <Config name="Debug"> <assembly path="bin\Debug\NHibernate.Caches.SysCache.Tests.dll"/> </Config> <Config name="Release"> <assembly path="bin\Release\NHibernate.Caches.SysCache.Tests.dll"/> </Config> </NUnitProject> |