238 lines
9.3 KiB
C#
238 lines
9.3 KiB
C#
//using System;
|
|
//using System.Collections;
|
|
//using System.Collections.Concurrent;
|
|
//using System.Collections.Generic;
|
|
//using System.Linq;
|
|
//using System.Runtime.Caching;
|
|
//using System.Threading;
|
|
//using System.Web;
|
|
//using Umbraco.Core.Models.EntityBase;
|
|
|
|
//namespace Umbraco.Core.Persistence.Caching
|
|
//{
|
|
// //TODO: Remove this singleton!
|
|
|
|
// /// <summary>
|
|
// /// The Runtime Cache provider looks up objects in the Runtime cache for fast retrival
|
|
// /// </summary>
|
|
// /// <remarks>
|
|
// ///
|
|
// /// If a web session is detected then the HttpRuntime.Cache will be used for the runtime cache, otherwise a custom
|
|
// /// MemoryCache instance will be used. It is important to use the HttpRuntime.Cache when a web session is detected so
|
|
// /// that the memory management of cache in IIS can be handled appopriately.
|
|
// ///
|
|
// /// When a web sessions is detected we will pre-fix all HttpRuntime.Cache entries so that when we clear it we are only
|
|
// /// clearing items that have been inserted by this provider.
|
|
// ///
|
|
// /// NOTE: These changes are all temporary until we finalize the ApplicationCache implementation which will support static cache, runtime cache
|
|
// /// and request based cache which will all live in one central location so it is easily managed.
|
|
// ///
|
|
// /// Also note that we don't always keep checking if HttpContext.Current == null and instead check for _memoryCache != null. This is because
|
|
// /// when there are async requests being made even in the context of a web request, the HttpContext.Current will be null but the HttpRuntime.Cache will
|
|
// /// always be available.
|
|
// ///
|
|
// /// </remarks>
|
|
// internal sealed class RuntimeCacheProvider : IRepositoryCacheProvider
|
|
// {
|
|
// #region Singleton
|
|
|
|
// private static readonly Lazy<RuntimeCacheProvider> lazy = new Lazy<RuntimeCacheProvider>(() => new RuntimeCacheProvider());
|
|
|
|
// public static RuntimeCacheProvider Current { get { return lazy.Value; } }
|
|
|
|
// //internal for testing! - though I'm not a huge fan of these being singletons!
|
|
// internal RuntimeCacheProvider()
|
|
// {
|
|
// if (HttpContext.Current == null)
|
|
// {
|
|
// _memoryCache = new MemoryCache("in-memory");
|
|
// }
|
|
// }
|
|
|
|
// #endregion
|
|
|
|
// //TODO Save this in cache as well, so its not limited to a single server usage
|
|
// private readonly ConcurrentHashSet<string> _keyTracker = new ConcurrentHashSet<string>();
|
|
// private ObjectCache _memoryCache;
|
|
// private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim();
|
|
|
|
// public IEntity GetById(Type type, Guid id)
|
|
// {
|
|
// var key = GetCompositeId(type, id);
|
|
// var item = _memoryCache != null
|
|
// ? _memoryCache.Get(key)
|
|
// : HttpRuntime.Cache.Get(key);
|
|
// var result = item as IEntity;
|
|
// if (result == null)
|
|
// {
|
|
// //ensure the key doesn't exist anymore in the tracker
|
|
// _keyTracker.Remove(key);
|
|
// return null;
|
|
// }
|
|
|
|
// //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
|
// return (IEntity)result.DeepClone();
|
|
// }
|
|
|
|
// public IEnumerable<IEntity> GetByIds(Type type, List<Guid> ids)
|
|
// {
|
|
// var collection = new List<IEntity>();
|
|
// foreach (var guid in ids)
|
|
// {
|
|
// var key = GetCompositeId(type, guid);
|
|
// var item = _memoryCache != null
|
|
// ? _memoryCache.Get(key)
|
|
// : HttpRuntime.Cache.Get(key);
|
|
// var result = item as IEntity;
|
|
// if (result == null)
|
|
// {
|
|
// //ensure the key doesn't exist anymore in the tracker
|
|
// _keyTracker.Remove(key);
|
|
// }
|
|
// else
|
|
// {
|
|
// //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
|
// collection.Add((IEntity)result.DeepClone());
|
|
// }
|
|
// }
|
|
// return collection;
|
|
// }
|
|
|
|
// public IEnumerable<IEntity> GetAllByType(Type type)
|
|
// {
|
|
// var collection = new List<IEntity>();
|
|
// foreach (var key in _keyTracker)
|
|
// {
|
|
// if (key.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name)))
|
|
// {
|
|
// var item = _memoryCache != null
|
|
// ? _memoryCache.Get(key)
|
|
// : HttpRuntime.Cache.Get(key);
|
|
|
|
// var result = item as IEntity;
|
|
// if (result == null)
|
|
// {
|
|
// //ensure the key doesn't exist anymore in the tracker
|
|
// _keyTracker.Remove(key);
|
|
// }
|
|
// else
|
|
// {
|
|
// //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
|
// collection.Add((IEntity)result.DeepClone());
|
|
// }
|
|
// }
|
|
// }
|
|
// return collection;
|
|
// }
|
|
|
|
// public void Save(Type type, IEntity entity)
|
|
// {
|
|
// //IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259
|
|
// var clone = (IEntity)entity.DeepClone();
|
|
|
|
// var key = GetCompositeId(type, clone.Key);
|
|
|
|
// _keyTracker.TryAdd(key);
|
|
|
|
// //NOTE: Before we were checking if it already exists but the MemoryCache.Set handles this implicitly and does
|
|
// // an add or update, same goes for HttpRuntime.Cache.Insert.
|
|
|
|
// if (_memoryCache != null)
|
|
// {
|
|
// _memoryCache.Set(key, clone, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
|
// }
|
|
// else
|
|
// {
|
|
// HttpRuntime.Cache.Insert(key, clone, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
|
// }
|
|
// }
|
|
|
|
// public void Delete(Type type, IEntity entity)
|
|
// {
|
|
// var key = GetCompositeId(type, entity.Key);
|
|
// if (_memoryCache != null)
|
|
// {
|
|
// _memoryCache.Remove(key);
|
|
// }
|
|
// else
|
|
// {
|
|
// HttpRuntime.Cache.Remove(key);
|
|
// }
|
|
|
|
// _keyTracker.Remove(key);
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// Clear cache by type
|
|
// /// </summary>
|
|
// /// <param name="type"></param>
|
|
// public void Clear(Type type)
|
|
// {
|
|
// using (new WriteLock(ClearLock))
|
|
// {
|
|
// var keys = new string[_keyTracker.Count];
|
|
// _keyTracker.CopyTo(keys, 0);
|
|
// var keysToRemove = new List<string>();
|
|
// foreach (var key in keys.Where(x => x.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name))))
|
|
// {
|
|
// _keyTracker.Remove(key);
|
|
// keysToRemove.Add(key);
|
|
// }
|
|
// foreach (var key in keysToRemove)
|
|
// {
|
|
// if (_memoryCache != null)
|
|
// {
|
|
// _memoryCache.Remove(key);
|
|
// }
|
|
// else
|
|
// {
|
|
// HttpRuntime.Cache.Remove(key);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// public void Clear()
|
|
// {
|
|
// using (new WriteLock(ClearLock))
|
|
// {
|
|
// _keyTracker.Clear();
|
|
|
|
// ClearDataCache();
|
|
// }
|
|
// }
|
|
|
|
// //DO not call this unless it's for testing since it clears the data cached but not the keys
|
|
// internal void ClearDataCache()
|
|
// {
|
|
// if (_memoryCache != null)
|
|
// {
|
|
// _memoryCache.DisposeIfDisposable();
|
|
// _memoryCache = new MemoryCache("in-memory");
|
|
// }
|
|
// else
|
|
// {
|
|
// foreach (DictionaryEntry c in HttpRuntime.Cache)
|
|
// {
|
|
// if (c.Key is string && ((string)c.Key).InvariantStartsWith(CacheItemPrefix))
|
|
// {
|
|
// if (HttpRuntime.Cache[(string)c.Key] == null) return;
|
|
// HttpRuntime.Cache.Remove((string)c.Key);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// We prefix all cache keys with this so that we know which ones this class has created when
|
|
// /// using the HttpRuntime cache so that when we clear it we don't clear other entries we didn't create.
|
|
// /// </summary>
|
|
// private const string CacheItemPrefix = "umbrtmche_";
|
|
|
|
// private string GetCompositeId(Type type, Guid id)
|
|
// {
|
|
// return string.Format("{0}{1}-{2}", CacheItemPrefix, type.Name, id);
|
|
// }
|
|
|
|
// }
|
|
//} |