void MessageFactory::_adjustHeapStartBounds(uint32 size) { // Are we going to overflow our heap? uint32 heapSize = _getHeapSize(); // _getHeapSize() returns the size of already constructed packets, // but NOT the parts we already have been added for THIS message under construction. uint32 messageSize = (mCurrentMessageEnd - mCurrentMessageStart); //assert(mHeapTotalSize > messageSize + heapSize + size); assert(mHeapTotalSize > messageSize + heapSize && "Message heap overflow."); // Check to see if this add is going to push past the heap boundry. if(mCurrentMessageEnd + size > mMessageHeap + mHeapTotalSize) { // We've gone past the end of our heap, copy this message to the front of the heap and continue memcpy(mMessageHeap, mCurrentMessageStart, messageSize); // Reset our main heap pointer(s) if(mHeapStart == mHeapEnd) { mHeapEnd = mMessageHeap; } mHeapStart = mMessageHeap; mHeapRollover = mCurrentMessageStart; // Reinit our message pointers. mCurrentMessage = (Message*)mMessageHeap; mCurrentMessageStart = mMessageHeap; mCurrentMessageEnd = mMessageHeap + messageSize; mCurrentMessage->setData(mMessageHeap + sizeof(Message)); LOG(WARNING)<< "Heap Rollover Service " << mServiceId << "STATS: MessageHeap - size:" << heapSize << " maxUsed: " << mMaxHeapUsedPercent <<", created: " << mMessagesCreated <<", destroyed: " << mMessagesDestroyed; } }
Message* MessageFactory::EndMessage(void) { assert(mCurrentMessage && "Must call StartMessage before EndMessage."); // Do some garbage collection if we can. //_processGarbageCollection(); // Just cast the message start Message* message = mCurrentMessage; message->setData(mCurrentMessageStart + sizeof(Message)); message->setSize((uint16)(mCurrentMessageEnd - mCurrentMessageStart) - sizeof(Message)); message->setCreateTime(gClock->getSingleton()->getStoredTime()); mCurrentMessageStart = mCurrentMessageEnd; // Zero out our mCurrentMessage so we know we're not working on one. mCurrentMessage = 0; //adjust heapstart to past our new message mHeapStart += message->getSize() + sizeof(Message); //Update our stats. mMessagesCreated++; mCurrentUsed = ((float)_getHeapSize() / (float)mHeapTotalSize)* 100.0f; mMaxHeapUsedPercent = std::max<float>(mMaxHeapUsedPercent, mCurrentUsed); // warn if we get near our boundaries if(mCurrentUsed > mHeapWarnLevel) { mHeapWarnLevel = static_cast<float>(mCurrentUsed+1.2); LOG(WARNING) << "MessageFactory Heap at " << mCurrentUsed; } else if (((mCurrentUsed+2.2) < mHeapWarnLevel) && mHeapWarnLevel > 80.0) mHeapWarnLevel = mCurrentUsed; return message; }
void MessageFactory::_processGarbageCollection(void) { uint32 mlt = 3; if(_getHeapSize() > 70.0) mlt = 2; // Just check to see if the oldest message is ready to be deleted yet. //start with the oldest message assert(mHeapEnd < mMessageHeap + mHeapTotalSize && "mHeapEnd not within mMessageHeap bounds"); Message* message = reinterpret_cast<Message*>(mHeapEnd); //when the oldest Message wont get deleted No other messages get deleted from the heap !!!!!!!! uint32 count = 0; bool further = true; while((count < 50) && further) { if (mHeapEnd != mHeapStart) { if (message->getPendingDelete()) { //uint32 size = message->getSize(); message->~Message(); //memset(mHeapEnd, 0xed, size + sizeof(Message)); mHeapEnd += message->getSize() + sizeof(Message); mMessagesDestroyed++; // If we're at the end of the queue, rollover to the front again. if (mHeapEnd == mHeapRollover) { if (mHeapEnd == mHeapStart) { mHeapStart = mMessageHeap; } mHeapEnd = mMessageHeap; mHeapRollover = 0; } message = reinterpret_cast<Message*>(mHeapEnd); if(!message) return; assert(mHeapEnd < mMessageHeap + mHeapTotalSize && "mHeapEnd not within mMessageHeap bounds"); further = (mHeapEnd != mHeapStart) && message->getPendingDelete(); }//pending delete else if(Anh_Utils::Clock::getSingleton()->getStoredTime() - message->getCreateTime() > MESSAGE_MAX_LIFE_TIME) { further = false; if (!message->mLogged) { LOG(WARNING) << "Garbage Collection found a new stuck message!" << "age : " << ( uint32((Anh_Utils::Clock::getSingleton()->getStoredTime() - message->getCreateTime())/1000)); message->mLogged = true; message->mLogTime = Anh_Utils::Clock::getSingleton()->getStoredTime(); Session* session = (Session*)message->mSession; if(!session) { LOG(INFO) << "Packet is Sessionless."; message->setPendingDelete(true); } else if(session->getStatus() > SSTAT_Disconnected || session->getStatus() == SSTAT_Disconnecting) { LOG(INFO) << "Session is about to be destroyed."; } } Session* session = (Session*)message->mSession; if(!session) { LOG(INFO) << "Garbage Collection found sessionless packet"; message->setPendingDelete(true); } else if(Anh_Utils::Clock::getSingleton()->getStoredTime() >(message->mLogTime +10000)) { LOG(WARNING) << "Garbage Collection found a old stuck message!" << "age : "<< (uint32((Anh_Utils::Clock::getSingleton()->getStoredTime() - message->getCreateTime())/1000)) << "Session status : " << session->getStatus(); message->mLogTime = Anh_Utils::Clock::getSingleton()->getStoredTime(); return; } else if(Anh_Utils::Clock::getSingleton()->getStoredTime() - message->getCreateTime() > MESSAGE_MAX_LIFE_TIME*mlt) { if(session) { // make sure that the status is not set again from Destroy to Disconnecting // otherwise we wont ever get rid of that session if(session->getStatus() < SSTAT_Disconnecting) { session->setCommand(SCOM_Disconnect); LOG(WARNING) << "Garbage Collection Message Heap Time out. Destroying Session"; } if(session->getStatus() == SSTAT_Destroy) { LOG(WARNING) << "Garbage Collection Message Heap Time out. Session about to Destroyed."; } return; } else { message->setPendingDelete(true); LOG(WARNING) << "Garbage Collection Message Heap Time out. Session Already Destroyed. Tagged Message as Deletable."; return; } } } else return; }//Heap start != Heapend else { return; } //we need to be accurate here count++; } }