IDBRoleServer.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:11k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "IDBRoleServer.h"
  3. #include "DBTable.h"
  4. #include "DBBackup.h"
  5. #include "../../../../Headers/KGmProtocol.h"
  6. #include "CRC32.h"
  7. #include <iostream>
  8. #include <strstream>
  9. using namespace std;
  10. #include "Macro.h"
  11. static ZDBTable *db_table = NULL;
  12. static size_t nMaxRoleCount_InAccount = 3;
  13. static CDBBackup::TStatData GameStatData;//游戏统计数据(服务器初始化时填入)
  14. static CDBBackup* DBBackup = NULL;
  15. static HANDLE hDeadLockThread = NULL; //检查数据库有没有死锁的线程
  16. static HANDLE hRemoveLogThread = NULL; //删除没用日志文件的线程
  17. HWND hListOutput = NULL; //输出list
  18. int get_account(DB *db, const DBT *pkey, const DBT *pdata, DBT *ikey) 
  19. {
  20. //给定一个完整的buffer,得到account作为索引
  21. memset( ikey, 0, sizeof( DBT ) );
  22. TRoleData *pRoleData = (TRoleData *)pdata->data;
  23. ikey->data = pRoleData->BaseInfo.caccname;
  24. ikey->size = strlen( pRoleData->BaseInfo.caccname ) + 1;
  25. return 0;
  26. }
  27. //==========检查数据库有没有死锁的线程 Add By Fellow 2003.9.10==============
  28. DWORD WINAPI DeadlockProc(LPVOID lpParameter) {
  29. while(!db_table->bStop) {
  30. Sleep(5 * 1000); //5秒钟一次
  31. db_table->deadlock();
  32. }
  33. return 0;
  34. }
  35. //==========删除没用日志文件的线程 Add By Fellow 2003.9.10==============
  36. DWORD WINAPI RemoveLogProc(LPVOID lpParameter) {
  37. while(!db_table->bStop) {
  38. db_table->removeLog();
  39. Sleep(60 * 60 * 1000); //1小时一次
  40. }
  41. return 0;
  42. }
  43. BOOL InitDBInterface( size_t nMaxRoleCount )
  44. {
  45. nMaxRoleCount_InAccount = nMaxRoleCount;
  46. db_table = new ZDBTable( "database", "roledb" );
  47. db_table->addIndex( get_account );
  48. if ( db_table->open() )
  49. {
  50. DWORD dwThreadId, dwThrdParam = 1;
  51. /*
  52. hDeadLockThread = CreateThread(
  53. NULL, // no security attributes 
  54. 0, // use default stack size  
  55. DeadlockProc, // thread function 
  56. &dwThrdParam, // argument to thread function 
  57. 0, // use default creation flags 
  58. &dwThreadId); // returns the thread identifier 
  59. if(!hDeadLockThread)
  60. {
  61. //创建线程失败,暂时没有处理
  62. }
  63. */
  64. hRemoveLogThread = CreateThread(
  65. NULL, // no security attributes 
  66. 0, // use default stack size  
  67. RemoveLogProc, // thread function 
  68. &dwThrdParam, // argument to thread function 
  69. 0, // use default creation flags 
  70. &dwThreadId); // returns the thread identifier 
  71. if(!hRemoveLogThread)
  72. {
  73. //创建线程失败,暂时没有处理
  74. }
  75. return TRUE;
  76. }
  77. return FALSE;
  78. }
  79. void ReleaseDBInterface() //释放数据库引擎
  80. {
  81. if ( db_table )
  82. {
  83. db_table->commit();
  84. /*
  85. if(!hDeadLockThread)
  86. TerminateThread(hDeadLockThread, 0);
  87. */
  88. if(!hRemoveLogThread)
  89. TerminateThread(hRemoveLogThread, 0);
  90. db_table->removeLog();
  91. StopBackupTimer();//停止备份线程
  92. db_table->close();
  93. delete db_table;
  94. }
  95. }
  96. //[wxb 2003-7-23]
  97. void SetRoleInfoForGM(int nInfoID, char* pRoleBuffer, char* strUser, int nBufLen)
  98. {
  99. char* aBuffer = new char[64 * 1024];
  100. TRoleData* pRoleData = NULL;
  101. int size;
  102. GetRoleInfo(aBuffer, strUser, size);
  103. if(size)
  104. {
  105. pRoleData = (TRoleData*)aBuffer;
  106. switch (nInfoID)
  107. {
  108. case gm_role_entergame_position:
  109. ASSERT(nBufLen == sizeof(GM_ROLE_DATA_SUB_ENTER_POS));
  110. memcpy(&(pRoleData->BaseInfo.ientergameid), pRoleBuffer, sizeof(GM_ROLE_DATA_SUB_ENTER_POS));
  111. break;
  112. default:
  113. ASSERT(0);
  114. return;
  115. break;
  116. }
  117. SaveRoleInfo(aBuffer, strUser, false);
  118. }
  119.     delete aBuffer;
  120. }
  121. //[wxb 2003-7-22]
  122. void *GetRoleInfoForGM(int nInfoID, char * pRoleBuffer, char * strUser, int &nBufLen)
  123. {
  124. int size = 0;
  125. ZCursor *cursor = db_table->search( strUser, strlen( strUser ) + 1 );
  126. // char *buffer = db_table->search( strUser, strlen( strUser ) + 1, size );
  127. if ( cursor )
  128. {
  129. TRoleData* pRole = (TRoleData*)cursor->data;
  130. switch(nInfoID) {
  131. case gm_role_entergame_position:
  132. nBufLen = sizeof(pRole->BaseInfo.ientergameid) + sizeof(pRole->BaseInfo.ientergamex) + sizeof(pRole->BaseInfo.ientergamey);
  133. memcpy( pRoleBuffer, &(pRole->BaseInfo.ientergameid), nBufLen );
  134. break;
  135. default:
  136. ASSERT(0);
  137. nBufLen = 0;
  138. break;
  139. }
  140. db_table->closeCursor(cursor);
  141. }
  142. else
  143. {
  144. nBufLen = 0;
  145. }
  146. return pRoleBuffer;
  147. }
  148. void *GetRoleInfo( char * pRoleBuffer, char * strUser, int &nBufLen )
  149. {
  150. //输出数据======
  151. char aStr[1024];
  152. sprintf(aStr,"GetRoleInfo:%s",strUser);
  153. AddOutputString(hListOutput,aStr);
  154. //===============
  155. int size = 0;
  156. ZCursor *cursor = db_table->search( strUser, strlen( strUser ) + 1 );
  157. // char *buffer = db_table->search( strUser, strlen( strUser ) + 1, size );
  158. if ( cursor )
  159. {
  160. nBufLen = size;
  161. memcpy( pRoleBuffer, cursor->data, cursor->size );
  162. nBufLen = cursor->size;
  163. db_table->closeCursor(cursor);
  164. }
  165. else
  166. {
  167. nBufLen = 0;
  168. }
  169. return pRoleBuffer;
  170. }
  171. //保存角色的信息,如果数据库不存在该玩家,则增加该玩家
  172. //bAutoInsertWhenNoExistUser 设为TRUE时表示,如果需要保存的该玩家在数据库中并不存在则自动加入到数据库中,FALSE则不增加直接返回错误
  173. //注意INI文件只须存放将需要改动的数据,不需改动的数据将自动保存原状。
  174. int SaveRoleInfo( char * pRoleBuffer, const char *strUser, BOOL bAutoInsertWhenNoExistUser )
  175. {
  176. ASSERT( pRoleBuffer );
  177. //需要存放帐号首先找到数据
  178. TRoleData *pRoleData = ( TRoleData * )pRoleBuffer;
  179. //输出数据======
  180. char aStr[1024];
  181. sprintf(aStr,"SaveRoleInfo:%s dwDataLen=%d",pRoleData->BaseInfo.szName,pRoleData->dwDataLen);
  182. AddOutputString(hListOutput,aStr);
  183. //===============
  184. if(pRoleData->dwDataLen >= 64 * 1024) return 0;//如果数据大于64K就不添加到数据库
  185. if(bAutoInsertWhenNoExistUser)
  186. {//如果是新增角色就把账号名转成小写
  187. char *ptr = pRoleData->BaseInfo.caccname; //把账号名转成小写
  188. while(*ptr) {
  189. if(*ptr >= 'A' && *ptr <= 'Z') *ptr += 'a' - 'A';
  190. ptr++;
  191. }
  192. }
  193. if (!bAutoInsertWhenNoExistUser)
  194. {
  195. DWORD dwCRC = 0;
  196. dwCRC = CRC32(dwCRC, pRoleData, pRoleData->dwDataLen - 4);
  197. DWORD dwOrigCRC = *(DWORD *)(pRoleBuffer + pRoleData->dwDataLen - 4);
  198. if (dwCRC != dwOrigCRC)
  199. {
  200. // TODO:
  201. FILE *fLog = fopen("crc_error", "a+b");
  202. if(fLog) {
  203. char buffer[255];
  204. sprintf(buffer, "----rn%srb%srn", pRoleData->BaseInfo.szName, pRoleData->BaseInfo.caccname);
  205. fwrite(buffer, 1, strlen(buffer), fLog);
  206. fwrite(pRoleBuffer, 1, pRoleData->dwDataLen, fLog);
  207. fclose(fLog);
  208. }
  209. return 0;
  210. }
  211. }
  212. char szAccountName[32];
  213. int nLength = strlen( pRoleData->BaseInfo.caccname );
  214. ASSERT( nLength > 0 );
  215. nLength = nLength > 31 ? 31 : nLength;
  216. memcpy( szAccountName, pRoleData->BaseInfo.caccname, nLength );
  217. szAccountName[nLength] = '';
  218. char szName[32];
  219. const char *pName = szName;
  220. if ( NULL == strUser || strUser[0] == 0 )
  221. {
  222. int len = strlen( pRoleData->BaseInfo.szName );
  223. ASSERT( len > 0 );
  224. len = len > 31 ? 31 : len;
  225. memcpy( szName, pRoleData->BaseInfo.szName, len );
  226. szName[len] = '';
  227. }
  228. else
  229. {
  230. int len = strlen( strUser );
  231. ASSERT( len > 0 );
  232. memcpy( szName, strUser, len );
  233. szName[len] = '';
  234. }
  235. if ( bAutoInsertWhenNoExistUser )
  236. {
  237. int nCount = 0;
  238. int size = 0;
  239. /*
  240.  * Role of same name only
  241.  */
  242. ZCursor *user_cursor = db_table->search(pName, strlen( pName ) + 1 );
  243. // char *user_data = db_table->search( pName, strlen( pName ) + 1, size );
  244. if ( user_cursor )
  245. {
  246. db_table->closeCursor(user_cursor);
  247. return 0;
  248. }
  249. /*
  250.  * Get count of role by the key of account
  251.  */
  252. ZCursor *cursor = db_table->search( szAccountName, strlen( szAccountName ) + 1, 0 );
  253. // char *buffer = db_table->search( szAccountName, strlen( szAccountName ) + 1, size, 0 );
  254. while ( cursor )
  255. {
  256. nCount ++;
  257. if(!db_table->next( cursor ))break;
  258. }
  259. if ( nCount >= nMaxRoleCount_InAccount )
  260. {
  261. return 0;
  262. }
  263. }
  264. if ( db_table->add( pName, strlen( pName ) + 1, pRoleBuffer, pRoleData->dwDataLen ) )
  265. {
  266. return 1;
  267. }
  268. return 0;
  269. }
  270. int GetRoleListOfAccount( char * szAccountName, S3DBI_RoleBaseInfo * RoleBaseList, int nMaxCount )
  271. {
  272. int size = 0;
  273. int count = 0;
  274. char *ptr = szAccountName; //把账号名转成小写
  275. while(*ptr) {
  276. if(*ptr >= 'A' && *ptr <= 'Z') *ptr += 'a' - 'A';
  277. ptr++;
  278. }
  279. //输出数据======
  280. char aStr[1024];
  281. sprintf(aStr,"GetRoleListOfAccount:%s",szAccountName);
  282. AddOutputString(hListOutput,aStr);
  283. //===============
  284. S3DBI_RoleBaseInfo *base_ptr = RoleBaseList;
  285. ZCursor *cursor = db_table->search( szAccountName, strlen( szAccountName ) + 1, 0 );
  286. // char *buffer = db_table->search( szAccountName, strlen( szAccountName ) + 1, size, 0 );
  287. while ( count < nMaxCount && cursor )
  288. {
  289. TRoleData *pRoleData = (TRoleData *)cursor->data;
  290. strncpy( base_ptr->szName, pRoleData->BaseInfo.szName, 32 ); 
  291.         base_ptr->szName[31] = '';
  292. base_ptr->Sex = pRoleData->BaseInfo.bSex;
  293. base_ptr->Series = pRoleData->BaseInfo.ifiveprop;
  294. // base_ptr->HelmType = pRoleData->BaseInfo.ihelmres;
  295. // base_ptr->ArmorType = pRoleData->BaseInfo.iarmorres;
  296. // base_ptr->WeaponType = pRoleData->BaseInfo.iweaponres;
  297. base_ptr->Level = pRoleData->BaseInfo.ifightlevel;
  298. base_ptr++;
  299. /*
  300.  * Get next info from database
  301.  */
  302. count++;
  303. if(!db_table->next( cursor ))break;
  304. }
  305. return count;
  306. }
  307. bool DeleteRole( const char * strUser )
  308. {
  309. if ( db_table && strUser && strUser[0] )
  310. {
  311. return db_table->remove( strUser, strlen( strUser ) + 1 );
  312. }
  313. return false;
  314. }
  315. // 下面的函数可能存在内存泄漏问题
  316. //char* GetAccountByUser(char * strUser)
  317. //{//通过用户名查找帐户
  318. // char* aBuffer = new char[64 * 1024];
  319. // TRoleData* pRoleData;
  320. // int size;
  321. //
  322. // GetRoleInfo(aBuffer, strUser, size);
  323. // if(size)
  324. // {
  325. // pRoleData = (TRoleData*)aBuffer;
  326. // return pRoleData->BaseInfo.caccname;
  327. // }
  328. // else
  329. // {
  330. // return NULL;
  331. // }
  332. //}
  333. //------------------------------------------------------------------------
  334. //数据库备份与数据统计 Add By Fellow At 2003.08.14
  335. bool StartBackupTimer(int aTime)
  336. {//开始运行备份线程
  337. DBBackup = new CDBBackup( "database", "roledb", db_table );
  338. DBBackup->SaveStatInfo();
  339. bool aStartResult = DBBackup->Open(aTime);
  340. return aStartResult;
  341. }
  342. bool StopBackupTimer()
  343. {//结束运行备份线程
  344. if(!DBBackup)return false;
  345. while(IsBackupWorking()){}//等待备份线程结束
  346. bool aResult = DBBackup->Close();
  347. delete DBBackup;
  348. DBBackup = NULL;
  349. return aResult;
  350. }
  351. bool SuspendBackupTimer()
  352. {//挂起线程
  353. if(!DBBackup)return false;
  354. return DBBackup->Suspend();
  355. }
  356. bool ResumeBackupTimer()
  357. {//继续运行线程
  358. if(!DBBackup)return false;
  359. return DBBackup->Resume();
  360. }
  361. bool IsBackupThreadWorking()
  362. {//线程是否正在运行
  363. if(!DBBackup)return false;
  364. return DBBackup->IsWorking();
  365. }
  366. bool IsBackupWorking()
  367. {//是否在备份
  368. if(!DBBackup)return false;
  369. return DBBackup->IsBackuping();
  370. }
  371. bool DoManualBackup()
  372. {//手工备份
  373. if(!DBBackup)return false;
  374. return DBBackup->ManualBackup();
  375. }
  376. bool GetGameStat(TGAME_STAT_DATA* aStatData)
  377. {
  378. if(!DBBackup)return false;
  379. TGAME_STAT_DATA tmpStatData = DBBackup->GetSendStatData();
  380. memcpy(aStatData, &tmpStatData, sizeof(TGAME_STAT_DATA));
  381. return true;
  382. }
  383. void AddOutputString(HWND hListCtrl, char* aStr)
  384. {//添加操作输出文字
  385. if ( hListCtrl && ::IsWindow( hListCtrl ) )
  386. {
  387. int nCount = ::SendMessage( hListCtrl, LB_GETCOUNT, 0, 0 );
  388. if(nCount >= 100)
  389. {
  390. ::SendMessage( hListCtrl, LB_DELETESTRING, 100, 0 );
  391. }
  392. int nIndex = ::SendMessage( hListCtrl, LB_INSERTSTRING, 0, ( LPARAM )aStr );//把新的信息添到第一个
  393. }
  394. }