1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "config.h"
  4. #include "event.h"
  5. #include "minilzo.h"
  6. #include "packet.h"
  7. #include "desc_manager.h"
  8. #include "item_manager.h"
  9. #include "char.h"
  10. #include "char_manager.h"
  11. #include "mob_manager.h"
  12. #include "motion.h"
  13. #include "sectree_manager.h"
  14. #include "shop_manager.h"
  15. #include "regen.h"
  16. #include "text_file_loader.h"
  17. #include "skill.h"
  18. #include "pvp.h"
  19. #include "party.h"
  20. #include "questmanager.h"
  21. #include "profiler.h"
  22. #include "lzo_manager.h"
  23. #include "messenger_manager.h"
  24. #include "db.h"
  25. #include "log.h"
  26. #include "p2p.h"
  27. #include "guild_manager.h"
  28. #include "dungeon.h"
  29. #include "cmd.h"
  30. #include "refine.h"
  31. #include "banword.h"
  32. #include "priv_manager.h"
  33. #include "war_map.h"
  34. #include "building.h"
  35. #include "login_sim.h"
  36. #include "target.h"
  37. #include "marriage.h"
  38. #include "wedding.h"
  39. #include "fishing.h"
  40. #include "item_addon.h"
  41. #include "TrafficProfiler.h"
  42. #include "locale_service.h"
  43. #include "arena.h"
  44. #include "OXEvent.h"
  45. #include "monarch.h"
  46. #include "polymorph.h"
  47. #include "blend_item.h"
  48. #include "castle.h"
  49. #include "ani.h"
  50. #include "BattleArena.h"
  51. #include "over9refine.h"
  52. #include "horsename_manager.h"
  53. #include "pcbang.h"
  54. #include "MarkManager.h"
  55. #include "spam.h"
  56. #include "panama.h"
  57. #include "threeway_war.h"
  58. #include "DragonLair.h"
  59. #include "skill_power.h"
  60. #include "SpeedServer.h"
  61. #include "DragonSoul.h"
  62. #include <boost/bind.hpp>
  63. //#define __FILEMONITOR__
  64. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  65. #include "FileMonitor_FreeBSD.h"
  66. #endif
  67. #ifndef __WIN32__
  68. #include <gtest/gtest.h>
  69. #endif
  70. #ifdef USE_STACKTRACE
  71. #include <execinfo.h>
  72. #endif
  73. extern void WriteVersion();
  74. //extern const char * _malloc_options;
  75. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  76. extern void (*_malloc_message)(const char* p1, const char* p2, const char* p3, const char* p4);
  77. // FreeBSD _malloc_message replacement
  78. void WriteMallocMessage(const char* p1, const char* p2, const char* p3, const char* p4) {
  79. FILE* fp = ::fopen(DBGALLOC_LOG_FILENAME, "a");
  80. if (fp == NULL) {
  81. return;
  82. }
  83. ::fprintf(fp, "%s %s %s %s\n", p1, p2, p3, p4);
  84. ::fclose(fp);
  85. }
  86. #endif
  87. // TRAFFIC_PROFILER
  88. static const DWORD TRAFFIC_PROFILE_FLUSH_CYCLE = 3600; ///< TrafficProfiler ÀÇ Flush cycle. 1½Ã°£ °£°İ
  89. // END_OF_TRAFFIC_PROFILER
  90. // °ÔÀÓ°ú ¿¬°áµÇ´Â ¼ÒÄÏ
  91. volatile int num_events_called = 0;
  92. int max_bytes_written = 0;
  93. int current_bytes_written = 0;
  94. int total_bytes_written = 0;
  95. BYTE g_bLogLevel = 0;
  96. socket_t tcp_socket = 0;
  97. socket_t udp_socket = 0;
  98. socket_t p2p_socket = 0;
  99. LPFDWATCH main_fdw = NULL;
  100. int io_loop(LPFDWATCH fdw);
  101. int start(int argc, char **argv);
  102. int idle();
  103. void destroy();
  104. void test();
  105. enum EProfile
  106. {
  107. PROF_EVENT,
  108. PROF_CHR_UPDATE,
  109. PROF_IO,
  110. PROF_HEARTBEAT,
  111. PROF_MAX_NUM
  112. };
  113. static DWORD s_dwProfiler[PROF_MAX_NUM];
  114. int g_shutdown_disconnect_pulse;
  115. int g_shutdown_disconnect_force_pulse;
  116. int g_shutdown_core_pulse;
  117. bool g_bShutdown=false;
  118. extern int speed_server;
  119. extern void CancelReloadSpamEvent();
  120. void ContinueOnFatalError()
  121. {
  122. #ifdef USE_STACKTRACE
  123. void* array[200];
  124. std::size_t size;
  125. char** symbols;
  126. size = backtrace(array, 200);
  127. symbols = backtrace_symbols(array, size);
  128. std::ostringstream oss;
  129. oss << std::endl;
  130. for (std::size_t i = 0; i < size; ++i) {
  131. oss << " Stack> " << symbols[i] << std::endl;
  132. }
  133. free(symbols);
  134. sys_err("FatalError on %s", oss.str().c_str());
  135. #else
  136. sys_err("FatalError");
  137. #endif
  138. }
  139. void ShutdownOnFatalError()
  140. {
  141. if (!g_bShutdown)
  142. {
  143. sys_err("ShutdownOnFatalError!!!!!!!!!!");
  144. {
  145. char buf[256];
  146. strlcpy(buf, LC_TEXT("¼­¹ö¿¡ Ä¡¸íÀûÀÎ ¿À·ù°¡ ¹ß»ıÇÏ¿© ÀÚµ¿À¸·Î ÀçºÎÆÃµË´Ï´Ù."), sizeof(buf));
  147. SendNotice(buf);
  148. strlcpy(buf, LC_TEXT("10ÃÊÈÄ ÀÚµ¿À¸·Î Á¢¼ÓÀÌ Á¾·áµÇ¸ç,"), sizeof(buf));
  149. SendNotice(buf);
  150. strlcpy(buf, LC_TEXT("5ºĞ ÈÄ¿¡ Á¤»óÀûÀ¸·Î Á¢¼ÓÇϽǼö ÀÖ½À´Ï´Ù."), sizeof(buf));
  151. SendNotice(buf);
  152. }
  153. g_bShutdown = true;
  154. g_bNoMoreClient = true;
  155. g_shutdown_disconnect_pulse = thecore_pulse() + PASSES_PER_SEC(10);
  156. g_shutdown_disconnect_force_pulse = thecore_pulse() + PASSES_PER_SEC(20);
  157. g_shutdown_core_pulse = thecore_pulse() + PASSES_PER_SEC(30);
  158. }
  159. }
  160. namespace
  161. {
  162. struct SendDisconnectFunc
  163. {
  164. void operator () (LPDESC d)
  165. {
  166. if (d->GetCharacter())
  167. {
  168. if (d->GetCharacter()->GetGMLevel() == GM_PLAYER)
  169. d->GetCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "quit Shutdown(SendDisconnectFunc)");
  170. }
  171. }
  172. };
  173. struct DisconnectFunc
  174. {
  175. void operator () (LPDESC d)
  176. {
  177. if (d->GetType() == DESC_TYPE_CONNECTOR)
  178. return;
  179. if (d->IsPhase(PHASE_P2P))
  180. return;
  181. d->SetPhase(PHASE_CLOSE);
  182. }
  183. };
  184. }
  185. extern std::map<DWORD, CLoginSim *> g_sim; // first: AID
  186. extern std::map<DWORD, CLoginSim *> g_simByPID;
  187. extern std::vector<TPlayerTable> g_vec_save;
  188. unsigned int save_idx = 0;
  189. void heartbeat(LPHEART ht, int pulse)
  190. {
  191. DWORD t;
  192. t = get_dword_time();
  193. num_events_called += event_process(pulse);
  194. s_dwProfiler[PROF_EVENT] += (get_dword_time() - t);
  195. t = get_dword_time();
  196. // 1Ãʸ¶´Ù
  197. if (!(pulse % ht->passes_per_sec))
  198. {
  199. if (!g_bAuthServer)
  200. {
  201. TPlayerCountPacket pack;
  202. pack.dwCount = DESC_MANAGER::instance().GetLocalUserCount();
  203. db_clientdesc->DBPacket(HEADER_GD_PLAYER_COUNT, 0, &pack, sizeof(TPlayerCountPacket));
  204. }
  205. else
  206. {
  207. DESC_MANAGER::instance().ProcessExpiredLoginKey();
  208. }
  209. {
  210. int count = 0;
  211. itertype(g_sim) it = g_sim.begin();
  212. while (it != g_sim.end())
  213. {
  214. if (!it->second->IsCheck())
  215. {
  216. it->second->SendLogin();
  217. if (++count > 50)
  218. {
  219. sys_log(0, "FLUSH_SENT");
  220. break;
  221. }
  222. }
  223. it++;
  224. }
  225. if (save_idx < g_vec_save.size())
  226. {
  227. count = MIN(100, g_vec_save.size() - save_idx);
  228. for (int i = 0; i < count; ++i, ++save_idx)
  229. db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, 0, &g_vec_save[save_idx], sizeof(TPlayerTable));
  230. sys_log(0, "SAVE_FLUSH %d", count);
  231. }
  232. }
  233. }
  234. //
  235. // 25 PPS(Pulse per second) ¶ó°í °¡Á¤ÇÒ ¶§
  236. //
  237. // ¾à 1.16Ãʸ¶´Ù
  238. if (!(pulse % (passes_per_sec + 4)))
  239. CHARACTER_MANAGER::instance().ProcessDelayedSave();
  240. //4ÃÊ ¸¶´Ù
  241. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  242. if (!(pulse % (passes_per_sec * 5)))
  243. {
  244. FileMonitorFreeBSD::Instance().Update(pulse);
  245. }
  246. #endif
  247. // ¾à 5.08Ãʸ¶´Ù
  248. if (!(pulse % (passes_per_sec * 5 + 2)))
  249. {
  250. ITEM_MANAGER::instance().Update();
  251. DESC_MANAGER::instance().UpdateLocalUserCount();
  252. }
  253. s_dwProfiler[PROF_HEARTBEAT] += (get_dword_time() - t);
  254. DBManager::instance().Process();
  255. AccountDB::instance().Process();
  256. CPVPManager::instance().Process();
  257. if (g_bShutdown)
  258. {
  259. if (thecore_pulse() > g_shutdown_disconnect_pulse)
  260. {
  261. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  262. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::SendDisconnectFunc());
  263. g_shutdown_disconnect_pulse = INT_MAX;
  264. }
  265. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse)
  266. {
  267. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  268. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::DisconnectFunc());
  269. }
  270. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse + PASSES_PER_SEC(5))
  271. {
  272. thecore_shutdown();
  273. }
  274. }
  275. }
  276. static void CleanUpForEarlyExit() {
  277. CancelReloadSpamEvent();
  278. }
  279. int main(int argc, char **argv)
  280. {
  281. #ifdef DEBUG_ALLOC
  282. DebugAllocator::StaticSetUp();
  283. #endif
  284. #ifndef __WIN32__
  285. // <Factor> start unit tests if option is set
  286. if ( argc > 1 )
  287. {
  288. if ( strcmp( argv[1], "unittest" ) == 0 )
  289. {
  290. ::testing::InitGoogleTest(&argc, argv);
  291. return RUN_ALL_TESTS();
  292. }
  293. }
  294. #endif
  295. ilInit(); // DevIL Initialize
  296. WriteVersion();
  297. SECTREE_MANAGER sectree_manager;
  298. CHARACTER_MANAGER char_manager;
  299. ITEM_MANAGER item_manager;
  300. CShopManager shop_manager;
  301. CMobManager mob_manager;
  302. CMotionManager motion_manager;
  303. CPartyManager party_manager;
  304. CSkillManager skill_manager;
  305. CPVPManager pvp_manager;
  306. LZOManager lzo_manager;
  307. DBManager db_manager;
  308. AccountDB account_db;
  309. LogManager log_manager;
  310. MessengerManager messenger_manager;
  311. P2P_MANAGER p2p_manager;
  312. CGuildManager guild_manager;
  313. CGuildMarkManager mark_manager;
  314. CDungeonManager dungeon_manager;
  315. CRefineManager refine_manager;
  316. CBanwordManager banword_manager;
  317. CPrivManager priv_manager;
  318. CWarMapManager war_map_manager;
  319. building::CManager building_manager;
  320. CTargetManager target_manager;
  321. marriage::CManager marriage_manager;
  322. marriage::WeddingManager wedding_manager;
  323. CItemAddonManager item_addon_manager;
  324. CArenaManager arena_manager;
  325. COXEventManager OXEvent_manager;
  326. CMonarch Monarch;
  327. CHorseNameManager horsename_manager;
  328. CPCBangManager pcbang_manager;
  329. DESC_MANAGER desc_manager;
  330. TrafficProfiler trafficProfiler;
  331. CTableBySkill SkillPowerByLevel;
  332. CPolymorphUtils polymorph_utils;
  333. CProfiler profiler;
  334. CBattleArena ba;
  335. COver9RefineManager o9r;
  336. SpamManager spam_mgr;
  337. CThreeWayWar threeway_war;
  338. CDragonLairManager dl_manager;
  339. CSpeedServerManager SSManager;
  340. DSManager dsManager;
  341. if (!start(argc, argv)) {
  342. CleanUpForEarlyExit();
  343. return 0;
  344. }
  345. quest::CQuestManager quest_manager;
  346. if (!quest_manager.Initialize()) {
  347. CleanUpForEarlyExit();
  348. return 0;
  349. }
  350. MessengerManager::instance().Initialize();
  351. CGuildManager::instance().Initialize();
  352. fishing::Initialize();
  353. OXEvent_manager.Initialize();
  354. if (speed_server)
  355. CSpeedServerManager::instance().Initialize();
  356. Cube_init();
  357. Blend_Item_init();
  358. ani_init();
  359. PanamaLoad();
  360. if ( g_bTrafficProfileOn )
  361. TrafficProfiler::instance().Initialize( TRAFFIC_PROFILE_FLUSH_CYCLE, "ProfileLog" );
  362. // Client PackageCrypt
  363. //TODO : make it config
  364. const std::string strPackageCryptInfoDir = "package/";
  365. if( !desc_manager.LoadClientPackageCryptInfo( strPackageCryptInfoDir.c_str() ) )
  366. {
  367. sys_err("Failed to Load ClientPackageCryptInfo File(%s)", strPackageCryptInfoDir.c_str());
  368. }
  369. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  370. PFN_FileChangeListener pPackageNotifyFunc = &(DESC_MANAGER::NotifyClientPackageFileChanged);
  371. //FileMonitorFreeBSD::Instance().AddWatch( strPackageCryptInfoName, pPackageNotifyFunc );
  372. #endif
  373. while (idle());
  374. sys_log(0, "<shutdown> Starting...");
  375. g_bShutdown = true;
  376. g_bNoMoreClient = true;
  377. if (g_bAuthServer)
  378. {
  379. int iLimit = DBManager::instance().CountQuery() / 50;
  380. int i = 0;
  381. do
  382. {
  383. DWORD dwCount = DBManager::instance().CountQuery();
  384. sys_log(0, "Queries %u", dwCount);
  385. if (dwCount == 0)
  386. break;
  387. usleep(500000);
  388. if (++i >= iLimit)
  389. if (dwCount == DBManager::instance().CountQuery())
  390. break;
  391. } while (1);
  392. }
  393. sys_log(0, "<shutdown> Destroying CArenaManager...");
  394. arena_manager.Destroy();
  395. sys_log(0, "<shutdown> Destroying COXEventManager...");
  396. OXEvent_manager.Destroy();
  397. sys_log(0, "<shutdown> Disabling signal timer...");
  398. signal_timer_disable();
  399. sys_log(0, "<shutdown> Shutting down CHARACTER_MANAGER...");
  400. char_manager.GracefulShutdown();
  401. sys_log(0, "<shutdown> Shutting down ITEM_MANAGER...");
  402. item_manager.GracefulShutdown();
  403. sys_log(0, "<shutdown> Flushing db_clientdesc...");
  404. db_clientdesc->FlushOutput();
  405. sys_log(0, "<shutdown> Flushing p2p_manager...");
  406. p2p_manager.FlushOutput();
  407. sys_log(0, "<shutdown> Destroying CShopManager...");
  408. shop_manager.Destroy();
  409. sys_log(0, "<shutdown> Destroying CHARACTER_MANAGER...");
  410. char_manager.Destroy();
  411. sys_log(0, "<shutdown> Destroying ITEM_MANAGER...");
  412. item_manager.Destroy();
  413. sys_log(0, "<shutdown> Destroying DESC_MANAGER...");
  414. desc_manager.Destroy();
  415. sys_log(0, "<shutdown> Destroying quest::CQuestManager...");
  416. quest_manager.Destroy();
  417. sys_log(0, "<shutdown> Destroying building::CManager...");
  418. building_manager.Destroy();
  419. sys_log(0, "<shutdown> Flushing TrafficProfiler...");
  420. trafficProfiler.Flush();
  421. destroy();
  422. #ifdef DEBUG_ALLOC
  423. DebugAllocator::StaticTearDown();
  424. #endif
  425. return 1;
  426. }
  427. void usage()
  428. {
  429. printf("Option list\n"
  430. "-p <port> : bind port number (port must be over 1024)\n"
  431. "-l <level> : sets log level\n"
  432. "-v : log to stdout\n"
  433. "-r : do not load regen tables\n"
  434. "-t : traffic proflie on\n");
  435. }
  436. int start(int argc, char **argv)
  437. {
  438. std::string st_localeServiceName;
  439. bool bVerbose = false;
  440. char ch;
  441. //_malloc_options = "A";
  442. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  443. _malloc_message = WriteMallocMessage;
  444. #endif
  445. while ((ch = getopt(argc, argv, "npverltI")) != -1)
  446. {
  447. char* ep = NULL;
  448. switch (ch)
  449. {
  450. case 'I': // IP
  451. strlcpy(g_szPublicIP, argv[optind], sizeof(g_szPublicIP));
  452. printf("IP %s\n", g_szPublicIP);
  453. optind++;
  454. optreset = 1;
  455. break;
  456. case 'p': // port
  457. mother_port = strtol(argv[optind], &ep, 10);
  458. if (mother_port <= 1024)
  459. {
  460. usage();
  461. return 0;
  462. }
  463. printf("port %d\n", mother_port);
  464. optind++;
  465. optreset = 1;
  466. break;
  467. case 'l':
  468. {
  469. long l = strtol(argv[optind], &ep, 10);
  470. log_set_level(l);
  471. optind++;
  472. optreset = 1;
  473. }
  474. break;
  475. // LOCALE_SERVICE
  476. case 'n':
  477. {
  478. if (optind < argc)
  479. {
  480. st_localeServiceName = argv[optind++];
  481. optreset = 1;
  482. }
  483. }
  484. break;
  485. // END_OF_LOCALE_SERVICE
  486. case 'v': // verbose
  487. bVerbose = true;
  488. break;
  489. case 'r':
  490. g_bNoRegen = true;
  491. break;
  492. // TRAFFIC_PROFILER
  493. case 't':
  494. g_bTrafficProfileOn = true;
  495. break;
  496. // END_OF_TRAFFIC_PROFILER
  497. }
  498. }
  499. // LOCALE_SERVICE
  500. config_init(st_localeServiceName);
  501. // END_OF_LOCALE_SERVICE
  502. #ifdef __WIN32__
  503. // In Windows dev mode, "verbose" option is [on] by default.
  504. bVerbose = true;
  505. #endif
  506. if (!bVerbose)
  507. freopen("stdout", "a", stdout);
  508. bool is_thecore_initialized = thecore_init(25, heartbeat);
  509. if (!is_thecore_initialized)
  510. {
  511. fprintf(stderr, "Could not initialize thecore, check owner of pid, syslog\n");
  512. exit(0);
  513. }
  514. if (false == CThreeWayWar::instance().LoadSetting("forkedmapindex.txt"))
  515. {
  516. if (false == g_bAuthServer)
  517. {
  518. fprintf(stderr, "Could not Load ThreeWayWar Setting file");
  519. exit(0);
  520. }
  521. }
  522. signal_timer_disable();
  523. main_fdw = fdwatch_new(4096);
  524. if ((tcp_socket = socket_tcp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  525. {
  526. perror("socket_tcp_bind: tcp_socket");
  527. return 0;
  528. }
  529. #ifndef __UDP_BLOCK__
  530. if ((udp_socket = socket_udp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  531. {
  532. perror("socket_udp_bind: udp_socket");
  533. return 0;
  534. }
  535. #endif
  536. // if internal ip exists, p2p socket uses internal ip, if not use public ip
  537. //if ((p2p_socket = socket_tcp_bind(*g_szInternalIP ? g_szInternalIP : g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  538. if ((p2p_socket = socket_tcp_bind(g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  539. {
  540. perror("socket_tcp_bind: p2p_socket");
  541. return 0;
  542. }
  543. fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false);
  544. #ifndef __UDP_BLOCK__
  545. fdwatch_add_fd(main_fdw, udp_socket, NULL, FDW_READ, false);
  546. #endif
  547. fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false);
  548. db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true);
  549. if (!g_bAuthServer) {
  550. db_clientdesc->UpdateChannelStatus(0, true);
  551. }
  552. if (g_bAuthServer)
  553. {
  554. if (g_stAuthMasterIP.length() != 0)
  555. {
  556. fprintf(stderr, "SlaveAuth");
  557. g_pkAuthMasterDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, g_stAuthMasterIP.c_str(), g_wAuthMasterPort, PHASE_P2P, true);
  558. P2P_MANAGER::instance().RegisterConnector(g_pkAuthMasterDesc);
  559. g_pkAuthMasterDesc->SetP2P(g_stAuthMasterIP.c_str(), g_wAuthMasterPort, g_bChannel);
  560. }
  561. else
  562. {
  563. fprintf(stderr, "MasterAuth %d", LC_GetLocalType());
  564. }
  565. }
  566. else
  567. {
  568. extern unsigned int g_uiSpamBlockDuration;
  569. extern unsigned int g_uiSpamBlockScore;
  570. extern unsigned int g_uiSpamReloadCycle;
  571. sys_log(0, "SPAM_CONFIG: duration %u score %u reload cycle %u\n",
  572. g_uiSpamBlockDuration, g_uiSpamBlockScore, g_uiSpamReloadCycle);
  573. extern void LoadSpamDB();
  574. LoadSpamDB();
  575. }
  576. signal_timer_enable(30);
  577. return 1;
  578. }
  579. void destroy()
  580. {
  581. sys_log(0, "<shutdown> Canceling ReloadSpamEvent...");
  582. CancelReloadSpamEvent();
  583. sys_log(0, "<shutdown> regen_free()...");
  584. regen_free();
  585. sys_log(0, "<shutdown> Closing sockets...");
  586. socket_close(tcp_socket);
  587. #ifndef __UDP_BLOCK__
  588. socket_close(udp_socket);
  589. #endif
  590. socket_close(p2p_socket);
  591. sys_log(0, "<shutdown> fdwatch_delete()...");
  592. fdwatch_delete(main_fdw);
  593. sys_log(0, "<shutdown> event_destroy()...");
  594. event_destroy();
  595. sys_log(0, "<shutdown> CTextFileLoader::DestroySystem()...");
  596. CTextFileLoader::DestroySystem();
  597. sys_log(0, "<shutdown> thecore_destroy()...");
  598. thecore_destroy();
  599. }
  600. int idle()
  601. {
  602. static struct timeval pta = { 0, 0 };
  603. static int process_time_count = 0;
  604. struct timeval now;
  605. if (pta.tv_sec == 0)
  606. gettimeofday(&pta, (struct timezone *) 0);
  607. int passed_pulses;
  608. if (!(passed_pulses = thecore_idle()))
  609. return 0;
  610. assert(passed_pulses > 0);
  611. DWORD t;
  612. while (passed_pulses--) {
  613. heartbeat(thecore_heart, ++thecore_heart->pulse);
  614. // To reduce the possibility of abort() in checkpointing
  615. thecore_tick();
  616. }
  617. t = get_dword_time();
  618. CHARACTER_MANAGER::instance().Update(thecore_heart->pulse);
  619. db_clientdesc->Update(t);
  620. s_dwProfiler[PROF_CHR_UPDATE] += (get_dword_time() - t);
  621. t = get_dword_time();
  622. if (!io_loop(main_fdw)) return 0;
  623. s_dwProfiler[PROF_IO] += (get_dword_time() - t);
  624. log_rotate();
  625. gettimeofday(&now, (struct timezone *) 0);
  626. ++process_time_count;
  627. if (now.tv_sec - pta.tv_sec > 0)
  628. {
  629. pt_log("[%3d] event %5d/%-5d idle %-4ld event %-4ld heartbeat %-4ld I/O %-4ld chrUpate %-4ld | WRITE: %-7d | PULSE: %d",
  630. process_time_count,
  631. num_events_called,
  632. event_count(),
  633. thecore_profiler[PF_IDLE],
  634. s_dwProfiler[PROF_EVENT],
  635. s_dwProfiler[PROF_HEARTBEAT],
  636. s_dwProfiler[PROF_IO],
  637. s_dwProfiler[PROF_CHR_UPDATE],
  638. current_bytes_written,
  639. thecore_pulse());
  640. num_events_called = 0;
  641. current_bytes_written = 0;
  642. process_time_count = 0;
  643. gettimeofday(&pta, (struct timezone *) 0);
  644. memset(&thecore_profiler[0], 0, sizeof(thecore_profiler));
  645. memset(&s_dwProfiler[0], 0, sizeof(s_dwProfiler));
  646. }
  647. #ifdef __WIN32__
  648. if (_kbhit()) {
  649. int c = _getch();
  650. switch (c) {
  651. case 0x1b: // Esc
  652. return 0; // shutdown
  653. break;
  654. default:
  655. break;
  656. }
  657. }
  658. #endif
  659. return 1;
  660. }
  661. int io_loop(LPFDWATCH fdw)
  662. {
  663. LPDESC d;
  664. int num_events, event_idx;
  665. DESC_MANAGER::instance().DestroyClosed(); // PHASE_CLOSEÀÎ Á¢¼ÓµéÀ» ²÷¾îÁØ´Ù.
  666. DESC_MANAGER::instance().TryConnect();
  667. if ((num_events = fdwatch(fdw, 0)) < 0)
  668. return 0;
  669. for (event_idx = 0; event_idx < num_events; ++event_idx)
  670. {
  671. d = (LPDESC) fdwatch_get_client_data(fdw, event_idx);
  672. if (!d)
  673. {
  674. if (FDW_READ == fdwatch_check_event(fdw, tcp_socket, event_idx))
  675. {
  676. DESC_MANAGER::instance().AcceptDesc(fdw, tcp_socket);
  677. fdwatch_clear_event(fdw, tcp_socket, event_idx);
  678. }
  679. else if (FDW_READ == fdwatch_check_event(fdw, p2p_socket, event_idx))
  680. {
  681. DESC_MANAGER::instance().AcceptP2PDesc(fdw, p2p_socket);
  682. fdwatch_clear_event(fdw, p2p_socket, event_idx);
  683. }
  684. /*
  685. else if (FDW_READ == fdwatch_check_event(fdw, udp_socket, event_idx))
  686. {
  687. char buf[256];
  688. struct sockaddr_in cliaddr;
  689. socklen_t socklen = sizeof(cliaddr);
  690. int iBytesRead;
  691. if ((iBytesRead = socket_udp_read(udp_socket, buf, 256, (struct sockaddr *) &cliaddr, &socklen)) > 0)
  692. {
  693. static CInputUDP s_inputUDP;
  694. s_inputUDP.SetSockAddr(cliaddr);
  695. int iBytesProceed;
  696. s_inputUDP.Process(NULL, buf, iBytesRead, iBytesProceed);
  697. }
  698. fdwatch_clear_event(fdw, udp_socket, event_idx);
  699. }
  700. */
  701. continue;
  702. }
  703. int iRet = fdwatch_check_event(fdw, d->GetSocket(), event_idx);
  704. switch (iRet)
  705. {
  706. case FDW_READ:
  707. if (db_clientdesc == d)
  708. {
  709. int size = d->ProcessInput();
  710. if (size)
  711. sys_log(1, "DB_BYTES_READ: %d", size);
  712. if (size < 0)
  713. {
  714. d->SetPhase(PHASE_CLOSE);
  715. }
  716. }
  717. else if (d->ProcessInput() < 0)
  718. {
  719. d->SetPhase(PHASE_CLOSE);
  720. }
  721. break;
  722. case FDW_WRITE:
  723. if (db_clientdesc == d)
  724. {
  725. int buf_size = buffer_size(d->GetOutputBuffer());
  726. int sock_buf_size = fdwatch_get_buffer_size(fdw, d->GetSocket());
  727. int ret = d->ProcessOutput();
  728. if (ret < 0)
  729. {
  730. d->SetPhase(PHASE_CLOSE);
  731. }
  732. if (buf_size)
  733. sys_log(1, "DB_BYTES_WRITE: size %d sock_buf %d ret %d", buf_size, sock_buf_size, ret);
  734. }
  735. else if (d->ProcessOutput() < 0)
  736. {
  737. d->SetPhase(PHASE_CLOSE);
  738. }
  739. break;
  740. case FDW_EOF:
  741. {
  742. d->SetPhase(PHASE_CLOSE);
  743. }
  744. break;
  745. default:
  746. sys_err("fdwatch_check_event returned unknown %d", iRet);
  747. d->SetPhase(PHASE_CLOSE);
  748. break;
  749. }
  750. }
  751. return 1;
  752. }

MAIN.CPP