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;
    }
}
Beispiel #2
0
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;
}
Beispiel #3
0
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++;
    }

}