using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Caching;
using System.Threading;
namespace Ant.ORM.Cache
{
///
/// 全局缓存类
///
///
/// 使用示例:
/// 实例化: CacheManage cache=CacheManage.Instance;
/// 添加: cache.Add("路过秋天",new MDataTable);
/// 判断: if(cache.Contains("路过秋天"))
/// {
/// 获取: MDataTable table=cache.Get("路过秋天") as MDataTable;
/// }
///
public class CacheManage
{
private readonly System.Web.HttpContext H = new System.Web.HttpContext(new System.Web.HttpRequest("Null.File", "http://cyq1162.cnblogs.com", String.Empty), new System.Web.HttpResponse(null));
private System.Web.Caching.Cache theCache = null;
private Dictionary cacheState = new Dictionary();
private DateTime workTime;
///
/// 缓存信息
///
public Dictionary CacheInfo
{
get
{
return cacheState;
}
}
private CacheManage()
{
theCache = H.Cache;
Thread thread = new Thread(new ThreadStart(ClearState));
thread.IsBackground = true;
thread.Start();
workTime = DateTime.Now.AddMinutes(5);
}
private void ClearState()
{
List removeKeys = new List();
while (true)
{
try
{
Thread.Sleep(5 * 60 * 1000);//五分钟休眠时间
if (theCache.Count != cacheState.Count)//准备同步
{
foreach (KeyValuePair item in cacheState)
{
if ((item.Value.CreaeTime.AddMinutes(4) < DateTime.Now && item.Value.CallCount < 2) || //缓存调用次数太少
item.Value.CreaeTime.AddMinutes(item.Value.CacheMinutes) < DateTime.Now)//清过期cacheState进行同步
{
if (!removeKeys.Contains(item.Key))
{
removeKeys.Add(item.Key);
}
}
}
foreach (string key in removeKeys)
{
Remove(key);//移除
}
clearCount = removeKeys.Count;
removeKeys.Clear();
}
workTime = DateTime.Now.AddMinutes(5);
}
catch
{
System.Threading.Thread.Sleep(TimeSpan.FromHours(1));
}
}
}
private int errorCount = 0;//缓存捕异常次数
private int clearCount = 0;//清除的缓存数
///
/// 缓存工作信息
///
public string WorkInfo
{
get
{
return string.Format("try catch error:{0}(times)--clear count:{1}--next clear work time at:{2}", errorCount, clearCount, workTime);
}
}
///
/// 获和缓存总数
///
public int Count
{
get
{
return theCache == null ? 0 : theCache.Count;
}
}
///
/// 返回唯一实例
///
public static CacheManage Instance
{
get
{
return Shell.instance;
}
}
class Shell
{
internal static readonly CacheManage instance = new CacheManage();
}
///
/// 还可用的缓存百分比
///
public long RemainMemoryPercentage
{
get
{
return theCache.EffectivePercentagePhysicalMemoryLimit;
}
}
///
/// 还可用的缓存字节数
///
public long RemainMemoryBytes
{
get
{
return theCache.EffectivePrivateBytesLimit;
}
}
///
/// 获得一个Cache对象
///
/// 标识
///
public object Get(string key)
{
if (Contains(key))
{
try
{
cacheState[key].CallCount++;
}
catch
{
errorCount++;
}
return theCache[key];
}
return null;
}
///
/// 是否存在缓存
///
/// 标识
///
public bool Contains(string key)
{
if (theCache[key] != null)
{
return true;
}
else
{
if (cacheState.ContainsKey(key))
{
try
{
cacheState.Remove(key);
}
catch
{
errorCount++;
}
}
return false;
}
}
///
/// 添加一个Cache对象
///
/// 标识
/// 对象值
public void Add(string key, object value)
{
Add(key, value, null, 0);
}
public void Add(string key, object value, string filePath)
{
Add(key, value, filePath, 0);//再插入Cache
}
public void Add(string key, object value, string filePath, double cacheTimeMinutes)
{
if (Contains(key))
{
Remove(key);
}
Insert(key, value, filePath, cacheTimeMinutes);//再插入Cache
}
///
/// 缓存设置:有则更新,无则添加
///
///
///
public void Set(string key, object value)
{
if (Contains(key))
{
theCache[key] = value;
}
else
{
Insert(key, value, null, 0);//再插入Cache
}
}
///
/// 更新缓存,缓存存在则更更新,不存在则跳过
///
public void Update(string key, object value)
{
if (Contains(key))
{
theCache[key] = value;
}
}
///
/// 相对底层Cache添加方法,添加一个Cache请用Add方法
///
/// 标识
/// 对象值
/// 文件依赖路径
/// 缓存分钟数
private void Insert(string key, object value, string filePath, double cacheTimeMinutes)
{
CacheDependency theCacheDependency = null;
if (!string.IsNullOrEmpty(filePath))
{
theCacheDependency = new CacheDependency(filePath);
}
double cacheTime = cacheTimeMinutes;
if (cacheTimeMinutes == 0)
{
cacheTime = 30;
}
theCache.Insert(key, value == null ? string.Empty : value, theCacheDependency, DateTime.Now.AddMinutes(cacheTime), TimeSpan.Zero, CacheItemPriority.Default, null);
CacheDependencyInfo info = new CacheDependencyInfo(theCacheDependency, cacheTime);
if (cacheState.ContainsKey(key))
{
cacheState[key] = info;
}
else
{
try
{
cacheState.Add(key, info);
}
catch { }
}
}
///
/// 删除一个Cache对象
///
/// 标识
public void Remove(string key)
{
if (Contains(key))//检测存在时中会自动清除cacheState
{
try
{
theCache.Remove(key);
cacheState.Remove(key);
}
catch
{
errorCount++;
}
}
}
///
/// 清除所有缓存
///
public void Clear()
{
try
{
foreach (KeyValuePair item in cacheState)
{
theCache.Remove(item.Key);
}
cacheState.Clear();
}
catch
{
errorCount++;
}
}
///
/// 用户手动设置缓存对象已更改
///
///
///
public void SetChange(string key, bool change)
{
if (cacheState.ContainsKey(key) && Contains(key))
{
CacheDependencyInfo info = cacheState[key];
if (info != null)
{
info.UserSetChange(change);
}
}
else
{
Add("Ant.ORM.Cache:Temp_" + key, change, null, 0.1);//缓存失效时,产生6秒的key缓冲
}
}
///
/// 获取缓存对象是否已被用户手动设置更改
///
///
///
public bool GetHasChanged(string key)
{
if (cacheState.ContainsKey(key) && Contains(key))
{
CacheDependencyInfo info = cacheState[key];
if (info != null)
{
return info.IsChanged ? false : info.UserChange;
}
}
else if (Contains("Ant.ORM.Cache:Temp_" + key))
{
return (bool)theCache.Get("Ant.ORM.Cache:Temp_" + key);
}
return false;
}
}
///
/// 缓存依赖信息
///
public class CacheDependencyInfo
{
public int CallCount = 0;
///
/// 缓存产生的时间
///
public DateTime CreaeTime;
///
/// 缓存多少分钟
///
public Double CacheMinutes = 0;
DateTime CacheChangeTime = DateTime.MinValue;
CacheDependency FileDependency = null;
public CacheDependencyInfo(CacheDependency dependency, double cacheMinutes)
{
if (dependency != null)
{
FileDependency = dependency;
CacheChangeTime = FileDependency.UtcLastModified;
}
CreaeTime = DateTime.Now;
CacheMinutes = cacheMinutes;
}
///
/// 系统文件依赖是否发生改变
///
public bool IsChanged
{
get
{
if (FileDependency != null && (FileDependency.HasChanged || CacheChangeTime != FileDependency.UtcLastModified))
{
CacheChangeTime = FileDependency.UtcLastModified;
return true;
}
return false;
}
}
internal bool UserChange = false;
public void UserSetChange(bool change)
{
UserChange = IsChanged ? false : change;
}
}
}