|
|
//====== Copyright �, Valve Corporation, All rights reserved. =======
//
// Purpose: Maps message types to strings and vice versa
//
//=============================================================================
#ifndef MESSAGELIST_H
#define MESSAGELIST_H
#ifdef _WIN32
#pragma once
#endif
// Protobuf headers interfere with the valve min/max/malloc overrides. so we need to do all
// this funky wrapping to make the include happy.
#include <tier0/valve_minmax_off.h>
#include "google/protobuf/descriptor.h"
#include <tier0/valve_minmax_on.h>
#include "gcsdk/jobtime.h"
namespace GCSDK {
extern CGCEmitGroup g_EGMessages; extern const char *PchMsgNameFromEMsg( MsgType_t eMsg );
//-----------------------------------------------------------------------------
// message type flags
//-----------------------------------------------------------------------------
static const int MT_GC = 0x01; // this message is sent to or from a Game Coordinator (will be proxied by servers along the way)
static const int MT_GC_SYSTEM = 0x02; // this message was sent to or from the steam servers as a system message. Clients can't send these
//-----------------------------------------------------------------------------
// Various info about each message type
//-----------------------------------------------------------------------------
struct MsgInfo_t { MsgType_t eMsg; int nFlags; const char *pchMsgName;
struct Stats_t { Stats_t() : nSourceMask(0), nCount( 0 ), uBytes( 0 ) {} uint32 nSourceMask; uint32 nCount; uint64 uBytes; };
enum EStatsType { k_EStatsTypeSent, k_EStatsTypeReceived, k_EStatsTypeMultiplexedSends, k_EStatsTypeMultiplexedSendsRaw,
k_EStatsType_Count };
enum EStatsGroup { k_EStatsGroupGlobal, k_EStatsGroupProfile, k_EStatsGroupWindow,
k_EStatsGroup_Count };
Stats_t stats[ k_EStatsGroup_Count ][ k_EStatsType_Count ]; };
//-----------------------------------------------------------------------------
// Purpose: Using protobuf reflection, bind them into a message list
//-----------------------------------------------------------------------------
void MsgRegistrationFromEnumDescriptor( const ::google::protobuf::EnumDescriptor *pEnumDescriptor, int nTypeMask );
//-----------------------------------------------------------------------------
// manages a hashed list of messages, allowing fast tests for validity and
// info lookup.
//-----------------------------------------------------------------------------
class CMessageList { public: CMessageList(); ~CMessageList();
bool BInit( );
// returns false if a message isn't valid or isn't one of the types specified
// or true if the message is valid. ppMsgName can be NULL.
bool GetMessage( MsgType_t eMsg, const char **ppMsgName, int nTypeMask );
// make stats about sending messages
void TallySendMessage( MsgType_t eMsg, uint32 uMsgSize, uint32 nSourceMask = 0 ); void TallyReceiveMessage( MsgType_t eMsg, uint32 uMsgSize, uint32 nSourceMask = 0); void TallyMultiplexedMessage( MsgType_t eMsg, uint32 uSent, uint32 cRecipients, uint32 uMsgSize, uint32 nSourceMask = 0 );
// profiling
void EnableProfiling( bool bEnableProfiling );
// print out our stats
void PrintStats( bool bShowAll, bool bSortByFrequency, MsgInfo_t::EStatsGroup eGroup, MsgInfo_t::EStatsType eType, uint32 nSourceMask = 0 ) const; void PrintMultiplexStats( MsgInfo_t::EStatsGroup eGroup, bool bSortByFrequency, uint32 nSourceMask = 0 ) const;
// Window management - This is similar to profiling in many ways, but is separate so that the base system can monitor traffic rates without
// interfering with profiles.
//called to obtain the totals for the timing window
const MsgInfo_t::Stats_t& GetWindowTotal( MsgInfo_t::EStatsType eType ) const; //called to reset the window timings
void ResetWindow(); //returns how long this window has been running in microseconds
uint64 GetWindowDuration() const { return GetGroupDuration( MsgInfo_t::k_EStatsGroupWindow ); }
private: void TallyMessageInternal( MsgInfo_t &msgInfo, MsgInfo_t::EStatsType eBucket, uint32 unMsgSize, uint32 nSourceMask, uint32 cMessages = 1 );
void AssureBucket( int nBucket );
//-----------------------------------------------------------------------------
// given a particular message ID, find out what bucket it would be in,
// as well as which slot in that bucket.
//-----------------------------------------------------------------------------
static int HashMessage( MsgType_t eMsg, int &nSlot ) { // hash is everything except the lowest nibble,
// because buckets are 16 entries
int nBucket = eMsg / m_kcBucketSize; nSlot = eMsg % m_kcBucketSize; return nBucket; }
short GetMessageIndex( MsgType_t eMsg );
//given a group, this will return the time that the stats have been collected over
uint64 GetGroupDuration( MsgInfo_t::EStatsGroup eGroup ) const;
private:
//totalled stats for the current window. It would be too costly to total these all the time
MsgInfo_t::Stats_t m_WindowTotals[ MsgInfo_t::k_EStatsType_Count ];
//the time that we have been collecting each of these buckets
CJobTime m_sCollectTime[ MsgInfo_t::k_EStatsGroup_Count ]; //are we currently actively tracking a profile?
bool m_bProfiling; //the duration of the last finished profile (if it is no longer running, otherwise use the timer)
uint64 m_ulProfileMicrosecs;
CUtlVector< short* > m_vecMessageInfoBuckets; CUtlVector<MsgInfo_t> m_vecMsgInfo; static const int m_kcBucketSize = 16; };
extern CMessageList g_theMessageList;
//-----------------------------------------------------------------------------
// Purpose: Returns the true if the specified message is a valid GC system message.
// Input : eMsg - message type to test
// ppMsgName - Optional pointer to receive message name
//-----------------------------------------------------------------------------
inline bool BIsValidSystemMsg( MsgType_t eMsg, const char **ppMsgName ) { return g_theMessageList.GetMessage( eMsg, ppMsgName, MT_GC_SYSTEM ); }
} // namespace GCSDK
#endif // MESSAGELIST_H
|