diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /gcsdk/messagelist.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'gcsdk/messagelist.cpp')
| -rw-r--r-- | gcsdk/messagelist.cpp | 673 |
1 files changed, 673 insertions, 0 deletions
diff --git a/gcsdk/messagelist.cpp b/gcsdk/messagelist.cpp new file mode 100644 index 0000000..f1d9732 --- /dev/null +++ b/gcsdk/messagelist.cpp @@ -0,0 +1,673 @@ +//====== Copyright , Valve Corporation, All rights reserved. ======= +// +// Purpose: Provides names for GC message types +// +//============================================================================= + + +#include "stdafx.h" + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +namespace GCSDK +{ + +//----------------------------------------------------------------------------- +// Purpose: allow global initializers for a list of message infos. The message +// list will assemble them all into a single list when it initializes. +//----------------------------------------------------------------------------- +class CMessageListRegistration +{ +public: + CMessageListRegistration( MsgInfo_t *pMsgInfo, int cMsgInfo, void *pExtra = NULL ); + + static CMessageListRegistration *sm_pFirst; + CMessageListRegistration *m_pNext; + MsgInfo_t *m_pMsgInfo; + int m_cMsgInfo; +}; + + +DECLARE_GC_EMIT_GROUP( g_EGMessages, messages ); + +//function called when a message is tallied but not registered properly. Used to help consolidate behavior for untracked messages +static void HandleUntrackedMsg( const char* pszMsgOperation, uint32 nMsgID ) +{ + //for now output this as verbose so that we can clean up the initial spam. Then promote this to warnings in the future + EG_VERBOSE( g_EGMessages, "Found %s message with ID %d that was not properly registered. Unable to tally information\n", pszMsgOperation, nMsgID ); +} + + +CMessageListRegistration::CMessageListRegistration( MsgInfo_t *pMsgInfo, int cMsgInfo, void *pExtra ) +: m_pMsgInfo( pMsgInfo ), + m_cMsgInfo( cMsgInfo ) +{ + m_pNext = sm_pFirst; + sm_pFirst = this; +} + +CMessageListRegistration *CMessageListRegistration::sm_pFirst = NULL; + +//----------------------------------------------------------------------------- +// Purpose: Returns the name of a message type +//----------------------------------------------------------------------------- +const char *PchMsgNameFromEMsg( MsgType_t eMsg ) +{ + const char *pchMsgName = k_rgchUnknown; + g_theMessageList.GetMessage( eMsg, &pchMsgName, MT_GC ); + return pchMsgName; +} + + +//----------------------------------------------------------------------------- +void MsgRegistrationFromEnumDescriptor( const ::google::protobuf::EnumDescriptor *pEnumDescriptor, int nTypeMask ) +{ + // build the struct list for messages + MsgInfo_t *pMsgInfos = new MsgInfo_t[ pEnumDescriptor->value_count() ]; + memset( pMsgInfos, 0, sizeof( MsgInfo_t ) * pEnumDescriptor->value_count() ); + + for ( int i = 0; i < pEnumDescriptor->value_count(); ++i ) + { + const ::google::protobuf::EnumValueDescriptor *pEnumValueDescriptor = pEnumDescriptor->value(i); + pMsgInfos[ i ].eMsg = pEnumValueDescriptor->number(); + pMsgInfos[ i ].pchMsgName = pEnumValueDescriptor->name().c_str(); + pMsgInfos[ i ].nFlags = nTypeMask; + } + + new CMessageListRegistration( pMsgInfos, pEnumDescriptor->value_count() ); +} + +//----------------------------------------------------------------------------- + +CMessageList g_theMessageList; + +//----------------------------------------------------------------------------- +// CMessageList +// +// builds a hash of the MsgInfo_t table so that information about messages +// can be found without searching. +//----------------------------------------------------------------------------- + +CMessageList::CMessageList( ) : m_bProfiling( false ), m_ulProfileMicrosecs( 0 ) +{ +} + + +//----------------------------------------------------------------------------- +// CMessageList +// +// builds a hash of the MsgInfo_t table so that information about messages +// can be found without searching. +//----------------------------------------------------------------------------- +bool CMessageList::BInit( ) +{ + m_bProfiling = false; + m_ulProfileMicrosecs = 0; + + // figure out our message count + int cMessageInfos = 0; + for( CMessageListRegistration *pReg = CMessageListRegistration::sm_pFirst; pReg != NULL; pReg = pReg->m_pNext) + { + cMessageInfos += pReg->m_cMsgInfo; + } + + // message indexes should fit in a short + Assert( cMessageInfos < SHRT_MAX ); + + m_vecMsgInfo.EnsureCapacity( cMessageInfos ); + m_vecMsgInfo.RemoveAll(); + m_vecMessageInfoBuckets.RemoveAll(); + + int nIndex = 0; + for( CMessageListRegistration *pReg = CMessageListRegistration::sm_pFirst; pReg != NULL; pReg = pReg->m_pNext) + { + for ( int nRegIndex = 0; nRegIndex < pReg->m_cMsgInfo; nRegIndex++ ) + { + nIndex = m_vecMsgInfo.AddToTail( pReg->m_pMsgInfo[nRegIndex] ); + + int nSlot; + int nBucket = HashMessage( pReg->m_pMsgInfo[nRegIndex].eMsg, nSlot ); + + AssureBucket( nBucket ); + + if ( m_vecMessageInfoBuckets[nBucket][nSlot] != -1 ) + { + int otherIndex = m_vecMessageInfoBuckets[nBucket][nSlot]; + MsgInfo_t &otherMsg = m_vecMsgInfo[ otherIndex ]; + AssertFatalMsg2( false, "Message collision: %s redefined as %s", + otherMsg.pchMsgName, + pReg->m_pMsgInfo[nRegIndex].pchMsgName); + } + else + { + m_vecMessageInfoBuckets[nBucket][nSlot] = (short) nIndex; + } + } + } + + //start our window + ResetWindow(); + //and start our global timer + m_sCollectTime[ MsgInfo_t::k_EStatsGroupGlobal ].SetToJobTime(); + + return true; +} + + +//----------------------------------------------------------------------------- +// Tally the sending of a message +//----------------------------------------------------------------------------- +void CMessageList::TallySendMessage( MsgType_t eMsgType, uint32 unMsgSize, uint32 nSourceMask ) +{ + short nIndex = GetMessageIndex( eMsgType ); + if ( nIndex == - 1 ) + { + HandleUntrackedMsg( "send", eMsgType ); + return; + } + + TallyMessageInternal( m_vecMsgInfo[nIndex],MsgInfo_t::k_EStatsTypeSent, unMsgSize, nSourceMask ); +} + + +//----------------------------------------------------------------------------- +// Tally the receiving of a message +//----------------------------------------------------------------------------- +void CMessageList::TallyReceiveMessage( MsgType_t eMsgType, uint32 unMsgSize, uint32 nSourceMask ) +{ + short nIndex = GetMessageIndex( eMsgType ); + if ( nIndex == - 1 ) + { + HandleUntrackedMsg( "receive", eMsgType ); + return; + } + + TallyMessageInternal( m_vecMsgInfo[nIndex], MsgInfo_t::k_EStatsTypeReceived, unMsgSize, nSourceMask ); +} + + +//----------------------------------------------------------------------------- +// Tally the receiving of a message +//----------------------------------------------------------------------------- +void CMessageList::TallyMultiplexedMessage( MsgType_t eMsgType, uint32 uSent, uint32 cRecipients, uint32 uMsgSize, uint32 nSourceMask ) +{ + short nIndex = GetMessageIndex( eMsgType ); + if ( nIndex == - 1 ) + { + HandleUntrackedMsg( "multiplex", eMsgType ); + return; + } + + MsgInfo_t &msgInfo = m_vecMsgInfo[nIndex]; + TallyMessageInternal( msgInfo, MsgInfo_t::k_EStatsTypeMultiplexedSends, uSent, nSourceMask, 1 ); + TallyMessageInternal( msgInfo, MsgInfo_t::k_EStatsTypeMultiplexedSendsRaw, uMsgSize * cRecipients, nSourceMask, cRecipients ); +} + + +//----------------------------------------------------------------------------- +// Tally the receiving of a message +//----------------------------------------------------------------------------- +void CMessageList::TallyMessageInternal( MsgInfo_t &msgInfo, MsgInfo_t::EStatsType eBucket, uint32 unMsgSize, uint32 nSourceMask, uint32 cMessages ) +{ + //log this for global stats + msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].nCount += cMessages; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].uBytes += unMsgSize; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].nSourceMask |= nSourceMask; + + //track this in our current timing window + msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].nCount += cMessages; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].uBytes += unMsgSize; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].nSourceMask |= nSourceMask; + + //track our window totals as well + m_WindowTotals[ eBucket ].nCount += cMessages; + m_WindowTotals[ eBucket ].uBytes += unMsgSize; + m_WindowTotals[ eBucket ].nSourceMask |= nSourceMask; + + //and if we are profiling, track the data into our profiling window + if ( m_bProfiling ) + { + msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].nCount += cMessages; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].uBytes += unMsgSize; + msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].nSourceMask |= nSourceMask; + } +} + +//called to obtain the totals for the timing window +const MsgInfo_t::Stats_t& CMessageList::GetWindowTotal( MsgInfo_t::EStatsType eType ) const +{ + return m_WindowTotals[ eType ]; +} + +//called to reset the window timings +void CMessageList::ResetWindow() +{ + //reset when our window started + m_sCollectTime[ MsgInfo_t::k_EStatsGroupWindow ].SetToJobTime(); + + // starting a new window... clear everything + FOR_EACH_VEC( m_vecMsgInfo, nIndex ) + { + for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ ) + { + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].nCount = 0; + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].uBytes = 0; + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].nSourceMask = 0; + } + } + + //and clear our totals + for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ ) + { + m_WindowTotals[ nType ].nCount = 0; + m_WindowTotals[ nType ].uBytes = 0; + } +} + + +//----------------------------------------------------------------------------- +// Turns snapshot profiling on and off +//----------------------------------------------------------------------------- +void CMessageList::EnableProfiling( bool bEnableProfiling ) +{ + m_bProfiling = bEnableProfiling; + if ( m_bProfiling ) + { + m_sCollectTime[ MsgInfo_t::k_EStatsGroupProfile ].SetToJobTime(); + + // starting a new profile... clear everything + FOR_EACH_VEC( m_vecMsgInfo, nIndex ) + { + for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ ) + { + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].nCount = 0; + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].uBytes = 0; + m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].nSourceMask = 0; + } + } + } + else + { + m_ulProfileMicrosecs = m_sCollectTime[ MsgInfo_t::k_EStatsGroupProfile ].CServerMicroSecsPassed(); + } +} + + +uint64 CMessageList::GetGroupDuration( MsgInfo_t::EStatsGroup eGroup ) const +{ + //handle the special case of it being a profile, where if we are no longer profiling, we want to use our cached value + if( ( eGroup == MsgInfo_t::k_EStatsGroupProfile ) && !m_bProfiling ) + { + return m_ulProfileMicrosecs; + } + + //otherwise we can just use the timer directly + return m_sCollectTime[ eGroup ].CServerMicroSecsPassed(); +} + +//----------------------------------------------------------------------------- +// print statistics bout each message we handle +//----------------------------------------------------------------------------- +void CMessageList::PrintStats( bool bShowAll, bool bSortByFrequency, MsgInfo_t::EStatsGroup eGroup, MsgInfo_t::EStatsType eType, uint32 nSourceMask ) const +{ + // Figure out which time value we should use for rate calcs + uint64 ulMicroseconds = GetGroupDuration( eGroup ); + + // work out a sorted list + CUtlMap<uint64, uint32> mapValueToMsg( DefLessFunc( uint64 ) ); + uint64 unTotalBytes = 0; + uint32 unTotalMessages = 0; + + FOR_EACH_VEC( m_vecMsgInfo, n ) + { + //see if we are looking for a particular source, and if so, if this has that source set + if( nSourceMask && ( ( m_vecMsgInfo[n].stats[ eGroup ][ eType ].nSourceMask & nSourceMask ) == 0 ) ) + continue; + + uint32 nCount = m_vecMsgInfo[n].stats[ eGroup ][ eType ].nCount; + uint64 uBytes = m_vecMsgInfo[n].stats[ eGroup ][ eType ].uBytes; + + unTotalMessages += nCount; + unTotalBytes += uBytes; + + if ( nCount == 0 && !bShowAll ) + continue; + + mapValueToMsg.Insert( bSortByFrequency ? (uint64)nCount : uBytes, n ); + } + + double fSeconds = ulMicroseconds / ( 1000.0 * 1000.0 ); + + // 5, 46, 10, 6, 14, 6, 10, 10 + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "EMsg MessageName Count % Bytes % MsgPS Avg/Msg KBPS\n" ); + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "----- ---------------------------------------------- ---------- ------ -------------- ------ --------- ---------- ----------\n" ); + + for ( uint16 iValue = mapValueToMsg.LastInorder(); iValue != mapValueToMsg.InvalidIndex(); iValue = mapValueToMsg.PrevInorder( iValue ) ) + { + uint32 n = mapValueToMsg[iValue]; + + //see if we are looking for a particular source, and if so, if this has that source set + if( nSourceMask && ( ( m_vecMsgInfo[n].stats[ eGroup ][ eType ].nSourceMask & nSourceMask ) == 0 ) ) + continue; + + uint32 nCount = m_vecMsgInfo[n].stats[ eGroup ][ eType].nCount; + uint64 uBytes = m_vecMsgInfo[n].stats[ eGroup ][ eType].uBytes; + + uint32 uAvgMsg = 0; + if ( nCount > 0 ) + uAvgMsg = uBytes / nCount; + + float flCountPerc = 0; + if ( unTotalMessages > 0 ) + flCountPerc = nCount * 100.0f / unTotalMessages; + float flBytesPerc = 0; + if ( unTotalBytes > 0 ) + flBytesPerc = uBytes * 100.0f / unTotalBytes; + double fMsgPS = 0.0; + if ( ulMicroseconds > 0 ) + fMsgPS = nCount / fSeconds; + double fKBPS = 0.0f; + if ( ulMicroseconds > 0 ) + fKBPS = uBytes / ( fSeconds * 1000.0 ); + + + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%5u %-46s %10u %5.1f%% %14llu %5.1f%% %9.1f %10u %10.2f\n", + m_vecMsgInfo[n].eMsg, + m_vecMsgInfo[n].pchMsgName, + nCount, + flCountPerc, + uBytes, + flBytesPerc, + fMsgPS, + uAvgMsg, + fKBPS ); + } + + uint32 uAvgMsgTotal = 0; + if ( unTotalMessages > 0 ) + uAvgMsgTotal = unTotalBytes / unTotalMessages; + double fMsgPS = 0.0; + if ( ulMicroseconds > 0 ) + fMsgPS = unTotalMessages / fSeconds; + double fKBPSTotal = 0.0; + if ( ulMicroseconds > 0 ) + fKBPSTotal = unTotalBytes / ( fSeconds * 1000.0 ); + + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "----- ---------------------------------------------- ---------- ------ -------------- ------ --------- ---------- ----------\n" ); + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "Totals %10u 100.0%% %14llu 100.0%% %9.1f %10u %10.2f\n", + unTotalMessages, + unTotalBytes, + fMsgPS, + uAvgMsgTotal, + fKBPSTotal ); +} + + +//----------------------------------------------------------------------------- +// print statistics bout each message we handle +//----------------------------------------------------------------------------- +void CMessageList::PrintMultiplexStats( MsgInfo_t::EStatsGroup eGroup, bool bSortByFrequency, uint32 nSourceMask ) const +{ + // Figure out which time value we should use for rate calcs + uint64 ulMicroseconds = GetGroupDuration( eGroup ); + + MsgInfo_t::Stats_t rgTotals[MsgInfo_t::k_EStatsType_Count]; + + const MsgInfo_t::EStatsType eMultiType = MsgInfo_t::k_EStatsTypeMultiplexedSends; + const MsgInfo_t::EStatsType eRawType = MsgInfo_t::k_EStatsTypeMultiplexedSendsRaw; + + // work out a sorted list + CUtlMap<uint64, uint32> mapValueToMsg( DefLessFunc( uint64 ) ); + FOR_EACH_VEC( m_vecMsgInfo, n ) + { + const MsgInfo_t &msgInfo = m_vecMsgInfo[n]; + + //see if we are looking for a particular source, and if so, if this has that source set + if( nSourceMask && ( msgInfo.stats[ eGroup ][ eMultiType ].nSourceMask & nSourceMask ) == 0 ) + continue; + + rgTotals[eMultiType].nCount += msgInfo.stats[ eGroup ][ eMultiType ].nCount; + rgTotals[eMultiType].uBytes += msgInfo.stats[ eGroup ][ eMultiType ].uBytes; + rgTotals[eRawType].nCount += msgInfo.stats[ eGroup ][ eRawType ].nCount; + rgTotals[eRawType].uBytes += msgInfo.stats[ eGroup ][ eRawType ].uBytes; + + if ( msgInfo.stats[ eGroup ][ eMultiType ].nCount == 0 ) + continue; + + uint32 nCount = msgInfo.stats[ eGroup ][ eMultiType ].nCount; + uint64 uBytes = msgInfo.stats[ eGroup ][ eMultiType ].uBytes; + mapValueToMsg.Insert( bSortByFrequency ? (uint64)nCount : uBytes, n ); + } + + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "EMsg MessageName Count % KB % Avg/Msg KBPS Msg Saved % KB Saved %\n" ); + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "----- ---------------------------------------------- ---------- ------ -------------- ------ ---------- ---------- ---------- ------ -------------- ------\n" ); + + uint32 unTotalMessages = 0; + uint64 unTotalBytes = 0; + + for ( uint16 iValue = mapValueToMsg.LastInorder(); iValue != mapValueToMsg.InvalidIndex(); iValue = mapValueToMsg.PrevInorder( iValue ) ) + { + const MsgInfo_t &msgInfo = m_vecMsgInfo[ mapValueToMsg[iValue] ]; + + //see if we are looking for a particular source, and if so, if this has that source set + if( nSourceMask && ( msgInfo.stats[ eGroup ][ eMultiType ].nSourceMask & nSourceMask ) == 0 ) + continue; + + uint32 nCount = msgInfo.stats[ eGroup ][ eMultiType ].nCount; + uint64 uBytes = msgInfo.stats[ eGroup ][ eMultiType ].uBytes; + + unTotalMessages += nCount; + unTotalBytes += uBytes; + + int32 nMessagesSaved = msgInfo.stats[ eGroup ][ eRawType ].nCount - msgInfo.stats[ eGroup ][ eMultiType ].nCount; + int64 uBytesSaved = msgInfo.stats[ eGroup ][ eRawType ].uBytes - msgInfo.stats[ eGroup ][ eMultiType ].uBytes; + + uint32 nMessagesIfNotMultiplex = msgInfo.stats[ eGroup ][ eRawType ].nCount; + uint64 uBytesIfNotMultiplex = msgInfo.stats[ eGroup ][ eRawType ].uBytes; + + uint32 uAvgMsg = 0; + if ( nCount > 0 ) + uAvgMsg = uBytes / nCount; + + float flCountPerc = 0; + if ( rgTotals[eMultiType].nCount > 0 ) + flCountPerc = nCount * 100.0f / rgTotals[eMultiType].nCount; + float flBytesPerc = 0; + if ( rgTotals[eMultiType].uBytes > 0 ) + flBytesPerc = uBytes * 100.0f / rgTotals[eMultiType].uBytes; + float fKBPS = 0.0f; + if ( ulMicroseconds > 0 ) + fKBPS = uBytes * 1000.0f / ulMicroseconds; + + float flMessagesSavedPerc = 0.0f; + if ( nMessagesIfNotMultiplex > 0 ) + flMessagesSavedPerc = nMessagesSaved * 100.0f / nMessagesIfNotMultiplex; + float flBytesSavedPerc = 0.0f; + if ( uBytesIfNotMultiplex > 0 ) + flBytesSavedPerc = uBytesSaved * 100.0f / uBytesIfNotMultiplex; + + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%5u %-46s %10u %5.1f%% %14llu %5.1f%% %10u %10.2f %10d %5.1f%% %14lld %5.1f%%\n", + msgInfo.eMsg, + msgInfo.pchMsgName, + nCount, + flCountPerc, + uBytes / 1024, + flBytesPerc, + uAvgMsg, + fKBPS, + nMessagesSaved, + flMessagesSavedPerc, + uBytesSaved / 1024, + flBytesSavedPerc ); + } + + uint32 uAvgMsgTotal = 0; + if ( unTotalMessages > 0 ) + uAvgMsgTotal = unTotalBytes / unTotalMessages; + + float fKBPSTotal = 0.0f; + if ( ulMicroseconds > 0 ) + fKBPSTotal = unTotalBytes * 1000.0f / ulMicroseconds; + + float flTotalMessagesPct = 0.0f; + if ( rgTotals[eMultiType].nCount > 0 ) + flTotalMessagesPct = unTotalMessages * 100.0f / rgTotals[eMultiType].nCount; + + float flTotalBytesPct = 0.0f; + if ( rgTotals[eMultiType].uBytes > 0 ) + flTotalBytesPct = unTotalBytes * 100.0f / rgTotals[eMultiType].uBytes; + + int32 nTotalMessagesSaved = rgTotals[eRawType].nCount - rgTotals[eMultiType].nCount; + int64 nTotalBytesSaved = rgTotals[eRawType].uBytes - rgTotals[eMultiType].uBytes; + + int32 nTotalMessagesIfNotMultiplex = unTotalMessages - rgTotals[eMultiType].nCount + rgTotals[eRawType].nCount; + int64 uTotalBytesIfNotMultiplex = unTotalBytes - rgTotals[eMultiType].uBytes + rgTotals[eRawType].uBytes; + + float flTotalMessagesSavedPct = 0.0f; + if ( nTotalMessagesIfNotMultiplex > 0 ) + flTotalMessagesSavedPct = nTotalMessagesSaved * 100.0f / nTotalMessagesIfNotMultiplex; + + float flTotalBytesSavedPct = 0.0f; + if ( uTotalBytesIfNotMultiplex > 0 ) + flTotalBytesSavedPct = nTotalBytesSaved * 100.0f / uTotalBytesIfNotMultiplex; + + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "----- ---------------------------------------------- ---------- ------ -------------- ------ ---------- ---------- ---------- ------ -------------- ------\n" ); + EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "Totals %10u %5.1f%% %14llu %5.1f%% %10u %10.2f %10d %5.1f%% %14lld %5.1f%%\n", + unTotalMessages, + flTotalMessagesPct, + unTotalBytes / 1024, + flTotalBytesPct, + uAvgMsgTotal, + fKBPSTotal, + nTotalMessagesSaved, + flTotalMessagesSavedPct, + nTotalBytesSaved / 1024, + flTotalBytesSavedPct ); +} + + +//----------------------------------------------------------------------------- +// Destroys a message list by deallocating everything it's got +//----------------------------------------------------------------------------- +CMessageList::~CMessageList() +{ + int nUsedBuckets = 0; + for ( int nIndex = 0; nIndex < m_vecMessageInfoBuckets.Count(); nIndex++ ) + { + if ( m_vecMessageInfoBuckets[nIndex] != NULL ) + { + FreePv( m_vecMessageInfoBuckets[nIndex] ); + m_vecMessageInfoBuckets[nIndex] = NULL; + nUsedBuckets++; + } + } + + m_vecMessageInfoBuckets.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// assure that we've got the slots in the given bucket allocated +//----------------------------------------------------------------------------- +void CMessageList::AssureBucket( int nBucket ) +{ + // if this bucket is bigger then the array, extend the array + if ( nBucket >= m_vecMessageInfoBuckets.Count() ) + { + int nOldCount = m_vecMessageInfoBuckets.Count(); + // message ID "clumps" are usually 100 apart, so we'll try + // to grow by 100 each time. Divide 100 by the bucket size and add + // one for truncation to figure out our grow-by. + int nNewCount = nBucket + (1 + (100 / m_kcBucketSize)); + + // get that count + m_vecMessageInfoBuckets.EnsureCount( nNewCount ); + + // initialize the new ones to NULL + for ( int nIndex = nOldCount; nIndex < nNewCount; nIndex++ ) + { + m_vecMessageInfoBuckets[nIndex] = NULL; + } + } + + // is the bucket we want allocated? + if ( m_vecMessageInfoBuckets[nBucket] == NULL ) + { + // nope; get one and initialize it + m_vecMessageInfoBuckets[nBucket] = (short*) PvAlloc( sizeof(short) * m_kcBucketSize ); + for ( int nIndex = 0; nIndex < m_kcBucketSize; nIndex++) + m_vecMessageInfoBuckets[nBucket][nIndex] = -1; + } + + return; +} + + +//----------------------------------------------------------------------------- +// Purpose: Hash an MsgType_t and return the index into m_vecMsgInfo where it can be found +// returns -1 if the MsgType_t is unknown +//----------------------------------------------------------------------------- +short CMessageList::GetMessageIndex( MsgType_t eMsg ) +{ + // find the slot and bucket for this message in our hash + int nSlot; + int nBucket = HashMessage( eMsg, nSlot ); + + // taller than the hash? + if ( nBucket >= m_vecMessageInfoBuckets.Count() ) + return -1; + + // not a bucket? + if ( m_vecMessageInfoBuckets[nBucket] == NULL ) + return -1; + + // get the index back to the global array + short nIndex = m_vecMessageInfoBuckets[nBucket][nSlot]; + return nIndex; +} + + +//----------------------------------------------------------------------------- +// Tests to see if a message is valid; if so, return a pointer to its name. +// A message must match at least one of the nTypeMask flags to be considered +// valid. If provided, ppMsgName is set to k_rgchUnknown if no match, +// or the message name if matched. +//----------------------------------------------------------------------------- + +bool CMessageList::GetMessage( MsgType_t eMsg, const char **ppMsgName, int nTypeMask ) +{ + VPROF_BUDGET( "GetMessage", VPROF_BUDGETGROUP_JOBS_COROUTINES ); + + // if an out variable for the name is provided, + // initialize it with a pointer to "unknown" string + if ( ppMsgName != NULL ) + *ppMsgName = k_rgchUnknown; + + short nIndex = GetMessageIndex( eMsg ); + + // good index? + if ( nIndex == -1 ) + { + if ( ppMsgName != NULL ) + { + *ppMsgName = "Unknown MsgType - Not Found"; + } + return false; + } + + const MsgInfo_t &msgInfo = m_vecMsgInfo[nIndex]; + + // get the string out + if ( ppMsgName != NULL ) + *ppMsgName = msgInfo.pchMsgName; + + // it's good if it matches the flags + return ( 0 != ( msgInfo.nFlags & nTypeMask ) ); +} + + +} // namespace GCSDK + |