/// <summary> /// Insert an item into the cache with the specified time to live, /// sliding expiration and priority. /// </summary> /// <param name="keyName">The cache key</param> /// <param name="value">The cache value</param> /// <param name="timeToLive">How long in seconds the object should be cached.</param> /// <param name="slidingExpiration">Whether or not to reset the time to live if the object is touched.</param> /// <param name="priority">Priority of the cache entry.</param> public void Insert(object keyName, object value, int timeToLive, bool slidingExpiration, CacheItemPriority priority) { TimeSpan timeToLiveAsTimeSpan = TimeSpan.FromSeconds(timeToLive); Guard.IsNotNull(keyName, "key"); Guard.IsTrue(TimeSpan.Zero <= timeToLiveAsTimeSpan, "timeToLive"); System.Web.Caching.CacheItemPriority aspNetPriority = ConvertToAspNetPriority(priority); string key = BuildKey(keyName); if (TimeSpan.Zero < timeToLiveAsTimeSpan) { if (slidingExpiration) { _cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, timeToLiveAsTimeSpan, aspNetPriority, null); } else { DateTime absoluteExpiration = DateTime.Now.AddSeconds(timeToLive); _cache.Insert(key, value, null, absoluteExpiration, Cache.NoSlidingExpiration, aspNetPriority, null); } } else { _cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, aspNetPriority, null); } }
public object GetCacheItem( string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { using (var lck = new UpgradeableReadLock(Locker)) { var result = MemoryCache.Get(cacheKey); if (result == null) { lck.UpgradeToWriteLock(); result = getCacheItem(); if (result != null) { var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); MemoryCache.Set(cacheKey, result, policy); } } return(result); } }
/// <summary> /// 添加一个缓存对象(键值不能重复) /// </summary> /// <param name="key">缓存项键</param> /// <param name="value">缓存项值</param> /// <param name="absoluteExpiration">绝对到期时间 如果指定此时间 则slidingExpiration必须是TimeSpan.Zero</param> /// <param name="slidingExpiration">最后一次访问所插入对象时与该对象到期时之间的时间间隔(单位分钟)(现在时间与最后一次访问缓存对象的时间间隔超过指定间隔 则缓存对象过过期) 如果指定此间隔 则absoluteExpiration必须是DateTime.MaxValue</param> /// <param name="priority">优先级</param> /// <param name="onRemoveCallback">移除缓存项时通知应用程序的回调方法</param> public override void Add(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, Action <string, object, CacheItemRemovedReason> onRemoveCallback) { Guard.IsNotNull(key, "键不能为空"); if (Contains(key)) { throw new ArgumentNullException("key", "键已经存在"); } CacheItemRemovedCallback removeCallback = (s, o, c) => { if (onRemoveCallback != null) { onRemoveCallback(s, o, c); } }; System.Web.Caching.CacheItemPriority aspNetPriority = ConvertToAspNetPriority(priority); cache.Insert(key, value, null, absoluteExpiration, slidingExpiration, aspNetPriority, removeCallback); }
public void Insert(object keyName, object value, int timeToLive, bool slidingExpiration, CacheItemPriority priority) { TimeSpan timeSpan = TimeSpan.FromSeconds((double)timeToLive); Guard.IsNotNull(keyName, "key"); Guard.IsTrue(TimeSpan.Zero <= timeSpan, "timeToLive"); System.Web.Caching.CacheItemPriority priority2 = this.ConvertToAspNetPriority(priority); string key = this.BuildKey(keyName); if (!(TimeSpan.Zero < timeSpan)) { this._cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, priority2, null); return; } if (slidingExpiration) { this._cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, timeSpan, priority2, null); return; } DateTime absoluteExpiration = DateTime.Now.AddSeconds((double)timeToLive); this._cache.Insert(key, value, null, absoluteExpiration, Cache.NoSlidingExpiration, priority2, null); }
public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { object result = getCacheItem(); if (result != null) { var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); MemoryCache.Set(cacheKey, result, policy); } }
private static void BaseInsert(string key, object value, CacheDependency dep, DateTime absoluteExpiration, TimeSpan slidingExpiration, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) { if (value != null) { _cache.Insert(key, value, dep, absoluteExpiration, slidingExpiration, priority, onRemoveCallback); } }
/// <summary> /// 插入缓存 使用文件依赖与过期时间,另可设置缓存优先级与缓存失效回调函数 /// </summary> /// <param name="key"></param> /// <param name="obj"></param> /// <param name="absoluteExprition"></param> /// <param name="dep"></param> /// <param name="priority"></param> /// <param name="onRemoveCallback"></param> public static void Insert(string key, object obj, TimeSpan absoluteExprition, CacheDependency dep, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) { if (obj != null) { BaseInsert(key, obj, dep, DateTime.Now.Add(absoluteExprition), System.Web.Caching.Cache.NoSlidingExpiration, priority, onRemoveCallback); } }
public object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { // see notes in HttpRuntimeCacheProvider Lazy <object> result; using (var lck = new UpgradeableReadLock(_locker)) { result = MemoryCache.Get(cacheKey) as Lazy <object>; if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { result = new Lazy <object>(getCacheItem); var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); lck.UpgradeToWriteLock(); MemoryCache.Set(cacheKey, result, policy); } } return(result.Value); }
/// <summary> /// Only call with already munged (KeyInContext style) keys. /// </summary> private void RawSet(string cacheKey, object value, int?durationSecs, bool isSliding, System.Web.Caching.CacheItemPriority priority) { LocalCache.OnLogDuration(cacheKey, durationSecs, "RawSet"); var absolute = !isSliding && durationSecs.HasValue ? DateTime.UtcNow.AddSeconds(durationSecs.Value) : Cache.NoAbsoluteExpiration; var sliding = isSliding && durationSecs.HasValue ? TimeSpan.FromSeconds(durationSecs.Value) : Cache.NoSlidingExpiration; HttpRuntime.Cache.Insert(cacheKey, value, null, absolute, sliding, priority, Removed); var evt = Added; if (evt != null) { evt(cacheKey, value, absolute, sliding, priority, durationSecs, isSliding); } }
/// <summary> /// This overload is here for legacy purposes /// </summary> /// <param name="cacheKey"></param> /// <param name="getCacheItem"></param> /// <param name="timeout"></param> /// <param name="isSliding"></param> /// <param name="priority"></param> /// <param name="removedCallback"></param> /// <param name="dependency"></param> internal void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) { // NOTE - here also we must insert a Lazy<object> but we can evaluate it right now // and make sure we don't store a null value. var result = GetSafeLazy(getCacheItem); var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache if (value == null) { return; // do not store null values (backward compat) } cacheKey = GetCacheKey(cacheKey); var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value)); var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration); try { _locker.EnterWriteLock(); //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update! _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback); } finally { if (_locker.IsWriteLockHeld) { _locker.ExitWriteLock(); } } }
/// <summary> /// This overload is here for legacy purposes /// </summary> /// <param name="cacheKey"></param> /// <param name="getCacheItem"></param> /// <param name="timeout"></param> /// <param name="isSliding"></param> /// <param name="priority"></param> /// <param name="removedCallback"></param> /// <param name="dependency"></param> /// <returns></returns> internal object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) { cacheKey = GetCacheKey(cacheKey); // NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang, // getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and // nasty performance issues. // So.... we insert a Lazy<object> in the cache while holding the global application lock, and then rely // on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global // application lock has been released. // NOTE // The Lazy value creation may produce a null value. // Must make sure (for backward compatibility) that we pretend they are not in the cache. // So if we find an entry in the cache that already has its value created and is null, // pretend it was not there. If value is not already created, wait... and return null, that's // what prior code did. // NOTE // The Lazy value creation may throw. // So... the null value _will_ be in the cache but never returned Lazy <object> result; // Fast! // Only one thread can enter an UpgradeableReadLock at a time, but it does not prevent other // threads to enter a ReadLock in the meantime -- only upgrading to WriteLock will prevent all // reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of // having to re-lock in case there's no value. Would need to benchmark to figure out whether // it's worth it, though... try { _locker.EnterReadLock(); result = _cache.Get(cacheKey) as Lazy <object>; // null if key not found } finally { if (_locker.IsReadLockHeld) { _locker.ExitReadLock(); } } var value = result == null ? null : GetSafeLazyValue(result); if (value != null) { return(value); } using (var lck = new UpgradeableReadLock(_locker)) { result = _cache.Get(cacheKey) as Lazy <object>; // null if key not found // cannot create value within the lock, so if result.IsValueCreated is false, just // do nothing here - means that if creation throws, a race condition could cause // more than one thread to reach the return statement below and throw - accepted. if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { result = GetSafeLazy(getCacheItem); var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value)); var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration); lck.UpgradeToWriteLock(); //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update! _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback); } } // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache // exceptions (but try again and again) and silently eat them - however at // some point we have to report them - so need to re-throw here // this does not throw anymore //return result.Value; value = result.Value; // will not throw (safe lazy) if (value is ExceptionHolder eh) { eh.Exception.Throw(); // throw once! } return(value); }
public void Insert(string keyString, object value, int cacheDurationInSeconds, System.Web.Caching.CacheItemPriority priority) { }
/// <inheritdoc /> public object Get(string key, Func <object> factory, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { // see notes in HttpRuntimeAppCache Lazy <object> result; try { _locker.EnterUpgradeableReadLock(); result = MemoryCache.Get(key) as Lazy <object>; if (result == null || FastDictionaryAppCacheBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { result = FastDictionaryAppCacheBase.GetSafeLazy(factory); var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); try { _locker.EnterWriteLock(); //NOTE: This does an add or update MemoryCache.Set(key, result, policy); } finally { if (_locker.IsWriteLockHeld) { _locker.ExitWriteLock(); } } } } finally { if (_locker.IsUpgradeableReadLockHeld) { _locker.ExitUpgradeableReadLock(); } } //return result.Value; var value = result.Value; // will not throw (safe lazy) if (value is FastDictionaryAppCacheBase.ExceptionHolder eh) { eh.Exception.Throw(); // throw once! } return(value); }
///// <summary> ///// Добавляет данные в кэш ///// </summary> ///// <param name="key">Название ключа кэша</param> ///// <param name="data">Данные, которые надо положить в кэш</param> ///// <param name="cacheDuration">Длительность хранения</param> ///// <param name="priority">Приоритет кэша</param> ///// <param name="onRemoved">Событие при удалении данных из кэша</param> //public static void AddCacheData(string key, object data, uint cacheDuration, CacheItemPriority priority, CacheItemRemovedCallback onRemoved) //{ // AddCacheData(key, data, null, cacheDuration, 0, priority, onRemoved); //} /// <summary> /// Вставка объекта в объект Cache с политиками сроков действия и приоритетов, а также с делегатом, /// которого можно использовать для уведомления приложения при удалении вставленного элемента из Cache. /// </summary> /// <param name="key">Ключ кэша, используемый для ссылки на объект.</param> /// <param name="data">Объект для вставки в кэш.</param> /// <param name="dependency">Переменная зависимостей кэша</param> /// <param name="cacheDuration">Время по истечению которого объект будет удален из кэша</param> /// <param name="slidingExpiration">Интервал в секундах между временем последнего обращения к вставленному объекту и временем истечения срока действия этого объекта. /// Если это значение равно 20 минутам, срок действия объекта истечет, и он будет удален из кэша через 20 минут после последнего обращения к этому объекту. /// Если используется скользящий срок действия, параметр cacheDuration должен быть равен 0.</param> /// <param name="priority">Цена объекта относительно других элементов, сохраненных в кэше, выраженная перечислением CacheItemPriority. /// Это значение используется в кэше при исключении объектов. Объекты с более низкой ценой удаляются из кэша раньше, чем объекты с более высокой ценой.</param> /// <param name="onRemoved">Цена объекта относительно других элементов, сохраненных в кэше, выраженная перечислением CacheItemPriority. /// Это значение используется в кэше при исключении объектов. Объекты с более низкой ценой удаляются из кэша раньше, чем объекты с более высокой ценой.</param> /// <param name="isTagMode">Добавлять ли данные в кэш как Insert или как Add (http://habrahabr.ru/post/61617/)</param> public static void AddCacheData(string key, object data, CacheDependency dependency, uint cacheDuration, uint slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoved, bool isTagMode = false) { if (Globals.Settings.Cache.Enabled) { switch (Globals.CacheMode) { case StorageModes.AspNet: if (!isTagMode) { //перезаписывваем значение в любом случае Cache.Insert(key, data, dependency, (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration, slidingExpiration > 0 ? new TimeSpan(0, 0, (int)cacheDuration) : Cache.NoSlidingExpiration, priority, onRemoved); } else { Cache.Add(key, data, dependency, (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration, slidingExpiration > 0 ? new TimeSpan(0, 0, (int)cacheDuration) : Cache.NoSlidingExpiration, priority, onRemoved); } break; case StorageModes.Redis: if (onRemoved == null) { onRemoved = OnRemovedRedisCacheValue; } InsertCacheIntoRedisDb(key, data, cacheDuration); if (!isTagMode) { Cache.Insert(key, false, dependency, (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration, slidingExpiration > 0 ? new TimeSpan(0, 0, (int)slidingExpiration) : Cache.NoSlidingExpiration, priority, onRemoved); } else { Cache.Add(key, false, dependency, (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration, slidingExpiration > 0 ? new TimeSpan(0, 0, (int)slidingExpiration) : Cache.NoSlidingExpiration, priority, onRemoved); } break; case StorageModes.Memory: if (!MemCache.ContainsKey(key)) { MemCache.Add(key, data); } else { MemCache[key] = data; } break; } } }
public object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { // see notes in HttpRuntimeCacheProvider Lazy <object> result; using (var lck = new UpgradeableReadLock(_locker)) { result = MemoryCache.Get(cacheKey) as Lazy <object>; if (result == null || DictionaryCacheProviderBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); lck.UpgradeToWriteLock(); //NOTE: This does an add or update MemoryCache.Set(cacheKey, result, policy); } } //return result.Value; var value = result.Value; // will not throw (safe lazy) var eh = value as DictionaryCacheProviderBase.ExceptionHolder; if (eh != null) { throw eh.Exception; // throw once! } return(value); }
public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { CacheDependency dependency = null; if (dependentFiles != null && dependentFiles.Any()) { dependency = new CacheDependency(dependentFiles); } InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency); }
public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { // NOTE - here also we must insert a Lazy<object> but we can evaluate it right now // and make sure we don't store a null value. var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); var value = result.Value; // force evaluation now if (value == null) { return; // do not store null values (backward compat) } var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); //NOTE: This does an add or update MemoryCache.Set(cacheKey, result, policy); }
/// <summary> /// Non-standard set for when we want to be absolutely explicit about cache priorities /// </summary> public void SetWithPriority <T>(string key, T value, int?durationSecs, bool isSliding, System.Web.Caching.CacheItemPriority priority) { LocalCache.OnLogDuration(key, durationSecs, "LocalCache.SetWithPriority"); key = KeyInContext(key); RawSet(key, value, durationSecs, isSliding, priority); }