From 3b982b80f5732b97488205b713e2d4bdcf441d23 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Sat, 23 Mar 2013 04:01:52 +0600 Subject: [PATCH] Fixes test issues, needed to disable application cache for these tests since the cache invalidation happens at the CacheRefresher level but for these tests (any many other ones) we are not 'booting' umbraco with the Boot managers so the CacheRefreshers are not wired up to listen to events to clear the cache. This puts us another step closer to having a proper global cache solution that will work for everything. At least now, all of the legacy code is using the ApplicationCache which we can now control from a central location. Changed NiceUrlsProviderWithDomainsTests to only require a new db schema per fixture. --- src/Umbraco.Core/ApplicationContext.cs | 45 ++- src/Umbraco.Core/Cache/CacheProviderBase.cs | 33 ++ .../Cache/HttpRuntimeCacheProvider.cs | 342 ++++++++++++++++++ src/Umbraco.Core/Cache/NullCacheProvider.cs | 81 +++++ src/Umbraco.Core/CacheHelper.cs | 253 ++++++------- src/Umbraco.Core/Umbraco.Core.csproj | 3 + src/Umbraco.Tests/BusinessLogic/BaseTest.cs | 2 +- src/Umbraco.Tests/Macros/MacroTests.cs | 3 +- .../Persistence/BaseTableByTableTest.cs | 7 +- .../Persistence/DatabaseContextTests.cs | 2 +- .../PublishedContentCacheTests.cs | 7 +- .../NiceUrlsProviderWithDomainsTests.cs | 5 + .../TestHelpers/BaseDatabaseFactoryTest.cs | 7 +- .../TestHelpers/BaseDatabaseTest.cs | 7 +- .../TestHelpers/BaseUmbracoApplicationTest.cs | 3 +- src/umbraco.cms/businesslogic/cache/Cache.cs | 2 +- 16 files changed, 654 insertions(+), 148 deletions(-) create mode 100644 src/Umbraco.Core/Cache/CacheProviderBase.cs create mode 100644 src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs create mode 100644 src/Umbraco.Core/Cache/NullCacheProvider.cs diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs index 36deb96dd1..27ade0f7b5 100644 --- a/src/Umbraco.Core/ApplicationContext.cs +++ b/src/Umbraco.Core/ApplicationContext.cs @@ -3,6 +3,7 @@ using System.Configuration; using System.Threading; using System.Web; using System.Web.Caching; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; @@ -23,27 +24,47 @@ namespace Umbraco.Core /// Constructor /// internal ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext) - :this() + : this(dbContext, serviceContext, true) { - if (dbContext == null) throw new ArgumentNullException("dbContext"); - if (serviceContext == null) throw new ArgumentNullException("serviceContext"); - - _databaseContext = dbContext; - _services = serviceContext; + } + /// + /// Constructor + /// + /// + /// + /// + internal ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache) + : this(enableCache) + { + if (dbContext == null) throw new ArgumentNullException("dbContext"); + if (serviceContext == null) throw new ArgumentNullException("serviceContext"); + + _databaseContext = dbContext; + _services = serviceContext; + } + /// /// Empty constructor normally reserved for unit tests when a DatabaseContext or a ServiceContext is not /// necessarily required or needs to be set after construction. /// - internal ApplicationContext() - { - //create a new application cache from the HttpRuntime.Cache - ApplicationCache = HttpRuntime.Cache == null - ? new CacheHelper(new System.Web.Caching.Cache()) - : new CacheHelper(HttpRuntime.Cache); + internal ApplicationContext() : this(true) + { } + /// + /// Constructor used to specify if we will enable application cache or not + /// + /// + internal ApplicationContext(bool enableCache) + { + //create a new application cache from the HttpRuntime.Cache + ApplicationCache = HttpRuntime.Cache == null + ? new CacheHelper(new System.Web.Caching.Cache(), enableCache) + : new CacheHelper(HttpRuntime.Cache, enableCache); + } + /// /// Singleton accessor /// diff --git a/src/Umbraco.Core/Cache/CacheProviderBase.cs b/src/Umbraco.Core/Cache/CacheProviderBase.cs new file mode 100644 index 0000000000..3bcb7373c1 --- /dev/null +++ b/src/Umbraco.Core/Cache/CacheProviderBase.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.Caching; + +namespace Umbraco.Core.Cache +{ + /// + /// An abstract class for implementing a cache helper + /// + /// + /// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC... + /// + internal abstract class CacheProviderBase + { + public abstract void ClearAllCache(); + public abstract void ClearCacheItem(string key); + public abstract void ClearCacheObjectTypes(string typeName); + public abstract void ClearCacheObjectTypes(); + public abstract void ClearCacheByKeySearch(string keyStartsWith); + public abstract void ClearCacheByKeyExpression(string regexString); + public abstract IEnumerable GetCacheItemsByKeySearch(string keyStartsWith); + public abstract T GetCacheItem(string cacheKey); + public abstract T GetCacheItem(string cacheKey, Func getCacheItem); + public abstract T GetCacheItem(string cacheKey, TimeSpan timeout, Func getCacheItem); + public abstract T GetCacheItem(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem); + public abstract T GetCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem); + public abstract T GetCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan timeout, Func getCacheItem); + public abstract void InsertCacheItem(string cacheKey, CacheItemPriority priority, TimeSpan timeout, Func getCacheItem); + public abstract void InsertCacheItem(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan timeout, Func getCacheItem); + public abstract void InsertCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func getCacheItem); + } +} diff --git a/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs new file mode 100644 index 0000000000..af67d2959c --- /dev/null +++ b/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web.Caching; +using Umbraco.Core.Logging; + +namespace Umbraco.Core.Cache +{ + /// + /// A CacheProvider that wraps the logic of the HttpRuntime.Cache + /// + internal class HttpRuntimeCacheProvider : CacheProviderBase + { + private readonly System.Web.Caching.Cache _cache; + private static readonly object Locker = new object(); + + public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache) + { + _cache = cache; + } + + /// + /// Clears everything in umbraco's runtime cache, which means that not only + /// umbraco content is removed, but also other cache items from pages running in + /// the same application / website. Use with care :-) + /// + public override void ClearAllCache() + { + var cacheEnumerator = _cache.GetEnumerator(); + while (cacheEnumerator.MoveNext()) + { + _cache.Remove(cacheEnumerator.Key.ToString()); + } + } + + /// + /// Clears the item in umbraco's runtime cache with the given key + /// + /// Key + public override void ClearCacheItem(string key) + { + // NH 10 jan 2012 + // Patch by the always wonderful Stéphane Gay to avoid cache null refs + lock (Locker) + { + if (_cache[key] == null) return; + _cache.Remove(key); ; + } + } + + + /// + /// Clears all objects in the System.Web.Cache with the System.Type name as the + /// input parameter. (using [object].GetType()) + /// + /// The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument" + public override void ClearCacheObjectTypes(string typeName) + { + try + { + lock (Locker) + { + foreach (DictionaryEntry c in _cache) + { + if (_cache[c.Key.ToString()] != null + && _cache[c.Key.ToString()].GetType().ToString().InvariantEquals(typeName)) + { + _cache.Remove(c.Key.ToString()); + } + } + } + } + catch (Exception e) + { + LogHelper.Error("Cache clearing error", e); + } + } + + /// + /// Clears all objects in the System.Web.Cache with the System.Type specified + /// + public override void ClearCacheObjectTypes() + { + try + { + lock (Locker) + { + foreach (DictionaryEntry c in _cache) + { + if (_cache[c.Key.ToString()] != null + && _cache[c.Key.ToString()].GetType() == typeof(T)) + { + _cache.Remove(c.Key.ToString()); + } + } + } + } + catch (Exception e) + { + LogHelper.Error("Cache clearing error", e); + } + } + + /// + /// Clears all cache items that starts with the key passed. + /// + /// The start of the key + public override void ClearCacheByKeySearch(string keyStartsWith) + { + foreach (DictionaryEntry c in _cache) + { + if (c.Key is string && ((string)c.Key).InvariantStartsWith(keyStartsWith)) + { + ClearCacheItem((string)c.Key); + } + } + } + + /// + /// Clears all cache items that have a key that matches the regular expression + /// + /// + public override void ClearCacheByKeyExpression(string regexString) + { + foreach (DictionaryEntry c in _cache) + { + if (c.Key is string && Regex.IsMatch(((string)c.Key), regexString)) + { + ClearCacheItem((string)c.Key); + } + } + } + + public override IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) + { + return (from DictionaryEntry c in _cache + where c.Key is string && ((string)c.Key).InvariantStartsWith(keyStartsWith) + select c.Value.TryConvertTo() + into attempt + where attempt.Success + select attempt.Result).ToList(); + } + + /// + /// Returns a cache item by key, does not update the cache if it isn't there. + /// + /// + /// + /// + public override TT GetCacheItem(string cacheKey) + { + var result = _cache.Get(cacheKey); + if (result == null) + { + return default(TT); + } + return result.TryConvertTo().Result; + } + + /// + /// Gets (and adds if necessary) an item from the cache with all of the default parameters + /// + /// + /// + /// + /// + public override TT GetCacheItem(string cacheKey, Func getCacheItem) + { + return GetCacheItem(cacheKey, CacheItemPriority.Normal, null, null, null, getCacheItem, Locker); + } + + /// + /// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW) + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + /// + public override TT GetCacheItem(string cacheKey, + TimeSpan timeout, Func getCacheItem) + { + return GetCacheItem(cacheKey, null, timeout, getCacheItem); + } + + /// + /// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW) + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + /// + public override TT GetCacheItem(string cacheKey, + CacheItemRemovedCallback refreshAction, TimeSpan timeout, + Func getCacheItem) + { + return GetCacheItem(cacheKey, CacheItemPriority.Normal, refreshAction, timeout, getCacheItem); + } + + /// + /// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW) + /// + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + /// + public override TT GetCacheItem(string cacheKey, + CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, + Func getCacheItem) + { + return GetCacheItem(cacheKey, priority, refreshAction, null, timeout, getCacheItem); + } + + /// + /// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW) + /// + /// + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + /// + public override TT GetCacheItem(string cacheKey, + CacheItemPriority priority, + CacheItemRemovedCallback refreshAction, + CacheDependency cacheDependency, + TimeSpan timeout, + Func getCacheItem) + { + return GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem, Locker); + } + + /// + /// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW) + /// + /// + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + /// + /// + private TT GetCacheItem(string cacheKey, + CacheItemPriority priority, CacheItemRemovedCallback refreshAction, + CacheDependency cacheDependency, TimeSpan? timeout, Func getCacheItem, object syncLock) + { + var result = _cache.Get(cacheKey); + if (result == null) + { + lock (syncLock) + { + result = _cache.Get(cacheKey); + if (result == null) + { + result = getCacheItem(); + if (result != null) + { + //we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it. + _cache.Insert(cacheKey, result, cacheDependency, + timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), + TimeSpan.Zero, priority, refreshAction); + } + } + } + } + return result.TryConvertTo().Result; + } + + /// + /// Inserts an item into the cache, if it already exists in the cache it will be replaced + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + public override void InsertCacheItem(string cacheKey, + CacheItemPriority priority, + TimeSpan timeout, + Func getCacheItem) + { + InsertCacheItem(cacheKey, priority, null, null, timeout, getCacheItem); + } + + /// + /// Inserts an item into the cache, if it already exists in the cache it will be replaced + /// + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + public override void InsertCacheItem(string cacheKey, + CacheItemPriority priority, + CacheDependency cacheDependency, + TimeSpan timeout, + Func getCacheItem) + { + InsertCacheItem(cacheKey, priority, null, cacheDependency, timeout, getCacheItem); + } + + /// + /// Inserts an item into the cache, if it already exists in the cache it will be replaced + /// + /// + /// + /// + /// + /// + /// This will set an absolute expiration from now until the timeout + /// + public override void InsertCacheItem(string cacheKey, + CacheItemPriority priority, + CacheItemRemovedCallback refreshAction, + CacheDependency cacheDependency, + TimeSpan? timeout, + Func getCacheItem) + { + object result = getCacheItem(); + if (result != null) + { + //we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it. + _cache.Insert(cacheKey, result, cacheDependency, + timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), + TimeSpan.Zero, priority, refreshAction); + } + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Cache/NullCacheProvider.cs b/src/Umbraco.Core/Cache/NullCacheProvider.cs new file mode 100644 index 0000000000..8178b95278 --- /dev/null +++ b/src/Umbraco.Core/Cache/NullCacheProvider.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Caching; + +namespace Umbraco.Core.Cache +{ + internal class NullCacheProvider : CacheProviderBase + { + public override void ClearAllCache() + { + } + + public override void ClearCacheItem(string key) + { + } + + public override void ClearCacheObjectTypes(string typeName) + { + } + + public override void ClearCacheObjectTypes() + { + } + + public override void ClearCacheByKeySearch(string keyStartsWith) + { + } + + public override void ClearCacheByKeyExpression(string regexString) + { + } + + public override IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) + { + return Enumerable.Empty(); + } + + public override T GetCacheItem(string cacheKey) + { + return default(T); + } + + public override T GetCacheItem(string cacheKey, Func getCacheItem) + { + return getCacheItem(); + } + + public override T GetCacheItem(string cacheKey, TimeSpan timeout, Func getCacheItem) + { + return getCacheItem(); + } + + public override T GetCacheItem(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) + { + return getCacheItem(); + } + + public override T GetCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) + { + return getCacheItem(); + } + + public override T GetCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan timeout, Func getCacheItem) + { + return getCacheItem(); + } + + public override void InsertCacheItem(string cacheKey, CacheItemPriority priority, TimeSpan timeout, Func getCacheItem) + { + } + + public override void InsertCacheItem(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan timeout, Func getCacheItem) + { + } + + public override void InsertCacheItem(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func getCacheItem) + { + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/CacheHelper.cs b/src/Umbraco.Core/CacheHelper.cs index 4f032a278a..bcde711df3 100644 --- a/src/Umbraco.Core/CacheHelper.cs +++ b/src/Umbraco.Core/CacheHelper.cs @@ -6,6 +6,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Web.Caching; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; namespace Umbraco.Core @@ -17,29 +18,33 @@ namespace Umbraco.Core /// /// This class may be opened publicly at some point but needs a review of what is absoletely necessary. /// - public class CacheHelper + public class CacheHelper //: CacheProviderBase { - private readonly System.Web.Caching.Cache _cache; + private readonly bool _enableCache; + private readonly HttpRuntimeCacheProvider _httpCache; + private readonly NullCacheProvider _nullCache = new NullCacheProvider(); public CacheHelper(System.Web.Caching.Cache cache) + : this(cache, true) { - _cache = cache; } - private static readonly object Locker = new object(); - - /// - /// Clears everything in umbraco's runtime cache, which means that not only - /// umbraco content is removed, but also other cache items from pages running in - /// the same application / website. Use with care :-) - /// + internal CacheHelper(System.Web.Caching.Cache cache, bool enableCache) + { + _httpCache = new HttpRuntimeCacheProvider(cache); + _enableCache = enableCache; + } + public void ClearAllCache() { - var cacheEnumerator = _cache.GetEnumerator(); - while (cacheEnumerator.MoveNext()) - { - _cache.Remove(cacheEnumerator.Key.ToString()); - } + if (!_enableCache) + { + _nullCache.ClearAllCache(); + } + else + { + _httpCache.ClearAllCache(); + } } /// @@ -48,12 +53,13 @@ namespace Umbraco.Core /// Key public void ClearCacheItem(string key) { - // NH 10 jan 2012 - // Patch by the always wonderful Stéphane Gay to avoid cache null refs - lock (Locker) + if (!_enableCache) { - if (_cache[key] == null) return; - _cache.Remove(key);; + _nullCache.ClearCacheItem(key); + } + else + { + _httpCache.ClearCacheItem(key); } } @@ -65,23 +71,13 @@ namespace Umbraco.Core /// The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument" public void ClearCacheObjectTypes(string typeName) { - try + if (!_enableCache) { - lock (Locker) - { - foreach (DictionaryEntry c in _cache) - { - if (_cache[c.Key.ToString()] != null - && _cache[c.Key.ToString()].GetType().ToString().InvariantEquals(typeName)) - { - _cache.Remove(c.Key.ToString()); - } - } - } + _nullCache.ClearCacheObjectTypes(typeName); } - catch (Exception e) + else { - LogHelper.Error("Cache clearing error", e); + _httpCache.ClearCacheObjectTypes(typeName); } } @@ -90,23 +86,13 @@ namespace Umbraco.Core /// public void ClearCacheObjectTypes() { - try + if (!_enableCache) { - lock (Locker) - { - foreach (DictionaryEntry c in _cache) - { - if (_cache[c.Key.ToString()] != null - && _cache[c.Key.ToString()].GetType() == typeof(T)) - { - _cache.Remove(c.Key.ToString()); - } - } - } + _nullCache.ClearCacheObjectTypes(); } - catch (Exception e) + else { - LogHelper.Error("Cache clearing error", e); + _httpCache.ClearCacheObjectTypes(); } } @@ -116,13 +102,14 @@ namespace Umbraco.Core /// The start of the key public void ClearCacheByKeySearch(string keyStartsWith) { - foreach (DictionaryEntry c in _cache) - { - if (c.Key is string && ((string) c.Key).InvariantStartsWith(keyStartsWith)) - { - ClearCacheItem((string) c.Key); - } - } + if (!_enableCache) + { + _nullCache.ClearCacheByKeySearch(keyStartsWith); + } + else + { + _httpCache.ClearCacheByKeySearch(keyStartsWith); + } } /// @@ -131,23 +118,26 @@ namespace Umbraco.Core /// public void ClearCacheByKeyExpression(string regexString) { - foreach (DictionaryEntry c in _cache) + if (!_enableCache) { - if (c.Key is string && Regex.IsMatch(((string)c.Key), regexString)) - { - ClearCacheItem((string)c.Key); - } + _nullCache.ClearCacheByKeyExpression(regexString); + } + else + { + _httpCache.ClearCacheByKeyExpression(regexString); } } public IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) { - return (from DictionaryEntry c in _cache - where c.Key is string && ((string) c.Key).InvariantStartsWith(keyStartsWith) - select c.Value.TryConvertTo() - into attempt - where attempt.Success - select attempt.Result).ToList(); + if (!_enableCache) + { + return _nullCache.GetCacheItemsByKeySearch(keyStartsWith); + } + else + { + return _httpCache.GetCacheItemsByKeySearch(keyStartsWith); + } } /// @@ -158,12 +148,14 @@ namespace Umbraco.Core /// public TT GetCacheItem(string cacheKey) { - var result = _cache.Get(cacheKey); - if (result == null) + if (!_enableCache) { - return default(TT); + return _nullCache.GetCacheItem(cacheKey); + } + else + { + return _httpCache.GetCacheItem(cacheKey); } - return result.TryConvertTo().Result; } /// @@ -175,7 +167,14 @@ namespace Umbraco.Core /// public TT GetCacheItem(string cacheKey, Func getCacheItem) { - return GetCacheItem(cacheKey, CacheItemPriority.Normal, null, null, null, getCacheItem, Locker); + if (!_enableCache) + { + return _nullCache.GetCacheItem(cacheKey, getCacheItem); + } + else + { + return _httpCache.GetCacheItem(cacheKey, getCacheItem); + } } /// @@ -189,7 +188,14 @@ namespace Umbraco.Core public TT GetCacheItem(string cacheKey, TimeSpan timeout, Func getCacheItem) { - return GetCacheItem(cacheKey, null, timeout, getCacheItem); + if (!_enableCache) + { + return _nullCache.GetCacheItem(cacheKey, timeout, getCacheItem); + } + else + { + return _httpCache.GetCacheItem(cacheKey, timeout, getCacheItem); + } } /// @@ -205,7 +211,14 @@ namespace Umbraco.Core CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) { - return GetCacheItem(cacheKey, CacheItemPriority.Normal, refreshAction, timeout, getCacheItem); + if (!_enableCache) + { + return _nullCache.GetCacheItem(cacheKey, refreshAction, timeout, getCacheItem); + } + else + { + return _httpCache.GetCacheItem(cacheKey, refreshAction, timeout, getCacheItem); + } } /// @@ -222,7 +235,14 @@ namespace Umbraco.Core CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, Func getCacheItem) { - return GetCacheItem(cacheKey, priority, refreshAction, null, timeout, getCacheItem); + if (!_enableCache) + { + return _nullCache.GetCacheItem(cacheKey, priority, refreshAction, timeout, getCacheItem); + } + else + { + return _httpCache.GetCacheItem(cacheKey, priority, refreshAction, timeout, getCacheItem); + } } /// @@ -243,49 +263,16 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - return GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem, Locker); + if (!_enableCache) + { + return _nullCache.GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem); + } + else + { + return _httpCache.GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem); + } } - - /// - /// This is used only for legacy purposes as I did not want to change all of the locking to one lock found on this object, - /// however, the reason this is used for legacy purposes is because I see zero reason to use different sync locks, just the one - /// lock (Locker) on this class should be sufficient. - /// - /// - /// - /// - /// - /// - /// This will set an absolute expiration from now until the timeout - /// - /// - /// - internal TT GetCacheItem(string cacheKey, - CacheItemPriority priority, CacheItemRemovedCallback refreshAction, - CacheDependency cacheDependency, TimeSpan? timeout, Func getCacheItem, object syncLock) - { - var result = _cache.Get(cacheKey); - if (result == null) - { - lock (syncLock) - { - result = _cache.Get(cacheKey); - if (result == null) - { - result = getCacheItem(); - if (result != null) - { - //we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it. - _cache.Insert(cacheKey, result, cacheDependency, - timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), - TimeSpan.Zero, priority, refreshAction); - } - } - } - } - return result.TryConvertTo().Result; - } - + /// /// Inserts an item into the cache, if it already exists in the cache it will be replaced /// @@ -299,7 +286,14 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - InsertCacheItem(cacheKey, priority, null, null, timeout, getCacheItem); + if (!_enableCache) + { + _nullCache.InsertCacheItem(cacheKey, priority, timeout, getCacheItem); + } + else + { + _httpCache.InsertCacheItem(cacheKey, priority, timeout, getCacheItem); + } } /// @@ -317,7 +311,14 @@ namespace Umbraco.Core TimeSpan timeout, Func getCacheItem) { - InsertCacheItem(cacheKey, priority, null, cacheDependency, timeout, getCacheItem); + if (!_enableCache) + { + _nullCache.InsertCacheItem(cacheKey, priority, cacheDependency, timeout, getCacheItem); + } + else + { + _httpCache.InsertCacheItem(cacheKey, priority, cacheDependency, timeout, getCacheItem); + } } /// @@ -337,14 +338,14 @@ namespace Umbraco.Core TimeSpan? timeout, Func getCacheItem) { - object result = getCacheItem(); - if (result != null) - { - //we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it. - _cache.Insert(cacheKey, result, cacheDependency, - timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value), - TimeSpan.Zero, priority, refreshAction); - } + if (!_enableCache) + { + _nullCache.InsertCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem); + } + else + { + _httpCache.InsertCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem); + } } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index edc730c879..477e3696e8 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -111,8 +111,11 @@ + + + diff --git a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs index 1ea9110f5d..90944c4e32 100644 --- a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs +++ b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.BusinessLogic [SetUp] public void Initialize() { - ApplicationContext.Current = new ApplicationContext(){IsReady = true}; + ApplicationContext.Current = new ApplicationContext(false){IsReady = true}; InitializeDatabase(); InitializeApps(); InitializeAppConfigFile(); diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index ba6bfffc8c..19a0a4c14f 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -18,7 +18,8 @@ namespace Umbraco.Tests.Macros [SetUp] public void Setup() { - ApplicationContext.Current = new ApplicationContext(); + //we DO want cache enabled for these tests + ApplicationContext.Current = new ApplicationContext(true); } [TearDown] diff --git a/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs b/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs index 37659fd5d0..f8f56d6dcb 100644 --- a/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs @@ -32,7 +32,12 @@ namespace Umbraco.Tests.Persistence //assign the db context new DatabaseContext(new DefaultDatabaseFactory()), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy())) { IsReady = true }; + new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()), + //disable cache + false) + { + IsReady = true + }; Resolution.Freeze(); } diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index 099ddfa4c2..420905536d 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Persistence _dbContext = new DatabaseContext(new DefaultDatabaseFactory()); //unfortunately we have to set this up because the PetaPocoExtensions require singleton access - ApplicationContext.Current = new ApplicationContext + ApplicationContext.Current = new ApplicationContext(false) { DatabaseContext = _dbContext, IsReady = true diff --git a/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs index f25cb9b315..f1c5db3d24 100644 --- a/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs @@ -70,6 +70,9 @@ namespace Umbraco.Tests.PublishedCache { TestHelper.SetupLog4NetForTests(); + //create the app context + ApplicationContext.Current = new ApplicationContext(false); + _httpContextFactory = new FakeHttpContextFactory("~/Home"); //ensure the StateHelper is using our custom context StateHelper.HttpContext = _httpContextFactory.HttpContext; @@ -85,8 +88,8 @@ namespace Umbraco.Tests.PublishedCache }; _umbracoContext = new UmbracoContext( - _httpContextFactory.HttpContext, - new ApplicationContext(), + _httpContextFactory.HttpContext, + ApplicationContext.Current, cache, new PublishedMediaCache()); diff --git a/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs index a2c09469b3..4ee5868e77 100644 --- a/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs @@ -23,6 +23,11 @@ namespace Umbraco.Tests.Routing TestHelper.DropForeignKeys("umbracoDomains"); } + protected override DatabaseBehavior DatabaseTestBehavior + { + get { return DatabaseBehavior.NewSchemaPerFixture; } + } + protected override void FreezeResolution() { SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index b9dd4c1a4a..a749765fa7 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -60,7 +60,12 @@ namespace Umbraco.Tests.TestHelpers //assign the db context new DatabaseContext(new DefaultDatabaseFactory()), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy())) { IsReady = true }; + new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()), + //disable cache + false) + { + IsReady = true + }; DatabaseContext.Initialize(); diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs index 0870862cc1..8b46559528 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs @@ -64,7 +64,12 @@ namespace Umbraco.Tests.TestHelpers //assign the db context new DatabaseContext(new DefaultDatabaseFactory()), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy())) { IsReady = true }; + new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()), + //disable cache + false) + { + IsReady = true + }; SqlSyntaxContext.SqlSyntaxProvider = SyntaxProvider; diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index 354a69af50..1979df306c 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -61,7 +61,8 @@ namespace Umbraco.Tests.TestHelpers /// protected virtual void SetupApplicationContext() { - ApplicationContext.Current = new ApplicationContext {IsReady = true}; + //DO NOT ENABLE CACHE + ApplicationContext.Current = new ApplicationContext(false) {IsReady = true}; } /// diff --git a/src/umbraco.cms/businesslogic/cache/Cache.cs b/src/umbraco.cms/businesslogic/cache/Cache.cs index fb53436a40..6669d369bf 100644 --- a/src/umbraco.cms/businesslogic/cache/Cache.cs +++ b/src/umbraco.cms/businesslogic/cache/Cache.cs @@ -118,7 +118,7 @@ namespace umbraco.cms.businesslogic.cache { var helper = new CacheHelper(System.Web.HttpRuntime.Cache); Func f = () => getCacheItem(); - return helper.GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, f, syncLock); + return helper.GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, f); } } }