You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
355 lines
15 KiB
355 lines
15 KiB
/*
|
|
Sog 游戏基础库
|
|
2016 by zouwei
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Org.BouncyCastle.Ocsp;
|
|
using ProtoCSStruct;
|
|
using Sog;
|
|
|
|
namespace Chat
|
|
{
|
|
public static class ChatCacheOp
|
|
{
|
|
private static int ChannalCacheMax = 100; //单频道消息缓存数量限制
|
|
private static int SaveFileCdSec = 300; //存盘cd 单位秒
|
|
private static int SaveMaxDay = 14; //起服只读X天以内数据
|
|
|
|
public static void InitChatCacheConfig(ChatServerConfig serverConfig)
|
|
{
|
|
if (serverConfig == null)
|
|
{
|
|
TraceLog.Error("ChatCacheOp.InitChatCacheConfig error");
|
|
return;
|
|
}
|
|
ChannalCacheMax = serverConfig.ChannalCacheMax;
|
|
SaveFileCdSec = Math.Max(300, serverConfig.SaveFileCdSec); //不要低于5分钟
|
|
SaveMaxDay = serverConfig.SaveMaxDay;
|
|
}
|
|
|
|
public static string GetSaveFilePath()
|
|
{
|
|
return "./ChannalChatCacheData_" + ChatServerUtils.GetApp().ServerID.ToString() + ".fdb";
|
|
}
|
|
|
|
public static void WriteChatCacheStat()
|
|
{
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
TraceLog.Stat("ChatCacheStruct total {0} used {1} rate {2}%"
|
|
, chatCache.m_cacheStrutChatReq.GetTotalCount()
|
|
, chatCache.m_cacheStrutChatReq.GetUsedCount()
|
|
, chatCache.m_cacheStrutChatReq.GetUsedPercent());
|
|
}
|
|
|
|
public static void ChatCacheTick(long nowSec)
|
|
{
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
long saveCdSec = SaveFileCdSec;
|
|
//停服时5s
|
|
if (ChatServerUtils.GetApp().IsStopping)
|
|
{
|
|
saveCdSec = 5;
|
|
}
|
|
if (chatCache.m_lastSaveTime + saveCdSec < nowSec)
|
|
{
|
|
SaveCacheToFile();
|
|
chatCache.m_lastSaveTime = nowSec;
|
|
WriteChatCacheStat();
|
|
}
|
|
}
|
|
|
|
public static int AddChatCache(ref CSChatRes res, ChatChannelType type = ChatChannelType.None)
|
|
{
|
|
long channelId = ChatServerData.GetChatChannelId(res.ChatChannelType, res.ChannelParam);
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
chatCache.m_needSave = true;
|
|
if (channelId <= 0)
|
|
{
|
|
TraceLog.Error("ChatCacheOp.AddChatCache channelId {0} ChatChannelType {1} ChannelParam:{2}", channelId, res.ChatChannelType, res.ChannelParam);
|
|
return -1;
|
|
}
|
|
if (chatCache.m_channalCacheMap.ContainsKey(channelId))
|
|
{
|
|
//看有没有到单Id上限
|
|
var list = chatCache.m_channalCacheMap[channelId];
|
|
if (list.Count < ChannalCacheMax)
|
|
{
|
|
ref ChatCacheDataStruct cache = ref chatCache.m_cacheStrutChatReq.Malloc();
|
|
if (!cache.IsNull())
|
|
{
|
|
cache.cacheData.CopyFrom(ref res);
|
|
list.AddLast(cache.GetObjectID());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//需要顶掉老的缓存
|
|
if (list.Count > 0)
|
|
{
|
|
//取最早的覆盖数据后放到末尾
|
|
int index = list.First.Value;
|
|
list.RemoveFirst();
|
|
ref ChatCacheDataStruct cache = ref chatCache.m_cacheStrutChatReq.GetByIndex(index);
|
|
if (!cache.IsNull())
|
|
{
|
|
cache.cacheData.CopyFrom(ref res);
|
|
list.AddLast(index);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
//下标有问题
|
|
TraceLog.Error("ChatCacheOp.AddChatCache not find index:{0}", index);
|
|
return -1;
|
|
}
|
|
}
|
|
TraceLog.Error("ChatCacheOp.AddChatCache list count error {0} {1}", channelId, list.Count);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
ref ChatCacheDataStruct cache = ref chatCache.m_cacheStrutChatReq.Malloc();
|
|
if (!cache.IsNull())
|
|
{
|
|
cache.cacheData.CopyFrom(ref res);
|
|
LinkedList<int> linkList = new LinkedList<int>();
|
|
linkList.AddLast(cache.GetObjectID());
|
|
chatCache.m_channalCacheMap.Add(channelId, linkList);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
//空间不够
|
|
TraceLog.Error("ChatCacheOp.AddChatCache not space");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//获取对应id的缓存数据
|
|
public static void OnGetChannelCacheData(PlayerOnChat player, ChatChannelType channel, long channelParam, long seq)
|
|
{
|
|
long channelId = ChatServerData.GetChatChannelId(channel, channelParam);
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
CSChannelCacheDataRes channelChatCache = new CSChannelCacheDataRes()
|
|
{
|
|
ChatChannelType = channel,
|
|
ChannelParam = channelParam,
|
|
};
|
|
|
|
Dictionary<long, long> dicChatBlack = ChatSvc.GetPlayerDicChatBlack(player);
|
|
|
|
TraceLog.Trace("ChatCacheOp.OnGetChannelCacheData player {0} channel {1} {2} seq {3} dicChatBlackCount {4}",
|
|
player.UserID, channel, channelParam, seq, dicChatBlack.Count);
|
|
|
|
if (chatCache.m_channalCacheMap.ContainsKey(channelId))
|
|
{
|
|
if (chatCache.m_channalCacheMap[channelId].Count > 0)
|
|
{
|
|
var list = chatCache.m_channalCacheMap[channelId];
|
|
var node = list.Last;
|
|
while (node != null)
|
|
{
|
|
ref var cache = ref chatCache.m_cacheStrutChatReq.GetByIndex(node.Value);
|
|
|
|
if (!cache.IsNull()
|
|
&& cache.cacheData.ChatSeq > seq
|
|
&& channelChatCache.ChatCache.Count < channelChatCache.ChatCache.GetMaxCount())
|
|
{
|
|
long chatBlackTime = 0;
|
|
if (dicChatBlack.TryGetValue(cache.cacheData.Uid, out chatBlackTime)) //找聊天缓存的话,聊天屏蔽黑名单中的,并且是屏蔽时间之后的,才进行过滤
|
|
{
|
|
if (chatBlackTime > cache.cacheData.SendTime)
|
|
{
|
|
channelChatCache.ChatCache.Add(ref cache.cacheData);
|
|
if (channelChatCache.ChatCache.Count >= channelChatCache.ChatCache.GetMaxCount())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceLog.Trace("ChatCacheOp.OnGetChannelCacheData filter user {0} chatBlackUid {1} chatBlackTime {2} SendTime {3}", player.UserID, cache.cacheData.Uid, chatBlackTime, cache.cacheData.SendTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
channelChatCache.ChatCache.Add(ref cache.cacheData);
|
|
if (channelChatCache.ChatCache.Count >= channelChatCache.ChatCache.GetMaxCount())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
node = node.Previous;
|
|
}
|
|
}
|
|
}
|
|
PlayerPacketSender.SendToPlayer(player, (int)CSGameMsgID.ChannelCacheDataRes, ref channelChatCache);
|
|
TraceLog.Trace("ChatCacheOp.OnGetChannelCacheData player {0} channel {1} {2} seq {3} realcount {4}",
|
|
player.UserID, channel, channelParam, seq, channelChatCache.ChatCache.Count);
|
|
}
|
|
|
|
//占居内存大的话不适用
|
|
/*public static void SaveChatCache(bool forceSave = false)
|
|
{
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
if ((!chatCache.m_needSave) && (!forceSave))
|
|
{
|
|
return;
|
|
}
|
|
int needSaveNum = chatCache.m_cacheStrutChatReq.GetUsedCount();
|
|
TraceLog.Trace("ChatCache.SaveChatCache save file {0} begin time {1} needSave {2}", saveFile, AppTime.GetNowSysMs(), needSaveNum);
|
|
ChannelChatCacheData needSaveData = new ChannelChatCacheData();
|
|
foreach (var idQueueKv in chatCache.m_channalCacheMap)
|
|
{
|
|
foreach (int index in idQueueKv.Value)
|
|
{
|
|
ref var dataOne = ref chatCache.m_cacheStrutChatReq.GetByIndex(index);
|
|
if (!dataOne.IsNull())
|
|
{
|
|
needSaveData.ChatList.Add(ref dataOne.cacheData);
|
|
}
|
|
}
|
|
|
|
}
|
|
int iRet = Sog.IO.FileDBSave.SaveToFile(ref needSaveData, saveFile);
|
|
if (iRet != 0)
|
|
{
|
|
TraceLog.Error("ChatCache.SaveChatCache save file {0} error, ret {1}", saveFile, iRet);
|
|
}
|
|
if (needSaveData.ChatList.Count != needSaveNum)
|
|
{
|
|
TraceLog.Error("ChatCache.SaveChatCache save less need:{0} have:{1}", needSaveNum, needSaveData.ChatList.Count);
|
|
}
|
|
TraceLog.Trace("ChatCache.SaveChatCache save file {0} success time {1}", saveFile, AppTime.GetNowSysMs());
|
|
}*/
|
|
|
|
/*public static void LoadChatCache()
|
|
{
|
|
TraceLog.Trace("ChatCache.LoadChatCache load file:{0} begin time:{0}", saveFile, AppTime.GetNowSysMs());
|
|
ChannelChatCacheData data = new ChannelChatCacheData();
|
|
if (File.Exists(saveFile) == false)
|
|
{
|
|
TraceLog.Debug("ChatCache.LoadChatCache file not exist {0}", saveFile);
|
|
return;
|
|
}
|
|
bool success = Sog.IO.FileDBSave.ReadFromFile(ref data, saveFile);
|
|
if ( !success)
|
|
{
|
|
TraceLog.Error("ChatCache.LoadChatCache failed! file:{0}", saveFile);
|
|
return;
|
|
}
|
|
for(int i = 0; i < data.ChatList.Count; ++i)
|
|
{
|
|
ref var chatRes = ref data.ChatList[i];
|
|
AddChatCache(ref chatRes);
|
|
ChatServerUtils.GetChatServerData().SetChannalChatSeq(chatRes.ChatSeq, chatRes.ChatChannelType, chatRes.ChannelParam);
|
|
}
|
|
TraceLog.Trace("ChatCache.LoadChatCache load file:{0} success time:{0}", saveFile, AppTime.GetNowSysMs());
|
|
SaveChatCache(true);
|
|
}*/
|
|
|
|
public static void SaveCacheToFile()
|
|
{
|
|
ref var chatCache = ref ChatServerUtils.GetChatServerData().m_chatCacheInfo;
|
|
if (chatCache.m_needSave == false)
|
|
{
|
|
return;
|
|
}
|
|
int haveSave = 0;
|
|
string saveFile = GetSaveFilePath();
|
|
TraceLog.Trace("ChatCacheOp.SaveCacheToFile save file {0} begin time {1}", saveFile, AppTime.GetNowSysMs());
|
|
try
|
|
{
|
|
FileStream fileStream = File.OpenWrite(saveFile);
|
|
//清空文件
|
|
fileStream.SetLength(0);
|
|
BinaryWriter sw = new BinaryWriter(fileStream);
|
|
foreach (var item in chatCache.m_channalCacheMap)
|
|
{
|
|
foreach (int index in item.Value)
|
|
{
|
|
ref var dataOne = ref chatCache.m_cacheStrutChatReq.GetByIndex(index);
|
|
if (!dataOne.IsNull())
|
|
{
|
|
int size = dataOne.cacheData.CalculateSize();
|
|
byte[] dataByte = new byte[size];
|
|
CodedOutputStream ouput = new CodedOutputStream(dataByte);
|
|
dataOne.cacheData.WriteTo(ouput);
|
|
sw.Write(size); //写入长度
|
|
sw.Write(dataByte); //写入数据
|
|
sw.Flush();
|
|
++haveSave;
|
|
}
|
|
}
|
|
}
|
|
sw.Dispose();
|
|
fileStream.Dispose();
|
|
chatCache.m_needSave = false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TraceLog.Error("ChatCacheOp.SaveCacheToFile write file failed! {0}", saveFile);
|
|
TraceLog.Exception(ex);
|
|
return;
|
|
}
|
|
TraceLog.Trace("ChatCacheOp.SaveCacheToFile save file {0} num {1} success time {2}", saveFile, haveSave, AppTime.GetNowSysMs());
|
|
}
|
|
|
|
public static bool LoadCacheFromFile()
|
|
{
|
|
string saveFile = GetSaveFilePath();
|
|
TraceLog.Trace("ChatCacheOp.LoadCacheFromFile load file {0} begin time {1}", saveFile, AppTime.GetNowSysMs());
|
|
var chatServerData = ChatServerUtils.GetChatServerData();
|
|
ref var chatCache = ref chatServerData.m_chatCacheInfo;
|
|
if (File.Exists(saveFile) == false)
|
|
{
|
|
TraceLog.Trace("ChatCacheOp.LoadCacheFromFile file not exist {0}", saveFile);
|
|
return true;
|
|
}
|
|
long nowSec = ChatServerUtils.GetTimeSecond();
|
|
long needSaveTime = nowSec - SaveMaxDay * 24 * 3600;
|
|
try
|
|
{
|
|
FileStream fileStream = File.OpenRead(saveFile);
|
|
BinaryReader sw = new BinaryReader(fileStream);
|
|
long lenth = fileStream.Length;
|
|
long pos = 0;
|
|
while (pos < lenth)
|
|
{
|
|
int size = sw.ReadInt32(); //读长度
|
|
byte[] data = sw.ReadBytes(size); //读数据
|
|
pos += (sizeof(Int32) + size);
|
|
if (pos <= lenth)
|
|
{
|
|
CodedInputStream input = new CodedInputStream(data);
|
|
CSChatRes chatRes = new CSChatRes();
|
|
chatRes.ReadFrom(input);
|
|
//XX天以前的消息就不存了
|
|
if (chatRes.SendTime > needSaveTime)
|
|
{
|
|
AddChatCache(ref chatRes);
|
|
chatServerData.SetChannalChatSeq(chatRes.ChatSeq, chatRes.ChatChannelType, chatRes.ChannelParam);
|
|
}
|
|
}
|
|
}
|
|
sw.Dispose();
|
|
fileStream.Dispose();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TraceLog.Error("ChatCacheOp.LoadCacheFromFile parse message failed! {0}", saveFile);
|
|
TraceLog.Exception(ex);
|
|
return false;
|
|
}
|
|
TraceLog.Trace("ChatCacheOp.LoadCacheFromFile load file {0} success time {1}", saveFile, AppTime.GetNowSysMs());
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|