//////////////////////////////////////////////////////////////////////////////////////////////////// /// /// @file CompositionOrDecompositionHandler.cpp /// @author hukim /// @email silped@gmail.com /// @brief [2010/11/29 by hukim] This is created.\n /// //////////////////////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "./Handler_FromGameServer.Composition.h" // #include #include #include //////////////////////////////////////////////////////////////////////////////////////////////////// // REGION : Constructor & Destructor //////////////////////////////////////////////////////////////////////////////////////////////////// CompositionOrDecompositionHandler::CompositionOrDecompositionHandler() { } CompositionOrDecompositionHandler::~CompositionOrDecompositionHandler() { } //////////////////////////////////////////////////////////////////////////////////////////////////// // REGION : Implement //////////////////////////////////////////////////////////////////////////////////////////////////// namespace util { namespace internal { // ºÒ¸°°ªÀ» ¼ýÀÚ·Î º¯È¯ÇÑ´Ù. static int BooleanToNumber(const bool boolean) { return (boolean ? 1 : 0); } // ¹®ÀÚ¸¦ ¼ýÀÚ·Î º¯È¯ÇÑ´Ù. template static bool StringToNumber(const std::string& str, NUMBER_T& OUT number) { try { number = boost::lexical_cast(str); } catch (boost::bad_lexical_cast&) { return false; } return true; } // ÇÕ¼º ¶Ç´Â ºÐÇØ ³»¿ª¿¡ »ç¿ëµÈ ¾ÆÀÌÅÛ ¸ñ·ÏÀ» ¹®ÀÚ¿­·Î ÀÎÄÚµùÇÑ´Ù. static bool EncodeUsedItemList( const ItemCompositionOrDecompositionHistory& history, std::string& OUT used_item_list_string) { enum { kMaxUsedItemListString = 255 }; enum { kMaxUsedItemListSize = _countof(history.used_item_list) }; if (history.used_item_list_size > ItemCompositionOrDecompositionHistory::kMaxUsedItemSize || history.used_item_list_size > kMaxUsedItemListSize) { return false; } std::ostringstream oss; for (ItemCompositionOrDecompositionHistory::UsedItemListSize i = 0; i < history.used_item_list_size; ++i) { const ItemCompositionOrDecompositionHistory::UsedItem& used_item = history.used_item_list[i]; oss << BooleanToNumber(used_item.is_material); // Àç·á¿©ºÎ oss << ","; oss << used_item.item_code; // ¾ÆÀÌÅÛÄÚµå oss << ","; oss << static_cast(used_item.number_of_item); // ¾ÆÀÌÅÛ°³¼ö oss << ","; oss << static_cast(used_item.ig_type); // ¾ÆÀÌÅÛÁ¾·ù if (i != (history.used_item_list_size-1)) { oss << ";"; } } used_item_list_string = oss.str(); if (used_item_list_string.size() > kMaxUsedItemListString) { return false; } return true; } // »ç¿ëµÈ ¾ÆÀÌÅÛ ¸ñ·Ï ¹®ÀÚ¿­·ÎºÎÅÍ ÇÕ¼º ¶Ç´Â ºÐÇØ ³»¿ªÀÇ »ç¿ëµÈ ¾ÆÀÌÅÛ ¸ñ·ÏÀ» µðÄÚµùÇÑ´Ù. static bool DecodeUsedItemList( const char* used_item_list_string, ItemCompositionOrDecompositionHistory& OUT history) { typedef boost::char_separator Seperator; typedef boost::tokenizer Tokenizer; const Seperator used_item_sep(";"); const Seperator used_item_member_sep(","); std::string temp_used_item_list_string(used_item_list_string); const Tokenizer used_item_token(temp_used_item_list_string, used_item_sep); for (Tokenizer::const_iterator used_item_pos = used_item_token.begin(); used_item_pos != used_item_token.end(); ++used_item_pos) { // »ç¿ëµÈ ¾ÆÀÌÅÛÀ» ¼³Á¤ÇÑ´Ù. ItemCompositionOrDecompositionHistory::UsedItem used_item; { enum UsedItemMemberIndex { kIsMaterial = 0, kItemCode, kNumberOfItem, kIGType, kMaxMemberSize }; const std::string& used_item_string = *used_item_pos; const Tokenizer used_item_member_token(used_item_string, used_item_member_sep); Tokenizer::const_iterator used_item_member_pos = used_item_member_token.begin(); for (int used_item_member_index = 0; used_item_member_index < kMaxMemberSize; ++used_item_member_index) { if (used_item_member_pos == used_item_member_token.end()) { return false; } const std::string& used_item_member = *used_item_member_pos; switch (used_item_member_index) { case kIsMaterial: { int converted_member = 0; if (!StringToNumber(used_item_member, converted_member)) { return false; } used_item.is_material = (converted_member == 1); } break; case kItemCode: if (!StringToNumber(used_item_member, used_item.item_code)) { return false; } break; case kNumberOfItem: { int converted_member = 0; if (!StringToNumber(used_item_member, converted_member)) { return false; } used_item.number_of_item = static_cast(converted_member); } break; case kIGType: { int converted_member = 0; if (!StringToNumber(used_item_member, converted_member)) { return false; } typedef ItemCompositionOrDecompositionHistory::UsedItem::IGType IGType; used_item.ig_type = static_cast(converted_member); } break; default: assert(false); return false; } ++used_item_member_pos; } } if (!history.AddUsedItem(used_item)) { return false; } } return true; } // ³»¿ªÀ» ¼öÁ¤ÇÒ Á¶°Ç ¸ñ·ÏÀ» ÀÎÄÚµùÇÑ´Ù. static bool EncodeUpdateConditionList( const MSG_DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD& update_histories_cmd, std::string& OUT condition_list_string) { enum { kMaxConditionListStringSize = 255 }; enum { kMaxUpdateConditionListSize = sizeof(update_histories_cmd.modify_condition_list) / sizeof(update_histories_cmd.modify_condition_list[0]) }; typedef MSG_DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD UpdateHistoriesCmd; if (update_histories_cmd.condition_list_size > UpdateHistoriesCmd::kMaxConditionListSize || update_histories_cmd.condition_list_size > kMaxUpdateConditionListSize) { return false; } std::ostringstream oss; for (UpdateHistoriesCmd::ConditionListSize i = 0; i < update_histories_cmd.condition_list_size; ++i) { const ItemCompositionOrDecompositionHistory::ModifyCondition& modify_condition = update_histories_cmd.modify_condition_list[i]; oss << modify_condition.history_id; // ³»¿ª¾ÆÀ̵ð oss << ","; oss << BooleanToNumber(modify_condition.is_memorize); // ±â¾ï¿©ºÎ if (i != (update_histories_cmd.condition_list_size-1)) { oss << ";"; } } condition_list_string = oss.str(); if (condition_list_string.size() > kMaxConditionListStringSize) { return false; } return true; } // Äõ¸® ¿äûÀÌ ÆøÁÖÇØ¼­ Äõ¸® ½ÇÇàÁß¿¡´Â ´Ù¸¥ Äõ¸®¸¦ ¹ÞÁö ¾Ê´Â ¿ëµµ·Î »ç¿ëÇÑ´Ù. class InterTransactionManager { typedef DWORD UserKey; typedef int UserAction; struct Transaction // Æ®·£Àè¼Ç { enum { kMaxTransactionWaitTime = 1 * 1000 * 60 }; // Æ®·£Àè¼Ç ´ë±â½Ã°£ Transaction() : is_running(false) { wait_timer.Clear(); } bool Begin() { if (!is_running) { is_running = true; wait_timer.SetTimer(kMaxTransactionWaitTime); return true; } if (wait_timer.IsExpired(false)) // ½ÇÇàÁßÀÎ °æ¿ì ´ë±â ½Ã°£ÀÌ Áö³µ´ÂÁö °Ë»çÇÑ´Ù. { wait_timer.SetTimer(kMaxTransactionWaitTime); return true; } return false; } bool is_running; util::Timer wait_timer; }; typedef unsigned __int64 TransactionKey; typedef boost::shared_ptr TransactionPtr; typedef STLX_HASH_MAP TransactionMap; private: InterTransactionManager() {} public: static InterTransactionManager& GetInstance() { static InterTransactionManager instance; return instance; } bool BeginTransaction(const UserKey user_key, const UserAction user_action) { const TransactionKey transaction_key = MakeTransactionKey(user_key, user_action); TransactionMap::iterator pos = transaction_map_.find(transaction_key); if (pos != transaction_map_.end()) { return (pos->second)->Begin(); } TransactionPtr new_transaction(new Transaction); transaction_map_[transaction_key] = new_transaction; return new_transaction->Begin(); } void EndTransaction(const UserKey user_key, const UserAction user_action) { const TransactionKey transaction_key = MakeTransactionKey(user_key, user_action); transaction_map_.erase(transaction_key); } private: TransactionKey MakeTransactionKey(const UserKey user_key, const UserAction user_action) const { BOOST_STATIC_ASSERT(sizeof(UserKey) <= (sizeof(TransactionKey) / 2)); BOOST_STATIC_ASSERT(sizeof(UserAction) <= (sizeof(TransactionKey) / 2)); TransactionKey user_action_part = (((TransactionKey)user_action) & 0xffffffff) << 16; user_action_part = user_action_part << 16; return (((TransactionKey)user_key) & 0xffffffff) | user_action_part; } TransactionMap transaction_map_; __DISABLE_COPY(InterTransactionManager); }; } // util } // internal //////////////////////////////////////////////////////////////////////////////////////////////////// // REGION : Public //////////////////////////////////////////////////////////////////////////////////////////////////// void CompositionOrDecompositionHandler::HandleInsertHistory( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { const MSG_DG_OTHER_INSERT_COMPOSITION_OR_DECOMPOSITION_HISTORY_CMD* const insert_history_cmd = static_cast(message); #ifdef _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK // Áß±¹¿¡¼­´Â »ç¿ëÇÏÁö ¾Ê´Â´Ù. return; #endif // ÆÐŶ Å©±â¸¦ °Ë»çÇÑ´Ù. if (insert_history_cmd->GetSize() != message_size) { assert(false); return; } // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. const DWORD user_key = message->m_dwKey; DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } } const ItemCompositionOrDecompositionHistory& history = insert_history_cmd->new_composition_or_decomposition_history; // »ç¿ëµÈ ¾ÆÀÌÅÛ ¸ñ·ÏÀ» ÀÎÄÚµùÇÑ´Ù. std::string used_item_list_string; if (!util::internal::EncodeUsedItemList(history, used_item_list_string)) { SUNLOG(eCRITICAL_LOG, _T("|%s|ʹÓõÄÎïÆ·Áбí±àÂëʧ°Ü.|UserKey = %u|"), __FUNCTION__, user_key); return; } const char* used_item_list_c_str = used_item_list_string.c_str(); // Æ®·£Àè¼ÇÀ» ½ÃÀÛÇÑ´Ù. if (!util::internal::InterTransactionManager::GetInstance().BeginTransaction( user_key, DG_OTHER_INSERT_COMPOSITION_OR_DECOMPOSITION_HISTORY_CMD)) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÊÂÎñ¿ªÊ¼Ê§°Ü.|UserKey = %u|"), __FUNCTION__, user_key); return; } // Äõ¸® ¹®ÀÚ¿­À» ¸¸µç´Ù. STRING_SAFER_QUERY512 query_string; query_string.MakeString( _T("{?=call S_CompositionOrDecompositionHistory_Insert(%u,%u,%u,%I64d,'%s')}"), requester->GetUserGuid(), // 1. »ç¿ëÀÚ static_cast(history.request_type), // 2. ¿äûÁ¾·ù util::internal::BooleanToNumber(history.is_composition), // 3. ÇÕ¼º¿©ºÎ static_cast<__int64>(history.history_date_time), // 4. ³»¿ªÀÏÀÚ used_item_list_c_str); // 5. »ç¿ëµÈ¾ÆÀÌÅÛ¸ñ·Ï // Äõ¸®¸¦ ½ÇÇàÇÑ´Ù. CompositionOrDecompositionHistoryInsertQuery* const query = CompositionOrDecompositionHistoryInsertQuery::ALLOC(); { query->SetUserKey(message->m_dwKey); query->SetQuery(query_string); query->SetVoidObject(server_session); } requester->DBQuery(DG_OTHER, DG_OTHER_INSERT_COMPOSITION_OR_DECOMPOSITION_HISTORY_DBR, query); } void CompositionOrDecompositionHandler::HandleInsertHistoryDBR( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { __UNUSED(server_session); __UNUSED(message_size); // Äõ¸®¸¦ ¾ò´Â´Ù. const MSG_DBPROXY_RESULT* const db_result = static_cast(message); CompositionOrDecompositionHistoryInsertQuery* query = static_cast(db_result->m_pData); // Æ®·£Àè¼ÇÀ» Á¾·áÇÑ´Ù. const DWORD user_key = query->GetUserKey(); util::internal::InterTransactionManager::GetInstance().EndTransaction( user_key, DG_OTHER_INSERT_COMPOSITION_OR_DECOMPOSITION_HISTORY_CMD); // Äõ¸® ÇØÁ¦ º¸Àå ºí·°À» ½ÃÀÛÇÑ´Ù. bool dummy_loop = false; do { // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. const DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); break; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); break; } } // Äõ¸®°¡ ¼º°øÇß´ÂÁö °Ë»çÇÑ´Ù. if (!query->IsSuccess()) { SUNLOG(eCRITICAL_LOG, _T("|%s|²éѯʧ°Ü.|UserKey = %u|"), __FUNCTION__, user_key); break; } } while (dummy_loop); CompositionOrDecompositionHistoryInsertQuery::FREE(query); } void CompositionOrDecompositionHandler::HandleSelectHistories( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { const MSG_DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN* const select_histories_syn = static_cast(message); #ifdef _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK return; #endif // _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK // ÆÐŶ Å©±â¸¦ °Ë»çÇÑ´Ù. if (select_histories_syn->GetSize() != message_size) { assert(false); return; } // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. const DWORD user_key = message->m_dwKey; DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } } // Æ®·£Àè¼ÇÀ» ½ÃÀÛÇÑ´Ù. if (!util::internal::InterTransactionManager::GetInstance().BeginTransaction( user_key, DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN)) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÊÂÎñ¿ªÊ¼Ê§°Ü.|UserKey = %u|"), __FUNCTION__, user_key); return; } // Äõ¸® ¹®ÀÚ¿­À» ¸¸µç´Ù. STRING_SAFER_QUERY128 query_string; query_string.MakeString( _T("{?=call S_CompositionOrDecompositionHistory_Select(%u,%u,%u)}"), requester->GetUserGuid(), // 1. »ç¿ëÀÚ static_cast(select_histories_syn->request_type), // 2. ¿äûÁ¾·ù util::internal::BooleanToNumber(select_histories_syn->is_composition)); // 3. ÇÕ¼º¿©ºÎ // Äõ¸®¸¦ ½ÇÇàÇÑ´Ù. CompositionOrDecompositionHistorySelectQuery* const query = CompositionOrDecompositionHistorySelectQuery::ALLOC(); { query->SetUserKey(message->m_dwKey); query->SetQuery(query_string); query->SetVoidObject(server_session); } requester->DBQuery(DG_OTHER, DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_DBR, query); } void CompositionOrDecompositionHandler::HandleSelectHistoriesDBR( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { __UNUSED(server_session); __UNUSED(message_size); // Äõ¸®¸¦ ¾ò´Â´Ù. const MSG_DBPROXY_RESULT* const db_result = static_cast(message); CompositionOrDecompositionHistorySelectQuery* query = static_cast(db_result->m_pData); // Æ®·£Àè¼ÇÀ» Á¾·áÇÑ´Ù. const DWORD user_key = query->GetUserKey(); util::internal::InterTransactionManager::GetInstance().EndTransaction( user_key, DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_SYN); // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); CompositionOrDecompositionHistorySelectQuery::FREE(query); return; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); CompositionOrDecompositionHistorySelectQuery::FREE(query); return; } } // ÀÀ´äÀ» »ý¼ºÇؼ­ º¸³½´Ù. MSG_DG_OTHER_SELECT_COMPOSITION_OR_DECOMPOSITION_HISTORIES_ACK response; response.Init(); bool dummy_loop = false; do { // Äõ¸®°¡ ¼º°øÇß´ÂÁö °Ë»çÇÑ´Ù. if (!query->IsSuccess()) { response.result_code = RC::RC_ITEM_FAILED_TO_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES; SUNLOG(eCRITICAL_LOG, _T("|%s|²éѯʧ°Ü.|UserKey = %u|"), __FUNCTION__, user_key); break; } // °á°úÇà¼ö¸¦ °Ë»çÇÑ´Ù. ULONG number_of_result_row = query->GetResultRowNum(); { enum { kMaxHistoryListSize = sizeof(response.history_list) / sizeof(response.history_list[0]) }; if (number_of_result_row > kMaxHistoryListSize) { number_of_result_row = kMaxHistoryListSize; } } // ³»¿ªÀ» ¼³Á¤ÇÑ´Ù. for (ULONG result_row_index = 0; result_row_index < number_of_result_row; ++result_row_index) { ItemCompositionOrDecompositionHistory& response_history = response.history_list[response.history_list_size]; { const CompositionOrDecompositionHistorySelectQuery::ResultSet& result_row = query->result_set[result_row_index]; response_history.history_id = result_row.history_id; response_history.request_type = result_row.request_type; response_history.is_memorized = (result_row.is_memorized == 1); response_history.is_composition = (result_row.is_composition == 1); response_history.history_date_time = result_row.history_date_time; if (!util::internal::DecodeUsedItemList( result_row.used_item_list_string, response_history)) { // »ç¿ë ¾ÆÀÌÅÛ µðÄÚµù¿¡ ½ÇÆÐÇßÀ» °æ¿ì Àüü ½ÇÆÐ°¡ ¾Æ´Ï¶ó ´ÙÀ½ ³»¿ªÀ» °è¼Ó ó¸®ÇÑ´Ù. SUNLOG(eCRITICAL_LOG, _T("|%s|ʹÓõÄÎïÆ·Áбí½âÂëʧ°Ü.|UserKey = %u, HistoryID = %u|"), __FUNCTION__, user_key, result_row.history_id); continue; } } ++response.history_list_size; } response.result_code = RC::RC_ITEM_SUCCESS_TO_GET_COMPOSITION_OR_DECOMPOSITION_HISTORIES; } while (dummy_loop); // NOTE: f110429.8L, report about data layouts, low data density. requester->SendPacketToGameServer(&response, response.GetSize()); CompositionOrDecompositionHistorySelectQuery::FREE(query); } void CompositionOrDecompositionHandler::HandleUpdateHistories( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { const MSG_DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD* const update_histories_cmd = static_cast(message); #ifdef _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK return; #endif // _CN_000000_20130729_COMPOSE_OR_DECOMPOSE_HISTORY_BLOCK // ÆÐŶ Å©±â¸¦ °Ë»çÇÑ´Ù. if (update_histories_cmd->GetSize() != message_size) { assert(false); return; } // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. const DWORD user_key = message->m_dwKey; DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); return; } } // ¼öÁ¤ Á¶°Ç ¸ñ·ÏÀ» ÀÎÄÚµùÇÑ´Ù. std::string condition_list_string; if (!util::internal::EncodeUpdateConditionList(*update_histories_cmd, condition_list_string)) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÐÞ¸ÄÌõ¼þÁбí±àÂëʧ°Ü.|UserKey = %u|"), __FUNCTION__, user_key); return; } const char* condition_list_c_str = condition_list_string.c_str(); // Æ®·£Àè¼ÇÀ» ½ÃÀÛÇÑ´Ù. if (!util::internal::InterTransactionManager::GetInstance().BeginTransaction( user_key, DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD)) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÊÂÎñ¿ªÊ¼Ê§°Ü.|UserKey = %u|"), __FUNCTION__, user_key); return; } // Äõ¸® ¹®ÀÚ¿­À» ¸¸µç´Ù. STRING_SAFER_QUERY512 query_string; query_string.MakeString( _T("{?=call S_CompositionOrDecompositionHistory_Update('%s')}"), condition_list_c_str); // 1. ¼öÁ¤ Á¶°Ç ¸ñ·Ï // Äõ¸®¸¦ ½ÇÇàÇÑ´Ù. CompositionOrDecompositionHistoryUpdateQuery* const query = CompositionOrDecompositionHistoryUpdateQuery::ALLOC(); { query->SetUserKey(message->m_dwKey); query->SetQuery(query_string); query->SetVoidObject(server_session); } requester->DBQuery(DG_OTHER, DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_DBR, query); } void CompositionOrDecompositionHandler::HandleUpdateHistoriesDBR( ChildServerSession* const server_session, const MSG_BASE* const message, const MessageSize message_size) const { __UNUSED(server_session); __UNUSED(message_size); // Äõ¸®¸¦ ¾ò´Â´Ù. const MSG_DBPROXY_RESULT* const db_result = static_cast(message); CompositionOrDecompositionHistoryUpdateQuery* query = static_cast(db_result->m_pData); // Æ®·£Àè¼ÇÀ» Á¾·áÇÑ´Ù. const DWORD user_key = query->GetUserKey(); util::internal::InterTransactionManager::GetInstance().EndTransaction( user_key, DG_OTHER_UPDATE_COMPOSITION_OR_DECOMPOSITION_HISTORIES_CMD); // Äõ¸® ÇØÁ¦ º¸Àå ºí·°À» ½ÃÀÛÇÑ´Ù. bool dummy_loop = false; do { // ¿äûÀÚ¸¦ °Ë»çÇÑ´Ù. const DBUser* const requester = g_DBUserManager.FindUser(user_key); { if (!requester) { SUNLOG(eCRITICAL_LOG, _T("|%s|ÇëÇó²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); break; } if (!requester->GetConnectedChar()) { SUNLOG(eCRITICAL_LOG, _T("|%s|µÇ¼ÖеĽÇÉ«²»´æÔÚ.|UserKey = %u|"), __FUNCTION__, user_key); break; } } // Äõ¸®°¡ ¼º°øÇß´ÂÁö °Ë»çÇÑ´Ù. if (!query->IsSuccess()) { SUNLOG(eCRITICAL_LOG, _T("|%s|²éѯʧ°Ü.|UserKey = %u|"), __FUNCTION__, user_key); break; } } while (dummy_loop); CompositionOrDecompositionHistoryUpdateQuery::FREE(query); }