Files
mir_server/server/DBServer/DBGateManager.cpp

496 lines
12 KiB
C++
Raw Normal View History

2025-01-09 17:45:40 +08:00

#include "StdAfx.h"
CDBGateManager::CDBGateManager(CDBServer *lpDBEngine)
:Inherited()
{
m_dwReconnectSQLTick = 0;
m_pDBServer = lpDBEngine;
m_bLoadZyJobData = false;
m_SQLConnection.SetMultiThread(TRUE);
m_nNextZyJobSaveTime = _getTickCount();
m_bZyDataDirty = false;
m_bJobDataDirty = false;
}
CDBGateManager::~CDBGateManager()
{
}
BOOL CDBGateManager::ConnectSQL()
{
if ( !m_SQLConnection.Connected() )
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pDBServer->SetupSQLConnection(&m_SQLConnection);
if ( m_SQLConnection.Connect() )
{
mysql_options(m_SQLConnection.GetMySql(), MYSQL_SET_CHARSET_NAME, "utf8");
//if (m_SQLConnection.Exec("charset utf8"))
//{
// OutputMsg( rmError, _T("设置utf8字符编码出错"));
//}
//else
//{
// m_SQLConnection.ResetQuery();
//}
OnDBConnected();
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
return TRUE;
}
VOID CDBGateManager::AllocCharIdResult(const int nSessionId, const INT_PTR nResult, const int nCharId)
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_Gates); ++i )
{
if ( m_Gates[i].NameServerAllocCharIdResult(nSessionId, nResult, nCharId) )
{
break;
}
}
}
VOID CDBGateManager::LogicResponseSessionData(const unsigned int nSessionId,unsigned int nActorId)
{
for ( INT_PTR i=0; i< ArrayCount(m_Gates); ++i )
{
m_Gates[i].OnLogicRsponseSessionData(nSessionId,nActorId);
}
}
VOID CDBGateManager::Initialize()
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_Gates); ++i )
{
m_Gates[i].m_pSQLConnection = &m_SQLConnection;
m_Gates[i].m_pDBServer = m_pDBServer;
m_Gates[i].SetGateManager(this);
// 需保证在调用InitDBReqHandler之前 CDBGate对象已经设置好SQlConnection以及GateManager
//m_Gates[i].InitDBReqHandler();
//将网关添加到列表
m_GateList[i] = &m_Gates[i];
}
}
VOID CDBGateManager::Uninitialize()
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_GateList); ++i )
{
//将网关从列表移除
m_GateList[i] = NULL;
}
}
VOID CDBGateManager::Stop()
{
OutputMsg(rmNormal, _T("Save Zy Data..."));
SaveZyData();
OutputMsg(rmNormal, _T("Save Job Data..."));
SaveJobData();
OutputMsg(rmNormal, _T("Stop GateManager..."));
Inherited::Stop();
OutputMsg(rmNormal, _T("Stop GateManager End..."));
}
VOID CDBGateManager::OnResultGateUserExists(int nSessionId, const BOOL boOnline)
{
m_pDBServer->PostQueryUserExistsBySessionIdResult(nSessionId, boOnline);
}
VOID CDBGateManager::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
switch (uMsg)
{
case GTIM_ALLOC_CHARID_RESULT://申请角色ID返回此消息由NSClient发送(Param1=会话ID,Param2=操作结果,Param3=角色ID仅在操作成功时有效)
AllocCharIdResult((int)uParam1, (int)uParam2, (int)uParam3);
break;
case LOGIC_RESPONSE_DB_SESSION_DATA:
LogicResponseSessionData((unsigned int)uParam1, (unsigned int)uParam2);
break;
default:
Inherited::DispatchInternalMessage(uMsg, uParam1, uParam2, uParam3,uParam4);
break;
}
}
VOID CDBGateManager::OnRun()
{
if ( Started() )
{
ConnectSQL();
TICKCOUNT curTime = _getTickCount();
if (m_nNextZyJobSaveTime <= curTime)
{
if (m_bLoadZyJobData && m_SQLConnection.Connected())
{
SaveZyData();
SaveJobData();
}
m_nNextZyJobSaveTime = curTime + 1000 * 300; // 300s 存一次盘
}
}
}
VOID CDBGateManager::OnDBConnected()
{
if (!m_bLoadZyJobData)
{
OutputMsg(rmNormal, _T("DBConnected, Load Zy and Job Data"));
LoadZyInitData();
LoadJobInitData();
m_bLoadZyJobData = true;
}
else
{
OutputMsg(rmNormal, _T("DBReConnected, Save Zy and Job Data"));
SaveZyData();
SaveJobData();
}
}
VOID CDBGateManager::LoadZyInitData()
{
m_zyLock.Lock();
int nError = m_SQLConnection.Query(szSQLSP_LoadZyDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
int nCount = m_SQLConnection.GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nZy, nUserCount, nSrvIdx;
PlayerZYDistribute zyDist;
zyDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nZy);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nZy > zyNone && nZy < zyMax && nUserCount > 0) // 只保存nUserCount大于0的阵营
{
if (nLastSrvIdx != nSrvIdx)
{
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
zyDist.Reset();
zyDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
zyDist.m_anPlayerCount[nZy] = nUserCount;
}
pRow = m_SQLConnection.NextRow();
}
// add last server zy distribute info
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
m_SQLConnection.ResetQuery();
m_bLoadZyJobData = true;
}
m_zyLock.Unlock();
}
VOID CDBGateManager::SaveZyData()
{
m_zyLock.Lock();
if (m_bLoadZyJobData && m_bZyDataDirty)
{
if (m_SQLConnection.Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
// clean first
PlayerZYDistribute& dist = m_vecZyDist[i];
sprintf(szSql, szSQLSP_CleanZyDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddZyDistributeData);
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection.ResetQuery();
nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add zy count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection.ResetQuery();
}
}
}
m_bZyDataDirty = false;
}
}
m_zyLock.Unlock();
}
tagZhenying CDBGateManager::GetPriorityZY(int nSrvIdx)
{
m_zyLock.Lock();
tagZhenying priorZy = zyNone;
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
// find zy in which less user
INT_PTR nCount = 0x7FFFFFFF;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
if (dist.m_anPlayerCount[j] < nCount /*&& dist.m_anPlayerCount[j] >= 0*/)
{
priorZy = (tagZhenying)j;
nCount = dist.m_anPlayerCount[j];
}
}
}
}
if (priorZy == zyNone)
priorZy = zyWuJi;
m_zyLock.Unlock();
return priorZy;
}
VOID CDBGateManager::LoadJobInitData()
{
m_jobLock.Lock();
int nError = m_SQLConnection.Query(szSQLSP_LoadJobDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
int nCount = m_SQLConnection.GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nJob, nUserCount, nSrvIdx;
PlayerJobDistribute jobDist;
jobDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nJob);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nJob > enVocNone && nJob < enMaxVocCount && nUserCount > 0) // 只保存nUserCount大于0的职业
{
if (nLastSrvIdx != nSrvIdx)
{
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
jobDist.Reset();
jobDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
jobDist.m_anPlayerCount[nJob] = nUserCount;
}
pRow = m_SQLConnection.NextRow();
}
// add last server zy distribute info
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
m_SQLConnection.ResetQuery();
m_bLoadZyJobData = true;
}
m_jobLock.Unlock();
}
VOID CDBGateManager::SaveJobData()
{
m_jobLock.Lock();
if (m_bLoadZyJobData && m_bJobDataDirty)
{
if (m_SQLConnection.Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
// clean first
PlayerJobDistribute& dist = m_vecJobDist[i];
sprintf(szSql, szSQLSP_CleanJobDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddJobDistributeData);
for (INT_PTR j = enVocNone+1; j < enMaxVocCount; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection.ResetQuery();
nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add job count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection.ResetQuery();
}
}
}
m_bJobDataDirty = false;
}
}
m_jobLock.Unlock();
}
int CDBGateManager::GetPriorityJob(int nSrvIdx)
{
m_jobLock.Lock();
int priorJob = enVocNone;
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
PlayerJobDistribute& dist = m_vecJobDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
// find jobs in which less user
INT_PTR nCount = 0x7FFFFFFF;
static INT_PTR sValidVoc[] = {1, 2, 3};
static const INT_PTR snValidVocCount = ArrayCount(sValidVoc);
//for (INT_PTR j = enVocNone+1; j < enMaxVocCount; j++)
for (INT_PTR j = 0; j < snValidVocCount; j++)
{
INT_PTR nVoc = sValidVoc[j];
if (dist.m_anPlayerCount[nVoc] < nCount/* && dist.m_anPlayerCount[j] >= 0*/)
{
priorJob = (tagActorVocation)nVoc;
nCount = dist.m_anPlayerCount[nVoc];
}
}
}
}
if (priorJob == enVocNone)
priorJob = 1;
m_jobLock.Unlock();
return (int)priorJob;
}
int CDBGateManager::GetOptionalZy(int nSrvIdx)
{
m_zyLock.Lock();
int nOptMask = 7; // all zy are optional
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
INT_PTR nTotalCount = 0;
for (INT_PTR i = zyNone+1; i < zyMax; i++)
nTotalCount += dist.m_anPlayerCount[i];
if (nTotalCount > 0)
{
float nRate;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
nRate = (dist.m_anPlayerCount[j] / (float)nTotalCount);
if (nRate > 0.35)
{
nOptMask &= ~(1 << (j-1));
}
}
}
}
}
m_zyLock.Unlock();
return nOptMask;
}
void CDBGateManager::OnNewPlayerCreated(int nSrvIdx, tagZhenying zy, tagActorVocation voc)
{
//OutputMsg(rmNormal, _T("create new player, zy=%d, voc=%d"), (int)zy, (int)voc);
if (zy > zyNone && zy < zyMax)
{
m_zyLock.Lock();
INT_PTR i = 0;
for (; i < m_vecZyDist.count(); i++)
{
if (m_vecZyDist[i].m_nServerIdx == nSrvIdx)
{
m_vecZyDist[i].m_anPlayerCount[zy]++;
break;
}
}
// add new node
if (i == m_vecZyDist.count())
{
PlayerZYDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[zy] = 1;
m_vecZyDist.add(dist);
}
m_bZyDataDirty = true;
m_zyLock.Unlock();
}
if (voc > enVocNone && zy < enMaxVocCount)
{
m_jobLock.Lock();
INT_PTR i = 0;
for (; i < m_vecJobDist.count(); i++)
{
if (m_vecJobDist[i].m_nServerIdx == nSrvIdx)
{
m_vecJobDist[i].m_anPlayerCount[voc]++;
break;
}
}
// add new node
if (i == m_vecJobDist.count())
{
PlayerJobDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[voc] = 1;
m_vecJobDist.add(dist);
}
m_bJobDataDirty = true;
m_jobLock.Unlock();
}
}