private static void Remove(CacheDependency dependency) { lock (dependencies) { dependencies.Remove(dependency.fileOrDirectory); } }
/// <summary> /// 使用指定的文件名或目录获取一个依赖项,如果与指定的文件名或目录对应的依赖项不存在,那么新建一个与其关联的依赖项并返回它。 /// </summary> /// <param name="fileOrDirectory">指定的文件名或目录。</param> /// <returns>CacheDependency 对象。</returns> /// <remarks> /// 如果传入的文件名或目录不合法,那么该方法返回 null。 /// </remarks> public static CacheDependency Get(string fileOrDirectory) { if (!String.IsNullOrEmpty(fileOrDirectory)) { // fileOrDirectory GetFileName GetDirectoryName // \zhaixd\a\b > b \zhaixd\a // D:\a\b > b D:\a // D:\a\b\ > String.Empty D:\a\b // \zhaixd\a\b.txt > b.txt \zhaixd\a // D:\a\b.txt > b.txt D:\a // D:\ > String.Empty null // a > String.Empty String.Empty string directoryName = Path.GetDirectoryName(fileOrDirectory); if (!String.IsNullOrEmpty(directoryName)) { string fileName = Path.GetFileName(fileOrDirectory); lock (dependencies) { CacheDependency cacheDependency; if (dependencies.ContainsKey(fileOrDirectory)) { cacheDependency = dependencies[fileOrDirectory]; if (!cacheDependency.hasChanged) { return cacheDependency; } } cacheDependency = new CacheDependency(fileOrDirectory, directoryName, fileName); dependencies.Add(fileOrDirectory, cacheDependency); cacheDependency.fsw.EnableRaisingEvents = true; return cacheDependency; } } } return null; }
private void SetItemInternal(string key, object value, CacheDependency dependency, TimeSpan timeToLive, DateTime? nextUpdateTime, params string[] tags) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullOrWhiteSpaceException("key"); } if (value == null) { throw new ArgumentNullException("value"); } CachedItem item = new CachedItem(); if (tags != null && tags.Length > 0) { EnsureTags(tags); item.Tags = tags; } item.Key = key; item.Value = value; item.ExpiredTime = timeToLive.Days > 1000 ? DateTime.Now.AddDays(1000) : DateTime.Now + timeToLive; item.NextUpdateTime = nextUpdateTime; item.Dependency = dependency; // 优化实现: 使用读写锁,减少高并发读取阻塞 this.lock4Items.EnterWriteLock(); try { // 覆盖时处理旧项 if (this.cachedItems.ContainsKey(key)) { this.RemoveItemInternal(key); } #region LRU 支持 if (this.cachedItems.Count >= this.capacity) { this.RemoveItemInternal(this.linkedList.Last.item.Key); } #endregion this.cachedItems.Add(key, item); #region LRU 支持,新添加的设为第一个 this.linkedList.AddFirst(item); item.Node = this.linkedList.First; #endregion if (tags != null && tags.Length > 0) { foreach (string tag in tags) { if (!this.cachedItemKeyByTags.ContainsKey(tag)) { this.cachedItemKeyByTags.Add(tag, new Dictionary<string, KeyValuePair<string, CachedItem>>(StringComparer.InvariantCultureIgnoreCase)); } Dictionary<string, KeyValuePair<string, CachedItem>> keys = this.cachedItemKeyByTags[tag]; if (!this.cachedItemObjectByTags.ContainsKey(tag)) { this.cachedItemObjectByTags.Add(tag, new List<KeyValuePair<string, CachedItem>>()); } List<KeyValuePair<string, CachedItem>> objects = this.cachedItemObjectByTags[tag]; KeyValuePair<string, CachedItem> newKvp = new KeyValuePair<string, CachedItem>(key, item); int index; if (keys.ContainsKey(key) && ((index = objects.IndexOf(keys[key])) >= 0)) // 覆盖时 { objects[index] = newKvp; } else { objects.Add(newKvp); } keys[key] = newKvp; } } } finally { this.lock4Items.ExitWriteLock(); } }
public void SetItem(string key, object value, CacheDependency dependency, TimeSpan timeToLive, params string[] tags) { this.SetItemInternal(key, value, dependency, timeToLive, null, tags); }
public Region(NamedCache owner, string name, int capacity, int asyncUpdateInterval, string fileOrDirectory) { this.owner = owner; this.name = name; this.capacity = capacity; this.asyncUpdateInterval = asyncUpdateInterval; this.cachedItems = new Dictionary<string, CachedItem>(this.capacity, StringComparer.InvariantCultureIgnoreCase); this.cachedItemKeyByTags = new Dictionary<string, Dictionary<string, KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.cachedItemObjectByTags = new Dictionary<string, List<KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.Dependency = CacheDependency.Get(fileOrDirectory); }
public NamedCache(string name, string fileOrDirectory) { this.name = name; this.Dependency = CacheDependency.Get(fileOrDirectory); }
private object GetAndSetItem(string cacheName, string regionName, string key, Func<object, object> callback, object callBackState, CacheDependency dependency, params string[] tags) { if (string.IsNullOrWhiteSpace(cacheName)) { throw new ArgumentNullOrWhiteSpaceException("cacheName"); } if (string.IsNullOrWhiteSpace(regionName)) { throw new ArgumentNullOrWhiteSpaceException("regionName"); } if (callback == null) { throw new ArgumentNullException("callback"); } return this.GetOrCreateCache(cacheName).GetOrCreateRegion(regionName).GetAndSetItem(key, callback, callBackState, dependency, tags); }
public object GetAndSetItem(string regionName, string key, Func<object, object> callback, object callBackState, CacheDependency dependency) { object result = null; try { result = LocalCacheManager.Instance.GetAndSetItem(CacheName, regionName, key, callback, callBackState, dependency, null); } catch (ArgumentException are) { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, are.GetFriendlyToString()), LogCategory.Cache); } catch (ConfigurationException confExp) { if (confExp is IgnoredConfigurationException) // 这种类型的配置错误不做任何处理,以避免产生大量同类型的配置错误日志 { } else { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, confExp.GetFriendlyToString()), LogCategory.Cache); } } catch (Exception err) { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, err.GetFriendlyToString()), LogCategory.Cache); } return result; }
public void SetItem(string cacheName, string regionName, string key, object value, CacheDependency dependency, TimeSpan timeToLive, params string[] tags) { if (string.IsNullOrWhiteSpace(cacheName)) { throw new ArgumentNullOrWhiteSpaceException("cacheName"); } if (string.IsNullOrWhiteSpace(regionName)) { throw new ArgumentNullOrWhiteSpaceException("regionName"); } this.GetOrCreateCache(cacheName).GetOrCreateRegion(regionName).SetItem(key, value, dependency, timeToLive, tags); }
public void SetItem(string key, object value, CacheDependency dependency, int timeToLiveInSeconds, params string[] tags) { this.SetItemInternal(key, value, dependency, TimeSpan.FromSeconds(timeToLiveInSeconds), null, tags); }
public CachedItemCallbackWrapper(CachedItem item, Func<object, object> callback, object callBackState, CacheDependency dependency, TimeSpan timeToLive, params string[] tags) { this.Item = item; this.Callback = callback; this.CallBackState = callBackState; this.Dependency = dependency; this.TTL = timeToLive; this.Tags = tags; }
public Region(NamedCache owner, string name, int capacity, TimeSpan asyncTimeToLive, TimeSpan asyncUpdateInterval, string fileOrDirectory) { this.owner = owner; this.name = name; if (this.name == "_CFG_AppSettings") this.isAppsettingRegion = true; this.capacity = capacity; this.asyncTimeToLive = asyncTimeToLive; this.asyncUpdateInterval = asyncUpdateInterval; this.cachedItems = new Dictionary<string, CachedItem>(this.capacity, StringComparer.InvariantCultureIgnoreCase); this.cachedItemKeyByTags = new Dictionary<string, Dictionary<string, KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.cachedItemObjectByTags = new Dictionary<string, List<KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.Dependency = CacheDependency.Get(fileOrDirectory); }
public object GetAndSetItem(string regionName, string key, Func<object, object> callback, object callBackState, CacheDependency dependency, params string[] tags) { object result = null; try { result = LocalCacheManager.Instance.GetAndSetItem(CacheName, regionName, key, callback, callBackState, dependency, tags); } catch (ArgumentException are) { Container.LogService.Warn(are.Message, LogCategory.Cache); } catch (Exception err) { Container.LogService.Warn(err, LogCategory.Cache); } return result; }
public void SetItemWithNoExpiration(string regionName, string key, object value, CacheDependency dependency, params string[] tags) { if (value == null) { return; } try { LocalCacheManager.Instance.SetItemWithNoExpiration(CacheName, regionName, key, value, dependency, tags); } catch (ArgumentException are) { Container.LogService.Warn(are.Message, LogCategory.Cache); } catch (Exception err) { Container.LogService.Warn(err, LogCategory.Cache); } }
public void SetItem(string regionName, string key, object value, CacheDependency dependency, int timeToLiveInSeconds, params string[] tags) { try { LocalCacheManager.Instance.SetItem(CacheName, regionName, key, value, dependency, timeToLiveInSeconds, tags); } catch (ArgumentException are) { Container.LogService.Warn(are.Message, LogCategory.Cache); } catch (Exception err) { Container.LogService.Warn(err, LogCategory.Cache); } }
public CachedItemCallbackWrapper(CachedItem item, Func<object, object> callback, object callBackState, CacheDependency dependency, int timeToLiveInSeconds, params string[] tags) { this.Item = item; this.Callback = callback; this.CallBackState = callBackState; this.Dependency = dependency; this.TTL = TimeSpan.FromSeconds(timeToLiveInSeconds); this.Tags = tags; }
public object GetAndSetItem(string key, Func<object, object> callback, object callBackState, CacheDependency dependency, params string[] tags) { CachedItem cachedItem = this.GetCachedItem(key); // 缓存项不存在时立即添加新的缓存项并返回 if (cachedItem == null) { object cacheItemLock = null; lock (cacheItemLocks) { if (!cacheItemLocks.ContainsKey(key)) { cacheItemLock = new object(); cacheItemLocks[key] = cacheItemLock; } else { cacheItemLock = cacheItemLocks[key]; } } object value = null; lock (cacheItemLock) { cachedItem = this.GetCachedItem(key); if (cachedItem == null) { value = callback(callBackState); if (value != null) { // 缓存项在缓存服务器中的生存时间为:异步更新间隔+5分钟,这足够保证缓存项能够及时成功更新 // 同时,可以避免添加当前缓存项的客户端应用终止时(客户端应用中保存的 cacheItemVersions 失效,其它客户端因为仅读取该缓存项而没有存储其版本,永远不会更新该缓存项) // 缓存项将可能在很长时间(由传入的 timeToLive 值决定)内不再更新的问题 this.SetItemInternal(key, value, dependency, TimeSpan.FromSeconds(this.asyncUpdateInterval + this.asyncUpdateAdditionalLiveTime), DateTime.Now.AddSeconds(this.asyncUpdateInterval), tags); } } else { value = cachedItem.Value; } } lock (cacheItemLocks) { cacheItemLocks.Remove(key); } return value; } // 首先不是处于更新过程中且时间上判断应更新缓存项,使用双重检查锁定机制并通过任务并行库异步更新缓存项 if (!cachedItem.IsUpdating && cachedItem.NextUpdateTime < DateTime.Now) { lock (cachedItem) // 仅锁定当前缓存项,尽可能的避免阻塞对其它缓存项的访问 { if (!cachedItem.IsUpdating && cachedItem.NextUpdateTime < DateTime.Now) { cachedItem.IsUpdating = true; System.Threading.Tasks.Task.Factory.StartNew(this.UpdateCacheItem, new CachedItemCallbackWrapper(cachedItem, callback, callBackState, dependency, this.asyncUpdateInterval + this.asyncUpdateAdditionalLiveTime, tags)); } } } // 在异步更新缓存项之前立即返回当前缓存项的值。 return cachedItem.Value; }
public void SetItem(string cacheName, string regionName, string key, object value, CacheDependency dependency, int timeToLiveInSeconds, params string[] tags) { this.SetItem(cacheName, regionName, key, value, dependency, TimeSpan.FromSeconds(timeToLiveInSeconds), tags); }
public void SetItemWithNoExpiration(string cacheName, string regionName, string key, object value, CacheDependency dependency, params string[] tags) { this.SetItem(cacheName, regionName, key, value, dependency, TimeSpan.MaxValue, tags); }
public bool SetItemWithNoExpiration(string regionName, string key, object value, CacheDependency dependency) { if (value == null) { return false; } try { LocalCacheManager.Instance.SetItemWithNoExpiration(CacheName, regionName, key, value, dependency, null); return true; } catch (ArgumentException are) { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, are.GetFriendlyToString()), LogCategory.Cache); } catch (ConfigurationException confExp) { if (confExp is IgnoredConfigurationException) // 这种类型的配置错误不做任何处理,以避免产生大量同类型的配置错误日志 { } else { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, confExp.GetFriendlyToString()), LogCategory.Cache); } } catch (Exception err) { Container.LogService.Warn(String.Format("{0}_{1}:{2}", regionName, key, err.GetFriendlyToString()), LogCategory.Cache); } return false; }