#include "stdafx.h" #include "HighLoadBalancer.h" // #include // #include "GameZone.h" // @history: waverix, refactoring, changed by _NA001605_EP2_CHANGE_SKILL_BROADCASTER_ namespace nsGrid { ; struct HLB_SequentialNode : public util::__LList { typedef HLB_BufferInfo::NetMsgSizeType NetMsgSizeType; NetMsgSizeType msg_size; // Next // User defined message .... (with msg_size) }; struct HLB_Buffer { HLB_Buffer(const DWORD input_hlb_key) : HLBKEY(hlb_key) , hlb_key(input_hlb_key) { region_header->size = 0; util::LList::Init(&sequential_root); } // Integrity check (&HLBKEY == &m_HLBKey) // const DWORD& HLBKEY; DWORD hlb_key; HLB_SequentialNode sequential_root; #pragma pack(push, 1) WAR_MSG_HDR region_header[1]; uint8_t region_stream[HighLoadBalancer::kMaxRegionStreamSize]; // #pragma pack(pop) }; //================================================================================================== // Sync Message Format (v0200) // // ----------------------------------------------------------------------------- // | MSG_BASE | WAR_MSG_HDR | MSGSUB_SYNC_MESSAGEs // | HLBKEY | m_HLBKey | ulong(size) | byte stream[xxxx] ... // ----------------------------------------------------------------------------- // MSGSUB_SYNC_MESSAGEs // ----------------------------------------------------------------------------- // | __LListNode | Size | TypeCode | // | prev | next | uint16_t | BYTE | // ----------------------------------------------------------------------------- // |-> MSGSUB_(SYNC, SKILL, ...) }; // end of namespace //================================================================================================== // Sequential Message Format (v0100) // // ----------------------------------------------------------------------------- // | WAR_MSG_HDR | NORMAL_MESSAGEs or SEQUENTIAL_STREAM // | ulong(size) | byte stream[xxxx] ... // ----------------------------------------------------------------------------- // NORMAL_MESSAGEs // ----------------------------------------------------------------------------- // | Size | header | body | // | uint16_t | MSG_BASE | .... | // ----------------------------------------------------------------------------- // SEQUENTIAL_STREAM buffer format // ----------------------------------------------------------------------------- // | sequential_root | ... | LinkedListNode | NetMsgSizeType | UserMessage | // ----------------------------------------------------------------------------- //================================================================================================== // EP2 removed // Post Action Synchronization Message Stream Format (v0.1.0.0) // SectorIdx | Size | MSGSUB_xxx | SectorIdx | Size | MSGSUB_xxx | ... // 0~ | > 0 | TAG_ | BODY_ | 0~ | > 0 | TAG_ | BODY_ | ... #ifdef BUF_ALIGN_PTR #error "this macro should be used as local declaration only" #endif #define BUF_ALIGN_PTR(__size) (((__size) + ((sizeof(void*)) - 1)) & (~((sizeof(void*)) - 1))) void HLB_BufferInfo::AppendTimeSyncMsg(MSG_BASE* const msg, const WORD msg_size) { HLB_SequentialNode* root = sequential_root_; WAR_MSG_HDR::MSG_SIZE_T header_offset = region_header_->size; ; header_offset = BUF_ALIGN_PTR(header_offset); //const uint16_t size = GetSize(); WAR_MSG_HDR::MSG_SIZE_T next_offset = header_offset + sizeof(*root) + msg_size; // if (next_offset >= HighLoadBalancer::kMaxRegionStreamSize) { HighLoadBalancer::Instance()->Update(game_field_, true); // recalculate header_offset = region_header_->size; header_offset = BUF_ALIGN_PTR(header_offset); next_offset = header_offset + sizeof(*root) + msg_size; }; // HLB_SequentialNode* const dest = reinterpret_cast( reinterpret_cast(region_header_ + 1) + header_offset); ;{ util::LList::Init(dest); dest->msg_size = msg_size; }; ;{ CopyMemory((dest + 1), msg, msg_size); }; ;{ region_header_->size = next_offset; // util::LList::AddPrev(dest, root); }; } void HLB_BufferInfo::AppendTimeSyncMsgArray(const DWORD number_of_messages, BYTE** const IN message_array, WORD* const message_size_array) { WAR_MSG_HDR::MSG_SIZE_T total_size = 0; if (DWORD loop = number_of_messages) { NetMsgSizeType* size_it = message_size_array; while (loop--) { total_size += *size_it++; } }; BOOST_STATIC_ASSERT(static_cast(-1) > static_cast(0) && static_cast(-1) == USHRT_MAX); if (total_size == 0 || total_size > USHRT_MAX) { return; } //----------------------------------------------- HLB_SequentialNode* root = sequential_root_; WAR_MSG_HDR::MSG_SIZE_T header_offset = region_header_->size; ; header_offset = BUF_ALIGN_PTR(header_offset); //const uint16_t size = GetSize(); WAR_MSG_HDR::MSG_SIZE_T next_offset = header_offset + sizeof(*root) + total_size; // if (next_offset >= HighLoadBalancer::kMaxRegionStreamSize) { HighLoadBalancer::Instance()->Update(game_field_, true); // recalculate header_offset = region_header_->size; header_offset = BUF_ALIGN_PTR(header_offset); next_offset = header_offset + sizeof(*root) + total_size; }; // HLB_SequentialNode* const dest = reinterpret_cast( reinterpret_cast(region_header_ + 1) + header_offset); ;{ util::LList::Init(dest); dest->msg_size = static_cast(total_size); }; if (DWORD loop = number_of_messages) { uint8_t* msg_it = reinterpret_cast(dest + 1); NetMsgSizeType* input_size_it = message_size_array; uint8_t** input_msg_it = message_array; while (loop--) { CopyMemory(msg_it, *input_msg_it++, *input_size_it); msg_it += *input_size_it++; } }; ;{ region_header_->size = next_offset; // util::LList::AddPrev(dest, root); }; } //================================================================================================== // HighLoadBalancer // HighLoadBalancer* HighLoadBalancer::instance_static_ = 0; void HighLoadBalancer::CreateInstance() { if (instance_static_ == NULL) { instance_static_ = new HighLoadBalancer; }; } void HighLoadBalancer::DestroyInstance() { SAFE_DELETE(instance_static_); } //-------------------------------------------------------------------------------------------------- HighLoadBalancer::~HighLoadBalancer() { FOREACH_CONTAINER(MSG_STREAM_BUFFER_POOLLIST::value_type& pool_node, msg_buffer_pool_, MSG_STREAM_BUFFER_POOLLIST) { nsGrid::HLB_Buffer* hlb_buffer = pool_node; TAllocFree(hlb_buffer); } FOREACH_CONTAINER(MSG_STREAM_BUFFER_INDEXER::value_type& index_node, msg_buffer_indexer_, MSG_STREAM_BUFFER_INDEXER) { nsGrid::HLB_Buffer* hlb_buffer = index_node.second; if (hlb_buffer) { TAllocFree(hlb_buffer); } } } //-------------------------------------------------------------------------------------------------- void HighLoadBalancer::RegisterBuffer(GameField* const game_field) { const ulong hash_key = util::StreamHashKey::GetMemoryHashKey(&game_field, sizeof(game_field)); HLB_Buffer*& hlb_buffer = msg_buffer_indexer_[hash_key]; // reference if (hlb_buffer != NULL) { return; }; const bool is_pool_empty = msg_buffer_pool_.empty(); hlb_buffer = is_pool_empty ? (HLB_Buffer*)TAllocMalloc(sizeof(*hlb_buffer)) : msg_buffer_pool_.front(); new (hlb_buffer) HLB_Buffer(hash_key); HLB_BufferInfo*& field_hlb_buffer = game_field->m_pHLB; // reference if (field_hlb_buffer == NULL) { field_hlb_buffer = TAllocNew(HLB_BufferInfo); } ;{ field_hlb_buffer->game_field_ = game_field; field_hlb_buffer->region_header_ = hlb_buffer->region_header; field_hlb_buffer->sequential_root_ = &hlb_buffer->sequential_root; }; if (is_pool_empty == false) { msg_buffer_pool_.pop_front(); } } //-------------------------------------------------------------------------------------------------- void HighLoadBalancer::UnRegisterBuffer(GameField* const game_field) { const ulong hash_key = util::StreamHashKey::GetMemoryHashKey(&game_field, sizeof(game_field)); MSG_STREAM_BUFFER_INDEXER::iterator it = msg_buffer_indexer_.find(hash_key); if (it == msg_buffer_indexer_.end()) { // game_field->m_pSyncStreamRootÀº ¿©±â¼­¸¸ Á¦¾îÇÏ´Â °ÍÀ» ÀüÁ¦ÇÑ´Ù. µû¶ó¼­ ±×³É 0¼³Á¤ game_field->m_pHLB = NULL; return; } // found HLB_BufferInfo*& field_hlb_buffer = game_field->m_pHLB; if (field_hlb_buffer) { TAllocDelete(HLB_BufferInfo, field_hlb_buffer); } field_hlb_buffer = 0; // ³²°ÜÁø Á¤º¸ º¸³¾±îµµ »ý°¢ÇØ ºÃÁö¸¸, Çʵ尡 Á¾·áµÇ´Â ½ÃÁ¡ÀÌ´Ù... // À¯Àú°¡ ÀÖÀ» ¸® ¾øÀݾÆ? ¾Æ´Ï ¾ø¾î¾ß ÇÑ´Ù. // (ºÎ¿¬) - ´õ ÀÌ»ó ÀÇ¹Ì ¾ø´Â Á¤º¸ÀÏ °¡´É¼ºÀÌ ³ô´Ù. ;{ HLB_Buffer* const hlb_buffer = it->second; msg_buffer_indexer_.erase(it); msg_buffer_pool_.push_back(hlb_buffer); }; } //-------------------------------------------------------------------------------------------------- void HighLoadBalancer::RecyclingBuffer(GameField* const pGameField) { HLB_BufferInfo* const hlb_buffer = pGameField->m_pHLB; if (hlb_buffer) { hlb_buffer->region_header_->size = 0; util::LList::Init(hlb_buffer->sequential_root_); } } void HighLoadBalancer::Update(GameField* const game_field, const BOOLEAN need_flush) { __UNUSED(need_flush); HLB_BufferInfo* const hlb_buffer = game_field->m_pHLB; if (hlb_buffer == NULL) { return; } WAR_MSG_HDR* const region_header = hlb_buffer->region_header_; //const BOOLEAN need_flush_internal // = need_flush ? true // : (kMaxRegionStreamAlarmSize < region_header->size); //if (need_flush_internal == false) { // return; //} // // #1: send time sync buffer HLB_SequentialNode* const sequential_root = hlb_buffer->sequential_root_; HLB_SequentialNode* seq_it = static_cast(sequential_root->next); for ( ; seq_it != sequential_root; seq_it = static_cast(seq_it->next)) { g_pGameServer->SendToServer(AGENT_SERVER, reinterpret_cast(seq_it + 1), seq_it->msg_size); }; // #2: notify region events game_field->SectorGridRef.Update(game_field); // ;{ // clear region_header->size = 0; util::LList::Init(sequential_root); }; return; } //================================================================================================== //================================================================================================== //==================================================================================================