📄 tcpcacheprovider.cs
字号:
//===============================================================================
// CSDN HeyCache
//===============================================================================
// 修改记录:[按最后修改时间倒排序]
// modify: 2007.06.14 by tangwei
// create: 2007.06.11 by tangwei
//
// 代码来源:tangwei
//===============================================================================
namespace HeyCacher.Providers
{
using System;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Collections.Specialized;
using HeyCacher.Components;
using HeyCacher.Components.Scavenger;
using HeyCacher.Components.Expirations;
using System.Collections;
using System.IO;
/// <summary>
/// 基于Tcp通讯的缓存实现
/// </summary>
public class TcpCacheProvider : CacheProvider
{
Cnlamar.Pool.ObjectPool<NetClient> pool; //连接对象池
#region 初始化
/// <summary>
/// 初始化
/// </summary>
/// <param name="name"></param>
/// <param name="config"></param>
public override void Initialize(string name, NameValueCollection config)
{
//
int ScavengInSeconds = 10; //资源回收间隔时间,单位为秒
int PoolCreateSize = 2;
int PoolMaxSize = 100;
string ServerAddress = "127.0.0.1";
int Port = 8750;
int ReConnectTimespan = 60;
int SendTimeout = -1;
int ReceiveTimeout = -1;
int SendBufferSize = -1;
#region 初始化配置
base.Initialize(name, config);
try
{
if (config != null)
{
if (config["PoolCreateSize"] != null)
{
PoolCreateSize = int.Parse(config["PoolCreateSize"]);
config.Remove("PoolCreateSize");
}
if (config["PoolMaxSize"] != null)
{
PoolMaxSize = int.Parse(config["PoolMaxSize"]);
config.Remove("PoolMaxSize");
}
if (config["ServerAddress"] != null)
{
ServerAddress = config["ServerAddress"];
config.Remove("ServerAddress");
}
if (config["Port"] != null)
{
Port = int.Parse(config["Port"]);
config.Remove("Port");
}
if (config["ReConnectTimespan"] != null)
{
ReConnectTimespan = int.Parse(config["ReConnectTimespan"]);
config.Remove("ReConnectTimespan");
}
if (config["SendTimeout"] != null)
{
SendTimeout = int.Parse(config["SendTimeout"]);
config.Remove("SendTimeout");
}
if (config["ReceiveTimeout"] != null)
{
ReceiveTimeout = int.Parse(config["ReceiveTimeout"]);
config.Remove("ReceiveTimeout");
}
if (config["SendBufferSize"] != null)
{
SendBufferSize = int.Parse(config["SendBufferSize"]);
config.Remove("SendBufferSize");
}
if (config["ScavengInSeconds"] != null)
{
ScavengInSeconds = int.Parse(config["ScavengInSeconds"]);
config.Remove("ScavengInSeconds");
}
}
}
catch
{
}
#endregion
//建立连接对象池
try
{
NetClientParam netClientParam = new NetClientParam(ServerAddress, Port, ReConnectTimespan, SendTimeout, ReceiveTimeout, SendBufferSize, base.Encoding);
pool = new Cnlamar.Pool.ObjectPool<NetClient>(netClientParam, PoolCreateSize, PoolMaxSize);
}
catch
{
}
//建立各种回收任务与控制器对象,并启动
ExpirationTask expirationTask = new ExpirationTask(this);
BackgroundScheduler scheduler = new BackgroundScheduler(expirationTask);
scheduler.Start();
//启动回收定时器
ScavengerTimer timer = new ScavengerTimer();
//timer.StartPolling(new TimerCallback(scheduler.ExpirationTimeoutExpired), ScavengInSeconds); //系统线程池定时器
timer.StartPolling(new System.Timers.ElapsedEventHandler(scheduler.ExpirationTimeoutExpired), ScavengInSeconds); //普通定时器
}
#endregion
#region Count
/// <summary>
///
/// </summary>
public override int Count
{
get
{
string ResultString = String.Empty;
NetClient nc = null;
try
{
nc = pool.Get();
ResultString = base.Encoding.GetString(nc.Send("Count", null, null, XmlSerialize, false));
}
catch { }
finally
{
if (nc != null)
{
pool.FreeObject(nc);
}
}
int count = -1;
int.TryParse(ResultString, out count);
return count;
}
}
#endregion
#region Contains
public override bool Contains(string Key, CacheTack cacheTack)
{
//获取
string ResultString = String.Empty;
NetClient nc = null;
try
{
nc = pool.Get();
ResultString = base.Encoding.GetString(nc.SendString("Contains", Key, cacheTack, XmlSerialize, false));
}
catch (Exception ex)
{
Caches.log.Error("执行Tcp缓存客户端中的Contains方法时出现未知错误。", ex);
}
finally
{
if (nc != null)
{
pool.FreeObject(nc);
}
}
return ResultString[0] == 1;
}
#endregion
#region Get
/// <summary>
///
/// </summary>
/// <param name="Key"></param>
/// <returns></returns>
public override CacheItem GetCacheItem(string Key, CacheTack cacheTack)
{
#region 更新本地依赖
ExpirationItem expirationItemBeforeLock = null;
//独占锁
bool LockFlag;
do
{
lock (ExpirationItemTable.SyncRoot)
{
if (!ExpirationItemTable.ContainsKey(Key))
{
break;
}
expirationItemBeforeLock = (ExpirationItem)ExpirationItemTable[Key];
LockFlag = Monitor.TryEnter(expirationItemBeforeLock);
}
if (!LockFlag)
{
Thread.Sleep(0);
}
} while (!LockFlag);
//操作
if (expirationItemBeforeLock != null)
{
//过期
if (expirationItemBeforeLock.HasExpired())
{
expirationItemBeforeLock.TouchedByUserAction(true);
ExpirationItemTable.Remove(Key);
realRemove(Key, cacheTack);
return null;
}
}
//释放锁
if (expirationItemBeforeLock != null)
{
Monitor.Exit(expirationItemBeforeLock);
}
#endregion
return innerGet(Key, cacheTack);
}
private CacheItem innerGet(string Key, CacheTack cacheTack)
{
//获取
byte[] ResultBytes = null;
NetClient nc = null;
try
{
string Cmd = "Get";
if (DataCompress)
{
Cmd += "_C";
}
nc = pool.Get();
ResultBytes = nc.SendString(Cmd, Key, cacheTack, XmlSerialize, DataCompress);
}
catch (Exception ex)
{
Caches.log.Error("执行Tcp缓存客户端中的innerGet方法时出现未知错误。", ex);
}
finally
{
if (nc != null)
{
pool.FreeObject(nc);
}
}
CacheItem ci = null;
try
{
object obj = null;
obj = Cnlamar.Serialization.Deserialize(ResultBytes, XmlSerialize, DataCompress);
ci = obj as CacheItem;
//解封value
ci.DeserializeValue();
}
catch(Exception ex)
{
Caches.log.Error("执行Tcp缓存客户端中的innerGet方法,并在做反序列化操作的时候,出现未知错误。", ex);
}
return ci;
}
#endregion
#region innerInsert
protected override object innerInsert(bool Replace, CacheItem ci, CacheTack cacheTack, out bool Insertd)
{
Insertd = false; //是否被插入
//
string Cmd;
if (Replace)
{
Cmd = "Set";
}
else
{
Cmd = "Add";
}
if (DataCompress)
{
Cmd += "_C";
}
//
CacheItem resultCI = innerInsert(Cmd, ci, cacheTack);
if (resultCI == null)
{
return null;
}
Insertd = true;
//判断返回
return resultCI.realValue;
}
private CacheItem innerInsert(string cmd, CacheItem ci, CacheTack cacheTack)
{
//建立缓存策略副本
ICacheItemExpiration[] RemoteExpirations;
InsertCacheItemExpiration(ci.Key, ci.Priority, ci.RefreshAction, ci.Expirations, out RemoteExpirations);
//封装value
ci.SerializeValue();
//建立缓存项
byte[] CacheData = Cnlamar.Serialization.Serialize(ci, XmlSerialize, DataCompress);
//发送命令
string ResultString = String.Empty;
NetClient nc = null;
try
{
nc = pool.Get();
byte[] result = nc.Send(cmd, CacheData, cacheTack, XmlSerialize, DataCompress);
if (result != null)
{
ResultString = base.Encoding.GetString(result);
}
}
catch (System.Net.Sockets.SocketException ex)
{
//套接字错误,通常是服务器无法连接
Caches.log.Error("执行Tcp缓存客户端中的innerInsert方法时出现SocketException错误。", ex);
}
catch (Exception ex)
{
//其他错误,未知错误
Caches.log.Error("执行Tcp缓存客户端中的innerInsert方法时出现未知错误。", ex);
}
finally
{
if (nc != null)
{
pool.FreeObject(nc);
}
}
//判断反馈
if (String.IsNullOrEmpty(ResultString) || ResultString[0] != '1')
{
return null;
}
return ci;
}
private void InsertCacheItemExpiration(string key, HeyCacher.Components.CacheItemPriority priority, object RefreshAction, ICacheItemExpiration[] expirations, out ICacheItemExpiration[] RemoteExpirations)
{
RemoteExpirations = null; //远程过期策略
//如果过期规则为空,则不建立本地本地过期策略
if (expirations == null)
{
return;
}
//整理本地与远程过期策略
List<ICacheItemExpiration> LocalExpirationsList = new List<ICacheItemExpiration>();
List<ICacheItemExpiration> RemoteExpirationsList = new List<ICacheItemExpiration>();
foreach (ICacheItemExpiration tmpExpiration in expirations)
{
if (tmpExpiration is INetCacheItemExpiration)
{
bool IsLocal = false;
foreach (string DependencyMark in ((INetCacheItemExpiration)tmpExpiration).AvailableIn())
{
if (DependencyMark == AppSetting.Mark)
{
IsLocal = true;
break;
}
}
if (IsLocal)
{
LocalExpirationsList.Add(tmpExpiration);
}
else
{
RemoteExpirationsList.Add(tmpExpiration);
}
}
else if (tmpExpiration != null)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -