From 04976f8063dc181aad36e4f22c6eaacc2b92ef58 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 8 Jul 2015 11:08:19 +0200 Subject: [PATCH] U4-6202 - cache clearing by object type Conflicts: src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs --- .../Cache/DictionaryCacheProviderBase.cs | 29 +++++++------- src/Umbraco.Core/Cache/ICacheProvider.cs | 38 +++++++++++++++++++ .../Cache/ObjectCacheRuntimeCacheProvider.cs | 30 ++++++++------- 3 files changed, 69 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs index a6666d4e76..543609dd2e 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs +++ b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs @@ -105,6 +105,9 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(string typeName) { + var type = Type.GetType(typeName); + if (type == null) return; + var isInterface = type.IsInterface; using (WriteLock) { foreach (var entry in GetDictionaryEntries() @@ -114,7 +117,10 @@ namespace Umbraco.Core.Cache // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - return value == null || value.GetType().ToString().InvariantEquals(typeName); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); }) .ToArray()) RemoveEntry((string) entry.Key); @@ -124,6 +130,7 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes() { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; using (WriteLock) { foreach (var entry in GetDictionaryEntries() @@ -135,14 +142,9 @@ namespace Umbraco.Core.Cache // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return value == null || - (typeOfT.IsInterface - ? (value is T) - : value.GetType() == typeOfT); + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); }) .ToArray()) RemoveEntry((string) entry.Key); @@ -152,6 +154,7 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(Func predicate) { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; var plen = CacheItemPrefix.Length + 1; using (WriteLock) { @@ -165,11 +168,9 @@ namespace Umbraco.Core.Cache var value = GetSafeLazyValue((Lazy)x.Value, true); if (value == null) return true; - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return ((typeOfT.IsInterface && value is T) || (value.GetType() == typeOfT)) + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return (isInterface ? (value is T) : (value.GetType() == typeOfT)) // run predicate on the 'public key' part only, ie without prefix && predicate(((string) x.Key).Substring(plen), (T) value); })) diff --git a/src/Umbraco.Core/Cache/ICacheProvider.cs b/src/Umbraco.Core/Cache/ICacheProvider.cs index 6cec619be8..0d2bb1bdb6 100644 --- a/src/Umbraco.Core/Cache/ICacheProvider.cs +++ b/src/Umbraco.Core/Cache/ICacheProvider.cs @@ -8,13 +8,51 @@ namespace Umbraco.Core.Cache /// public interface ICacheProvider { + /// + /// Removes all items from the cache. + /// void ClearAllCache(); + + /// + /// Removes an item from the cache, identified by its key. + /// + /// The key of the item. void ClearCacheItem(string key); + + /// + /// Removes items from the cache, of a specified type. + /// + /// The name of the type to remove. + /// + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). + /// Performs a case-sensitive search. + /// void ClearCacheObjectTypes(string typeName); + + /// + /// Removes items from the cache, of a specified type. + /// + /// The type of the items to remove. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). void ClearCacheObjectTypes(); + + /// + /// Removes items from the cache, of a specified type, satisfying a predicate. + /// + /// The type of the items to remove. + /// The predicate to satisfy. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). void ClearCacheObjectTypes(Func predicate); + void ClearCacheByKeySearch(string keyStartsWith); void ClearCacheByKeyExpression(string regexString); + IEnumerable GetCacheItemsByKeySearch(string keyStartsWith); IEnumerable GetCacheItemsByKeyExpression(string regexString); diff --git a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs index 19fbb0694b..197fdce7f7 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Reflection; using System.Runtime.Caching; using System.Text.RegularExpressions; using System.Threading; @@ -53,6 +54,9 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(string typeName) { + var type = Type.GetType(typeName); + if (type == null) return; + var isInterface = type.IsInterface; using (new WriteLock(_locker)) { foreach (var key in MemoryCache @@ -62,7 +66,10 @@ namespace Umbraco.Core.Cache // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); - return value == null || value.GetType().ToString().InvariantEquals(typeName); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); }) .Select(x => x.Key) .ToArray()) // ToArray required to remove @@ -75,6 +82,7 @@ namespace Umbraco.Core.Cache using (new WriteLock(_locker)) { var typeOfT = typeof (T); + var isInterface = typeOfT.IsInterface; foreach (var key in MemoryCache .Where(x => { @@ -83,14 +91,9 @@ namespace Umbraco.Core.Cache // get non-created as NonCreatedValue & exceptions as null var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return value == null || - (typeOfT.IsInterface - ? (value is T) - : value.GetType() == typeOfT); + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); }) .Select(x => x.Key) @@ -104,6 +107,7 @@ namespace Umbraco.Core.Cache using (new WriteLock(_locker)) { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; foreach (var key in MemoryCache .Where(x => { @@ -113,11 +117,9 @@ namespace Umbraco.Core.Cache var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); if (value == null) return true; - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return ((typeOfT.IsInterface && value is T) || (value.GetType() == typeOfT)) + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return (isInterface ? (value is T) : (value.GetType() == typeOfT)) && predicate(x.Key, (T)value); }) .Select(x => x.Key)